1 开发流程

微信支付开发流程

业务流程说明:

(1)商户后台系统根据用户选购的商品生成订单。

(2)用户确认支付后调用微信支付【统一下单API】生成预支付交易;

(3)微信支付系统收到请求后生成预支付交易单,并返回交易会话的二维码链接code_url。

(4)商户后台系统根据返回的code_url生成二维码。

(5)用户打开微信“扫一扫”扫描二维码,微信客户端将扫码内容发送到微信支付系统。

(6)微信支付系统收到客户端请求,验证链接有效性后发起用户支付,要求用户授权。

(7)用户在微信客户端输入密码,确认支付后,微信客户端提交授权。

(8)微信支付系统根据用户授权完成支付交易。

(9)微信支付系统完成支付交易后给微信客户端返回交易结果,并将交易结果通过短信、微信消息提示用户。微信客户端展示支付交易结果页面。

(10)微信支付系统通过发送异步消息通知商户后台系统支付结果。商户后台系统需回复接收情况,通知微信后台系统不再发送该单的支付通知。

(11)未收到支付通知的情况,商户后台系统调用【查询订单API】。

(12)商户确认订单已支付后给用户发货。

下载微信SDK

微信没有提供maven仓库坐标,因此我们必须下载使用

微信SDK下载,点击下载java对应的SDK,然后安装到maven的本地仓库中。
进入下载好的SDK的项目目录,然后打开黑窗口,输入命令:

mvn source:jar install -Dmaven.test.skip=true

在pom.xml中引入

<dependency> <groupId>com.github.wxpay</groupId> <artifactId>wxpay-sdk</artifactId><version>3.0.9</version>
</dependency>

WXPay工具

微信SDK提供了一个统一的微信支付工具类:WXPay:

com.github.wxpay.sdk.WXPay类下提供了对应的方法:

生成支付链接

根据微信提供的WXPay类编写了一个支付工具类PayUtils

import com.github.wxpay.sdk.PayConfig;
import com.github.wxpay.sdk.WXPay;
import org.apache.commons.lang3.StringUtils;import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;/*** 微信支付工具类*/
public class PayUtils {private static WXPay wxPay;// 支付成功回调地址private static String notifyUrl = "http://xxx.com/test/PayNotify";// 初始化微信支付static {try {PayConfig payConfig = new PayConfig();payConfig.setAppID("wxXXXX"); // 公众账号IDpayConfig.setMchID("XXXXX");// 商户号payConfig.setKey("XXXXXX");// 生成签名的密钥wxPay = new WXPay(payConfig);} catch (Exception e) {// e.printStackTrace();throw new RuntimeException(e.getMessage());}}// 生成微信订单支付 urlpublic static String createOrder(String orderId, Integer totalPay) {Map<String, String> data = new HashMap<>();// 商品描述data.put("body", "商品支付");// 订单号data.put("out_trade_no", orderId);//金额,单位是分data.put("total_fee", totalPay.toString());//调用微信支付的终端IPdata.put("spbill_create_ip", "127.0.0.1");//回调地址data.put("notify_url", notifyUrl);// 支付有效时间10分钟Date now = new Date();Date now_10 = new Date(now.getTime() + 600000); //10分钟后的时间SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");//可以方便地修改日期格式String nowTime_10 = dateFormat.format(now_10);data.put("time_expire", nowTime_10);// 交易类型为扫码支付data.put("trade_type", "NATIVE");// 利用wxPay工具,完成下单Map<String, String> result = null;try {result = wxPay.unifiedOrder(data);} catch (Exception e) {throw new RuntimeException("微信下单失败", e);}// 校验业务状态checkResultCode(result);// 下单成功,获取支付链接String url = result.get("code_url");if (StringUtils.isBlank(url)) {throw new RuntimeException("微信下单失败,支付链接为空");}return url;}// 检查业务状态public static void checkResultCode(Map<String, String> result) {String resultCode = result.get("result_code");if ("FAIL".equals(resultCode)) {throw new RuntimeException("【微信支付】微信支付业务失败");}}
}

下单并生成支付链接

