java-springboot微信扫码(Native方式二)支付以及支付回调
官方API文档https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_51.使用jar包<!--微信支付--><dependency><groupId>com.github.wxpay</groupId><artifactId>wxpay-sdk</artifactId
文章共7,347字 · 阅读需要大约25分钟
一键AI生成摘要,助你高效阅读
问答
·
1.使用到的jar包
<!--微信支付 -->
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>3.0.9</version>
</dependency>
<!--httpclient-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
2.ServiceImpl中写统一下单接口
public Map createNative(String out_trade_no, String total_fee) {
// TODO 自动生成的方法存根
Map<String,String> param=new HashMap<>();
param.put("appid", appid); //小程序id
param.put("mch_id", partner);//商户号
param.put("nonce_str", WXPayUtil.generateNonceStr());//随机字符串
param.put("body", "测试数据");//商品描述
param.put("out_trade_no", out_trade_no);//商户订单号
param.put("total_fee",total_fee);//总金额(分)
param.put("spbill_create_ip", "127.0.0.1");//IP
param.put("notify_url", notifyurl);//回调地址
param.put("trade_type", "NATIVE");//交易类型
param.put("product_id",out_trade_no);//订单
try {
//2.生成要发送的xml
//partnerkey 商户秘钥
String xmlParam = WXPayUtil.generateSignedXml(param, partnerkey);
HttpClientM client = new HttpClientM("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);
Map<String, String> resultMap = WXPayUtil.xmlToMap(result);
Map<String, String> map=new HashMap<>();
map.put("code_url", resultMap.get("code_url"));//二维码支付地址
map.put("total_fee", total_fee);//总金额
map.put("out_trade_no",out_trade_no);//订单号
return map;
} catch (Exception e) {
e.printStackTrace();
return new HashMap<>();
}
}
上面用到的HttpClientM类
package com.pj.project.wxpay;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.ParseException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.net.ssl.SSLContext;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
/**
* http请求客户端
*
* @author ren
*
*/
public class HttpClientM {
private String url;
private Map<String, String> param;
private int statusCode;
private String content;
private String xmlParam;
private boolean isHttps;
public boolean isHttps() {
return isHttps;
}
public void setHttps(boolean isHttps) {
this.isHttps = isHttps;
}
public String getXmlParam() {
return xmlParam;
}
public void setXmlParam(String xmlParam) {
this.xmlParam = xmlParam;
}
public HttpClientM(String url, Map<String, String> param) {
this.url = url;
this.param = param;
}
public HttpClientM(String url) {
this.url = url;
}
public void setParameter(Map<String, String> map) {
param = map;
}
public void addParameter(String key, String value) {
if (param == null)
param = new HashMap<String, String>();
param.put(key, value);
}
public void post() throws ClientProtocolException, IOException {
HttpPost http = new HttpPost(url);
setEntity(http);
execute(http);
}
public void put() throws ClientProtocolException, IOException {
HttpPut http = new HttpPut(url);
setEntity(http);
execute(http);
}
public void get() throws ClientProtocolException, IOException {
if (param != null) {
StringBuilder url = new StringBuilder(this.url);
boolean isFirst = true;
for (String key : param.keySet()) {
if (isFirst)
url.append("?");
else
url.append("&");
url.append(key).append("=").append(param.get(key));
}
this.url = url.toString();
}
HttpGet http = new HttpGet(url);
execute(http);
}
/**
* set http post,put param
*/
private void setEntity(HttpEntityEnclosingRequestBase http) {
if (param != null) {
List<NameValuePair> nvps = new LinkedList<NameValuePair>();
for (String key : param.keySet())
nvps.add(new BasicNameValuePair(key, param.get(key))); // 参数
http.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8)); // 设置参数
}
if (xmlParam != null) {
http.setEntity(new StringEntity(xmlParam, Consts.UTF_8));
}
}
private void execute(HttpUriRequest http) throws ClientProtocolException, IOException {
CloseableHttpClient httpClient = null;
try {
if (isHttps) {
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
// 信任所有
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
return true;
}
}).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
} else {
httpClient = HttpClients.createDefault();
}
CloseableHttpResponse response = httpClient.execute(http);
try {
if (response != null) {
if (response.getStatusLine() != null)
statusCode = response.getStatusLine().getStatusCode();
HttpEntity entity = response.getEntity();
// 响应内容
content = EntityUtils.toString(entity, Consts.UTF_8);
}
} finally {
response.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
httpClient.close();
}
}
public int getStatusCode() {
return statusCode;
}
public String getContent() throws ParseException, IOException {
return content;
}
}
Controller调用Service中的方法
@RequestMapping("/createNative")
public AjaxJson createNativePay(){
//雪花算法类 随机生成号码
IdWorker idworker=new IdWorker();
long oid=idworker.nextId();
//订单实体类
SfOrders sfOrders=new SfOrders();
//set订单id
sfOrders.setOid(oid);
//支付状态
sfOrders.setPay_id(2);
//添加到数据库
int x=ordersMapper.add(sfOrders);
//判断是否添加成功
if(x>=1) {
//获取插入的id
Long keyid=publicMapper.getPrimarykey();
//转换keyid类型
int k=keyid.intValue();
//根据id查询这一条数据
SfOrders orders=ordersMapper.getById(k);
//根据订单id,支付金额生成二维码
Map map=weixinPayService.createNative(orders.getOid()+"","1");
return AjaxJson.getSuccessData(map);
}
return AjaxJson.getSuccess();
}
页面写法,有想要测试的话朋友可以试试点击下载生成二维码的包qrcode.js
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<!-- 所有的 css & js 资源 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui@2.13.0/lib/theme-chalk/index.css">
<link rel="stylesheet" href="../../static/sa.css">
<script src="https://unpkg.com/vue@2.6.10/dist/vue.min.js"></script>
<script src="https://unpkg.com/element-ui@2.13.0/lib/index.js"></script>
<script src="https://unpkg.com/jquery@3.4.1/dist/jquery.min.js"></script>
<script src="https://www.layuicdn.com/layer-v3.1.1/layer.js"></script>
<script src="../../static/sa.js"></script>
<script src="../../static/qrcode/qrcode.js"></script>
<style>
</style>
</head>
<body>
<div class="vue-box">
<div class="c-item" style="min-width: 0px;">
<el-button @click="queryCode()">点击事件二维码</el-button>
</div>
</div>
<div id="code"></div>
<script>
var app = new Vue({
el: '.vue-box',
data: {
code_url: '',
out_trade_no: ''
},
methods: {
queryCode: function() {
// 统一下单
// ajax返回 下单的数据
sa.ajax('/pay/createNative', function(res) {
console.log(res);
new QRCode(document.getElementById('code'), res.data.code_url); // 创建二维码
this.out_trade_no = res.data.out_trade_no; // 赋值 res里获取的赋值给data里面的
console.log(res.data.out_trade_no + "----------订单id")
}.bind(this), {});
},
},
created: function() {
}
})
</script>
</body>
</html>
写到这里了是可以去页面测试扫码支付的。
3.支付回调
@RequestMapping("/wxnotify")
public void wxnotify(HttpServletRequest request, HttpServletResponse response) {
String resXml = "";
InputStream inStream;
try {
inStream = request.getInputStream();
ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = inStream.read(buffer)) != -1) {
outSteam.write(buffer, 0, len);
}
WXPayUtil.getLogger().info("wxnotify:微信支付----start----");
// 获取微信调用我们notify_url的返回信息
String result = new String(outSteam.toByteArray(), "utf-8");
WXPayUtil.getLogger().info("wxnotify:微信支付----result----=" + result);
// 关闭流
outSteam.close();
inStream.close();
// xml转换为map
Map<String, String> resultMap = WXPayUtil.xmlToMap(result);
//判断状态 验证签名是否正确
boolean isSuccess = false;
if (WXPayConstants.SUCCESS.equalsIgnoreCase(resultMap.get(WXPayConstants.RESULT_CODE))) {
WXPayUtil.getLogger().info("wxnotify:微信支付----返回成功");
if (WXPayUtil.isSignatureValid(resultMap, WXPayConstants.API_KEY)) {
WXPayUtil.getLogger().info("wxnotify:微信支付----验证签名成功");
resXml = resSuccessXml;
isSuccess = true;
} else {
WXPayUtil.getLogger().error("wxnotify:微信支付----判断签名错误");
}
} else {
WXPayUtil.getLogger().error("wxnotify:支付失败,错误信息:" + resultMap.get(WXPayConstants.ERR_CODE_DES));
resXml = resFailXml;
}
// 回调方法,处理业务 - 修改订单状态
WXPayUtil.getLogger().info("wxnotify:微信支付回调:修改的订单===>" + resultMap.get("out_trade_no"));
int x=ordersService.updateByOid(resultMap.get("out_trade_no"));
if (x>=1) {
WXPayUtil.getLogger().info("wxnotify:微信支付回调:修改订单支付状态成功");
} else {
WXPayUtil.getLogger().error("wxnotify:微信支付回调:修改订单支付状态失败");
}
} catch (Exception e) {
WXPayUtil.getLogger().error("wxnotify:支付回调发布异常:", e);
} finally {
try {
// 处理业务完毕
BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
out.write(resXml.getBytes());
out.flush();
out.close();
} catch (IOException e) {
WXPayUtil.getLogger().error("wxnotify:支付回调发布异常:out:", e);
}
}
}
上面定义的WXPayConstants这个类是自己封装的类。例如:
public class WXPayConstants {
//返回code码
public static final String RESULT_CODE = "result_code";
//返回成功状态
public static final String SUCCESS = "SUCCESS";
//商户秘钥
public static final String API_KEY = "lentonxxxxxxxxx";
//返回错误状态
public static final String ERR_CODE_DES = "err_code_des";
//返回失败状态
public static final String FAIL = "FAIL";
}
定义的resSuccessXml,resFailXml写为常量用String接收,写在本类就可以。例如:
/**
* 返回成功xml
*/
private String resSuccessXml = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
/**
* 返回失败xml
*/
private String resFailXml = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml>";
写到这里就已经完成扫码支付了,如果有朋友是用这个方法做支付的话可以参考。有不懂的地方可以在下面留言。
接一篇退款的博客可点击👉 微信支付(native方式二)原路退款
更多推荐
已为社区贡献2条内容
所有评论(0)