统一支付系统
Table of Contents
背景 #
已有的支付服务经常出现支付失败、支付状态不准确等问题,且由于历史原因使用的.net开发,维护上有一定困难,因此我们决定重新做一个统一支付系统。
需求 #
统一支付系统需要满足以下几点需求:
- 对接微信、支付宝中的多种支付方式
- 处理微信、支付宝的回调结果,并通过事件分发平台通知业务方。
- 开发环境和测试环境要支持1分钱开关,打开开关后,任何支付都是1分钱
- 支持退款
- 需要对账功能
架构设计 #
-
红色流程为订单的预支付流程。
-
黄色流程为用户支付流程,为用户与第三方服务商交互。
-
绿色流程为第三方服务商回调流程
预支付流程 #
- 用户在客户端点击商品选择支付
- 业务系统处理订单逻辑,并调用通用支付系统发起下单请求
- 通用支付系统调用对应的第三方服务商,获取支付二维码地址或者唤起客户端支付地址,并返回给业务系统,业务系统将其返回给前端
- 前端接收到地址后,将其转换为二维码或者调换到微信/支付宝客户端支付页面
回调流程 #
-
第三方服务商在收到用户支付或者拒绝后,会发送支付结果到回调网关
-
回调网关对数据进行解密、校验并将解析出来的数据发往事件分发平台
-
由于通用支付系统订阅了该事件,因此事件分发平台会将该事件发送给通用支付系统
-
通用支付系统处理支付结果,并将最终的支付状态通过事件分发平台发送给业务子系统
时序图-以微信的Native支付为例 #
注意事项 #
支付和退款分离 #
由于是统一支付系统,需要兼容各服务商的支付和退款,因此,为了高扩展性,将支付和退款作为两种订单处理,每种都有自己的订单状态
统一支付接口参数 #
支付宝和微信的支付接口支持非常多的参数,这其中大部分是用不到的,因此在做接口设计时,没必要将这些参数放进去,保持接口的简洁。
统一支付/退款状态 #
支付宝和微信的支付/退款状态并不同。
- 微信有:未支付、已关闭、已撤销、支付失败、支付成功、转入退款、等待扣款
- 支付宝有:订单创建、交易成功、交易超时或者已全额退款、交易结束
作为统一支付系统,我们需要有自己的一套交易状态来兼容第三方服务商的交易状态。
支付状态:
- 交易创建:即未收到任何回调时
- 交易成功:存在真实的资金流动
- 交易失败:由于服务商内部服务原因导致交易失败,比如由银行返回的支付失败。
- 交易关闭:没有真实的资金流动,如交易被撤销,用户付款超时导致交易取消
退款状态:
- 退款订单创建
- 退款关闭
- 退款成功
- 退款失败
统一单位 #
微信支付的最小单位为分,而支付宝的单位为元,支持小数。统一支付接口设计上以分为单位,不支持小数。
幂等性 #
为了避免由于网络原因导致的超时重试,需要保证重复请求的数据保持一致。方案为:
- 调用方需要携带幂等参数,该参数为uuid等唯一值
- 统一支付系统接收到请求后,对该uuid值进行分布式全局锁处理,并且将响应结果已uuid为key存入redis中。如果使用请求中的幂等参数在获取锁时,发现该锁已存在,则等待锁结束,从redis中获取其结果,并返回。
公众号配置 #
用于JSAPI支付,官方文档
配置项 #
关联appid与商户 #
https://kf.qq.com/faq/1801116VJfua1801113QVNVz.html
支付目录 #
支付目录需要在商户系统配置,且只需要配置一次
授权域名 #
配置授权域名,并将所得证书放在对应域名下的根目录
JS安全域名 #
同上
设置ip白名单 #
授权域名和JS安全域名设置都需要设置相关的ip白名单,而腾讯需要对证书进行访问,以证明我们对域名的拥有。
- 获取accesstoken
- 获取微信服务器地址(注意,是用第二个接口)