一、需求场景
我们在开发业务需求中,很容易遇到类似调用第三方接口进行扣减类的业务需求,比如支付、红包领取、代金券领取、积分兑换等。那么会遇到那些问题呢?
三、小白实现逻辑
如果我们用简单的如下逻辑实现
1、开启事务
2、调用第三方扣减接口
3、本地权益赠送
4、提交事务
这个方案,稍微有点开发经验的程序员就会发现问题大大的。
问题1、若是在步骤2调用第三方扣减接口因为网络抖动,超时了怎么办?
步骤2超时,程序抛出异常,本地权益赠送失败,但是有可能第三方接口实际是扣减成功的,可怜的用户被扣减了却啥都没得到!
问题2、若是步骤2第三方扣减成功,本地权益赠送失败,第三方回滚不了,可怜的用户还是啥都得不到。
也许有同学说可以把步骤3和2调过来,结果是一样的。那么可行性的流程是啥呢?
四、可行性方案分析
其实具体方案要看第三方提供的接口情况,根据第三方提供的接口情况来采取不同的方案措施。
1、方案1,第三方提供了扣减接口、回调接口、主动查询接口。
若第三方这三个接口都提供了,我们的业务逻辑就可以变为
1、开启事务
2、本地权益赠送,状态为处理中
3、提交事务
4、调用第三方扣减接口(传权益流水)
上面的逻辑,步骤2我们把权益赠送改为处理中,然后先提交事务,然后调用第三方扣减接口,第三方扣减接口需要保障权益流水幂等。
此时我们会再提供个回调接口给第三方,如果第三方扣减成功,会调用我们这个回调接口,回调接口会把本地权益状态改为处理成功。
此时如果第三方因为网络问题或者调用我们的回调接口失败,我们还需要启动一个定时任务定时去根据权益流水调用主动查询接口查询最终状态。
注:这里有可能有同学会问,为啥不在步骤四调用成功后直接修改本地权益状态?这里如果第三方提供了回调接口,表明这个扣减业务在第三方肯定也是异步的,比如支付,虽然你调用支付接口支付了,但是最终有没有成功,还需要后续才能知道。
2、方案2、第三方只提供了扣减接口和主动查询接口。
若第三方没有提供回调接口,那么要跟第三方确认扣减返回成功是不是就是成功了,如果是的话,我们就可以在步骤方案1的基础上做如下逻辑修改
1、开启事务
2、本地权益赠送,状态为处理中
3、提交事务
4、调用第三方扣减接口(传权益流水),返回扣减成功后修改本地权益状态为处理成功。
当然还需要主动查询接口来兜底。比较虽然正常流程几乎不会出问题,但是怕的就是万一。
注:这里如果第三方说,他的扣减还是异步的怎么办?这不扯蛋么,你异步还不回调我告知我结果,如果第三方比较拽就是没有,那么只能用方案1,加消费程序了。逻辑变为如下。
1、开启事务
2、本地权益赠送,状态为处理中
3、提交事务
4、调用第三方扣减接口(传权益流水)。
5、登记扣减消息
然后我们在消费程序进行主动查询,这样就可以保证准实时,当然我们的定时轮询主动查询也还是必须的,毕竟最终的兜底少不了,谁知道消费程序查询多少次能有结果呢?可能对方网络断了呢?所以兜底方案少不了。
3、方案3、第三方只提供了扣减接口(有幂等)。
这种就比较难搞了,特别是若对方是异步对方说你就算调用我的接口成功,但是也不一定算成功的,那么就扯蛋吧,不带这么玩人的,如果不是,是同步那么得问问是否有幂等的字段,比如权益流水,相同的权益流水调用多次,返回结果是一样的,那么我们可以采取如下方案
1、开启事务
2、本地权益赠送,状态为处理中
3、提交事务
4、调用第三方扣减接口(传权益流水),返回扣减成功后修改本地权益状态为处理成功,若接口调用失败,则重新发起调用
上面步骤四可以用消费程序来实现,重复发起,直到有明确结果为止。
4、方案4、第三方只提供了扣减接口(没有幂等)
如果第三方实在是太小白,只是只有一个扣减,且没有幂等,那就只能业务上进行干预,如果有异常就人工介入了,逻辑也变为最简单的。
1、开启事务
2、本地权益赠送,状态为处理中
3、提交事务
4、调用第三方扣减接口(传权益流水),返回扣减成功后修改本地权益状态为处理成功,若接口调用失败,则失败
五、总结
所以对于这种扣减业务,得看扣减接口提供了啥,有没有幂等,有没有回调,有没有主动查询接口,是不是异步等,然后具体问题具体分析,主要目的是考虑超时,失败这些异常情况怎么解决。
拙见,个人随笔观点,供参考!