概述

场景介绍 用户使用微信“扫一扫”扫描二维码后,获取商品支付信息,引导用户完成支付。

详细

一、相关配置

Demo上都有官网的默认值,不需要修改直接使用

支付扫描模式二,流程图

https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5

SDK与DEMO下载

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

二、目录结构

三、准备工作

(1)设置热部署

作为程序员都知道,每次修改后台代码都要重启项目,工作效率非常慢,所以我们要加快效率。

pom.xml

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
</configuration>
</plugin>
</plugins>
</build>

application.properties

#禁止thymeleaf缓存(建议:开发环境设置为false,生成环境设置为true)
spring.thymeleaf.cache=false

开发工具是:idea

设置以下两项(第一项如已设置直接设置第二项)

  1) “File” -> “Settings” -> “Build,Execution,Deplyment” -> “Compiler”,选中打勾 “Build project automatically” 。

  2) 组合键:“Shift+Ctrl+Alt+/” ,选择 “Registry” ,选中打勾 “compiler.automake.allow.when.app.running”

相关链接:

https://www.cnblogs.com/jiangbei/p/8439394.html

https://blog.csdn.net/weixin_42884584/article/details/81561987

(2)内网穿透工具

让外网能直接访问,你本地的服务,场景用于,接口调试,支付方面等等。

为了大家找了一个,免费配置简单的。绝对不是卖广告,之前用过花生壳,麻烦到要死坑哇~,现在的所有穿透都要身份证登记,很正常国家出了对应的法规。

下载地址:https://natapp.cn/#download

配置和使用说明:https://blog.csdn.net/kingrome2017/article/details/77989442

四、功能讲解

(1)访问首页

打开WxPayController.java

/**
* 二维码首页
*/
@RequestMapping(value = {"/"}, method = RequestMethod.GET)
public String wxPayList(Model model){
//商户订单号
model.addAttribute("outTradeNo",WxUtil.mchOrderNo());
return "/wxPayList";
}

我们和穿透工具连在一起使用

SpringBoot 默认端口号为:8080,穿透工具映射端口设置为:8080

双击,natapp.exe 执行

127.0.0:8080 <=> http://9xnrh8.natappfree.cc

修改,application.properties

(划重点,支付成功后回调本地服务,修改后记得重启服务)

#统一下单-通知链接
wx.unifiedorder.notifyUrl=http://9xnrh8.natappfree.cc/wxPay/unifiedorderNotify

(2)生成二维码

从页面看到,有订单流水号和支付金额,0.01 代表一分钱。支付金额可以修改的,点击'生成二维码'按钮,然后把订单流水号和支付金额传到后台。

控制类:

final private String signType = WxConstants.SING_MD5;
/**
* 统一下单-生成二维码
*/
@RequestMapping(value = {"/wxPay/payUrl"})
public void payUrl(HttpServletRequest request, HttpServletResponse response,
@RequestParam(value = "totalFee")Double totalFee,
@RequestParam(value = "outTradeNo")String outTradeNo) throws Exception{
WxUtil.writerPayImage(response,wxMenuService.wxPayUrl(totalFee,outTradeNo,signType));
}

实现类:

@Override
public String wxPayUrl(Double totalFee,String outTradeNo,String signType) throws Exception {
HashMap<String, String> data = new HashMap<String, String>();
//公众账号ID
data.put("appid", WxConfig.appID);
//商户号
data.put("mch_id", WxConfig.mchID);
//随机字符串
data.put("nonce_str", WxUtil.getNonceStr());
//商品描述
data.put("body","测试支付");
//商户订单号
data.put("out_trade_no",outTradeNo);
//标价币种
data.put("fee_type","CNY");
//标价金额
data.put("total_fee",String.valueOf(Math.round(totalFee * 100)));
//用户的IP
data.put("spbill_create_ip","123.12.12.123");
//通知地址
data.put("notify_url",WxConfig.unifiedorderNotifyUrl);
//交易类型
data.put("trade_type","NATIVE");
//签名类型
data.put("sign_type",signType);
//签名
data.put("sign",WxUtil.getSignature(data, WxConfig.key,signType)); String requestXML = WxUtil.mapToXml(data);
String reponseString = HttpsClient.httpsRequestReturnString(WxConstants.PAY_UNIFIEDORDER,HttpsClient.METHOD_POST,requestXML);
Map<String,String> resultMap = WxUtil.processResponseXml(reponseString,signType);
if(resultMap.get(WxConstants.RETURN_CODE).equals("SUCCESS")){
return resultMap.get("code_url");
}
return null;
}

