最近在网上总结了spring cloud 微信扫码支付的流程,
本人是刚入行的小白,有不对的地方请大家指出
也欢迎大家来多多交流

我的商户APPID和秘钥的一些配置信息,是公司的 这些需要微信的商户认证

一.微信支付类型

微信native扫码支付

链接: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=1_1.

二. native扫码支付

2.1. 业务流程

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

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

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

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

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

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

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

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

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

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

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

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

2.2. 后端代码编写

2.2.1 引入依赖

<!--微信支付--><dependency><groupId>com.github.wxpay</groupId><artifactId>wxpay-sdk</artifactId><version>RELEASE</version></dependency>

编写application.properties

#微信
#APPID
wx.AppID=
#商户ID
wx.MchID=
#API秘钥
wx.Key=
#异步接收微信支付结果通知的回调地址(此处的值随意填写)
wx.NotifyUrl=

2.2.2 编写WxPayConfig 配置类

package com.hcloud.wxconfig;import java.io.InputStream;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;import com.github.wxpay.sdk.WXPayConfig;@Component
public class WxPayConfig implements WXPayConfig{@Value("${wx.AppID}")private String AppID;@Value("${wx.MchID}")private String MchID;@Value("${wx.Key}")private String Key;@Value("${wx.NotifyUrl}")private String NotifyUrl;/*** 获取 App ID** @return App ID*/@Overridepublic String getAppID() {return AppID;}/*** 获取 Mch ID** @return Mch ID*/@Overridepublic String getMchID() {return MchID;}/*** 获取 API 密钥** @return API密钥*/@Overridepublic String getKey() {return Key;}/*** 异步接收微信支付结果通知的回调地址** @return*/public String getNotifyUrl() {return NotifyUrl;}/*** 获取商户证书内容** @return 商户证书内容*/@Overridepublic InputStream getCertStream() {return null;}/*** HTTP(S) 连接超时时间,单位毫秒** @return*/@Overridepublic int getHttpConnectTimeoutMs() {return 8000;}/*** HTTP(S) 读数据超时时间,单位毫秒** @return*/@Overridepublic int getHttpReadTimeoutMs() {return 10000;}}

2.2.3 编写WxNativeService 扫码支付(这里调用微信的[统一下单]API)

