第三方支付架构设计之:商户回调通知系统的悲观和乐观策略

来源:互联网 发布:深圳策略一二三网络 编辑:程序博客网 时间:2024/04/30 23:51

第三方支付架构设计之:商户回调通知系统的悲观和乐观策略

         ps:最近很忙,好久没有时间写blog,对商户通知这块的处理思考一直想记录下来,今天终于抽空完成。


一, 背景的提出

        任何有接入第三方支付(如微信支付,支付宝等)经验的商户IT人员,基本都了解在调用第三方支付的统一下单接口的时候,需要传递一个后台回调的参数,如notify_url,要求该参数是一个外网的可访问地址,用于后台接收第三方支付的支付结果回调,一般第三方支付会通过两个方向通知商户用户在他们系统的支付情况,一个是及时的前端回调,还有一个异步的后台回调,两者的机制和目的都不同,其中前端回调是用于告知和处理前端的业务跳转,JSAPI回调等前端用户交互方面的体验;而后台的异步回调是更加安全的可靠的接收第三方支付结构的方式,基于安全的原因,商户需要在后台回调处理逻辑里面对第三方支付的灰度进行签名验证,同时,为了防止签名被破解导致的风险,兜底处理逻辑上,建议在验证完成后,还需要调用第三方支付的查单接口进行反查验证,从而确保支付回调结果是一个真实的结果。

         前面是从商户接入第三方支付的角度对需要做的事情和需要关注的点进行阐述,从第三方支付架构设计来看,商户回调通知系统是一个必备的关键系统,作为第三方支付,它的职责是负责资金流的扭转,确保安全和可靠,及时的把资金从用户的账户扣除和转移到商户在第三方支付的结算账户的职责,这是核心交易系统需要做的事情,在完成这些事情后,还需要及时和安全的把支付结果通知给商户的后台系统,以告知商户进行订单状态的扭转和发货处理等,商户通知系统是连接第三方核心支付系统和外部商户的桥梁。我们很多的业务模式,就是通过第三方支付系统和商户业务系统进行合作,有序有步骤,安全的实现资金流,信息流和物流等统一协调和扭转,从而保障了整个互联网交易生态的有序运转。

         因此,对第三方支付来说,商户回调通知系统是一个非常重要的必备系统,通知的安全性,健壮性和及时性非常重要。

1, 安全性:通知系统必须确保安全的把支付结果通知给商户,防止中间被非法篡改和劫持,因此,在设计上,必须要求第三方支付系统和商户后台系统按约定的API KEY进行签名和验签;通知系统需要对通知的参数进行全签名,而商户后台系统必须进行验签名。

2, 健壮性:有人说,核心支付系统的健壮性非常重要,商户通知系统健壮性要求没那么高,其实,在移动支付中,用户的体验要求越来越高,如果核心支付系统虽然很健壮,但如果商户通知系统关键时候掉链子,那么及时支付成功,也无法安全和及时的把支付结果送到商户后台系统,因此,商户后台系统就无法进行订单状态的扭转和后续发货等处理,用户就无法及时的购物,有人说,如果商户通知系统挂了,商户后台可以主动去第三方支付系统查询,理论上没错,只是在实际实现中,很多商户的查单补单可能是没有实现或者是T+1,或者是延迟较久的时间才进行调度,因此及时性上是打了折扣,体验就上不去。

3, 及时性:第三方支付商户通知系统,既然选择是主动通知模式,那么及时性就是其中一个关键的考虑因素,支付成功后能否及时的通知到商户,对商户的发货和订单扭转至关重要。

  

二,商户回调通知系统


 

图1-1

 支付的操作步骤如下:

1,  商户通过后台调用第三方支付的接入层进行下单,第三方支付返回预下单id给到商户后台系统,商户后台系统在前端调起支付收银台,用户输入授权信息后,调用核心支付系统。

2,   核心支付系统根据用户选择的支付方式(支付账户或者银行卡)选择不同的支付路径。

3,   如果是选择支付账户支付,则调用支付账户系统对用户的账户进行扣款。

4,   如果是银行卡支付,则调用银行前置系统,通过专线连接接入银行的快捷支付前置进行扣款;

5,   无论是3或者4,成功完成用户扣款后,对商户结算账户进行入账操作。

6,   核心支付系统根据商户下单传递的notify_url地址,调用商户通知系统;

7,   商户通知系统对支付结果进行签名,调用notify_url地址进行回调通知商户,若商户返回失败或者超时,则商户通知系统会按照一定的时间节奏进行后续补偿通知。

 

在具体进行如何通知商户的策略上,有两种基本的策略,分别是悲观和乐观策略,两者的实现方式和试用的场景不同。

 

