重复支付问题解决方案:使用补偿机制查询、冲正、退货

2024-09-01
来源:网络整理

重复支付的表现形式就是同一份订单被支付多次。

流程是,一个订单支付完毕,当没有返回结果时,才允许支付下一个订单,从而导致多次扣款。

在支付交易中,返回的结果不仅仅是预期的成功或失败,也可能因为各类问题(如系统异常)导致无法收到支付服务商反馈的结果。

但交易订单必须有最终时间,不能无限期地等待。用户不能总是眼睁睁地看着订单被处理,不知道购买是成功还是失败。万一他们认为订单成功了却没有付款怎么办?万一他们认为不成功,再次要求付款,这就意味着重复付款了怎么办?或者客户不耐烦了,多次点击支付按钮,扣了更多的钱怎么办?

解决此类问题需要使用补偿机制。

补偿机制:当交易无结果,且没有返回明确答复时,通过查询、更正、返回等措施明确交易结果,以及对明确结果的处理机制。

查询是针对未知交易结果的另一种补偿机制。对于返回没有明确交易结果的订单,系统会设置脚本规则,定期向支付服务商发送请求查询交易结果,比如每5分钟查询一次,直到第30分钟。在此期间,如果查询到成功或失败的明确结果,则更新订单状态;如果最后还是没有结果,通常的做法是直接置为失败。商户第二天会查看账单,看交易是否成功,如果成功,则会处理退款。

撤销是系统对未知交易结果的补偿机制。商户因系统超时、异常等原因无法确定支付结果,为了避免用户等待或重复扣款,商户向支付服务商发起交易撤销请求,将交易回滚。无论原交易成功或失败,均要求取消交易。撤销成功后,商户再反馈用户支付失败或整理消息重新发起交易。

逆转、取消和退回看似类似,但在使用上却有很大区别:逆转可以对结果未知的订单回滚交易,而取消和退回只能对成功结果明确的订单回滚交易。

图中展示的是一个简化的订单流程,从提交订单开始,然后是支付。对于支付,一般会经过支付网关(支付中心),然后支付中心与第三方支付通道(微信、支付宝、银联)进行交互。支付成功后会异步通知支付中心,支付中心更新自己的支付订单状态,然后通知业务应用,各个业务再更新自己的订单状态。

这个过程中可能遇到的一个常见问题就是订单掉单。不管是因为超时没收到回调通知,还是程序本身报错,总之因为各种原因,没能按预期收到通知并正确处理后续逻辑等等,都会导致用户支付成功,但是服务端的订单状态却没有更新。这时候就有可能产生投诉,也有可能用户重复支付。

由③⑤引起的订单下降称为外部订单下降,由④⑥引起的订单下降称为内部订单下降。

为了防止订单丢失,您可以进行如下操作:

1.为支付订单增加一个中间状态“支付中”。在对同一个订单进行支付时,先检查是否有状态为“支付中”的支付流水,当然支付时一定要加锁()。支付完成后,更新支付流水状态,改为“支付成功”状态。

2、支付中心需要定义一个超时时间(比如30秒),如果在这个时间内没有收到支付成功的回调,支付中心应该调用接口主动查询支付结果,比如10s一次,20s一次,30s一次,如果在最大查询次数内没有查询到结果,则需要处理异常。

3.支付中心收到支付结果后,会将结果同步到业务系统,可以发送MQ,也可以直接调用,如果直接调用需要重试(例如:)

4、无论是支付中心还是业务应用,在接收支付结果通知时,都要考虑接口幂等性,消息只处理一次,其余的都忽略。

5.当发生超时情况时,业务应用也应主动查询支付结果。

对于上面提到的超时主动查询,可以在发起支付的时候把这些支付订单放到一个表中,用定时任务来扫描

为了防止重复订单提交,您可以这样做:

1、创建订单时,会根据订单信息计算hash值,判断是否有key,如果有则不允许重复提交,如果没有则生成新的key,设置过期时间,再创建订单。其实就是在一段时间内不能重复进行相同的操作。

附上微信支付的最佳实践:

分享