支付服务架构
背景
目前我就职于大树网络科技,主要的产品是给信用优质都用户提供线上都信用贷款。而我所在的组是支付组,主要对接第三方支付。支付用于放款和还款两个操作,本次主要讲还款(其实两个都差不多)。目前还款主要有一下这几种方式:
- 用户通过APP主动还款
- 系统发起定时扣款任务
- 催收人员通过内部作业系统,发起扣款
大树没有支付牌照,只能通过第三方支付来完成扣款操作。我们对接了好多第三方支付服务,比如京东两方代扣、京东快捷、翼支付、网信支付等(这里把代扣和快捷区分开来了,因为业务处理上有些不同)。不同的第三方支付,支持的银行和对应的限额不同,稳定性和费用也不相同。这里就需要考虑到通道到可用性和稳定性还有费用等问题,我们通过支付路由选择出最优的通道(支付路由下期再讲)。因为第三方支付的各种问题,这里支付我们需要保证业务上的一致性,这也是本文介绍的主题。
支付面临的问题
支付结果一致性
1、由于真正的支付有第三方提供,存在不稳定性、且有小部分的交易需要很长时间才能确认支付结果。这里的一致性指的是第三方支付服务与我方系统的支付结果的一致性
2、我们采用的是微服务的方式,支付的成功并不表示着这次还款计划的成功,需要保证我们系统之间的信息一致性
信息追踪
我觉得一旦涉及到金钱,就需要格外小心。有句话:“有钱能使鬼推磨”。代扣能不声不响的从你银行卡扣钱,可怕不!!!一旦触及到了别人兜里的钱,就需要有理由(贷款协议)。还有跟第三方支付的扯皮(哈哈,在正式的业务当中没出现过,因为都以银行为准),真的到了扯皮,还是需要有证据的
最终支付架构
支付架构上图是我设计都最终架构图(欢迎大佬指正)。下面我将怎么演进的和注意点分析一下,懂了的大佬可以随意
正常流程
正常流程1分布式锁
这里使用分布式锁和重复订单检查目的是幂等,防止支付多次提交。支付服务提供的是dubbo服务,dubbo默认重试3次。用户的一次还款,被扣了三次。好可怕,投诉投诉!!!
支付路由
1、省钱,省钱,省钱,这是支付路由选择支付通道的最主要的规则。 哪个通道省钱,基本会优先考虑这个通道。
2、提升支付产品的QOS。这体现在系统的可靠性、稳定性、性能和可用性上。通过屏蔽掉无法连接、不稳定、性能低的通道来提升这些指标。
本次不讲,留到后面😁
第三方支付
第三方支付主要涉及到加密、签名等保证数据的一致性
本次不讲,留到后面😁
第三方支付回调
第三方的支付一般都是异步的,上面的发起支付,第三方支付系统只是收单。异步会调用银行的指令(这是以前的代扣,跟银行。现在应该会调用网联系统)。支付成功或失败后,第三方系统会进行回调
发送MQ给下游
发送给关注支付这个事件的系统,后续由它们去处理
改进一——添加日志追踪
改进一日志
可以看到每一步调用第三方之前都会插入一条日志记录,并在响应之后更新日志。这里日志我们需要记录什么呢?
1、支付订单的一些信息,比方支付发起方式、扣款银行卡等
2、支付操作
3、请求第三方信息
4、第三方返回信息
改进二——查询
改进二查询
天啊,这个第三方支付为什么没回调!!!没回调有2种
1、网络抖动丢掉了
2、他们本来就没有回调这样的接口😢(我碰到过)
查询不仅能弥补对方系统的不足,还能完善我们的系统。
发送MQ
记录该条查询
如果没发生MQ,在系统中轮询。可能机器突然挂了,这条查询命令就消失了。
缓冲
有好些第三方支付结果获取一般在3s左右。刚发起支付去查询,很大的概率还是在支付处理中。可以到消息队列里缓冲一下
改进三——未知订单
上述的系统是不是很完美了呢?当然没有,我们想一下下面几种情况
-
当第三方系统查询接口GG的时候,我们还是无脑的循环查询吗?这样肯定有问题
-
如果我想知道哪些支付是在支付处理中,我们是不是查询数据库
select * from pay_order where status = "处理中"
如果该表很大呢?而且status又不能做索引(分辨率低)。
- 如果程序处理到第三方支付支付,这时候程序挂了(假设该第三方支付没回调)该笔订单是不是就无法知道状态了
综上,出来了下面的架构
改进三
未知订单--超过10分钟
这里说的未知订单状态不是支付的状态。而是该未知订单是否可以查询的状态。这里有1个定时任务:
- 定时任务发起查询,查询的是未知订单创建时间超过10分钟
为什么要这么设计呢?
想一下这种情况,当支付请求进来,流程到了支付路由这一步骤。这时刚好发起了定时任务。查询第三方支付服务,第三方还没有收单(还没接收到我们支付请求),这是会返回无效订单。我们系统会认为该支付为失败。有这样10分钟的经验值。
发送查询MQ,次数限制
每次发送查询MQ,要对查询次数做限制,不要无脑查询(对方系统慢了,很大原因是它处理不过来了,我们也要给别人休息休息)
本地事务
事务一 事务二 事务三以上三个地方需要做本地事务,作用的话就不讲了
总结
上面就是我们支付服务中的核心交易系统,主要就是保证交易核心系统与第三方支付服务的一致性,交易核心系统与其他下游系统的一致性。
在我的理解里最终一致性的保证需要
1、“记录”
2、“补偿”
在做所有的不确定的事情之前,先把事情记录下来,然后去做不确定的事情,结果可能是:成功、失败或是不确定,“不确定”(例如超时等)可以等价为失败。成功就可以把记录的东西清理掉了,对于失败和不确定,可以依靠定时任务等方式把所有失败的事情重新搞一遍,直到成功为止。