1、微信支付之Native支付
关于如何开通微信支付大家可以直接去【微信支付】官网查阅。这里我们直接进入正题。
1.1 Native支付场景(以电商网站为例)
1.2 支付场景示例图
1.3 核心代码
1.3.1 统一下单封装后的方法
public static WeixinPayResult createNative(String callbackUrl, String app_id, String mch_id, String api_key, String out_trade_no, Integer total_fee, String body) {
//1.参数封装
Map param = new HashMap();
param.put("appid", app_id);//公众账号ID
param.put("mch_id", mch_id);//商户
param.put("nonce_str", WXPayUtil.generateNonceStr());//随机字符串
param.put("body", body);
param.put("out_trade_no", out_trade_no);//交易订单号(是由系统内部来生成)
param.put("total_fee", total_fee.toString());//金额(分)
param.put("spbill_create_ip", "127.0.0.1");//支付客户端的IP地址(这里没做记录)
param.put("notify_url", callbackUrl);
param.put("trade_type", "NATIVE");//交易类型
try {
//根据appkey来生成签名,并同时将参数进行转换为xml格式
String xmlParam = WXPayUtil.generateSignedXml(param, api_key);
//2.发送请求(按照官方接口要求,将数据以post请求方式发送)
HttpClient httpClient = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
httpClient.setHttps(true);//以https的协议发送请求
httpClient.setXmlParam(xmlParam);//设置post请求的参数列表
httpClient.post();
//3.获取结果
String xmlResult = httpClient.getContent();
Map<String, String> mapResult = WXPayUtil.xmlToMap(xmlResult);
//将返回的结果转换为对象
WeixinPayResult weixinPayResult = new WeixinPayResult();
//防止进行bean复制时,日期为null时报错
ConvertUtils.register(new DateConverter(null), Date.class);
BeanUtils.copyProperties(weixinPayResult, mapResult);
//注意:付款订单编号是后台动态生成,必须要手动添加到返回结果中 勿忘,切记!!!
weixinPayResult.setOut_trade_no(out_trade_no);
return weixinPayResult;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
- 封装统一下单涉及到的工具类
WXPayUtil.java
代码需要导入微信支付开发的pom坐标
<!-- 微信支付所需的依赖包-->
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>0.0.3</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.10</version>
</dependency>
1.3.2 根据订单号查询订单状态
public static WeixinPayResult queryPayStatus(String app_id, String mch_id, String api_key, String out_trade_no) {
Map resultMap = new HashMap();
//1.封装参数
Map param = new HashMap();
param.put("appid", app_id);//appid
param.put("mch_id", mch_id);//商户ID
param.put("out_trade_no", out_trade_no);//要查询的订单号(自己系统所生成订单号)
param.put("nonce_str", WXPayUtil.generateNonceStr());
try {
String xmlParam = WXPayUtil.generateSignedXml(param, api_key);
//2.发送请求
HttpClient httpClient = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");
httpClient.setHttps(true);
httpClient.setXmlParam(xmlParam);
httpClient.post();
//3.获取结果
String xmlResult = httpClient.getContent();
Map<String, String> mapResult = WXPayUtil.xmlToMap(xmlResult);
//封装结果数据
WeixinPayResult weixinPayResult = new WeixinPayResult();
//防止进行bean复制时,日期为null时报错
ConvertUtils.register(new DateConverter(null), Date.class);
BeanUtils.copyProperties(weixinPayResult, mapResult);
return weixinPayResult;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
1.3.3 关于生成付款码时的回调方法应用(重点!重点!重点!)
相信很多新手在使用【微信支付】接口时,都会选择在前端设置定时器来间隔查询,如果查询到订单状态为【支付成功】再走生成订单的流程。如这种方法的操作是非常错误的,而且还有非常多的安全隐患。
- 正确处理查看支付成功并处理后续业务的流程如下:
你没看错,流程图也没画错。其实正确的付款支付接口时,生成的付款码和查询订单支付状态是两个完全独立的操作。
- 前端在调用[统一下单]接口并生成【付款码】后,这步操作就结束
- 当用户扫码后,无论付款成功还是失败,只要完成这个扫码操作,就会调用【统一下单】接口中所配置的callback回调url。
- 这种实现方式优点:
- 支持离线支付(复制付款码后,可以关闭当前付款页面,只要扫码成功支付,购买成功业务都会执行)
- 支持代付(用户可以把付款码截图发给其他人代付)
- 安全性高
1.3.4 附加回调的方法
防止有些朋友不知道回调方法怎么写,这里也贴出回调方法的实现
- 如果你在调用【统一下单】封装方法,传入的callback参数值为
callbackUrl: http://你服务器的回调方法根路径/callbackpay
那么就应该在你当前工程的方法中,添加一个回调方法的实现
/**
* 微信支付成功后的回调函数
*/
@RequestMapping("/callbackpay")
public Result callbackPay(HttpServletRequest request) {
StringBuffer sb = new StringBuffer();
try {
List<String> readLines = IOUtils.readLines(request.getInputStream(), "utf-8");
for (String readLine : readLines) {
sb.append(readLine);
}
Map<String, String> mapResult = WXPayUtil.xmlToMap(sb.toString());
//防止进行bean复制时,日期为null时报错
ConvertUtils.register(new DateConverter(null), Date.class);
WeixinPayResult weixinPayResult = new WeixinPayResult();
BeanUtils.copyProperties(weixinPayResult, mapResult);
return weixinPayService.callbackPay(weixinPayResult);//这行代码是调用业务层的付款成功后的处理逻辑
} catch (Exception e) {
e.printStackTrace();
return new Result(false, "服务器异常");
}
}
注意:最后提醒一下,上面这个回调方法的url,一定要记得在你的权限框架中放行。
下一章会介绍【微信支付----- 微信红包和企业付款到微信用户零钱】