package com.hcloud.payservice;import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import com.github.wxpay.sdk.WXPay;
import com.hcloud.wxconfig.WxPayConfig;@Service
public class WxNativeService {@AutowiredWxPayConfig payConfig;/*** 统一下单接口(用于返回二维码的url)** @param money      金额* @param outTradeNo 商户订单号* @param ip         终端IP* @return*/public Map<String, String> unifiedOrder(String money, String outTradeNo, String ip) {Map<String, String> paramMap = new LinkedHashMap<>(8);WXPay wxPay = new WXPay(payConfig);//入参 根据微信开放文档的接口入参规则填写即可paramMap.put("device_info", "WEB");//自定义参数,可以为终端设备号(门店号或收银设备ID),PC网页或公众号内支付可以传"WEB"paramMap.put("body", "华远科技");//商品名称paramMap.put("out_trade_no", outTradeNo);//微信支付订单号paramMap.put("total_fee", money);//支付金额paramMap.put("spbill_create_ip", ip);//支持IPV4和IPV6两种格式的IP地址。用户的客户端IPparamMap.put("notify_url", payConfig.getNotifyUrl());//支付成功回调路径paramMap.put("trade_type", "NATIVE");//支付方式  NATIVE扫码支付 paramMap.put("product_id", "000000000");//商品IDHashMap<String, String> result = new HashMap<>(2);try {Map<String, String> map = wxPay.unifiedOrder(paramMap);//return_code是通信标识,非交易标识,交易是否成功需要查看result_code来判断if ("SUCCESS".equals(map.get("return_code"))) {if ("SUCCESS".equals(map.get("result_code"))) {result.put("status", "success");result.put("msg", "请求成功");result.put("code_url", map.get("code_url"));result.put("prepay_id", map.get("prepay_id"));result.put("trade_type", map.get("trade_type"));result.put("money", money);result.put("out_trade_no", outTradeNo);return result;} else {result.put("status", "fail");result.put("msg", map.get("err_code_des"));return result;}} else {result.put("status", "fail");result.put("msg", map.get("return_msg"));return result;}} catch (Exception e) {e.printStackTrace();}result.put("status", "fail");result.put("msg", "未知异常");return result;}/*** 查询订单** @param outTradeNo 商户订单号* @return*/public Map<String, String> orderQuery(String outTradeNo) {Map<String, String> paramMap = new LinkedHashMap<>(1);WXPay wxPay = new WXPay(payConfig);paramMap.put("out_trade_no", outTradeNo);Map<String, String> result = new HashMap<>();try {Map<String, String> map = wxPay.orderQuery(paramMap);if ("SUCCESS".equals(map.get("return_code"))) {if ("SUCCESS".equals(map.get("result_code"))) {//result.put("status", "success");result.put("out_trade_no", map.get("out_trade_no")); //商户订单号switch (map.get("trade_state")) {case "SUCCESS":result.put("trade_type", map.get("trade_type")); //支付类型result.put("trade_state", map.get("trade_state")); //支付状态result.put("transaction_id", map.get("transaction_id")); //微信支付订单号result.put("total_fee", map.get("total_fee")); //支付金额result.put("time_end", map.get("time_end")); //支付完成时间result.put("msg", "支付成功");break;case "REFUND":result.put("msg", "转入退款");break;case "NOTPAY":map.put("msg", "未支付");break;case "CLOSED":map.put("msg", "已关闭");break;case "REVOKED":map.put("msg", "已撤销");break;case "USERPAYING":map.put("msg", "用户支付中");break;case "PAYERROR":map.put("msg", "支付失败");break;default:map.put("msg", "支付失败");break;}return result;} else {result.put("status", "fail");result.put("out_trade_no", map.get("out_trade_no")); //商户订单号result.put("msg", map.get("err_code_des"));return result;}} else {result.put("status", "fail");result.put("msg", map.get("return_msg"));return result;}} catch (Exception e) {e.printStackTrace();}result.put("status", "fail");result.put("msg", "未知异常");return result;}}

2.2.4 编写WxIpUtil 生成终端IP工具类

package com.hcloud.payutil;import java.net.InetAddress;
import java.net.UnknownHostException;import javax.servlet.http.HttpServletRequest;/** @className: IpUtil* @description 获取终端IP* @since JDK1.8* @author ljh* @createdAt  2020/8/30 0030* @version 1.0.0**/
public class WxIpUtil {public static String getIpAddr(HttpServletRequest request) {String ipAddress = null;try {ipAddress = request.getHeader("x-forwarded-for");if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getHeader("Proxy-Client-IP");}if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getHeader("WL-Proxy-Client-IP");}if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getRemoteAddr();if (ipAddress.equals("127.0.0.1")) {// 根据网卡取本机配置的IPInetAddress inet = null;try {inet = InetAddress.getLocalHost();} catch (UnknownHostException e) {e.printStackTrace();}ipAddress = inet.getHostAddress();}}// 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割if (ipAddress != null && ipAddress.length() > 15) { // "***.***.***.***".length()// = 15if (ipAddress.indexOf(",") > 0) {ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));}}} catch (Exception e) {ipAddress="";}// ipAddress = this.getRequest().getRemoteAddr();return "0:0:0:0:0:0:0:1".equals(ipAddress) ? "127.0.0.1" : ipAddress;}
}

2.2.5 编写PayController

package com.hcloud.paycontroller;import java.math.BigDecimal;
import java.util.Map;import javax.servlet.http.HttpServletRequest;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;import com.github.wxpay.sdk.WXPayUtil;
import com.hcloud.payservice.WxNativeService;
import com.hcloud.payutil.WxIpUtil;@Controller
@EnableEurekaClient
public class AliPayController {@Autowiredprivate WxNativeService nativeService;/*** 微信支付页面* @return*/public String WxPay(String total, Map<String, Object> paramMap) {paramMap.put("total", total);return "/Pay/WxPay";}/*** 调用微信接口生成二维码* @param request* @param money* @return*/@ResponseBody@RequestMapping("/Wxpay/createNative")public Map<String, String> createNative(HttpServletRequest request, String money) {return nativeService.unifiedOrder(money, WXPayUtil.generateNonceStr(), WxIpUtil.getIpAddr(request));}/*** 定时查询微信是否支付成功* @param outTradeNo* @return*/@ResponseBody@RequestMapping("/Wxpay/orderQuery")public Map<String, String> orderQuery(String outTradeNo) {int i=0;while (true) {Map<String, String> map = nativeService.orderQuery(outTradeNo);i++;if ("SUCCESS".equals(map.get("trade_state"))) {return map;}try {//因为这里是循环调用查询订单,所以如果前台超过5分钟没有支付 就会让刷新页面重新生成二维码Thread.sleep(3000);if (i>=100){System.out.println(i);map.put("status","fail");map.put("msg","二维码已超时");return map;}} catch (InterruptedException e) {e.printStackTrace();map.put("msg", "支付失败");return map;}}}/***  微信支付成功的回调* */@RequestMapping("/WxPay/fallback")public String WxFallback (HttpServletRequest request) {Map<String, String[]> parameterMap = request.getParameterMap();System.err.println(parameterMap);System.out.println("进入了微信回调");//写更改数据库的方法  逻辑return "/Pay/WxPayReturn";}}

2.3 前端代码编写

微信扫码页面

<!DOCTYPE html>
<html><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=9; IE=8; IE=7; IE=EDGE"><meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7"/><title>微信支付页</title><link rel="stylesheet" type="text/css" href="css/webbase.css"/><link rel="stylesheet" type="text/css" href="css/pages-weixinpay.css"/><!--引入jQuery和qrious相关类库--><script src="js/jquery.min.js"></script><script src="js/qrious.js"></script></head><body>
<!--head-->
<div><!--主内容--><div class="pay"><div class="checkout-tit"><h4 class="fl tit-txt"><span class="success-icon"></span><span class="success-info">订单提交成功,请您及时付款!订单号:<span id="out_trade_no"></span></span></h4><span class="fr"><em class="sui-lead">应付金额:</em><em class="orange money">¥</em><span id="money"></span>元</span><div class="clearfix"></div></div><div class="checkout-steps"><div class="fl weixin">微信支付</div><div class="fl sao"><p class="red"></p><div class="fl code"><img id="qrious"><div class="saosao"><p>请使用微信扫一扫</p><p>扫描二维码支付</p></div></div><div class="fl phone"></div></div></div></div></div><script type="text/javascript">//页面一加载就调用window.onload = function() {createNative()}/*统一下单接口调用*/function createNative() {$.ajax({type: 'get',url: 'http://localhost:8080/createNative',success: function(data) {console.log(data);$("#money").html((data.money / 100).toFixed(2))$("#out_trade_no").html(data.out_trade_no)/*调用后端统一下单接口根据返回的code_url 用qrious生成二维码*/var qr = new QRious({element: document.getElementById('qrious'),size: 250,level: 'H', //二维码容错级别 从小到大 : L M Q Hvalue: data.code_url});orderQuery(data.out_trade_no)}})}/*查询订单接口调用*/function orderQuery(out_trade_no) {$.ajax({type: 'get',url: 'http://localhost:8080/orderQuery?outTradeNo=' + out_trade_no,success: function(data) {console.log(data);//支付成功后跳转成功页面if (data.trade_state == "SUCCESS") {location.href = 'paysuccess.html?money=' + ((data.total_fee) / 100).toFixed(2)} else {if (data.msg == "二维码已超时") {console.log(data.msg);//二维码超时后重新生成二维码createNative();} else {//跳转失败页面location.href = 'payfail.html'}}}})}</script>
</body></html>

成功页面paysuccess.html

<!DOCTYPE html>
<html><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=9; IE=8; IE=7; IE=EDGE"><meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7"/><title>支付页-成功</title><link rel="stylesheet" type="text/css" href="css/webbase.css"/><link rel="stylesheet" type="text/css" href="css/pages-paysuccess.css"/><script src="js/jquery.min.js"></script></head><body>
<!--head--><div class="cart"><!--logoArea--><div class="logoArea"><div class="fl logo"><span class="title">支付页</span></div></div><!--主内容--><div class="paysuccess"><div class="success"><h3><img src="img/right.png" width="48" height="48"> 恭喜您,支付成功啦!</h3><div class="paydetail"><p>支付方式:微信支付</p><p>支付金额:¥<span id="money"></span>元</p><p class="button"><a href="myOrder.html" class="sui-btn btn-xlarge btn-danger">查看订单</a>&nbsp;&nbsp;&nbsp;&nbsp;<a href="index.html" class="sui-btn btn-xlarge ">继续购物</a></p></div></div></div>
</div>
</body>
<script>window.onload = function() {var money = getUrlParam("money");$("#money").html(money)}//解析跳转过来时url携带的参数function getUrlParam(name) {var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); //构造一个含有目标参数的正则表达式对象var r = window.location.search.substr(1).match(reg);  //匹配目标参数if (r != null) return unescape(r[2]);return null; //返回参数值}
</script>
</html>

支付失败页面payfail.html

<!DOCTYPE html>
<html><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=9; IE=8; IE=7; IE=EDGE"><meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" /><title>支付页-失败</title><link rel="stylesheet" type="text/css" href="css/webbase.css" /><link rel="stylesheet" type="text/css" href="css/pages-payfail.css" />
</head><body><!--head--><div class="cart"><!--logoArea--><div class="logoArea"><div class="fl logo"><span class="title">支付页</span></div></div><!--主内容--><div class="payfail"><div class="fail"><h3><img src="img/fail.png" width="48" height="48"> 支付失败,请稍后再试</h3><div class="fail-text"><p>失败原因:不能使用金币购买!</p><p class="button"><a href="" class="sui-btn btn-xlarge btn-danger">重新支付</a></p></div></div></div></div><!--页面底部END--></body></html>

成功啦

Java 微信native扫码支付 亲测有用相关推荐

