zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Java微信Native支付扫码支付案例

JAVA案例微信 支付 native 扫码
2023-06-13 09:14:21 时间

场景

需要使用微信支付中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();
        }
    }
}