一个人如何开发产品
2021年度回顾
中国用户如何免费激活Stripe?
中国用户如何免费激活Stripe?
本文会介绍无需开设海外银行账号或者香港账号,并免费的通过注册激活Stripe账号并提现,亲测有效!
主要通过使用万里汇海外账号绑定激活,其中万里汇是蚂蚁金服旗下的产品,值得可靠。(不是给万里汇打广告哦)
什么是Stripe
想象你是一个跨境电商,想要把产品卖到全球,却面临一个问题,商品标价$100,日本客户想直接支付日元,欧洲客户想支付欧元。。。你不可能要求客户说我只支持美元,请兑换后再支付吧?
所以如果你还不知道Stripe,那推荐你去了解下。作为和PayPal一样存在的支付巨头(现在市值 $950亿),在国外早已火得一塌糊涂,使用他作为支付平台的商家和网站数不甚数,消费者渗透率覆盖了全球135个国家。。。
中国商户,NO
遗憾的是,如果你是身在中国,那么是不能激活Stripe 账号的(不激活只是注册账号倒是可以,但是没法收款和体现,只能测试),可以查看现在商户支持的40多个国家/地区列表, 其中香港是可以的。所以你能看到,这个注册公司地址里是没办法选择中国🇨🇳的,That’s the problem!
如果解决?万里汇 或者 TransferWise
问题的瓶颈在于stripe 激活的时候,需要提供你的商业信息以及银行信息,并且保证银行上的名字和账号里的个人姓名一致。但又由于商业信息的国家地区只有上面提到的,所以也就导致中国用户没办法激活。
解决办法的思路就是,使用万里汇注册个香港账号或者其他国家的银行账号(虽说是虚拟的,但和实际没区别),然后再根据账号的信息拿去Stripe激活,看似简单,但还有很多坑需要趟,且听我慢慢道来。
注册万里汇
点击注册地址 https://portal.worldfirst.com.cn/register,
- 然后按步骤选择支付网关, 这里可以按个人情况多选几个(最好把stripe 勾选上),虽然我也不知道有多大影响
选择类型,可以是个人, 也可以是公司,这里我选的个人
填写基本信息,按部就班的填好就行,注册就算成功
认证账号
注册好了,是非认证状态的,这时是不能创建海外账号,还需要提供相应的信息上传去验证(据说可以支付宝快捷验证,但是我没发现有,只能拍照上传)
认证一般会持续一两天验证,等着收邮件就好了,如果有问题,可以联系自己的万里汇客户经理(真是一对一服务啊,这点好)
创建海外货币账户
终于到了关键步骤了,这里可以创建多个账户,每个账户就像自己银行卡一样,有卡号,为了stripe 注册方便,我创建了一个香港账户和一个美国账户
到了这一步,恭喜你,你已经开通了海外账户!关键是这个银行信息对后面的Stripe激活是非常重要。
创建和激活 Stripe 账号
首先创建Stripe 账号,https://dashboard.stripe.com/register, 国家/地区可以选择香港,创建好之后,登录进入主页面, 这个时候如果你暂时不想激活,是完全可以的,可以切换测试模式进行你的支付开发测试,测试模式基本和在线模式一模一样,除了测试的支付账号是假的以外 (PS, 我就是没激活使用了一年多,纯粹作为开发使用)
激活Stripe 账户
点击 激活你的账户 , 这里看起来有很多步骤,不用怕填错,后面都是可以跳回去改的。
公司结构:
选择香港,或者其他上面货币账号国家,地址可以填银行账号地址,类型可以选个人(如果公司的话,据说stripe 会对你账号保护性或者服务更好),点击下一步
公司代表:必须是你自己在上述银行账号的姓名,否则可能会无法体现到你银行
地址信息可以继续用银行地址,电话号码最好是用中国的,可以选CN, 填写自己号码,因为后面可能会用来用来登录短信验证之类的,身份证ID 这个我没记错的话,是随便找的一个ID(只要位数和格式对了就行) ☹️
银行详情:选择在万里汇创建的银行信息就行
然后一直填下去,保存
激活成功了吗?
上述没问题的话,确实激活成功了,你也可以切换到线上模式去收款了,但是却无法提现(转账)到你银行卡里,还有两个重要的未完成步骤警告:
身份信息不匹配(个人信息验证失败,当然了,ID 都是假的) 和 US Tax Form (美国税收表)
两个问题一个一个解决:
- ID 不匹配,进入提示的配置,只需要上传自己的身份证正反面就好了,一天左右就验证成功(不知道如何验证的,可能是后台人工验证,保证姓名一致就行,所以一定上传自己真实的身份证就,地址用自己中国地址)
- W-8 form,一定要选非美国居民(勾选No),然后点击提交,会被导航至表单填写页面,基本信息stripe 已经帮你预填了,只需要签上个人姓名就好了
documents-for-identity-and-home-address-verification
等着这两个错误完成后,这个账号就算真正激活完成,并可以完成提现(每天,并且非常快)。
万里汇提现到人民币(成功)
现在万里汇香港账号已经有收到的港币了,但如果需要的话,需要转为人民币(可转到支付宝),但根据万里汇客户经理说明,这是需要提供相应凭据,也就是stripe 或者 paypal 上的支付记录,表明来历明确。提现过一次,因为金额不大,并且提供了paypay 的收款记录,所以成功提现。
特别提醒的是,这篇文章目的只是为激活stripe指南, 不为跨境转账成功负责,请酌情选择。
特此声明,本文禁止转载至除 troyyang.com, itstripe.com 以外的网站
Wordpress 插件 Stripe Express 发布啦!
Stripe Express 是什么?
简单来说,Stripe Express 是一款针对wordpress 平台,帮助你使用 stripe 快速,方便完成跨境支付的一款免费插件(扩展功能收费)。其中,包括多种已经创建好的支付组件,包括一次性支付(one-time),电子钱包(支付宝,微信,Apple Pay, Google Pay,下面重点会提到微信和支付宝),表单支付等等组件,需要提及的是,上面的组件都支持常见的各种信用卡,Master card, Visa, 等等等等,以及其他国家地区的主流支付方式比如 Bancontact, FPX, EPS, SEPA, Giropay, Sofort, iDeal。
所以,只有你有一个 Stripe 的账号,那么超过三十多个国家地区的客户都可以向你支付(对于微信和支付宝,你无需申请支付宝或者微信的商家账号,即可免费收款)。
问题: 什么人更需要这个组件?
回答: 现阶段,因为还没集成woocommence, 所以如果你没有一个完整的电子商务网站比如使用 woocommence搭建,只是一个简单的Wordpress 网站,但是你又有自己的产品或者服务需要销售,而你只是想你用户简单的点击购买,付款。
itstripe.com
在我们国内,大部分人肯定知道Paypal,却不知道Stripe,更别说用过,当然也和Stripe 暂不支持中国商家的原因分不开。殊不知,国外Stripe普及程度远大于我们的想象,很多网站都会加上对Stripe 的支持,因为这意味着你的网站可以面向全世界超过30个主要国家的客户收费,包括中国!所以想要做跨境支付的话,Stripe 你必须要熟悉!
众所周知,Wordpress全世界超过40%的网站都是他创建的,而且现在也依旧火爆。再加上之前很多朋友都在咨询我关于 stripe 在wordpress上的问题,所以主要侧重点会是在 stripe express 这款插件上。其次,网站会包括产品介绍,以及插件的文档,还有和stripe 相关集成服务,如果你有集成这方面的需求的话,或者Web 的支付开发,可以联系我们。
Stripe,微信 和 支付宝
这是一个最重要的原因之一促使我想要做这么一个东西。有这么一部分人:1. 小商家或者个人网站用户想要接入微信或者支付宝,方便国内用户收费,2. 国外的中小网站想要针对中国用户微信和支付宝收费。但是对于他们而言,由其老外,要想接入微信或者支付宝支付接口,门槛还是有点高,需要去申请商家账号
stripe 却在这方面有着天然优势,由于已经和alipay 和 wechat 达成协议,Stripe 完全可以实现上面的收费,其中stripe 会收取3.4% + $0.50每笔的服务费。
之前写过一篇关于 stripe集成 微信和支付宝的文章,反响挺大的,看到很多评论和转载,也收到很多咨询的邮件,但是之前的那篇从技术角度其实有点老了,我会另外抽时间重新写一个更通用的集成方式(已经在这款插件中实践了)
后续
回想这半年多的开发时间(包括插件和官网),白天正常上班,晚上继续开发,连周末都不想出门,像打鸡血一样的完善产品,终于迎来了发布的日子。无论这款插件将来如何,安装量怎样,有过这么一段为了某个目标而全力以赴的日子也是极好的!
Mobx在项目中的实践 及 与Redux的比较
之前在公司FEE内部做过一次技术分享,主要关于Mobx在项目中的使用一年后的体验以及和Redux 的一些比较(因为我们项目之前的状态管理选型选择的是mobx,而其他项目组的同学选择主要是Redux或者还在纠结如何选)。
以下都是根据查询各种资料后的个人理解概览
Mobx Overview
Mobx looks like a properties tracking and reaction lib.
基础部分就省了,只说结论:Mobx 看起来是属性追踪及作出相应反应的库,和Redux 不一样的是,他的状态是mutable的。
Mobx 4 & 5
- Mobx 4 Limitations (Observable)
- Mobx 5 Proxy based (Only ES 6 Browser, no polyfill)
Mobx & Third-Party view lib
- mobx & mobx-react
- redux & react-redux
- mobx & mobx-arch & mobx-backbone 有吗???
Mobx 是可以单独使用的,这点和Redux一样,可以不需要依赖于任何UI 库像,React, Vue,当然如果把他们结合到一起,那才能发挥出最大的作用,所以就理所应当的有mobx-react。
我们公司内部有个UI 库叫arch,很老的了,requirejs时代的,比react, vue, angular还早,没有响应式的更新,核心只有一个render 方法,所以其实可以通过Mobx 简单改造为响应式的,一旦外部属性发生变化,就会触发重新渲染,至于内部状态嘛,呵呵,不考虑了,反正这只是个例子。
1 | var { observable, autorun } = require("mobx"); |
Mobx Store Design
- Offical guide on Store design
- Best Practice
- UI State & Domain State
这是我觉得最难的部分,如何设计好Mobx的Store?官方给出的一个guide 是划分为Domain store 和 UI store。Domain store和Redux的one-single store 可不一样,这里是可以有多个的,像users, books, movies, orders 都可以是一个Domain Store, 至于UI store,暂时我们只是存储一些全局的属性。所以,我们的项目中Store的结构大致如下:
1 | stores |
root.ts初始化所有domain和ui store:
1 | export default class RootStore { |
但是在实际的问题中,我们发现大部分的状态其实都是本地UI状态,(也许有人说用setState啊,如果业务复杂,状态很多, 并且基本会依赖其他store,最好抽出来)所以,问题来了,这些ui store我们放在哪里呢?同时,我们需要把Container 组件里的状态隔离开来,为什么隔离,一是因为UT 不好写(因为有inject,所以在UT里需要写很多Provider),二是傻瓜组件更不容易出错,参考Redux的connect用法,我们得到下面的结构:
1 | ContainerAComponent |
ContainerAComponentUIStore.ts
1 | export default class ContainerAComponentUIStore { |
ContainerAComponent.tsx
1 | export class ContainerAComponent extends React.Component { |
这样,我们导出了两个组件,一个是ContainerAComponent,就是一个简单组件,我们可以通过传统传props的方式去测试组件核心内容,另一个是HOC组件,其实是不用测试的。
而至于connectComponentStore方法,就是一个很简单的HOC
1 | export default (WrapperedComponent, ComponentStore) => { |
我们业务里,绝大部分都是用到的这种本地UI Store + 简单组件组合这种方式,也许就是所谓的local state component (忘了哪里听到的了)
Mobx-State-Tree(MST)
也许MST在大型项目中使用是个很好的方式,但我们暂时还没有去尝试。
Project Structure
下面是Mobx的一些项目组织结构参考资料:
https://medium.com/@daniel.bischoff/how-to-structure-your-mobx-react-app-8fd6d9d821a4
https://github.com/gothinkster/react-mobx-realworld-example-app
Mobx-React vs Redux-React
个人简单的一些看法:
- Workflow
- Freestyle vs Strict
- OOP styles vs FP
- Small vs Large
- Time-traval problem (Resolved by MST)
- Container components (Inject vs Connect)
- redux-crud-example & mobx-crud-example
https://medium.com/@cameronfletcher92/mobdux-combining-the-good-parts-of-mobx-and-redux-61bac90ee448
https://www.sitepoint.com/redux-vs-mobx-which-is-best/
Learning Redux
在一些小项目中用过Redux, 不得不说,Redux的学习成本要比Mobx高得多,比如下面的点,
redux, reducer, action, container component, selectors(reselect), redux-thunk, normalizing, ducks, and more waiting…
Others links
Mobx-Best-Practice
Decorator (ES7/TS) vs no-decorators
End
如果你有更好Mobx使用的一些心得,欢迎交流!
纯JS实现按多列排序
重要的事情还是要说的
项目里没引用 lodash (因为和 underscore.js 冲突)
问题
数据结构类似这种:
1 | const testData = [ |
最近项目中有大量的对排序的新需求,由其是按多列来排序, 新需求大致如下:
- Archived 为true的排列到最后,否则排最前面
- 然后,按照 StartDate 时间,如果最新,则排前面
- 然后,如果 StartDate 相同,则按照 EndDate 来排,
- 然后,如果 EndDate 也相同,则按照 name 的字母表的顺序排
同时呢,之前项目中也有很多类似的需求:
- 先按照 ModifiedDate 排,
- 如果相同,则按 name 字母表顺序
或者
- Primary 为true 的排前面
- 如果Primary 相同, 按照 name 字母表排序
还有更多的类似需求,我们项目里原来有个 Sort.js 的公共方法来处理这些排序,选取了其中最长的一个 (其实上面需求的每一个实现都和这个差不多)
1 | const sortFlattenPrograms = (flattenPrograms) => |
是不是很长,很丑,而且这只是一个排序,还有很多这种和0比较,然后再比较,所以继续加下去肯定不可取,维护是个很大的问题,UT 也很难写,要是能抽出中间部分就好了???
解决办法
先贴代码,其实核心就是抽取上面的各种comparator, 并且采用链式的方式执行,这里使用reduce方法来取了个巧,其实,查看了lodash的实现后, 他们采用的是 while 实现。
注意排序的顺序,是按照从右到左,我想的是尽量和 functional programming 的方式来写,并且compose 方法在lodash 里也是这个顺序,如果想改为从左往右,只需要将 reduce 改为 reduceRight 即可
1 | /** |
所以,上面的需求可以简单改为下面,其实comparators 是一个我预先定义好的各种比较方法
1 | // 预先定义的方法 |
最终还是需要用到 array的sort 方法,但由于这不是纯函数,所以保险的做法就是调用sort前,先在clone一下
神奇的 ES6 继承执行顺序问题
刷推的时候无意间发现一位google 工程师发的一个感叹,感叹发现的一个神奇的JS 6继承顺序问题。。。
仔细看了看,确实好神奇,于是好奇的看了看babel转换出的结果:
1 | var SuperClass = function SuperClass() { |
就和他猜测的一样:没有supper的时候,字段的初始化是早于构造函数执行的,有supper的时候,字段初始化是在构造函数里的super后执行!
个人看法是故意放super之后是为了能在字段里访问到父类的字段?
使用NetlifyCMS在线编辑Github上的博客
Netlify CMS 介绍
使用Netlify CMS我感觉有以下优点:
- 无缝支持Hexo 等十几种主流静态网站生成器 的 文章后台管理*
- 可视化在线编辑、新增github 上的markdown
- 自带图片上传功能
- 自动部署
支持列表:
Jekyll, GitBook,Hugo, Gatsby, Nuxt, Next, Gridsome, Zola,Hexo, Middleman, Jigsaw,Spike ,Wyam,Pelican,VuePress,Elmstatic,11ty,preact-cli
为什么使用它
对于我的情况:使用Hexo 网站生成器,托管在github上 https://github.com/Troy-Yang/troy-yang.github.io,其中Source branch是存放markdown等生成前分支,Master branch存放的是生成后的静态文件分支。
对于以前,如果要写一篇文章,基本是在source 分支里,新增一个markdown文件(可github上在线添加或者本地新增然后push),然后自动触发github 上配置的travis 自动部署流程,整体感觉已经很不错了。现在配置上Netlify CMS后, 可视化的在线编辑以及图片管理更加方便,可以随时随地发文章。
可惜, Netlify有个致命缺点:需要翻墙访问
HEXO NetlifyCMS 配置
只需要在hexo 的source/ 目录下添加admin 目录,新增下面两个文件:
1 | config.yml |
config.yml需要根据自己情况进行配置:
1 | backend: |
index.html
1 | <!doctype html> |
Netlify 端配置
创建 Netlify website
注意:和大部分人的做法不同的是,我Deploy到的地方并不是托管在Netlify自己的平台上,而是github上,所以这里我选择部署的是Source分支,而不是Master,因为我只是想要Netlify去修改我的Source分支,然后触发Travis自动发布到Master分支。
但是我依旧需要填写Netlify的部署,因为Netlify会自动帮我创建域名为troyyang.netlify.com的网站,任何我Source分支上的修改也会触发这个网站的自动部署
开启Netlify Identity 和 Git Gateway
在Setting 的 Identity选项下:
- Enable Identity service
- External providers 新增github
- Enable Git Gateway
发布测试
打开 https://troyyang.netlify.com/admin/ 然后使用github Oauth登录即可看到:
新增文章后, 你会发现github 上的source目录下的_post 目录的markdown 文件新增了,如果上传了图片,也会看到source目录下多了images/upload目录,同时https://troyyang.netlify.com 和 https://troyyang.com 下也自动发布了新的文章, 两者都是因为Source分支里新增了文件导致的自动部署。
问题
当我尝试打开 https://troyyang.com/admin/ 使用github Oauth登录时,结果报错,而https://troyyang.netlify.com/admin/则没有:
1 | Failed to load settings from /.netlify/identity |
我怀疑是因为https://troyyang.com是托管在github上,而不是netlify上导致的。
Enjoy!
AWS系列之使用无服务器架构你的网站
Serverless 有什么用啊?
Jason最近又出新想法了,想要做一个简单的用户管理系统,好的,没问题,不就是在服务器上安装数据库,部署好网站吗?可答案是no,他不是专业人员,我也不可能永远维护这个服务器,更重要的是服务器开着就要美刀啊,还不能停,怎么办?有没有可以不用服务器的网站,有啊,你自己的静态博客不就是只用到了s3或者github的静态页面托管吗?可是数据库呢,后台api呢?额,这个嘛。。。
好了,成功引出话题,要知道这是21世纪的云时代,只有你想不到,没有做不到的,这不,AWS早就提出了Serverless解决方案:S3 + GateWay API + Lambda + DynamDB,其中举例的一个天气的app架构:
其中s3做静态页面托管,用户触发点击事件,调用Gateway API提供到接口,接口映射到Lambda服务端接口,Lambda再负责去处理和数据库相关到操作。整个过程不需要服务器,而且费用是极低的,按量付费,可扩展性也很强,基本做到可配置化。说了这么多,还是得用过才知道好不好。
实现思路
- 服务端RestFull: Node express 实现RestFull API
- 创建lambda并上传服务端代码
- 配置API Gateway映射到lambda函数
- 客户端实现: Bootstrap 实现登录 和 管理页面
- 修改客户端api接口地址并上传至S3
其中,到第三步的时候我们就已经创建好了一个完整的无服务器的 Restfull API,剩下的就是客户端调用了,客户端调用这个就可以是五花八门的了,这也不是本篇文章的重点。
简单 RestFull 服务端实现
服务端的实现和平时实现一个Node RestFull api的完全没有任何区别, 部分代码如下:
app.js
1 | 'use strict'; |
这一步做完,确保所有接口都能通过访问 localhost:3001/api/contacts
aws-serverless-express
要使得上面的服务端代码能在lambda中允许,只需借助 npm 包aws-serverless-express
在目录下新增 lambda.js文件
1 | // lambda.js |
这也是为什么我们要在 app.js最后一行exports的原因
1 | module.exports = app |
此时,将所有文件包括node_module目录全部打包为.zip 文件为后面使用。
创建 lambda
创建 IAM role
创建 Lambda的IAM Role是必须的,他指定了当前lamda能访问到的资源有那些,从我们的列子中,我们需要用到DynamoDB, 同时为了方便debug,我们还需要用到cloudwatch服务 (这个对于查找问题非常有用)。
登录aws console,打开 Service 找到 IAM ,再选择Roles,点击 create role 按钮 后如图,(第三步可选):
创建 lambda 函数
打开Service 找到lambda, 选择 create function:
创建后,在代码输入种类中选择上传 .zip 文件:
将服务端代码整个打包 (注意一定要包括packages目录下的所有文件)然后上传,大小不能超过10m,如果超过了,可以在代码输入种类选择s3上传。上传完成后,指定入口文件(即在处理程序)为 lambda.handler, 此文件将会映射到 lambda.js文件,一般情况,如果上传的zip包不是很大,aws会自动列出zip项目目录可供在线编辑,但如果大了的化,比如好几兆,则有可能不会列出项目目录,每次修改又只能重新上传。
当然,如果node 代码里包括了一些环境变量,你也可以为 lambda 做一些环境变量的设置:
一切ok后,就可以测试了,关于lambda的测试,则相对还比较麻烦,我也是最近才稍微懂那么一点。
测试 lambda 函数
在创建好的lambda 函数旁,点击配置测试事件按钮,在弹出对话框创建测试事件中选择创建新测试事件,在事件模板中选择 Amazon API Gateway AWS Proxy, 并给个测试名称,如图:
选择Amazon API Gateway AWS Proxy是因为我们的这个lambda函数最终会被API Gateway 触发调用,同时由于默认的事件模板是 post 的请求方式,而我们的这个服务端只有一个api/contacts的get方法,所以我们需要更改事件内容为:
1 | { |
保存测试事件,并点击执行,如果一切正常,会得到如下:
创建 API Gateway
找到Service下到API Gateway,并点击新建 api,
新增 api 资源(路径)
选择 api 资源,再新增子资源,并选为proxy
选择 proxy 资源,创建 集成环境为我们创建好的lambda 函数
创建完成之后,在操作选项中,选择部署,弹出对话框并命名为dev阶段:
部署完成后,得到如下结果:
API Gateway 测试
在部署完成后,我们会在上述结果中得到发布出来的api 地址为
https://ijihnuupmh.execute-api.ap-northeast-1.amazonaws.com/dev
此时如果直接访问,会得到Missing Authentication Token的错误,原因是我们地址不对
1 | {"message":"Missing Authentication Token"} |
正确地址应该为:
https://ijihnuupmh.execute-api.ap-northeast-1.amazonaws.com/dev/api/contacts
由于上述地址是永久的,除非你重新部署,所以我们可以放心的使用用来作为api地址。还有一个就是API Gateway似乎是不收取费用的,只会按照lambda函数的调用次数来收取费用,好像每月前100万次请求是免费的。所以还是相当划算。
OK! 一个无服务器的后端 api 就这样搭建好了,剩下的就是前端静态资源的托管了
前端静态资源
直接上传html,js,css 等静态资源到S3就好了,具体可以参见另一篇博客 AWS系列之S3 + Cloudfront搭建https静态网站