最终返回一个,二维码链接 → 转成二维码图片

/**
* 生成支付二维码
* @param response 响应
* @param contents url链接
* @throws Exception
*/
public static void writerPayImage(HttpServletResponse response, String contents) throws Exception{
ServletOutputStream out = response.getOutputStream();
try {
Map<EncodeHintType,Object> hints = new HashMap<EncodeHintType,Object>();
hints.put(EncodeHintType.CHARACTER_SET,"UTF-8");
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
hints.put(EncodeHintType.MARGIN, 0);
BitMatrix bitMatrix = new MultiFormatWriter().encode(contents, BarcodeFormat.QR_CODE,300,300,hints);
MatrixToImageWriter.writeToStream(bitMatrix,"jpg",out);
}catch (Exception e){
throw new Exception("生成二维码失败!");
}finally {
if(out != null){
out.flush();
out.close();
}
}
}

下面的请求是定时器,检查是否已支付,本来我想用socket。

(3)支付

(4)支付完毕

(5)回调接口

收到微信支付结果通知后,请严格按照示例返回参数给微信支付

/**
* 统一下单-通知链接
*/
@RequestMapping(value = {"/wxPay/unifiedorderNotify"})
public void unifiedorderNotify(HttpServletRequest request, HttpServletResponse response) throws Exception{ //商户订单号
String outTradeNo = null;
String xmlContent = "<xml>" +
"<return_code><![CDATA[FAIL]]></return_code>" +
"<return_msg><![CDATA[签名失败]]></return_msg>" +
"</xml>"; try{
String requstXml = WxUtil.getStreamString(request.getInputStream());
System.out.println("requstXml : " + requstXml);
Map<String,String> map = WxUtil.xmlToMap(requstXml);
String returnCode= map.get(WxConstants.RETURN_CODE);
//校验一下
if(StringUtils.isNotBlank(returnCode) && StringUtils.equals(returnCode,"SUCCESS") && WxUtil.isSignatureValid(map, WxConfig.key,signType)){
//商户订单号
outTradeNo = map.get("out_trade_no");
System.out.println("outTradeNo : "+ outTradeNo);
//微信支付订单号
String transactionId = map.get("transaction_id");
System.out.println("transactionId : "+ transactionId);
//支付完成时间
SimpleDateFormat payFormat= new SimpleDateFormat("yyyyMMddHHmmss");
Date payDate = payFormat.parse(map.get("time_end")); SimpleDateFormat systemFormat= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("支付时间:" + systemFormat.format(payDate));
//临时缓存
WxConfig.setPayMap(outTradeNo,"SUCCESS");
xmlContent = "<xml>" +
"<return_code><![CDATA[SUCCESS]]></return_code>" +
"<return_msg><![CDATA[OK]]></return_msg>" +
"</xml>";
}
}catch (Exception e){
e.printStackTrace();
}
WxUtil.responsePrint(response,xmlContent);
}

更多的信息,请看官网

官网相关链接:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_7&index=8

(6)微信支付,关于XML解析存在的安全问题指引

代码已修改

更多的信息,请看官网

官网相关链接:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=23_5

(7)前端页面

