支付网关

支付网关 #

业务需求 #

支付网关需实现路由功能,能根据不同支付单信息分发给不同的资产处理组件。

  • 内部资产处理组件:代金券系统、钱包系统等。
  • 外部资产处理组件:通过金融网关对接第三方支付系统和银行。

数据建模 #

  • 支付单表:流水号、支付金额、支付状态。
  • 支付中日志表:保存支付中和终态的支付单,用于进行补偿。为了保证查询效率,需要定期删除,控制表大小。
  • 支付日志表:保存支付过程中所有状态数据。只插入不更新,用于补偿中的操作恢复,类似断点续传。
  • 支付流水表:保存所有支付成功的数据。用于进行流水统计,同步给其它系统。

线上支付 #

  1. 事务一般设为自动提交,避免日志也被回滚。
  2. insert支付中日志表;insert支付日志表,支付状态为”扣款中“;update支付单状态为“扣款中”。
  3. 调用资产处理组件进行扣款,insert支付日志表,支付状态为”支付完成“。
  4. 根据同步调用的响应或异步调用的回调结果进行后续处理:
    • 接口返回扣款成功。
      1. 消息队列通知账务系统入账,insert支付日志表”通知账务系统完成“。
      2. 更新支付单状态为“扣款完成”,insert支付日志表”扣款成功“。
    • 接口返回扣款失败。
      1. 更新支付单状态为“支付失败”,insert支付日志表”扣款失败“。
    • 接口返回扣款中。
      1. 定期反查支付结果,直到出现完成或失败。

由于有多个地方可能会对同一笔订单进行支付

  • 正常执行扣款;
  • 提交到后台线程池的重试 / 轮询;
  • 定时任务补偿;
  • 人工执行扣款

所以针对单笔记录可以用分布式锁对同一支付单进行限制,在数据库层面通过令牌或版本号进行兜底。最后通过支付流水进行校正。

因为存在ABA问题,金额条件where amount=1000一般不适合用作兜底。只能通过amount>判断超卖。

支付补偿 #

  1. 每隔3分钟从支付中日志表中找出3分钟前开始且状态为“扣款中”的记录。
  2. 调用接口反查结果。
    • 接口返回扣款中,直接返回。
    • 接口返回其它结果。从支付日志表中取出最终执行状态,继续执行。

二维码支付 #

和在线支付的区别:微信/支付宝其他支付接口在支付成功之后,渠道方会发送消息通知支付结果。但是付款码是不会有消息通知的。

业务流程

  1. 商家通过扫码设备扫描用户支付宝付款码。
  2. 扫码设备上传条码信息到收银台。
  3. 收银台通过支付网关发起支付。
  4. 支付网关调用支付宝支付后台。
    • 采用免密支付时,支付宝后台同步返回支付结果。
    • 当支付宝风控要求用户输入密码时,支付宝后台返回“等待用户支付”状态。支付网关需要定时调用支付宝接口查询支付结果。如果在一段时间内(30s),轮询查询支付结果返回都是等待用户支付,或者失败和支付系统超时,这两种情况建议立刻调用撤销接口撤销交易。
  5. 如果用户支付失败,撤销接口会订单关闭;如果用户支付成功,撤销接口会将订单资金退还给用户。也就是说撤销支付接口功能上类似关闭订单加上退款。

撤销接口和退款接口的具体区别:

  • 支付类型限制:撤销支付仅能撤销付款码类型的订单,而退款可以支持多种支付类型的订单。
  • 退款金额:撤销接口只能是全额退款,而退款接口支持传入金额,可以全额退款或部分退款。
  • 时间限制:撤销接口时间限制短,微信支付撤销支持 7 天内的订单,而支付宝撤销接口仅支持当天的订单。退款接口可以支持较长时间订单退款,微信支付退款支持一年内的订单,而支付宝仅支持 3 个月内订单。

秒杀支付 #

业务需求

资金划拨流程:买家账号 -> 中间账号 -> 卖家账号

从支付系统角度来看,在处理秒杀的时候,只需要处理买家账号到中间账号的流量问题。中间账号稍微延迟一点打款完全没问题。再进一步分析,中间账号的打款就算丢了也问题不大。支付系统在每天晚上日切的时候进行对账就能补齐金额。所以中间账号可以异步处理。

实现方式

  1. 支付系统只处理买家账号,记录扣款流水。
  2. 通过异步方式处理中间账号,或者在秒杀结束后再处理中间账号。
  3. 日切进行对账补齐差异。

资金安全 #

  • 实时对账。
  • 出金一般设有结算周期,方便核对金额。
  • 防止资损。对退款,结算等出金操作做熔断控制。
  • 熔断支持按业务类型,业务单号和商户号。

还款计划 #

业务需求

还款计划往往每月最后一天进行计算,所以存在数据量多,数据库压力大的问题。

还款开始-写入还款请求-mq-还款计算-发起支付流程

沪ICP备17055033号-2