1、前言
微信支付和支付宝支付,几乎垄断了移动支付业务的市场。项目上最近也上线了有关微信支付的模块,虽然开发很简单,但是因为和钱相关,做方案时要谨慎再谨慎。
项目背景是,我们给客户食堂做了一款微信小程序,员工可以基于个人的一卡通登录使用和消费。这次他们要增加给一卡通充值的功能。一卡通就类似于我们大学时候的学生证,可用来吃饭消费,大家每天都要用,所以微信充值的频率还算比较高。
这个项目实际开发了两天,但前前后后的配合工作持续了快半年,我觉得挺典型的,在此做一下记录。
2、项目准备
客户是典型国企的氛围,财务部一般都是手动做账,要想让各级领导接受微信支付,前期要做很多工作。
2.1、开通商户号
微信支付需要先开通绑定银行的商户号,但是开通商户号一般需要企业的法人拿相关的营业执照去办理,所以这部分工作想想都难。协调集团董事长,财务和业务部门,几个月就过去了。
2.2、0.6%的手续费
经过微信支付的所有费用,腾讯公司会从中抽取 0.6%的手续费。这个其实也不算很高,但是客户领导还是很慎重,又考虑了一个月。我们甚至于做了两个版本:一个版本是三菱公司承担这笔手续费,员工充值100元,实际到账100元;另一个版本是在界面上提示让员工自己承担手续费,员工充值100元,实际到账99.4元。他们采用了后者。
2.3、安全
各级领导最关心,绝对就是微信支付的安全性了吧,所以前期保障安全的技术方案要做好,要是再弄个方便给领导汇报的ppt就更好了。
3、实际开发
3.1、微信官方api
微信支付官方开发文档十分详细,我这里就列几个我常用的吧。
- (后端)下订单:https://api.mch.weixin.qq.com...。商户在小程序中先调用该接口在微信支付服务后台生成预支付交易单,返回正确的预支付交易后调起支付。
- (后端)查订单:https://api.mch.weixin.qq.com...。该接口提供所有微信支付订单的查询,商户可以通过查询订单接口主动查询订单状态,完成下一步的业务逻辑。
- 小程序调起支付API:微信小程序代码,可以调起微信支付模块的组件,引导用户完成支付。
当然还有一些退款、发送账单等api,只不过我们这次没有这些需求,就没用上。
3.2、流程步骤
- (前端)点击“充值”按钮,输入需要充值的金额,点击“下一步”,调用后端下订单的接口。
- (后端)根据当前用户的金额,调用上文中“1. (后端)下订单”接口,生成微信订单,并将订单号返回给前端。
- (前端)根据微信订单号,通过“3. 小程序调起支付API”,调起微信的支付模块,引导用户去支付订单。支付成功后,会触发支付成功的回调函数,跳转到支付成功的界面。
- (微信异步),我们在 “1. (后端)下订单”接口中有定义一个成功的回调接口,当支付成功后,会异步的触发调用该回调接口,该回调接口的功能包括完成订单以及充值等。
- (后端)所谓业务系统入账的接口,在这里就是给一卡通充值的接口。不过要先拿前端提供的微信订单号,调用“2. (后端)查订单”接口,再次确认该订单是否真的支付完成,并非伪造。然后再写代码实现给一卡通的充值操作。
4、安全保障(重要!!!)
一般来说,你没有考虑到的地方,往往最容易出问题。我记下我遇到的和我能想到的,可能会出现问题的点,后续如果还有再补充。
4.1、本地微信订单中间表
在 3.2 中的流程操作,我们要考虑如果执行了一半,我们的服务器或者数据库故障,导致操作步骤中断了怎么办。例如执行到了步骤3,用户已经付过钱了,因为服务器宕机,步骤4中的充值操作就没了。
强烈建议在本地也建一个中间表,记录每一笔微信订单,并在每一步操作实时更新订单状态。然后再写一个轮询的脚本,当发现问题订单时,可以做出补救措施。还可以通过该中间表做一些前端报表页面,相关用户可以追溯到每笔订单的履历。
4.2、官方api的bug
微信官方提供的api也可能是会有问题的,我就遇到过。例如“3. 小程序调起支付API”中,在支付成功的回调函数里面,会去调用后端入账的接口。可是我就遇到过一个订单,用户在支付成功后,没有触发回调函数,导致扣了钱,却没有完成一卡通的实际入账。有可能是用户手机的问题,当时没办法调起微信客户端的支付API,有可能是网络波动导致的问题,甚至于,也有可能是微信官方API的bug。
我们一切要做最坏的打算,在基于已经有了订单中间表后,轮询的脚本就能捕捉所有未支付的订单。通过“2. (后端)查订单”接口查询订单状态,如果订单支付成功的,就做一卡通的入账,如果订单支付失败或者并未支付的,则关闭订单。
4.3、事务锁
以我们现在的方案,针对某次微信订单的入账操作就有两个了。一个是成功支付后的回调函数,触发入账操作;另一个是轮询脚本用于补救的入账。如果你的方案存在并发的风险,就要考虑事务锁,否则可能微信付款100元,一卡通到账的却是200元。
如果接口部署的服务器是集群,那还要考虑分布式的事务。千万别以为成功回调触发的支付接口,就比轮询的接口执行的早,这两个接口被分配到集群的随机节点上,不同服务器节点上的线程等待时间也不一致。我就遇到过一个成功回调触发的支付接口,在weblogic一个节点上卡了10分钟才执行,而轮询的接口被分配在另一个节点上,早就执行完了。
5、财务对账
也许有些人对这个“财务对账”这个过程感到奇怪,但你绝对会印象深刻,bug严重的话,程序员真的会被“祭天”。财务会对微信充值的每一笔钱做比对,不要小看平时测试的几块钱的脏数据,对账那一天,每块钱的差异都要讲清来龙去脉。
所以,在项目方案设计的时候,一定要做好支付流水的记录。详细再详细,例如手续费要单独做字段记录,否则因为政策上的变更,有的手续费扣了,有的没扣,在财务面前没办法说的清。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。