目录
- 微信支付
- 二维码
- 概述
- QRCode使用
- 微信支付
- 介绍
- 申请步骤
- 结算支付
- 在pay.html页面当中添加vue相关JS
- 页面加载完毕后,获取支付信息
- 支付接口
- web_portal/PayController
- 二维码
微信支付
二维码
概述
二维码又称QR Code,QR全称Quick Response,是一个近几年来移动设备上超流行的一种编码方式,它比传统的Bar Code条形码能存更多的信息,也能表示更多的数据类型。
二维条码/二维码(2-dimensional bar code)是用某种特定的几何图形按一定规律在平面(二维方向上)分布的黑白相间的图形记录数据符号信息的;在代码编制上巧妙地利用构成计算机内部逻辑基础的“0”、“1”比特流的概念,使用若干个与二进制相对应的几何形体来表示文字数值信息,通过图象输入设备或光电扫描设备自动识读以实现信息自动处理:它具有条码技术的一些共性:每种码制有其特定的字符集;每个字符占有一定的宽度;具有一定的校验功能等。同时还具有对不同行的信息自动识别功能、及处理图形旋转变化点。
QRCode使用
下载QRCode.js
使用
var qrcode = new QRCode(document.getElementById("qrcode"), {
width : 250,
height : 250
});
qrcode.makeCode(response.data.code_url);
微信支付
介绍
微信扫码支付是商户系统按微信支付协议生成支付二维码,用户再用微信“扫一扫”完成支付的模式。该模式适用于PC网站支付、实体店单品或订单支付、媒体广告支付等场景。
申请步骤
1.注册公众号(服务号-企业才能注册)
2.认证公众号(认证费300元/年)
3.提交资料申请微信支付
4.开户成功,登录商户平台进行验证
公众号/与商户号支付信息获取
- appid
- mch_id
- partnerkey
5.启用Native
微信支付API
支付流程
添加pom依赖
com.github.wxpay
wxpay-sdk
0.0.3
WXPayUtil
获取随机字符串
WXPayUtil.generateNonceStr()
MAP转换为XML字符串(自动添加签名)
WXPayUtil.generateSignedXml(param, partnerkey)
XML字符串转换为MAP
WXPayUtil.xmlToMap(result)
结算支付
在pay.html页面当中添加vue相关JS
页面加载完毕后,获取支付信息
定义属性
new Vue({
el:"#app",
data:{
money:0, //支付金额
out_trade_no:'' //支付订单号
},
createNative: function () {
let _this = this;
axios.post("/pay/createNative.do")
.then(function (response) {
//显示订单号和金额
_this.money= (response.data.total_fee/100).toFixed(2);
_this.out_trade_no=response.data.out_trade_no;
console.log(response.data);
var qrcode = new QRCode(document.getElementById("qrcode"), {
width : 250,
height : 250
});
qrcode.makeCode(response.data.code_url);
_this.queryPayStatus();//调用查询支付结果
}).catch(function (reason) {
console.log(reason);
});
},
queryPayStatus:function(){
let _this = this;
axios.get('/pay/queryPayStatus.do?out_trade_no='+_this.out_trade_no)
.then(function (response) {
if(response.data.success){
location.href="paysuccess.html#?money="+_this.money;
}else{
if(response.data.message=='二维码超时'){
this.createNative();//重新生成二维码
}else{
location.href="payfail.html";
}
}
}).catch(function (reason) {
console.log(reason);
});
}
});
支付接口
interface/PayService
public interface PayService {
/**
* 获取支付信息
* @param outTradeNo 订单号
* @param totalFee 支付金额
* @return 支付信息
*/
public Map createNative(String outTradeNo, String totalFee);
/**
* 根据订单号, 查询支付状态
* @param out_trade_no
* @return
*/
public Map queryPayStatus(String out_trade_no);
}
service_buyer/PayServiceImpl
在properties/weixinpay.properties添加支付商户信息
appid=
partner=
partnerkey=
notifyurl=
加载商户信息
@Service
public class PayServiceImpl implements PayService {
//微信公众账号或开放平台APP的唯一标识
@Value("${appid}")
private String appid;
//财付通平台的商户账号
@Value("${partner}")
private String partner;
//财付通平台的商户密钥
@Value("${partnerkey}")
private String partnerkey;
//回调地址
@Value("${notifyurl}")
private String notifyurl;
}
获取微信支付信息
@Override
public Map createNative(String outTradeNo, String totalFee) {
//1.创建参数
Map param=new HashMap();//创建参数
param.put("appid", appid);//公众号
param.put("mch_id", partner);//商户号
param.put("body", "myxq");//商品描述
param.put("nonce_str", WXPayUtil.generateNonceStr());//随机字符串
param.put("out_trade_no", outTradeNo);//商户订单号
param.put("total_fee",totalFee);//总金额(分)
param.put("spbill_create_ip", "127.0.0.1");//IP
param.put("notify_url", "http://www.baidu.com");//回调地址(随便写)
param.put("trade_type", "NATIVE");//交易类型
try {
//2.生成要发送的xml , 调用微信sdk的api接口将封装的map数据自动转换成xml格式字符串
String xmlParam = WXPayUtil.generateSignedXml(param, partnerkey);
System.out.println(xmlParam);
HttpClient client=new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
client.setHttps(true);
client.setXmlParam(xmlParam);
client.post();
//3.获得结果
String result = client.getContent();
System.out.println(result);
//调用微信sdk的api接口将xml格式字符串自动转换成Java对象
Map resultMap = WXPayUtil.xmlToMap(result);
Map map=new HashMap<>();
map.put("code_url", resultMap.get("code_url"));//支付地址
map.put("total_fee", totalFee);//总金额
map.put("out_trade_no",outTradeNo);//订单号
return map;
} catch (Exception e) {
e.printStackTrace();
return new HashMap<>();
}
}
查询支付状态
@Override
public Map queryPayStatus(String out_trade_no) {
Map param=new HashMap();
param.put("appid", appid);//公众账号ID
param.put("mch_id", partner);//商户号
param.put("out_trade_no", out_trade_no);//订单号
param.put("nonce_str", WXPayUtil.generateNonceStr());//随机字符串
String url="https://api.mch.weixin.qq.com/pay/orderquery";
try {
String xmlParam = WXPayUtil.generateSignedXml(param, partnerkey);
HttpClient client=new HttpClient(url);
client.setHttps(true);
client.setXmlParam(xmlParam);
client.post();
String result = client.getContent();
Map map = WXPayUtil.xmlToMap(result);
System.out.println(map);
return map;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
web_portal/PayController
支付接口
@RestController
@RequestMapping("/pay")
public class PayController {
@Reference
private OrderService orderService;
@Reference
private PayService payService;
/**
* 支付信息接口
* 获取当前登录用户名,
* 根据用户名获取redis中的支付日志对象,
* 根据支付日志对象中的支付单号和总金额
* 调用微信统一下单接口, 生成支付链接返回
* @return
*/
@RequestMapping("/createNative")
public Map createNative() {
//1. 获取当前登录用户的用户名
String userName = SecurityContextHolder.getContext().getAuthentication().getName();
//2. 根据用户名获取支付日志对象
PayLog payLog = orderService.getPayLogByUserName(userName);
if (payLog != null) {
//3. 调用统一下单接口生成支付链接
Map map = payService.createNative(payLog.getOutTradeNo(), "1");
return map;
}
return new HashMap();
}
/**
* 支付状态查询接口
* 调用查询订单接口, 查询是否支付成功
* @param out_trade_no
* @return
*/
@RequestMapping("/queryPayStatus")
public Result queryPayStatus(String out_trade_no) {
String userName = SecurityContextHolder.getContext().getAuthentication().getName();
Result result = null;
int flag = 1;
while(true) {
//1. 判断支付单号等于null
if (out_trade_no == null) {
result = new Result(false, "二维码超时");
break;
}
//2. 调用查询接口查询支付是否成功
Map map = payService.queryPayStatus(out_trade_no);
if ("SUCCESS".equals(map.get("trade_state"))) {
result = new Result(true, "支付成功!");
//3. 如果支付成功, 支付日志表和订单表的支付状态改为已支付, redis的支付日志对象删除
orderService.updatePayStatus(userName);
break;
}
try {
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
//如果5分钟没有支付则支付超时
if (flag > 100) {
result = new Result(false, "二维码超时");
break;
}
flag++;
}
return result;
}
}