支付系统对于异步通知的处理

461 阅读3分钟
1. 传统做法

调用第三方支付时,支付成功后通过第三方回调来获取最终的支付结果,之后处理支付成功的业务。

2. 如果接不到异步通知怎么办?
  • 一般来说,第三方支付,比如支付宝,新浪支付都会提供相应的交易查询接口,用来对该笔订单的最终结果进行查询。所以,部分企业采用发起交易之后,调用第三方查询来主动查询支付结果,彻底抛弃异步通知机制,保证不会因为网络等原因丢失交易结果。
  • 但是,这种方式也存在一些问题:调用第三支付查询接口时,交易不一定结束,查询到的可能是不确定的结果,比如交易已经在第三方创建成功,但是是否交易成功的结果还没有拿到。针对这种情况,有些企业会采取创建交易后,线程睡眠1秒或2秒进行查询,但这种方式势必会导致用户不必要的等待,降低用户体验,并且,到底等几秒才是最合理的也没有定论。并且,大多数第三方支付的交易查询接口所返回的参数一般都比异步通知的参数要少,比如新浪支付在主动调用交易查询时,无法获得内部交易流失号等,这样会导致获取参数不全的问题。
  • 所以,作者采用以异步通知为主,以定时任务运行交易查询作为异步通知的辅助措施。
3. 具体操作

在异步通知中处理所有的业务逻辑,包括对于必要参数的更新,以及通知订单或其他业务系统做后续的业务操作。使用分布式定时任务调度框架,添加定时查询任务,查询商户系统的流水表,对未拿到异步通知的订单主动去调用第三方查询,拿到最终的结果。作者这里使用的是XXL-JOB分布式任务调度平台。

4.注意事项
  • 定时任务设置多久一次,查询哪个时间段的订单?

    我们需要以异步通知的结果为准,所以定时任务查询的订单需要查询创建时间在当前时间一段时间之前的订单,仅作为没接到异步通知的保护措施。作者这里设置的是每两分钟一次定时任务,查询当前时间1分钟前到6分钟前的订单,这样可以保证每个待查询订单都有两次机会被定时任务保护,防止查询时仍然是待支付等不确定结果。

  • 定时任务中也进行业务逻辑,是否会和异步通知中重复,导致业务逻辑执行两次,比如两次发货等?

    可以给异步处理和定时查询的具体逻辑中加锁,作者采用的是mysql更新乐观锁,通过唯一请求号更新具体的交易状态,以update结果是否为1作为条件进行后续逻辑。