支付中心-重复支付问题解决方案
一笔订单,可以做多笔支付,怎么解决?
重复支付的异常背景
- 一笔订单,在支付中心可以选择多种支付方式。如支付宝扫码,支付宝app,微信扫码,微信小程序,银联....
- 用户选择支付方式后,系统需要和第三方进行交互,获取到结果后,可能跳转到第三方收银台,也可能在当前页面展示收款二维码;
- 用户打开一种支付方式,没有完成付款的情况下,又选择打开了其他支付方式。如准备用微信支付,打开收款二维码后,发现微信余额不足,遂即打开支付宝支付,此时两个支付方式都可以做支付操作。
- 由于产生待支付单后,支付状态是不可控的,支付状态由第三方回调信息中获取。所以很难控制支付单的再次产生。
概念解释:
- 支付单:具体的支付方式,如 支付宝的扫码支付,微信小程序支付
- 一个订单对应多个支付单,但一个订单下 只允许出现 一笔成功的支付单
支付流程
支付流程是一套异步的操作。
- 用户选择支付方式
- 跳转到对应的收银台
- 用户支付成功
- 第三方回调系统
- 修改订单状态
不可控的因素是在第三和第四步。
解决方案
第一步
用户的一个订单,选择支付方式触发第三方支付平台之前,先扫描该订单下的待支付订单,如果存在,调用其订单关闭接口,使之前的待支付单立即失效。然后再创建新的支付单做支付。
理想状态下,创建的支付单可以随时关闭,这就可以完美解决重复支付问题。
不完美的情况:支付宝的扫码支付可以随时关闭支付订单,但是支付宝的电脑网站支付,必须在用户扫码后才能关闭支付订单。(这一点被坑了很久),应对此问题,解决方案还需要往下走。
第二步
用户支付成功后,收到第三方的回调通知,修改订单状态后,再次扫描待支付的订单,对其进行关闭订单的操作。
这个步骤,不仅是对第一步的加强,也是可以适应不同的需求场景。如:一个业务方常用的是微信和支付宝两种支付方式,为了减少和支付中心的交互次数,就在创建订单的时候,替用户创建了这两种支付的二维码,让用户选择使用,这种情况下就不能对待支付单做立即关闭了,否则只有一个二维码是生效的。
所以创建订单时加了一个选择策略来控制是否立即关闭历史支付订单。然后用第二步来兜底。
到此还是不能完全解决重复支付,原因如下:
- 支付宝的不能及时关闭,到此不一定能完全解决。
- 部分银行的接口功能中,没有提供及时关闭订单的功能。
第三步
针对以上策略下的漏网之鱼,还需采取补偿策略:
定时任务:定时对账,通过定时任务,扫描那些支付成功,且实际支付金额大于应收金额的支付单,或者说一个订单号,存在多笔成功的支付订单的数据。按时间顺序,将后面支付的支付单做主动退款。
这一步还是不能完全解决问题。原因:部分支付平台不支持退款,这种情况下,无法做到主动退款,只能依赖人工操作。
第四步
最后的无奈之举:发现重复支付的支付单数据,且没有退款接口可用时。发起一条工单,通知到运营端,让运营去人工处理。
CLC