一、场景描述
PC收银台的浏览器展示了收款二维码,用户扫了支付二维码,支付完成后,浏览器需要实时响应支付结果。
二、问题描述
扫码支付的支付结果一般通过服务端回调或主动查询来获取,但显示二维码之后,如果不断的去轮询的话,增加了服务器的压力。如果服务端回调支付结果,能立马把支付结果响应给收银台的浏览器,问题就解决了。前端调用一次查询,如果状态还是处理中,就阻塞在那里,直到有支付结果再响应浏览器,想要阻塞,最开始想到用Java的队列,单机没问题,但是生产上的回调服务器和交易服务器不是同一台,所以无效。
三、实现逻辑
交易服务器获取收款二维码,在前端显示,在等待用户支付的同时,调用一次查询,在后台的查询方法中,如果支付完成,立马响应支付结果,如果没有支付完成,就利用redis订阅支付结果,用户扫码支付完成之后,微信、支付宝或银联会异步回调通知我们的回调服务器,我们回调服务器再调用redis的发布,把支付结果发布出去,这个时候交易服务器就订阅到支付结果了,就可以向浏览器作响应了。
四、实现代码
下面以Java为示例,介绍其实现过程。
1、创建Redis工具类RedisFactory,核心方法如下:
2、订阅支付状态
3、发布支付状态
五、注意事项
今天在测试的过程中发现,订单支付完成了,在更新支付结果的方法里,一发布支付结果,客户端就订阅了,但结果订阅的不是最新的状态。后来通过断点分析代码,终于找到原因。原来,更新状态和发布状态的这些方法在一个事务里面,虽然发布了状态,但事务还没结束,因此,数据更新还没提交就开始查询,查到的数据当然就不是最新的了。
为避免这个问题,因此,大家在使用的时候要注意:
●1、在更新的事务结束之后,再发布支付状态。(带有事务的更新方法在很多地方被调用,在外层加方法改动太多,不现实)
●2、在订阅的地方,订阅到消息,不要立马去数据库查询,每间隔等待一会儿再查,直到查到最终结果为止。