<html>
<head >
<title>微信支付二维码生产</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script type="text/javascript" src="/js/jquery/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="/js/jquery/jquery.timers-1.2.js"></script>
<script type='text/javascript'> $(function () {
getOutTradeNo(); }); //生成二维码
function save(){
var outTradeNo = $("#outTradeNo").val();
$("#payImg").attr("src",'/wxPay/payUrl'+"?totalFee="+ $("#totalFee").val()+"&outTradeNo=" + outTradeNo); $('body').everyTime('2s','payStatusTimer',function(){
$.ajax({
type : "POST",
url : '/wxPay/payStatus?outTradeNo='+ outTradeNo +"&random=" + new Date().getTime(),
contentType:"application/json",
dataType : "json",
async : "false",
success : function(json) {
if(json != null && json.status == 0){
alert("支付成功!");
$('body').stopTime ('payStatusTimer');
return false;
}
},
error:function(XMLHttpRequest,textStatus,errorThrown){
alert("服务器错误!状态码:"+json.status);
// 状态
console.log(json.readyState);
// 错误信息
console.log(json.statusText);
return false;
}
})
}); } //获取流水号
function getOutTradeNo(){
$.ajax({
type : "POST",
url : '/wxPay/outTradeNo',
success : function(json) {
if(json != null){
$("h3").html(json);
$("#outTradeNo").val(json);
}else{
alert("获取流水号失败!");
}
return false;
},
error:function(XMLHttpRequest,textStatus,errorThrown){
alert("服务器错误!状态码:"+XMLHttpRequest.status);
// 状态
console.log(XMLHttpRequest.readyState);
// 错误信息
console.log(textStatus);
return false;
}
});
} </script>
</head>
<body>
<p>订单流水号:<h3></h3></p>
支付金额:<input id="totalFee" type="text" value="0.01"/>
<button type="button" onclick="save();">生成二维码</button>
<input id="outTradeNo" type="hidden" value="${outTradeNo}"/>
&nbsp;&nbsp;<img id="payImg" width="300" height="300" > </body>
</html>

启动一个定时器,每个2秒去扫描是否已经支付~

因为相关配置,我是从官网下载的,所以支付后还有退款功能(退款要等很多天,请耐心等待),是不是很神奇~

还有微信登录,自定义微信公众号菜单创建-修改-删除功能(前台-数据库保存),微信公众号接受、回复信息Demo

但是,没有官网例子直接运行的,很多地方不能截图,后面我想想怎么做吧~

谢谢大家观看~

注:本文著作权归作者,由demo大师发表,拒绝转载,转载需要作者授权

Java微信扫描支付模式二Demo ,整合官网直接运行版本的更多相关文章

  1. PHP微信支付开发之扫描支付(模式二)后如何回调

    其实在写这篇文章的时候感觉自己已经落伍了,不过笔者在百度上搜索"微信支付开发之扫描支付(模式二)后如何回调"寻找答案时,发现依旧有很多朋友没有解决这个问题,所以就把自己的解决思路分 ...

  2. 微信公众号 扫码支付 模式二 demo

    扫码支付 本文附有代码,在下方,如果不熟悉场景的可以看看下面的场景介绍 场景介绍 官网介绍地址:https://pay.weixin.qq.com/wiki/doc/api/native.php?ch ...

  3. thinkphp5.0 微信扫码支付模式二

    仅供个人参考,方便大家. 一.1)https://pay.weixin.qq.com/index.php/core/home/login  复制此地址 打开微信商户平台. 2)下载安全操作证书(最好在 ...

  4. JAVA微信扫码支付模式二功能实现完整例子

    概述 本例子实现微信扫码支付模式二的支付功能,应用场景是,web网站微信扫码支付.实现从点击付费按钮.到弹出二维码.到用户用手机微信扫码支付.到手机上用户付费成功.web网页再自动调整到支付成功后的页 ...

  5. Java之微信支付(扫码支付模式二)案例实战

    摘要:最近的一个项目中涉及到了支付业务,其中用到了微信支付和支付宝支付,在做的过程中也遇到些问题,所以现在总结梳理一下,分享给有需要的人,也为自己以后回顾留个思路. 一:微信支付接入准备工作: 首先, ...

  6. (用微信扫的静态链接二维码)微信native支付模式官方提供的demo文件中的几个bug修正

    native支付模式一demo(用微信扫的静态链接二维码)BUG修复,一共4个BUG 1.native_call_qrcode.php这个文件中的代码无法生存native支付的短地址2.WxPayPu ...

  7. 微信支付Native扫码支付模式二之CodeIgniter集成篇

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

  8. .NET微信扫码支付模式二API接口开发测试

    主要实现微信扫码支付,官网的SDKdemo 就不要使用 一直不能调试通过的,还是自己按照API接口文档一步一步来实现,吐槽下微信一点责任感都木有,能不能demo搞个正常的吗,不要坑惨了一大群码农们有点 ...

  9. 【weixin】微信支付---Native支付模式二(PC端支付大多采用此模式)

    [模式二]:商户后台系统调用微信支付[统一下单API]生成预付交易,将接口返回的链接生成二维码,用户扫码后输入密码完成支付交易.注意:该模式的预付单有效期为2小时,过期后无法支付 模式二与模式一相比, ...

