前面分享了一篇 JAVA后端调用微信支付“统一下单”接口实现微信二维码扫码支付 的博客,虽然二维码在生成的时候可以设置有效期,但是这依旧不能保证整个业务流程和数据的安全。因为通常网站提供给用户的支付方式不止一种,除了微信支付,可能还有支付宝和银联支付等。

我们不妨先来假设下面几个场景:

场景一:张三在你的网购平台下了一个订单,起初是选择微信二维码扫码支付的,但是打开微信时发信微信零钱余额不足,于是张三就把这个二维码截图发给自己的基友李四,等了五分钟,李四可能因为手头有事要忙迟迟没有支付,这时张三实在没耐心了,就想起自己的支付包刚好还有点钱,于是就用支付宝支付成功了。恰巧此时李四那边也忙完自己的事情了,拿着自己的微信也成功扫码支付了。这是就造成一个订单,被成功支付两次了。

场景二:张三在你的网购平台下了一个订单,选择微信二维码扫码支付,因自己余额不足,将生成的二维码发给李四,由李四代付,大约过了五分钟,李四那边有事忙着一直没有支付,此时张三突然不想买了,于是取消了订单,过了几分钟才想起来要通知李四取消订单,恰好此时李四那边已经成功扫码支付了。这就造成已取消订单被支付成功的情况。

针对这种一个订单被多次支付和已取消订单被支付的情况,平台需要提供退款的功能,并且添加流水的操作应该由定时任务来执行,具体的流程准备另写一篇博客说明(如果我还记着这回事的话)。但是这就足够了吗?所谓种什么因得什么果,为什么不从源头上降低上面这两种情况发生的概率呢!假设订单取消后的30秒内,生成的微信二维码依旧有效,如果这还勉强能够说得过去的话,那么用户订单取消5分钟后(甚至更长时间),这个二维码还能被正常使用,那这就说不太过去了吧。你可能会说,可以在生成二维码的时候设置二维码的有效时间是5分钟或者更短(这个可参考 微信支付接口调用之二维码失效时间的设置),但是你总会遇到一些需求,比如要求二维码的有效时间跟着平台订单的有效时间走的情况,这时二维码的有效时间就不只10分钟了吧。

针对这种情况,我的解决方案是:新建一张表 t_qr_code,用来存储生成的二维码图片路径,并且保存二维码的失效时间。表的结构如下:

CREATE TABLE `t_qr_code` (`pk_id` varchar(50) NOT NULL COMMENT '主键',`order_id` varchar(50) DEFAULT NULL COMMENT '商户订单号',`code_url` varchar(255) DEFAULT NULL COMMENT '二维码保存的路径',`status` tinyint(3) DEFAULT '1' COMMENT '二维码状态,1,正常;2,已调用微信api使之失效;3,需要调用微信api关闭订单;',`expire` datetime DEFAULT NULL COMMENT '二维码失效日期',`create_date` datetime DEFAULT NULL COMMENT '二维码生成时间',`update_date` datetime DEFAULT NULL COMMENT '本记录更新时间',PRIMARY KEY (`pk_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

该表有以下几个用处:
(1)当用户关闭二维码所在页面,下次再次对这个订单发起微信二维码扫码支付时,如果这时二维码有效期超过15秒,就依旧返回这个二维码图片和失效时间,而不会重新跟微信请求。当然这个也需要前端根据这个二维码的失效时间做一些特效处理以提高用户体验,比如二维码失效了,就弹出一个按钮让用户点击刷新。
(2)当用户取消订单的时候,查询 t_qr_code 表中是否有未是失效的二维码,如果有,修改status=3,由定时任务调用微信关闭订单接口的接口。
(3)如果用户一开始选择二维码扫码支付,成功生成了二维码,但是最终却是选择其他方式支付成功的,其它方式的支付接口中,需要执行下面这台sql语句:

update t_qr_code set status=3 where expire>now() and status=1 where order_id=#{orderId}

大致思路大概就如此,顺便提醒一下,你的调用微信“关闭订单”接口的定时任务的扫描间隔时间应该设置的尽量短一些,这个时间越短,造成失效订单被支付的概率就越低。在分享源码之前,请参考官方文档  ,值得注意的是,微信H5支付,微信JSAPI支付,微信Native支付(即二维码扫码支付)和微信APP支付 的关闭订单接口都是同一个。感兴趣的可以去  微信支付  官网逐一查看。此接口本人亲测有效,测试方法:当微信生成二维码的时候,设置的二维码有效期是30分钟,但是在生成二维码3-5分钟后,调用下面这个关闭订单的接口,等再次拿微信扫描二维码的时候,微信提示该订单已失效。官方文档提示要再二维码生成的5分钟后再调用关闭订单的接口,但是实际测试发现3分钟后也能成功取消。

下面分享具体的实现代码,我把他封装到了一个工具类中,返回的参数都在map中,如果想知道有哪些参数,可以在自己的控制台打印一下或者参考官方文档 ,下面分享代码:

package wxpay;import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;public class WxApiUtils {/*** 关闭微信订单接口* @param orderId你自己网站生成的订单号,注意要和你申请二维码时候用的订单号一致,看过我前面那边申请二维码支付的朋友会发现,此时我的这个orderId应该是要带有支付标识的,如果我网站的订单号是:123456 ,那么此时的这个参数orderId=123456_NAVTIVE ,因为我申请二维码用的就是这个带标识的订单后* @return*/public static Map<String, String> closeOrder(String orderId){String appid =Constant.APP_ID;String mch_id = Constant.MCH_ID;String out_trade_no = orderId;String nonce_str = WXUtil.createNoncestr().substring(1, 32);SortedMap<String, String> packageParams = new TreeMap<String, String>();packageParams.put("appid", appid);packageParams.put("mch_id", mch_id);packageParams.put("out_trade_no", out_trade_no);packageParams.put("nonce_str", nonce_str);String sign = WXUtil.createSign(packageParams);packageParams.put("sign", sign);String xml =WXUtil.ArrayToXml(packageParams);logger.info("map转换成xml的结果:"+xml);String createOrderURL = "https://api.mch.weixin.qq.com/pay/closeorder";return GetWxOrderno.getReturnUrl(createOrderURL, xml);}}

涉及到的所有工具类和实体类,以及一些依赖的jar包,在我的另一篇博客 JAVA后端调用微信支付“统一下单”接口实现微信二维码扫码支付 中都能找到,时间有限,此处不再上传。

至此,分享结束,希望对各位有帮助。

支付宝扫码支付和微信扫码支付共存的情况下,如何避免同一个订单被多次支付相关推荐

  1. php验证是否是微信支付,利用thinkphp判断微信中的支付还是微信扫码支付还是手...

    进行判断,根不同的客户端,显示不同的内容,如果不是手机,则只显示扫码微信支付,如果是微信公众号中,则只显示公众号支付 阿里西西web开发网为大家整理了这篇利用thinkphp判断微信中的支付还是微信扫 ...

  2. 转码机器人(微信转码,小程序转码)

    转码机器人(微信转码,小程序转码) 小程序不能生成二维码,就无法将小程序分享到更多的地方,只能分享给微信好友,不能转发到朋友圈.不能转发到其它平台,现在只需要将小程序分享给机器人,即可自动转码!这样你 ...

  3. 企业微信如何养号,什么情况下可能被封号?

    最近,有的用户反映,他们的企业微信中有一个成员的账号被封了,不知道大家最近有没有遇到过.其实企业微信正常情况下是不会被封的. 腾讯不仅在微信个人号上面有各种限制,企业微信也并不例外,也有一些限制.只是 ...

  4. 微信支付宝支付代理 微信扫码支付收银系统

    随着城市的多元化,中西结合,现代与古代文化的交融,人们的衣食住行也在发生着翻天覆地的变化,在10年前,出门消费都是现金或者刷卡.而现在你去购物都有会考虑一个问题:能不能用支付宝,微信支付?扫码支付已经 ...

  5. 微信扫码充值 php,微信扫码支付,php版

    今天和大家分享一下关于微信扫码支付的主要流程. 1.从官网下载下来sdk后,按照说明进行商户信息的配置. 2.官网demo中,打开example文件夹中的native.php,可以看到一下两行.我们需 ...

  6. php CI 微信支付扩展 微信扫码支付 jssdk 支付 退款

    微信支付API类库来自:https://github.com/zhangv/wechat-pay 请先看一眼官方场景及支付时序图:https://pay.weixin.qq.com/wiki/doc/ ...

  7. 支付篇—微信扫码支付

    应用场景: 商户根据商品信息,生成商品二维码,用户通过微信扫一扫功能扫描该二维码,完成支付. 支付模式: 现在微信扫码支付支持两种模式. 模式一需要商户必须先在公众平台后台设置支付回调URL.URL实 ...

  8. PHP小程序码扫码登录网站,微信扫小程序码实现网页端登录

    常见的微信扫码登录有两种 这两种方式都需要提交企业资料认证和300元年费,有些想要学习或者自己的网站没有盈利的,其实不舍得花这个钱,特别是个人开发者,没有企业资料去做认证. 既然没法做企业认证,那我们 ...

  9. 微信小程序实现扫二维码时仿微信扫码音效

    需求分析:使用wx.scanCode时无交互感,对用户来说没有反馈,故增加扫码成功时震动及播放微信扫码音效 // index.html <view bindtap="scanCode& ...

最新文章

  1. 小猿圈linux之运维工程师面试题(答案版)
  2. 直播系统开发:功能创新提升用户留存
  3. maven整合jar包下载地址
  4. linux java转码_用Linux shell脚本批量转换java源文件编码(支持命令行选项)
  5. JavaScript中变量提升是什么?如何实现?
  6. JavaScript实现接口的三种经典方式
  7. 讲的是关于提高网站速度的内容|转自csdn
  8. BAT警示:没试过这个方法就别说会数据分析!!
  9. java获取当月1号 的时间chuo_java获取时间戳的方法
  10. Linux下部署WordPress
  11. php架构师都会有什么面试题,PHP架构师面试题目和答案
  12. 12.51单片机实现电子音乐盒
  13. 自动驾驶仿真测试标准ASAM OpenX简介
  14. TCP协议--复位报文段
  15. 记一下唐伯虎点秋香里的经典台词
  16. keil 调试 操作系统_调试操作系统:内存分配的经验教训
  17. 第一阶 08 单例模式、递归、方法参数和this等关键字
  18. office快速制作贺报方法
  19. 神舟S7-2021S5莫名其妙风扇声音贼大然后关机问题
  20. USB键盘在DOS下无法用,在BIOS和WIN中正常,奇怪情况,原来是PS2接口有问题

热门文章

  1. jvm之java内存区域详解篇guide哥yyds
  2. 自定义ZuulFilter用于验证生成的token
  3. 微服务网关Zuul路由ZuulFilter过滤
  4. Unity进行桌面截图并上传到服务器记录
  5. json类型大小 mysql_MySQL JSON数据类型
  6. Python-海龟画蟒蛇
  7. 苹果5g手机_iPhone 12 mini全面解析,最便宜最小的5G苹果手机
  8. 性能测试之脚本、工具、结果分析总结
  9. 如何分析android进程被杀问题
  10. Excel添加次坐标方法