  1. thinkphp3.2 微信 Native扫码支付功能

    Native 扫码支付之模式二 (模式一好像是不再支持了) 准备工作 认证过的服务号  商户号  业务域名 WxPay.Config.php 目录下面的这个文件记得要配置appid 这些 注意: 扫码 ...

  2. 【Java实战】微信Native扫码支付(主扫)开发详解

    文章目录 前言 一.功能实现 1.前置条件 2.代码实现 二.具体步骤 1.直接调用微信接口 2.基于binarywang对接 2.1.引入依赖 2.2.编写配置类 2.3.编写后台方法 总结 前言 ...

  3. 微信网页扫码支付(公众号)JAVA实现

    今天我们来说说微信网页扫码支付,这个支付的步骤和微信公众号网页是差不多的,也和微信小程序的步骤是一致的,不过appid是微信公众号的,我自己收集的微信开发文档希望对大家有用: https://blog ...

  4. ThinkPHP整合微信支付之Native 扫码支付 模式二

    大家好,这篇文章是继微信支付之Native 扫码支付 模式一之后的微信支付系列教程第三篇:扫码支付之模式二 介绍下扫码支付目前有两种模式,模式一比模式二稍微复杂点,至于模式一与模式二的具体内容,流程, ...

  5. ThinkPHP整合微信支付之Native 扫码支付 模式一

