JAVA微信支付

准备工作:
登录微信开放平台创建应用开通支付功能支付功能
获得AppID、商户ID、 秘钥

import com.alibaba.fastjson.JSON;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLConnection;
import java.nio.ByteBuffer;
import java.util.*;
import org.apache.commons.codec.binary.Base64;
import org.springframework.util.DigestUtils;
import java.nio.charset.StandardCharsets;

public class WxPayUtils {

    @Data
    public static class PayInfo<T> {
        private String orderId;
        private String subscriptionId;
        private boolean ifSandboxOrder;
        private T result;
        private String resultJson;
        private String tradeNo;
        private String tradeType;
        private String paymentType;
        private String payerType;
        private String recAccount;
        private String payTime;
        private String orderStatus = "0";
    }

    @Data
    public class WxPayAppPayResponse {
        //返回状态码
        private String return_code;
        //返回信息
        private String return_msg;

        //以下字段在return_code为SUCCESS的时候有返回
        //应用APPID
        private String appid;
        //商户号
        private String mch_id;
        //设备号
        private String device_info;
        //随机字符串
        private String nonce_str;
        //签名
        private String sign;
        //业务结果
        private String result_code;
        //错误代码
        private String err_code;
        //错误代码描述
        private String err_code_des;

        //以下字段在return_code 和result_code都为SUCCESS的时候有返回
        //交易类型
        private String trade_type;
        //预支付交易会话标识
        private String prepay_id;
    }

    private static final String WXPayUnifiedorder = "https://api.mch.weixin.qq.com/pay/unifiedorder";
    // APPID ,接入时生成
    private static final String appId = "XXXXXXX";
    // 商户ID,接入时生成
    private static final String mchId = "XXXXXXX";
    // appSecret密钥
    private static final String appSecret = "1636e***********a57222";
    private static final String FIELD_SIGN = "sign";
    private static int connectTimeout = 3000;

    /**
     * 微信支付加签
     *
     * @param body 业务主题
     * @param price 交易金额
     * @param notifyUrl 异步通知URL
     * @return
     */
    public WxPayUtils.PayInfo createOrder(String body, String price, String notifyUrl) {
        WxPayUtils.PayInfo<String> payInfo = new WxPayUtils.PayInfo<>();
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("appid", appId);
        paramMap.put("mch_id", mchId);
        paramMap.put("nonce_str", getRandom(16));
        paramMap.put("body", body);
        paramMap.put("out_trade_no", getBaseUUid());
        paramMap.put("total_fee", price);
        paramMap.put("fee_type", "CNY"); // 交易币种 默认人民币CNY
        paramMap.put("spbill_create_ip", "127.0.0.1"); // 终端ip
        paramMap.put("notify_url", notifyUrl);
        paramMap.put("trade_type", "APP"); // 支付场景 APP 微信app支付 NATIVE 扫码支付
        paramMap.put("sign", createMd5Sign(paramMap, appSecret));
        String xmlStr = sendPost(WXPayUnifiedorder, toWxStrXml(paramMap));
        WxPayAppPayResponse rstObj = strXmlToEntity(xmlStr, WxPayAppPayResponse.class);
        if (rstObj != null && StringUtils.isNotBlank(rstObj.getSign()) && StringUtils.isNotBlank(rstObj.getPrepay_id())) {
            payInfo.setResult(JSON.toJSONString(strXmlToMap(xmlStr)));
            paramMap = new HashMap<>();
            paramMap.put("appid", appId);
            paramMap.put("partnerid", mchId);
            paramMap.put("prepayid", rstObj.getPrepay_id());
            paramMap.put("package", "Sign=WXPay");
            paramMap.put("noncestr", rstObj.getNonce_str());
            paramMap.put("timestamp", System.currentTimeMillis() / 1000 + "");
            paramMap.put("sign", createMd5Sign(paramMap, appSecret)); // 生成二次签名,APP端调起支付客户端时无需再次签名
            payInfo.setResultJson(JSON.toJSONString(paramMap));
            return payInfo;
        }
        return payInfo;
    }

    public static String getBaseUUid() {
        ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
        UUID uuid = UUID.randomUUID();
        bb.putLong(uuid.getMostSignificantBits());
        bb.putLong(uuid.getLeastSignificantBits());
        return Base64.encodeBase64URLSafeString(bb.array());
    }

    public static String getRandom(int len) {
        String[] tempRandom = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",};
        Random a = new Random();
        int nextInt = a.nextInt(len);
        nextInt += 16;
        StringBuffer stringBuffer = new StringBuffer();
        for (int i = 0; i < nextInt; i++) {
            int nextInt2 = a.nextInt(36);
            stringBuffer.append(tempRandom[nextInt2]);
        }
        String currentTimeMillis = System.currentTimeMillis() + "";
        int length = stringBuffer.length();

        if (length < 32) {
            if ((currentTimeMillis.length() - 32) > 0) {
                stringBuffer.append(currentTimeMillis.substring(currentTimeMillis.length() - 32 + length));
            }
        }
        return stringBuffer.toString();
    }