随机推荐

  1. Jeeplus框架中问题解决

    1,文件上传后图片显示的问题 (1)问题:在这个组件的文档介绍里面写了这个组件是有预览功能的,但是我没有找到,就自己写了这个小功能. 在框架中下图中,这个文件上传组件只能将文件上传,然后将文件名显示出 ...

  2. asp.net 去除数据中带有的html标签

    1,在控制器中实现去除html标签的静态方法 //去除html标签 public static string ReplaceHtmlMark(object Contents) { string Htm ...

  3. PAT甲级1003. Emergency

    PAT甲级1003. Emergency 题意: 作为一个城市的紧急救援队长,你将得到一个你所在国家的特别地图.该地图显示了几条分散的城市,连接着一些道路.每个城市的救援队数量和任何一对城市之间的每条 ...

  4. 如何使用DotNet 2.0中的应用程序配置 Settings.settings

    对于桌面应用程序,常常会需要记录一些用户配置信息,早期的做法一般是使用读写INI文件的办法.    对于.NET应用程序,并没有提供直接操作INI文件的类,需要调用Win32API,具体办法可以参考: ...

  5. OC利用正则表达式获取网络资源(网络爬虫)

    在开发项目的过程,很多情况下我们需要利用互联网上的一些数据,在这种情况下,我们可能要写一个爬虫来爬我们所需要的数据.一般情况下都是利用正则表达式来匹配Html,获取我们所需要的数据.一般情况下分以下三 ...

  6. java多线程知识汇总(三)如何选择锁?如何加锁

    1.锁,保证的是被锁的代码,一次执行完毕才能被其他线程执行,锁保证了一个线程执行过程中不被其他线程打断.以保证数据的准确性. 2.数据的读写过程,是有冲突的,当一个线程正在读数据,另一个线程正在写同一 ...

  7. ODS与数据仓库

    数据仓库是目前主要的数据存储体系.数据仓库之增W.H.Inmon认为,数据仓库是指支持管理决策过程的.面向主题的.集成的.随时间而变的.持久的数据的集合.简单地说,一个数据仓库就一个自数据库的商业应用 ...

  8. 《.NET最佳实践》

    <.NET最佳实践> 基本信息 原书名:Pro .NET Best Practices 原出版社: Apress 作者: (美)Stephen Ritchie 译者: 黄灯桥 黄浩宇 李永 ...

  9. MySQL year函数

    mysql的日期函数,示例如下:

  10. Tomcat中JVM参数设置

    Tomcat本身不能直接在计算机上运行,需要依赖于硬件基础之上的操作系统和一个Java虚拟机.Tomcat的内存溢出本质就是JVM内存溢出,所以在本文开始时,应该先对JavaJVM有关内存方面的知识进 ...