Skip to main content
  1. internet/

统一支付系统

·1364 words·3 mins·

背景 #

已有的支付服务经常出现支付失败、支付状态不准确等问题,且由于历史原因使用的.net开发,维护上有一定困难,因此我们决定重新做一个统一支付系统。

需求 #

统一支付系统需要满足以下几点需求:

  1. 对接微信、支付宝中的多种支付方式
  2. 处理微信、支付宝的回调结果,并通过事件分发平台通知业务方。
  3. 开发环境和测试环境要支持1分钱开关,打开开关后,任何支付都是1分钱
  4. 支持退款
  5. 需要对账功能

架构设计 #

  • 红色流程为订单的预支付流程。

  • 黄色流程为用户支付流程,为用户与第三方服务商交互

  • 绿色流程为第三方服务商回调流程

预支付流程 #

  1. 用户在客户端点击商品选择支付
  2. 业务系统处理订单逻辑,并调用通用支付系统发起下单请求
  3. 通用支付系统调用对应的第三方服务商,获取支付二维码地址或者唤起客户端支付地址,并返回给业务系统,业务系统将其返回给前端
  4. 前端接收到地址后,将其转换为二维码或者调换到微信/支付宝客户端支付页面

回调流程 #

  1. 第三方服务商在收到用户支付或者拒绝后,会发送支付结果到回调网关

  2. 回调网关对数据进行解密、校验并将解析出来的数据发往事件分发平台

  3. 由于通用支付系统订阅了该事件,因此事件分发平台会将该事件发送给通用支付系统

  4. 通用支付系统处理支付结果,并将最终的支付状态通过事件分发平台发送给业务子系统

时序图-以微信的Native支付为例 #

注意事项 #

支付和退款分离 #

由于是统一支付系统,需要兼容各服务商的支付和退款,因此,为了高扩展性,将支付和退款作为两种订单处理,每种都有自己的订单状态

统一支付接口参数 #

支付宝和微信的支付接口支持非常多的参数,这其中大部分是用不到的,因此在做接口设计时,没必要将这些参数放进去,保持接口的简洁。

统一支付/退款状态 #

支付宝和微信的支付/退款状态并不同。

  • 微信有:未支付、已关闭、已撤销、支付失败、支付成功、转入退款、等待扣款
  • 支付宝有:订单创建、交易成功、交易超时或者已全额退款、交易结束

作为统一支付系统,我们需要有自己的一套交易状态来兼容第三方服务商的交易状态。

支付状态

  • 交易创建:即未收到任何回调时
  • 交易成功:存在真实的资金流动
  • 交易失败:由于服务商内部服务原因导致交易失败,比如由银行返回的支付失败。
  • 交易关闭:没有真实的资金流动,如交易被撤销,用户付款超时导致交易取消

退款状态:

  • 退款订单创建
  • 退款关闭
  • 退款成功
  • 退款失败

统一单位 #

微信支付的最小单位为分,而支付宝的单位为元,支持小数。统一支付接口设计上以分为单位,不支持小数。

幂等性 #

为了避免由于网络原因导致的超时重试,需要保证重复请求的数据保持一致。方案为:

  1. 调用方需要携带幂等参数,该参数为uuid等唯一值
  2. 统一支付系统接收到请求后,对该uuid值进行分布式全局锁处理,并且将响应结果已uuid为key存入redis中。如果使用请求中的幂等参数在获取锁时,发现该锁已存在,则等待锁结束,从redis中获取其结果,并返回。

公众号配置 #

用于JSAPI支付,官方文档

配置项 #

关联appid与商户 #

https://kf.qq.com/faq/1801116VJfua1801113QVNVz.html

支付目录 #

支付目录需要在商户系统配置,且只需要配置一次

授权域名 #

配置授权域名,并将所得证书放在对应域名下的根目录

JS安全域名 #

同上

设置ip白名单 #

授权域名和JS安全域名设置都需要设置相关的ip白名单,而腾讯需要对证书进行访问,以证明我们对域名的拥有。

  1. 获取accesstoken
  2. 获取微信服务器地址(注意,是用第二个接口)