概述

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

详细

一、相关配置

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. BZOJ 4443: [Scoi2015]小凸玩矩阵 最大流

    4443: [Scoi2015]小凸玩矩阵 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=4443 Description 小凸和小方是好 ...

  2. HTML5 book响应式翻页效果

    翻页,HTML5源码下载,HTML5响应式翻页效果,鼠标移到右上角会看到翻页效果,需要鼠标拖动后翻页,支持ie9+,html5浏览器. 单页和双页. 自动播放和暂停. 点击左右翻页. 鼠标点击左右页面 ...

  3. UVA 11205 The broken pedometer(子集枚举)

    B - The broken pedometer Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu ...

  4. Added components improve switching-regulator stability

    Added components improve switching-regulator stability

  5. Delphi DLL制作和加载 Static, Dynamic, Delayed 以及 Shared-Memory Manager

    一 Dll的制作一般分为以下几步:1 在一个DLL工程里写一个过程或函数2 写一个Exports关键字,在其下写过程的名称.不用写参数和调用后缀.二 参数传递1 参数类型最好与window C++的参 ...

  6. 任务驱动,Winform VS WEB对比式学习.NET开发系列第一篇------身份证解析(不断更新的WEB版本及Winform版本源码)

    一 本系列培训随笔适用人群 1. 软件开发初学者 2. 有志于转向Web开发的Winform程序员 3. 想了解桌面应用开发的Web程序员 二 高效学习编程的办法 1 任务驱动方式学习软件开发 大部分 ...

  7. Eclipse 中导入jar包

    导入到工程即可使用了1. 在程序目录下,创建一个文件夹,如 lib. 2. 将第三方jar包复制到该目录下3.右键工程,选择Build path4.java build path,选择 librari ...

  8. matlab画直线,指定斜率与x坐标范围

    闲话不说,直接上代码与图的效果!

  9. Run Redis On Windows

    If you go to the current version and open up the bin > release folder, you'll get a ZIP file cont ...

  10. 7.volatile关键字

    volatile:一个线程修改了某一个共享变量的值,其他线程也是否能够立即知道这个修改的 1.主要是让该“变量”在多个线程中可见,在java中每一个线程都有一块自己的工作区,其中就存放着所有线程“共享 ...