三,悲观的调度策略

          我们知道,在核心支付系统第一次支付成功返回的时候,会同步通过前端和后台进行商户通知,如果这个时候商户的后台通知,商户后台返回可能三种情况:成功,失败或者超时,针对这三种情况,商户通知系统的补偿系统的后续处理步骤是怎样的呢?

         在悲观的调度策略中,商户补偿系统认为前端的商户通知失败的情况下,有义务进行尽最大能力进行补偿通知,千方百计的进行补救通知,宁愿多通知一次商户也不愿意放弃,类似TCP协议的失败重传机制,是一种可靠的通知模型。

          那么为了实现这种机制,前端在同步通知商户后台系统成功后,会往MQ写入成功通知的消息,而商户补偿系统会在核心系统支付成功后,自动启动定时补偿通知机制,直到收到前端的MQ通知已经成功了才放弃补偿或者自身补偿通知得到商户的成功响应。

仔细分析一下上述的过程,前端通知商户后台系统:

(1)如果这个时候通知失败或者超时,则不会往MQ写成功消息告诉补偿系统,那么补偿系统肯定收不到该消息,因此,补偿系统在间隔一定的时间如10s后自动发起补偿通知;

(2)如果这个时候通知成功,则往MQ写入成功消息,补偿系统在自己的补偿间隔时间内收到了该成功MQ消息,则放弃补偿操作。

(3)如果这个时候通知成功,但往MQ写成功消息失败,MQ堵塞,MQ消息丢失等导致补偿服务无法在自己的间隔时间内收到了该成功MQ,则会自动进行补偿通知。

   综上分享,悲观的回调策略不信任前端,如果前端无法在指定的时间内告诉补偿服务已经成功通知,无法什么原因,补偿服务一定会按照自己的调度节奏重新发起通知。

   这种策略对商户的后台系统来说,有可能出现前面已经成功收到过第三方支付的成功支付回调并且返回成功了,但后续还收到第二次甚至第三次的回调通知,它的优点就是:商户系统可以得到多次的补偿通知,在比较及时的情况下实现订单的状态扭转,不足是如果支付量很大,在一定的极端情况下,商户回调处理服务可能收到大量的重复请求,给系统带来压力,浪费了计算资源,甚至处理不好导致雪崩。

 

四,乐观的调度策略

         前面分享了悲观的调度策略,那么如果对应支付频度非常高的场景下,如春节红包,在每秒达到几万甚至几十万的支付峰值下,如果出现MQ队列阻塞(高峰情况下,发生的可能性极大),补偿服务的自动补偿功能,不但不能提升支付的稳定性,反而成为最后压垮商户后台系统的罪魁恶首,因为,这个时候,商户的接受支付通知系统的支持的并发请求数需要至少double了一倍,对计算资源和成本是一个极大的挑战;另外一个方面,悲观的调度策略,每次通知成功后都会往MQ写一个消息,由于成功通知的概率是更大的,正常的是90%以上,意味着对MQ资源无论是存储量和MQ的消费者处理性能均有更高的要求,一旦出现堵塞,和处理不及时,那么补偿服务就会double后台通知请求,商户系统如果处理不当,雪崩就马上出现。

         那么,针对这种场景,有没更优的策略呢?笔记在实际的项目实战中,对类似红包这种高并发的支付商户通知模型,悲观的调度策略存在较多的风险,因此,提出一种乐观的调度策略,在乐观的调度策略中,我们乐观的认为前端首次通知商户的成功率是比较高的,对首次通知已经成功的,补偿服务就无需进行再次补偿,那么,为了实现这种模型:

         前端首次进行商户通知后,若商户返回成功,则无需做任何事情,如果商户返回失败或者超时,则往MQ队列写入一个通知失败的消息(注意:悲观的策略是每次成功都写MQ消息,这里是失败才写消息),由于前端首次通知成功的概率在99%以上(实践的真实数据已经验证),那么只针对失败才写MQ消息,意味着对MQ的存储量和请求量相比悲观策略降低了99倍,这个时候MQ发生阻塞和雪崩的可能性会大大的降低,而补偿服务不会定时进行补偿,只有收到了MQ的通知失败消息,才进行补偿操作。

         非常明显,该策略对商户系统来说,成功通知最多是一次,在高并发情况下,商户回调系统不会出现double的情况,但该策略,如果出现了MQ消息丢失,由于补偿服务这个时候不会自动进行补偿,商户是无法收到主动的回调通知的,对这种情况,商户可以选择主动反查订单进行补偿,由于量比较少,因此,对及时性的影响没那么大,当然,这里可以进行优化成由前端用户的行为触发查单行为,使得结果的通知符合用户的预期,从而提升了体验。

 

五,总结

         当然,以上两种策略没有好坏,只有根据不同的场景:并发数,可靠性,机器资源,及时性等要求选择不同的策略,我们认为在商业支付中,悲观的回调策略可能更合适,一个是并发数突发性较少,另外对支付的可靠性和及时性也有更多的及时补偿;而对类红包的社交支付等突发性很高的情况,乐观的回调策略可能是更好的选择。

阅读全文
1 0