订单支付相关问题总结

最近公司商城系统要重做,我接手了支付相关的需求,发现里面弯弯绕绕的地方还是有不少的,所以把碰到的问题记录一下。

支付问题

  1. 在第一次对接微信支付时,生成预支付单的接口会让使用微信商家平台的API密钥进行加签,但是就算你使用的API密钥确定没有问题,也可能会返回验签失败,一点办法也没有。 解决方法:使用UUID重新生成了32位纯小写的密钥(我怀疑就是密钥格式问题引起的,从来没有见过密钥让用户手填的),然后等待15分钟新的API密钥生效,重新调用接口即可。
  2. 支付宝统一下单接口中可以设置超时时间timeout_express,这个字段的含义是以用户点击了 “支付宝支付” 这一刻算起的TTL,有可能与业务上要求的订单超时时间并不一致。 解决方法:使用time_expire字段,该字段含义为在time_expire后的支付都为超时支付。

支付回调问题

支付回调的问题是最严重的,以支付宝举例(不管是微信还是支付宝,支付完成都有回调通知的)。支付宝的统一下单接口中可以传两个参数,return_url(页面跳转地址)和notify_url(结果通知地址)。
一般做法是在notify_url对应的接口中根据支付接口触发订单的后续逻辑的(更改订单状态什么的),因为这样做会比较安全,可以对参数设置加密返回或者对返回结果验签。这样做就会碰到以下几个问题。

  1. 因为notify_url是异步通知的,所以就会必然存在一个问题,用户收到了支付宝同步返回的支付结果,提示支付成功了,但是这时候,服务端还没有收到异步回调,相应的订单状态还没有进行修改,用户查看订单时显示的可能还是未支付状态。
  2. 可能因为网络问题、域名问题、或者支付宝本身问题(是系统就会出问题的= =),导致服务端根本就没有接收到回调,订单状态一直无法修改,直到超时取消。
  3. 支付宝发送异步通知时,如果服务端没有返回success,则支付宝有自身的重试机制,会进行重推,导致订单后续逻辑会重复执行。

针对问题三,这个是无法避免的,所以在异步通知的接口中订单处理逻辑一定要做幂等。
针对问题二,起定时任务,对待支付订单主动查询支付状态进行补偿。
针对问题一,成本最低的做法,可以让用户在收到支付成功时在页面上强制多停留几秒钟(测试的时候,用户收到支付成功和服务端收到回调的时间差也就一两秒钟以内,有时候收到回调可能还会更快。。),但是该种做法只能解决90%的场景,毕竟是网络环境,也可能几分钟才回调过来,或者网络直接崩了。

完美的办法(开发成本也是最高的),在用户收到支付成功后,由客户端调用接口执行订单后续逻辑的触发(加密啊、加签啊什么的都要做,为了安全),并且服务端收到调用后,也要主动去支付宝查询该笔订单的支付结果,进行再次确认。并且,为了防止因服务器处理异常产生的订单没有支付成功的现象,同时启动定时任务,定时轮询待支付的订单,查看支付到底有没有成功,进行补偿(会发生与客户端回调并发处理的问题,所以要加锁控制)。虽然这样基本上能够杜绝99%的问题发生了,但是性能上一定会有损耗,编码的难度也上升了。

所以,为了权衡,使用异步回调 + 定时任务的方式下,发生问题的概率就已经比较小了(会牺牲一下用户体验,就是用户支付成功了,可能要过个十分钟,订单状态才会变为已支付)。
毕竟系统越简单,bug才会越少。

猜你喜欢

转载自blog.csdn.net/lvqinglou/article/details/103947749