    /**
     * 拼接wx xml字符串
     *
     * @param paramMap
     * @return
     */
    public static String toWxStrXml(Map<String, String> paramMap) {
        StringBuilder sb = new StringBuilder();
        sb.append("<xml>");
        for (String key : paramMap.keySet()) {
            String value = paramMap.get(key);
            if (value == null) {
                value = "";
            }
            value = value.trim();
            sb.append("<").append(key).append(">").append("<![CDATA[").append(value).append("]]>").append("</").append(key).append(">");
        }
        sb.append("</xml>");
        return sb.toString();
    }

    public static Map<String, String> strXmlToMap(String strXml) {
        if (StringUtils.isBlank(strXml)) {
            return null;
        }
        try {
            Document document = DocumentHelper.parseText(strXml);
            Element root = document.getRootElement();
            Iterator<?> iter = root.elementIterator();
            //利用反射机制,调用set方法
            //获取该实体的元类型
            Map<String, String> msg = new HashMap<>();//创建这个实体的对象
            while (iter.hasNext()) {//对xml文件进行解析
                Element ele = (Element) iter.next();
                msg.put(ele.getName(), ele.getText());
            }
            return msg;
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 创建md5 数字签证
     *
     * @param paramMap
     * @param secret
     * @return
     */
    public static String createMd5Sign(Map<String, String> paramMap, String secret) {
        Set<String> keySet = paramMap.keySet();
        String[] keyArray = keySet.toArray(new String[0]);
        Arrays.sort(keyArray);
        StringBuilder sb = new StringBuilder();
        for (String key : keyArray) {
            if (key.equals(FIELD_SIGN)) {
                continue;
            }
            if (paramMap.get(key) != null && paramMap.get(key).trim().length() > 0) { // 参数值为空,则不参与签名
                sb.append(key).append("=").append(paramMap.get(key).trim()).append("&");
            }
        }
        sb.append("key=").append(secret);
        return DigestUtils.md5DigestAsHex(sb.toString().getBytes(StandardCharsets.UTF_8)).toUpperCase();
    }


    public static String sendPost(String url, String param) {
        try {
            URLConnection conn = null;
            URL realUrl = new URL(url);
            conn = realUrl.openConnection();
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setConnectTimeout(connectTimeout);
            PrintWriter out = new PrintWriter(new OutputStreamWriter(conn.getOutputStream(), StandardCharsets.UTF_8));
            Throwable var5 = null;

            try {
                out.print(param);
                out.flush();
                BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
                Throwable var7 = null;

                try {
                    StringBuffer result = new StringBuffer();

                    String line;
                    while((line = in.readLine()) != null) {
                        result.append(line);
                    }

                    String var10 = result.toString();
                    return var10;
                } catch (Throwable var35) {
                    var7 = var35;
                    throw var35;
                } finally {
                    if (in != null) {
                        if (var7 != null) {
                            try {
                                in.close();
                            } catch (Throwable var34) {
                                var7.addSuppressed(var34);
                            }
                        } else {
                            in.close();
                        }
                    }

                }
            } catch (Throwable var37) {
                var5 = var37;
                throw var37;
            } finally {
                if (out != null) {
                    if (var5 != null) {
                        try {
                            out.close();
                        } catch (Throwable var33) {
                            var5.addSuppressed(var33);
                        }
                    } else {
                        out.close();
                    }
                }

            }
        } catch (IOException var39) {
            var39.printStackTrace();
            return null;
        }
    }


    public static <T> T strXmlToEntity(String strXml, Class<T> c) {
        if (StringUtils.isBlank(strXml)) {
            return null;
        }
        try {
            Document document = DocumentHelper.parseText(strXml);
            Element root = document.getRootElement();
            Iterator<?> iter = root.elementIterator();

            //利用反射机制,调用set方法
            //获取该实体的元类型
            T msg = c.newInstance();//创建这个实体的对象

            while (iter.hasNext()) {//对xml文件进行解析
                Element ele = (Element) iter.next();
                Field field = null;
                try {
                    field = c.getDeclaredField(ele.getName());
                } catch (NoSuchFieldException | SecurityException ignored) {
                }
                if (field != null) {
                    //获取set方法,field.getType())获取它的参数数据类型
                    String name = ele.getName().substring(0, 1).toUpperCase() + ele.getName().substring(1);
                    Method method = c.getDeclaredMethod("set" + name, field.getType());
                    //调用set方法
                    method.invoke(msg, ele.getText());
                }
            }
            return msg;
        } catch (DocumentException | IllegalAccessException | InvocationTargetException | NoSuchMethodException | InstantiationException e) {
            e.printStackTrace();
        }
        return null;
    }

}

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值