如图是一个简化的下单流程,首先是提交订单,而后是支付。html
支付的话,通常是走支付网关(支付中心),而后支付中心与第三方支付渠道(微信、支付宝、银联)交互,支付成功之后,异步通知支付中心,支付中心更新自身支付订单状态,再通知业务应用,各业务再更新各自订单状态。java
这个过程当中常常可能遇到的问题是掉单,不管是超时未收到回调通知也好,仍是程序自身报错也好,总之因为各类各样的缘由,没有如期收到通知并正确的处理后续逻辑等等,都会形成用户支付成功了,可是服务端这边订单状态没更新,这个时候有可能产生投诉,或者用户重复支付。git
因为③⑤形成的掉单称之为外部掉单,由④⑥形成的掉单咱们称之为内部掉单github
为了防止掉单,这里能够这样处理:面试
一、支付订单增长一个中间状态“支付中”,当同一个订单去支付的时候,先检查有没有状态为“支付中”的支付流水,固然支付(prepay)的时候要加个锁。支付完成之后更新支付流水状态的时候再讲其改为“支付成功”状态。redis
二、支付中心这边要本身定义一个超时时间(好比:30秒),在此时间范围内若是没有收到支付成功回调,则应调用接口主动查询支付结果,好比10s、20s、30s查一次,若是在最大查询次数内没有查到结果,应作异常处理spring
三、支付中心收到支付结果之后,将结果同步给业务系统,能够发MQ,也能够直接调用,直接调用的话要加剧试(好比:SpringBoot Retry)微信
Spring Boot 推荐学习教程:intellij-idea
https://github.com/javastacks...异步
四、不管是支付中心,仍是业务应用,在接收支付结果通知时都要考虑接口幂等性,消息只处理一次,其他的忽略
五、业务应用也应作超时主动查询支付结果
对于上面说的超时主动查询能够在发起支付的时候将这些支付订单放到一张表中,用定时任务去扫
为了防止订单重复提交,能够这样处理:
一、建立订单的时候,用订单信息计算一个哈希值,判断redis中是否有key,有则不容许重复提交,没有则生成一个新key,放到redis中设置个过时时间,而后建立订单。其实就是在一段时间内不可重复相同的操做
附上微信支付最佳实践:
来源:废物大师兄\
地址:https://www.cnblogs.com/cjsbl...
近期热文推荐:
1.600+ 道 Java面试题及答案整理(2021最新版)
2.终于靠开源项目弄到 IntelliJ IDEA 激活码了,真香!
3.阿里 Mock 工具正式开源,干掉市面上全部 Mock 工具!
4.Spring Cloud 2020.0.0 正式发布,全新颠覆性版本!
以为不错,别忘了随手点赞+转发哦!