场景

需要使用微信支付中Native模式,完成扫码支付,这里只说代码实现,具体怎么申请微信商户等一些账户,自己解决 NATIVE支付,官方文档

准备

Jar包依赖

<!-- WeChat Pay -->
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-apache-httpclient</artifactId>
<version>0.2.0</version>
</dependency>
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>0.0.3</version>
</dependency>
<!-- 解析xml -->
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.1.1</version>
</dependency>
<!-- ZXing 二维码 -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.3.0</version>
</dependency>
<!-- 阿里巴巴 Fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.49</version>
</dependency>

方法

调用方法,具类在下方

/**
* 微信支付
* 将画好的二维码,以输出流输出,不做存储,输出结果就是一张二维码
* @param jsonParam
* @param response
* @Author: www.itze.cn
* @Email: gitlab@111.com
*/
@PostMapping("wxPay")
public void wxPay(HttpServletResponse response) {
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
response.setContentType("image/jpeg");
//传参方式,根据自己定义
String out_trade_no = "";
String trade_fee = "";
String body = "";
try {
JSONObject object = WeChatPayUtil.goPay(body, out_trade_no, Integer.parseInt(trade_fee));
String return_code = object.getString("return_code");
String result_code = object.getString("result_code");
if (return_code.equals(WXPayConstants.SUCCESS) && result_code.equals(WXPayConstants.SUCCESS)) {
//获取支付url
String code_url = object.getString("code_url");
//转二维码
WeChatPayUtil.createQRCode(code_url, response.getOutputStream());
} else {
//错误异常处理,根据自己业务补充


}
} catch (Exception e) {
e.printStackTrace();
}
}

WeChatPayUtil工具类

import com.alibaba.fastjson.JSONObject;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.tree.DefaultElement;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.URL;
import java.net.URLConnection;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.TreeMap;

/**
* Created with IDEA
* Author: www.itze.cn
* Email:gitlab@111.com
*/
public class WeChatPayUtil {

/**
* 获取本机IP
* @return
* @throws UnknownHostException
*/
public static String getLocalIp() throws UnknownHostException {
InetAddress localHost = InetAddress.getLocalHost();
return localHost.getHostAddress();
}


/**
* 解析字符串形式的XML内容
*
* @param xmlContent
* @return
* @throws DocumentException
*/
public static JSONObject xmlToJson(String xmlContent) throws DocumentException {
Document document = DocumentHelper.parseText(xmlContent);
Element rootElement = document.getRootElement();
Iterator iterator = rootElement.elementIterator();
JSONObject jsonObject = new JSONObject();
while (iterator.hasNext()) {
DefaultElement defaultElement = (DefaultElement) iterator.next();
jsonObject.fluentPut(defaultElement.getName(), defaultElement.getStringValue());
}
return jsonObject;
}

/**
* 请求内容
*
* @param body
* @param out_trade_no
* @param trade_fee
* @return
* @throws UnknownHostException
*/
private static String xmlContent(String body, String out_trade_no, String trade_fee) throws Exception {
String appid = "改成你微信商户绑定的APPID";
String mchid = "商户账户分配的APPID";
String notifyUrl = "回调通知地址,一定要外网可以访问";
String key = "自己生成的API私钥";
TreeMap<String, String> paramMap = new TreeMap<>();
//添加必须请求参数,额外请求参数详情见官方文档
paramMap.put("appid", appid);
paramMap.put("mch_id", mchid);
paramMap.put("nonce_str", WXPayUtil.generateNonceStr());
paramMap.put("body", body);
paramMap.put("out_trade_no", out_trade_no);
paramMap.put("total_fee", trade_fee);//订单金额,单位分,不能带小数点!
paramMap.put("spbill_create_ip", getLocalIp());
paramMap.put("notify_url", notifyUrl);
paramMap.put("trade_type", "NATIVE");
//加签
String signature = WXPayUtil.generateSignature(paramMap, key);
paramMap.put("sign", signature);
//请求内容
return WXPayUtil.mapToXml(paramMap);
}

/**
* 请求结果
*
* @param body
* @param out_trade_no
* @param trade_fee
* @return
* @throws UnknownHostException
* @throws DocumentException
*/
public static JSONObject goPay(String body, String out_trade_no, int trade_fee) throws Exception {
String sendContent = xmlContent(body, out_trade_no, String.valueOf(trade_fee));
//发送请求
String result = sendPostData(WXPayConstants.UNIFIEDORDER_URL, sendContent, null);
//转换请求结果
return xmlToJson(result);
}

/**
* 调用微信支付
*
* @param urlParam
* @param param
* @param contentType
* @return
*/
public static String sendPostData(String urlParam, String param, String contentType) {
try {
URL url = new URL(urlParam);
URLConnection connection = url.openConnection();
connection.setDoOutput(true);
connection.setConnectTimeout(5 * 60 * 1000);
connection.setReadTimeout(5 * 60 * 1000);
if (StringUtils.isNotBlank(contentType))
connection.setRequestProperty("content-type", contentType);
OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream(), "utf-8");
if (param == null)
param = "";
writer.write(param);
writer.flush();
writer.close();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"))) {
StringBuilder builder = new StringBuilder();
String content = null;
while ((content = reader.readLine()) != null) {
builder.append(content);
builder.append("\r\n");//写入回车
}
return builder.toString();
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

/**
* @param content 二维码内容
* @param outputStream 输出流
* @Author: www.itze.cn
* @Email: gitlab@111.com
*/
public static void createQRCode(String content, OutputStream outputStream) {
//定义长宽
int width = 160;
int height = 160;
//定义格式
String format = "jpg";
//定义二维码参数
HashMap hashMap = new HashMap();
hashMap.put(EncodeHintType.CHARACTER_SET, "utf-8");
/**
* 纠错能力
* L:约可纠错7%的数据码字
* M:约可纠错15%的数据码字
* Q:约可纠错25%的数据码字
* H:约可纠错30%的数据码字
*/
hashMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
//边距
hashMap.put(EncodeHintType.MARGIN, 1);
try {
BitMatrix matrix = new MultiFormatWriter()
.encode(content, BarcodeFormat.QR_CODE, width, height, hashMap);
MatrixToImageWriter.writeToStream(matrix, format, outputStream);
} catch (Exception e) {
e.printStackTrace();
}
}
}