✅下单支付过程,点击跳转支付,输入密码,支付完成后跳转到订单页,整个过程可能会有什么问题?架构方面做哪些设计?
典型回答
这个问题是个非常大的问题,从这个问题开始展开,几乎够聊一整场面试的了。非常考验一个人的能力。那么我们试着分析下,整个过程会涉及到哪些问题,以及该如何解决和优化。
问题1:支付跳转失败
这种情况一般出现在第三方支付系统出现异常,或者网络出现异常的情况,导致我们无法成功跳转到某个支付渠道的收银台上面去。
这里涉及到的其实是一个故障转移相关的问题,也就是当某个系统不可用了,出现故障了,那么如何降低对本系统的影响。
其实,最有效的办法就是限流、降级、熔断一把梭。
首先需要实时监控各个支付渠道的成功率,当某个渠道的成功率降到一定阈值之后,比如80%以下,则在收银台上渲染支付方式的时候直接不展示这个支付渠道,或者只给一部分用户展示这个支付渠道,这样就起到了一个限流、或者熔断的作用了。
等过一会支付成功率恢复了之后,再恢复收银台的展示即可。
问题2:支付状态未同步
对于第三方支付来说,支付结果一般都有多种方式通知的,一种是渠道会做回调,再创建支付的时候注册一个回调地址,在支付成功/支付失败后,会回调指定的地址,在这个地址中处理结果就行了。
对于页面来说,前端也会不断轮询这个支付单的状态,当回调处理完之后,前端就会直接跳转到成功页面上面去了。
还有一种就是调用方也可以主动轮训这个支付状态的,支付渠道会提供一个查询接口,我们可以通过定时任务轮训查询,或者最简单的就是页面上提供一个链接:如页面未跳转,请点击跳转。
这个点击其实就是向后端发起一个查询,后端会查询一下支付渠道,如果成功了,则直接处理成功要干的事儿,以及页面进行跳转。
另外,还需要一个兜底的定时任务,防止万一用户不点击链接导致不一致的情况。
问题3:用户重复支付
这个也是比较常见的,这个就不展开说了,下面几篇都写的很清晰了。
问题4:支付完成后页面未跳转
这种情况,和问题2其实处理方式一样,就是页面是增加主动查询的链接,主动去支付渠道查询结果。
问题5:支付成功后库存未扣减、或订单状态未推进
这个,其实就是涉及到分布式系统的一致性问题了。很多订单,会在支付成功后扣减库存,并且更新订单状态的。
这就涉及到订单、支付、库存三个系统之间的一致性了,其实就是个分布式事务的问题。
在这个场景下,可以考虑用TCC或者AT的分布式方案解决。不建议用MQ的方案,因为MQ的方案有延迟,是最终一致性,支付这个地方对一致性要求还是挺高的。
关于TCC,可以从下面这篇开始看:
关于AT,可以从下面这篇开始看:
在我的那个数藏项目中,支付成功后同样会处理订单、支付、藏品、链等几个模块的一致性,用到了Seata的AT模式,同时为了解决外部链平台不可用导致的额外回滚问题,引入了事务钩子机制。详细的代码和讲解可以从项目课中了解。
问题6:支付数据被篡改
这个问题一般很少会出现,因为成熟的第三方支付系统,都会需要进行加签验签、加密解密的。只要按照要求做了, 一般都没啥问题。
问题7:用户不支付,卡在支付中
如果支付一直没支付,那么我们需要有超时机制来让支付单失效。
这就需要一个超时关单的功能了,这个我也讲过很多方案:
建议大家优先考虑用定时任务的方案,而不是MQ的方案。
另外,这里的关单需要和支付渠道的时间保持一致,避免出现我们自己关单了,但是渠道还没关单,导致用户自己打开支付宝或者微信找到那个支付单自己付掉的情况。
一般就是给渠道的超时时间比自己系统的短一点,让他先超时,他超时的时候也会回调我们,我们直接处理我们的关单即可。如果他一直没回调,我们的时间到了之后,主动关单的时候也掉一下渠道的关单接口即可。