大厂是怎么做支付系统的流程容错的?

来源:JavaEdge

1 单据关联

如某些订单域内部的多种单据间存在关联关系一样,支付设计上也有单据间关联设计。如所有逆向过程都须持有正向的单据,因此退款须关联到原来的支付,退款支付单要关联到原支付单。单据之间关联只有以下用途:

状态一致性

正如订单域中的订单单据如果成功,则订单关联的营销单、支付单一定成功。支付场景各单据状态也存在关联关系,如创建退款支付单的前提是所关联的原支付单须成功

金额一致性

金额控制是退款核心问题,易产生资损。由于支持多次部分退款,金额须防止超退:总金额不能退超,各维度的资金组成组成不能退超。

实现:每笔退款的金额,都在原单累加记录到已退金额,记录已退款的总金额,校验不可超。

2 幂等

通过唯一键实现幂等。如:

  • 订单侧常见的重复支付退款以订单号关联 PaymentNo 做重复支付校验唯一键
  • 支付侧交易单以外部单号 + 商户号为唯一键,支付单以交易单号 + 操作码作为唯一键

幂等可重入问题:如对一笔整单退请求,上游请求退款 200 元,支付域已处理成功,上游由于超时基于同一笔支付单号进行退款重试,此时应返回成功而非业务校验异常。

3 重试

最大努力通知,支付领域常见的流程容错手段,分布式环境的网络抖动、服务暂时不可用都会造成业务流程处理异常。常见解决方案即将请求放入 MQ 异步重试,重试间隔逐次拉长:

  • 重试成功,则回调交易
  • 失败或处理中,则继续重试。所以接口幂等支持可重入很重要,才能支持重试!

如订单收到支付成功回调后,开始处理订单流程。如果在下单阶段仅锁定库存、营销等资源,需要在支付回调流程真正扣减资源的话,这里需要对超时等场景进行重试(调用下游需要做好幂等),如资源扣减失败则关单退款。

重试指定次数如业务单据仍未到达终态,则将订单信息持久到数据库中,通知人工进行处理。如用户卡注销,会员销户等问题导致退款退不出去,重试一定次数后支付单只能置为失败。等待产运联系用户后,在支付层重新生成退款支付单进行退款。

请使用浏览器的分享功能分享到微信等