@RestController
@RequestMapping("/test")
public class TestController {@GetMapping("createOrder")public String createOrder() throws Exception {String orderId = UUID.randomUUID().toString();orderId = orderId.substring(orderId.length()-33,orderId.length()-1);Integer totalPay = 1;String payUrl = PayUtils.createOrder(orderId, totalPay);return payUrl;}
}

前端通过调用这个节课就可以生成一个微信支付的订单链接,
然后使用qrcode.js生成一个微信支付的二维码.

pay.html

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! --><meta name="viewport"content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0,user-scalable=no,minimal-ui"><meta name="description" content=""><meta name="author" content=""><link rel="icon" href="../img/asset-favico.ico"><title>支付页面</title><script src="../plugins/vue/vue.js"></script><script src="../plugins/vue/axios-0.18.0.js"></script><script src="../js/qrious.js"></script><script src="../js/qrcode.js"></script><!--<script>var id = getUrlParam("id");</script>-->
</head>
<body data-spy="scroll" data-target="#myNavbar" data-offset="150">
<div id="app" class="app"><!-- 页面内容 --><center><h1>请扫描下方二维码进行支付!</h1></center><hr><div class="contentBox" style="width: 100%"><!--<img alt="" id="qrcode" style="height: 50%;width: 50%;">--><img alt="" id="qrious" style="height: 30%;width: 30%;display: block;margin:0 auto;"></div>
</div>
</body>
<script>var vue = new Vue({el: '#app',data: {payUrl: ''},created() {// alert(id);axios.get('/test/createOrder').then(res => {if (res.status === 200) {// alert("111")console.log(res)this.payUrl = res.data;// 生成二维码// new QRCode(document.getElementById("qrcode"), this.payUrl)new QRious({element: document.getElementById('qrious'),level: 'L',// 注意级别越高可能会影响到识别度size: 300,value: this.payUrl})}})}});
</script>
<script>// 生成二维码new QRious({element: document.getElementById('qrious'),level: 'L',// 注意级别越高可能会影响到识别度size: 300,value: '${payUrl}'})
</script>
</html>

支付结果通知

http://localhost:8080/test/PayNotify这个地址是在支付成功后的异步结果通知。官网介绍如下:
支付完成后,微信会把相关支付结果和用户信息发送给商户,商户需要接收处理,并返回应答。
所以,此处的地址必须是一个外网可访问地址,而且我们要定义好回调的处理接口。

内网穿透

此处我们肯定不能写:http://localhost:8080/travel/pay/notify,这个域名是本地,是不被外网识别的。可以通过内网穿透来实现。

内网穿透的目的是:让外网能访问你本地的应用,例如在外网打开你本地http://127.0.0.1指向的Web站点。

使用natapp实现内网穿透

使用的natapp得到的域名,设置指向到 PayUtils工具类的支付成功回调地址。

支付结果通知API

支付完成后,微信会把相关支付结果和用户信息发送给商户,商户需要接收处理,并返回应答。
对后台通知交互时,如果微信收到商户的应答不是成功或超时,微信认为通知失败,微信会通过一定的策略定期重新发起通知,尽可能提高通知的成功率,但微信不保证通知最终能成功。 (通知频率为15/15/30/180/1800/1800/1800/1800/3600,单位:秒)
注意:同样的通知可能会多次发送给商户系统。商户系统必须能够正确处理重复的通知。
推荐的做法是,当收到通知进行处理时,首先检查对应业务数据的状态,判断该通知是否已经处理过,如果没有处理过再进行处理,如果处理过直接返回结果成功。在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱。
特别提醒:商户系统对于支付结果通知的内容一定要做 签名验证,并校验返回的订单金额是否与商户侧的订单金额一致 ,防止数据泄漏导致出现“假通知”,造成资金损失。

支付完成后,微信服务会自动向 http://localhost:8080/test/PayNotify 地址发起POST请求,请求参数是xml格式:


通信成功,会返回下面信息:

编写回调api: /test/PayNotify

@PostMapping("PayNotify")public void PayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {// 1.接收请求参数(xml)ServletInputStream in = request.getInputStream();// 2.将xml转为java对象XmlMapper xmlMapper = new XmlMapper();Map param = xmlMapper.readValue(in, Map.class);// 3.调用orderService,修改订单状态
//        orderService.updateState(param);// 4.返回微信平台,接收成功..HashMap<String, String> result = new HashMap<>();result.put("return_code", "SUCCESS");result.put("return_msg", "OK");// 将map转为xmlString xml = xmlMapper.writeValueAsString(result);response.setContentType("application/xml;charset=utf-8");response.getWriter().write(xml);//        return "yyy";}

支付状态查询

当用户扫码支付成功,会自动调用回调接口,从而修改订单状态,完成订单支付。
可以在 /test/PayNotify 的第三步修改用户支付的该订单的支付状态pay_status为已支付;然后在页面的payOrder() 支付成功后调用this.isPay(),会采用定时任务,不断查询订单支付的状态:

<script>var vue = new Vue({el: '#app',data: {payUrl: '',orderNo: ''},methods: {payOrder() {axios.get('/order/createPayOrder/' + this.orderNo).then(res => {if (res.status === 200) {// alert("111")console.log(res)this.payUrl = res.data.data;// 生成二维码// new QRCode(document.getElementById("qrcode"), this.payUrl)new QRious({element: document.getElementById('qrious'),level: 'L',// 注意级别越高可能会影响到识别度size: 300,value: this.payUrl});this.isPay()}})},isPay() {// 开启定时任务,查询付款状态let num = setInterval(function () {// let url = '/order/isPay/'+this.orderNo;axios.get('/order/isPay/' + this.orderNo).then(res => {console.log(res.data)if (res.data.flag && res.data.data === '1') {alert("支付成功")window.location.href = "/pages/pay-success.html";}})}, 5000);// 同时设置一个定时任务,10分钟后,终止查询,认为付款失败setTimeout(function () {clearInterval(num);alert("支付失败")window.location.href = "/pages/pay-fail.html";}, 600000)}},created() {// alert(orderNo);this.orderNo = orderNo;this.payOrder()}});
</script>

每隔5秒就会查询一次,为了防止用户一直不支付的情况,又设置了一个定时任务,10分钟后跳转到支付失败页面

@GetMapping("/isPay/{orderNo}")public Result isPay(@PathVariable("orderNo") String orderNo){String isPay = orderService.isPay(orderNo);return new Result(true,"",isPay);}

调用微信支付api实现用户扫描二维码支付订单相关推荐

  1. iOS - 需求 - 微信扫描二维码支付(草稿)

    首先先讲一下这个流程: 1.商户即公司,根据微信官方支付的规则,为不同的商品或者是订单号生成不同的链接,将链接转换成二维码. 2.用户扫描二维码 3.微信客户端引导用户完成支付 4.用户完成支付,用户 ...

  2. JAVA实现的微信扫描二维码支付

    支付项目采用springMvc+Dubbo架构实现,只对外提供接口. 话说,为什么微信支付比支付宝来的晚了那么一点,一句话,那一阵挺忙的,然后就没有时间整理,最近做完支付宝支付,顺便也把微信支付的也整 ...

  3. 微信扫一扫功能扫描二维码调用外部浏览器打开指定页面实现微信中下载APP的功能

    需求分析 分享链接已经成为手机应用一个非常重要的推广传播形式.为了提高转化率,就需要用户不管是在微信内直接打开链接还是扫描二维码都能直接打下载app. 但由于微信对第三方应用管的非常严格,故目前的大环 ...

  4. 微信中点击链接或扫描二维码跳转外部浏览器的API接口

    很多朋友的APP推广链接需要在微信中进行的网页宣传.传播.下载等等,但是各位朋友一定发现了微信中是屏蔽掉了APP的下载链接的.但是微信最为一个最大的社交平台,为了自身的利益,屏蔽掉了所有APK的下载链 ...

  5. JAVA实现的支付宝扫描二维码支付

    支付项目采用springMvc+Dubbo架构实现,只对外提供接口 原文地址:http://blog.52itstyle.com/archives/169/ 前期酝酿准备 最近项目中要上线支付功能.前 ...

  6. 微信中点击链接或扫描二维码跳转外部浏览器的方法

    很多朋友的APP推广链接需要在微信中进行的网页宣传.传播.下载等等,但是各位朋友一定发现了微信中是屏蔽掉了APP的下载链接的.但是微信最为一个最大的社交平台,为了自身的利益,屏蔽掉了所有APK的下载链 ...

  7. 在微信中,实现微信点击链接或者扫描二维码在浏览器中打开指定的链接

    需求概述 最近很多朋友问我,为什么我的微信域名或者QQ域名怎么总是提示拦截呢?在这里跟大家说一下吧: 第一点:就是域名里面的内容违规或者诱导被举报而导致的拦截 第二点:就是被用户或者同行恶意举报而导致 ...

  8. 微信里的apk链接打不开,怎么让微信的扫一扫扫描二维码后安装apk?

    不管是app的下载链接还是普通文件的链接在微信内置浏览器或者QQ内置浏览器分享都会被拦截.这是腾讯对第三方下载域名实施的打压政策.被屏蔽了也就意味着链接在微信中是无法正常打开的,那么此时用户在微信内打 ...

  9. 用户扫描二维码进入公众号后自动发送指定消息_wetool的封杀、企业微信的崛起,我们要怎么利用企业微信进行用户增长?...

    我们先简单了解下企业微信的概念 企业微信是腾讯微信团队打造的企业通讯与办公工具,具有与微信一致的沟通体验,丰富的OA应用,和连接微信生态的能力,可帮助企业连接内部.连接生态伙伴.连接消费者. 前段时间 ...

  10. 微信中点击链接或者扫描二维码直接跳转外部浏览器打开指定网页下载

    大家在使用微信推广的时候是不是经常都会遇到推广链接被拦截导致无法下载app的情况,此时用户在微信中打开会提示"已停止访问该网页".这对于使用微信推广的商家来说非常不友好,而且造成的 ...

最新文章

  1. 隔空操作之隔空下象棋
  2. [Linux] Centos DenyHosts 禁止针对linux sshd的暴力破解
  3. pytho sin(1/x)震荡间断点
  4. SpringBoot实现懒加载@Lazy
  5. Linux内核文档翻译
  6. 国产浏览器 linux,360安全浏览器推出国产操作系统版,在deepin上架获得高度点赞...
  7. Prototype1.5.1源代码解读分析-3
  8. Linux命令的学习(目前需要的,紧急)
  9. 2019-0331视觉SLAM的学习第一讲
  10. 【图像融合】基于matalb小波变换(加权平均法+局域能量+区域方差匹配)图像融合【含Matlab源码 1819期】
  11. 微软采纳我的建议在WES7增加媒体中心组件
  12. 工行网银B2c第三方接口开发
  13. 【luogu P4218】珠宝商(SAM)(点分治)(根号分治)
  14. 低温工作笔记本计算机,电脑低温自动关机
  15. 期货量化策略的分类与概述(完整录播版)
  16. 从C/C++到Python(之一)(By Robinvane Suen)
  17. 中国知网caj转pdf的免费转换方法
  18. OpenGL ES EGL eglQueryContext
  19. 关于舆情系统的“准”
  20. K近邻(KNN)详解

热门文章

  1. 模拟信号隔离转换模块0-10V0-5V转4-20mA0-20mA直流转换
  2. php redis统计在线人数,每天活跃度
  3. 往超级表格导入Excel,让数据处理不再繁杂!
  4. 【老九学堂】【初识C语言】编码规范
  5. 快手-艳云脚本云控系统
  6. 3d游戏项目实训一周总结
  7. jQuery——淘宝购物车结算页面demo
  8. CVPR2020(Enhancement):论文解读《Zero-Reference Deep Curve Estimation for Low-Light Image Enhancement》
  9. matplotlib折线图(标记点、标记点大小、标记点边颜色、标记点边宽)
  10. Windows电脑垃圾的清理