todo 如何防止重复支付
1、业务订单和支付订单不是一个概念,我想讨论的是已经生成的支付单如何防止重复支付。一个业务订单是允许对应多个支付单的,也就是分多次支付,但是单个支付单不允许被支付两次。从系统层面来说,同一个业务订单ID可以对应多个支付流水号,但是同一笔支付流水只能向通道方发送一次。
2、重复支付有以下可能的原因:
1.客户端多次提交。可能由于弱网络环境,或者客户端按钮没有做限制用户手速过快等。
2.由于系统代码或设计问题导致的状态不一致,例如通道方超时的订单被系统判定为失败,或者高并发环境下没有做好锁的控制等等。分布式系统之间常常是弱一致性的设计,因此如果系统上下游没有做好足够的规约,很容易出现重复支付或重复出款。
3、针对上述原因,可以思考相对应的解决方案。客户端多次提交,可以选择在前端做控制,也可以不控制,任由用户进行多次支付,后续对金额和状态做检查,给用户发起退款也可以。对公司不会有什么资金损失,就是会损失一点用户体验。。。。系统上下游的规约或者代码问题是最应当关注的问题,整个支付系统要做好规范。
对于发起支付的订单,必须先从库中检查是否已经存在。
请求通道方超时或者上下游通信网络超时,结果码不能配置终态的结果码。
用户主动发起的多次支付,要对关联的业务订单做校验。
未知的状态要有补偿的策略来查询,必须在查询之后再判断是否关单或者冲正。
常见的解决方案是宁可让订单一直不置终态,等财务结算对账后再确认,也不要随意的允许用户或系统重新发送。
todo重复支付再思考
我在思考这样一个场景:一笔支付请求,愉快的从渠道拿到了处理结果,就在此时,啪唧,停电了。那么在系统全部重启之后,我方db中,该订单由于还没来得及更新任何状态,还是一副人畜无害的待处理模样。
此时系统重新处理该订单,势必会导致重复请求通道方。运气好的话,通道方帮你做了幂等,运气不好的话,该如何处理?
我的想法:如果订单在交易状态之外还存在发送状态,那么在发送之前就应该修改发送状态为已发送。那么在系统重启之后,已发送但是没结果的订单由系统自动发起补偿查询,如果结果不存在或者已经成功,就按正常流程处理。
如果订单不存在发送状态,交易状态是待处理,那应当如何处理?我认为此问题无解。因此渠道应用层必须对订单建立发送状态。