再谈电商之支付逻辑与坑

支付接口逻辑

三方支付

  • sm2加密传参、校验参数
  • 校验防重令牌,防止重复提交
  • 支付校验
    • 获取分布式锁
    • 校验预支付缓存
      • 不存在:订单超时
    • 校验支付缓存
      • 不存在:首次/超时后调起支付
      • 存在:校验此次支付和缓存,不一致需关闭之前三方支付
  • 调起支付
  • 发送消息到防掉单延迟队列
  • 返回调起结果

接口逻辑说明

这里存在两个缓存:

  • 预支付缓存,与延时队列取消订单时间一致,30min,缓存存在说明订单还未超时
  • 支付缓存,调起三方支付缓存,5min,超时后三方支付通道也会关闭。

支付中存在的问题

以下问题只针对于同一个人来说

支付调起

不同端之间,PC和APP间重复支付

针对于不同端之间的操作,在接口上使用分布式锁,锁住当前用户的操作,防止多端重复类型操作。

不同支付方式间,既调起了微信又调起了支付宝

针对于不同支付方式,可以使用缓存的方式,缓存有效期和支付有效期同步,即缓存存在说明调起的支付还有效,当存在有效支付时,调起了其他类型支付,需要对之前的支付方式做关单处理(三方提供)然后使用新调起的支付作为此用户的支付缓存。
保证当前最多有一种支付方式存在于缓存中。

支付

多端同时支付

在支付调起逻辑中可以保证当前最多有一种有效的支付方式。此时压力来到了三方支付系统,经测试(微信)两部设备同时扫描一个支付码,当其中有一个支付成功后,其他设备会有弹窗提示,保证一个码只能支付一次。

超时支付

三方支付调起时,有可选参数过期时间,当前时间超过此时间后扫码会显示此二维码失效,来防止可能得多次支付,压力存在于三方。

订单后续逻辑

支付回调

在防止了多次调起多次支付后,回调也存在坑,回调这个通知方式,由于是异步操作,就会存在不及时性,可能性很多,所以我们需要从多个方面进行限制。
首先讨论回调和订单超时问题,正常情况下:

  • 订单支付成功
  • 异步接收三方支付结果
  • 订单的后续逻辑
  • 延迟队列执行对订单是否超时处理

支付回调延时队列操作之后,若由于某些原因回调信息没有收到,导致系统误以为订单尚未支付,把订单修改为了未支付,出现了数据异常。
针对上述问题,

  • 延迟队列操作时,需要验证三方是否支付、正在支付,再对订单进行关单,若已经支付,直接走后续支付成功逻辑。
  • 当收到支付成功回调时,订单以变为未支付时,支付优先于一切,即便订单已变为取消状态也是需要更改为已支付,做支付成功逻辑。

支付问题解决方案

如何防止多端重复支付

对于同一用户来说,支付时获取分布式锁,当一端发起支付直到调起成功,其他端无法调起。

如何防止重复调起并支付

场景:PC调起微信支付后,扫码不付款,随后APP调起支付宝支付,扫码与微信同时付款。
获取此用户支付分布式锁后,校验缓存中是否已存在支付缓存(记录调起支付的信息),存在且不同支付方式需要对之前的支付方式做关单处理,才可以进行此次操作的调起。若支付方式相同,直接返回之前调起结果即可。
ps:关单后APP即便扫码了,也会提示订单关闭

用户压时间点支付存在的问题

前提:当订单创建时,就会把订单放入延时队列,默认30min后取出把未支付的订单改为取消状态
场景:用户支付逻辑中,验证订单过期时未过期,支付回调时订单过期。(角度刁钻)
分析一下,此时操作订单的逻辑有两个,一是延时队列进行订单超时操作,二是支付成功回调操作。

  • 回调在前,延时队列在后。没有影响,延时队列关单时校验三方支付状态。
  • 延时队列在前,回调在后。以支付为中心,即便订单取消,也是可以更改为已支付走支付成功逻辑。

上述情况中发生概率还是存在的,对于极端情况做了一些梳理。

如何防止重复支付

这里讨论的场景时,当一个订单支付成功后,由于种种原因没有接收到支付成功信息,导致订单还是未支付状态,用户可以再次发起支付

场景:使用微信支付后,由于网络等原因,支付回调没有调通。用户切换支付方式使用支付宝支付,并付款。
对于系统而言,什么时候支付的是无感知的,只是调用了三方接口生成支付链接/二维码,用户何时支付并不会感知,只能被动接收支付结果信息。想到这里,我们可以在调起支付后,添加异步线程,隔一段时间请求三方支付的结果,化被动为主动。
这里推荐使用延时队列的方式,间隔时间是由小到大的,例如,10s、30s、60s…
当请求三方支付结果时,显示支付成功,即便系统已经把订单修改为了取消状态,也是可以修改为支付成功的。

订单手动取消

取消前需要根据缓存,去对应支付方做关单处理后才可以关闭,若显示已支付,则直接走支付成功后续逻辑。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值