    大家好,这篇文章是继微信支付jsapi篇之后的微信支付系列教程第二篇:扫码支付之模式一 介绍下扫码支付目前有两种模式,模式一比模式二稍微复杂点,至于模式一与模式二的具体内容,流程,微信开发文档都有详细 ...

  6. Win10环境前后端分离项目基于Vue.js+Django+Python3实现微信(wechat)扫码支付流程(2021年最新攻略)

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_182 之前的一篇文章:mpvue1.0+python3.7+Django2.0.4实现微信小程序的支付功能,主要介绍了微信小程序内 ...

  7. Win10环境前后端分离项目基于Vue.js+Tornado+Python3实现微信(wechat)扫码支付流程

    在生活具有广泛性.高效性.使用方便性的支付方式是扫码支付,扫码的优点在于推广成本低,上至钓鱼台国宾馆,下至发廊地摊都能用,打印出来就完事了,而相比其他支付方式,现金的找零及假钞问题,信用卡的办理门槛. ...

  8. 关于微信PC扫码支付

    关于微信PC扫码支付 扫码支付 有两种模式 官网有说  这里采用简单明白的模式2 前期准备  1 需要公众号 开通了微信支付权限 2 需要微信支付商户平台账号 服务器生成订单号 发送请求 https: ...

  9. 微信支付宝扫码支付聚合系统

    一.简介 微信支付宝扫码支付聚合系统,聚合了微信支付和支付宝的所有扫码支付模式.并支持微信支付服务商子商户模式.支持五种扫码技术. 二.主要功能 1. 微信扫码支付:包括扫码支付模式一.扫码支付模式二 ...

最新文章

  1. 看完微软大神写的求平均值代码,我意识到自己还是too young了
  2. jtessboxeditorfx 界面显示不出来_鞋友疑问:奥莱的AJ1本来有完整盒子,为什么不愿意给我?...
  3. MATLAB 获取某个文件夹下所有文件夹或者文件的名字
  4. P2324 骑士精神
  5. .NET 排序 Array.SortT 实现分析
  6. mysql 全文本检索的列_排序数据列以检索MySQL中的最大文本值
  7. TensorFlow Hub介绍:TensorFlow中可重用的机器学习模块库
  8. Memcache图形化管理工具MemAdmin
  9. 前端,后端,全栈哪个好找工作?
  10. [转载] .NET 中可以有类似 JVM 的幻像引用吗?
  11. 工业机器人技术基础及其应用总结
  12. 常用DB9 232接口定义
  13. 【EmmyLua插件】Rider无法跳转lua文件解决
  14. 抖音短视频APP——市场需求文档
  15. (瑞萨,norti系统,partner-jet2) 实时系统下DMAC使用的注意事项
  16. 绕流运动与附面层基本概念
  17. mysql 备份 发送邮件_mysql 自动备份发邮件 到指定邮箱
  18. 2020年起重机司机(限桥式起重机)考试及起重机司机(限桥式起重机)答案解析
  19. 通用课程表教师表php,利用Access实现学校课程表的科学管理
  20. reverse()的使用

热门文章

  1. SUSE Linux安全大揭秘之“十诫”
  2. Kubernetes Autoscaling是如何工作的?
  3. 【科普】优质变色镜片的选择
  4. 夸父可以追上“光”吗?
  5. 算法题--讨厌的青蛙
  6. 怎样将cad布局导出来_请问 CAD布局里面的图 怎么复制出来
  7. 如何实现人员基础信息一体化采集系统建设_修订1
  8. linux 图标显示 异常,在Ubuntu 18.04系统中VSCode图标显示异常的解决方法
  9. 北邮通信原理公开课 杨鸿文老师 课程学习笔记【第五课 许瓦兹不等式】
  10. php, ZF2 框架有表单创建工具