【Java】微信企业付款到零钱 工具类封装

WxService.java:

package com.lws.test.core.wechat;

import com.ygxk.social.core.utils.MD5Util;
import com.ygxk.social.core.utils.StringUtil;
import com.ygxk.social.core.wechat.WxKeyConstant;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.springframework.util.ResourceUtils;

import javax.net.ssl.SSLContext;
import java.io.*;
import java.security.KeyStore;
import java.util.*;

/**
 * @Description 微信 工具类
 * @Author Li Wei Shan
 * @Date 2020-12-09 18:25
 * @Version 1.0
 **/
@Slf4j
public class WxService {
    /**
     * 微信提现(企业付款)
     */
    public static Map payForUser(String orderNo, String openId, Long amount, String ip, String desc) {
        Map map;
        SortedMap<String, Object> params = new TreeMap<>();
        params.put("mch_appid", WxKeyConstant.APP_ID);
        params.put("mchid", WxKeyConstant.MCH_ID);
        params.put("partner_trade_no", orderNo);
        params.put("nonce_str", StringUtil.getRandomString(32));
        params.put("openid", openId);
        params.put("check_name", WxKeyConstant.CHECK_NAME);
        params.put("amount", amount.toString());
        params.put("spbill_create_ip", ip);
        params.put("desc", desc);
        String sign = createSign(params);
        params.put("sign", sign);
        String xmlInfo = getRequestXml(params);
        log.debug("WxService==payForUser==xmlInfo==" + xmlInfo);
        try {
            CloseableHttpResponse response = WxPost(WxKeyConstant.WITHDRAW_URL, xmlInfo, true);
            String transfersXml = EntityUtils.toString(response.getEntity(), "utf-8");
            log.debug("transfersXml---"+transfersXml);
            map = doXMLParse(transfersXml);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return map;
    }

    /**
     * 生成签名
     * @return
     */
    private static String createSign(SortedMap<String, Object> parameters) {
        StringBuilder sb = new StringBuilder();
        Set es = parameters.entrySet();
        for (Object e : es) {
            Map.Entry entry = (Map.Entry) e;
            String k = (String) entry.getKey();
            Object v = entry.getValue();
            if (null != v && !"".equals(v)
                    && !"sign".equals(k) && !"key".equals(k)) {
                sb.append(k).append("=").append(v).append("&");
            }
        }
        sb.append("key=").append(WxKeyConstant.WX_SING_KEY);
        log.debug("签名结果==" + sb.toString());
        return MD5Util.MD5Encode(sb.toString(), "UTF-8").toUpperCase();
    }

    /**
     * 请求xml组装
     * @return
     */
    private static String getRequestXml(SortedMap<String, Object> parameters) {
        StringBuilder sb = new StringBuilder();
        sb.append("<xml>");
        Set es = parameters.entrySet();
        for (Object e : es) {
            Map.Entry entry = (Map.Entry) e;
            String key = (String) entry.getKey();
            String value = (String) entry.getValue();
            if ("attach".equalsIgnoreCase(key) || "body".equalsIgnoreCase(key) || "sign".equalsIgnoreCase(key)) {
                sb.append("<").append(key).append(">").append("<![CDATA[").append(value).append("]]></").append(key).append(">");
            } else {
                sb.append("<").append(key).append(">").append(value).append("</").append(key).append(">");
            }
        }
        sb.append("</xml>");
        return sb.toString();
    }

    /**
     * xml解析
     * @return
     */
    private static Map doXMLParse(String strxml) throws JDOMException, IOException {
        strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");
        if ("".equals(strxml)) {
            return null;
        }
        Map m = new HashMap();
        InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));
        SAXBuilder builder = new SAXBuilder();
        Document doc = builder.build(in);
        Element root = doc.getRootElement();
        List list = root.getChildren();
        for (Object aList : list) {
            Element e = (Element) aList;
            String k = e.getName();
            String v = "";
            List children = e.getChildren();
            if (children.isEmpty()) {
                v = e.getTextNormalize();
            } else {
                v = getChildrenText(children);
            }
            m.put(k, v);
        }
        //关闭流
        in.close();
        return m;
    }

    private static String getChildrenText(List children) {
        StringBuilder sb = new StringBuilder();
        if (!children.isEmpty()) {
            for (Object aChildren : children) {
                Element e = (Element) aChildren;
                String name = e.getName();
                String value = e.getTextNormalize();
                List list = e.getChildren();
                sb.append("<").append(name).append(">");
                if (!list.isEmpty()) {
                    sb.append(getChildrenText(list));
                }
                sb.append(value);
                sb.append("</").append(name).append(">");
            }
        }
        return sb.toString();
    }

    /**
     * 发送post请求
     * @param url          请求地址
     * @param outputEntity 发送内容
     * @param isLoadCert   是否加载证书
     */
    public static CloseableHttpResponse WxPost(String url, String outputEntity, boolean isLoadCert) throws Exception {
        HttpPost httpPost = new HttpPost(url);
        // 得指明使用UTF-8编码,否则到API服务器XML的中文不能被成功识别
        httpPost.addHeader("Content-Type", "text/xml");
        httpPost.setEntity(new StringEntity(outputEntity, "UTF-8"));
        if (isLoadCert) {
            // 加载含有证书的http请求
            return HttpClients.custom().setSSLSocketFactory(initCert()).build().execute(httpPost);
        } else {
            return HttpClients.custom().build().execute(httpPost);
        }
    }

    /**
     * 加载证书
     */
    public static SSLConnectionSocketFactory initCert() throws Exception {
        FileInputStream instream = null;
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        File file = ResourceUtils.getFile(WxKeyConstant.CERT_PATH);
        instream = new FileInputStream(file);
        keyStore.load(instream, WxKeyConstant.MCH_ID.toCharArray());

        if (null != instream) {
            instream.close();
        }
        SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, WxKeyConstant.MCH_ID.toCharArray()).build();
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1"}, null, new DefaultHostnameVerifier());
        return sslsf;
    }

}
WxKeyConstant.java:
package com.lws.test.core.wechat;

/**
 * @Description 微信使用的Key的常量定义
 * @Author Li Wei Shan
 * @Date 2020-12-09 18:26
 * @Version 1.0
 **/
public class WxKeyConstant {
    /**
     * appid
     */
    public static final String APP_ID = "xxx";
    /**
     * appSercet
     */
    public static final String APP_SECRET = "xxx";
    /**
     * 商户号
     */
    public static final String MCH_ID = "xxx";
    /**
     * 支付秘钥
     */
    public static final String WX_SING_KEY = "xxx";
    /**
     * 证书路径
     */
    public static final String CERT_PATH = "/apiclient_cert.p12";
    /**
     * 回调地址
     */
    public static final String NOTIFY_URL = "";
    /**
     * 是否校验用户姓名 NO_CHECK:不校验真实姓名  FORCE_CHECK:强校验真实姓名
     */
    public static final String CHECK_NAME = "NO_CHECK";
    /**
     * 付款url
     */
    public static final String WITHDRAW_URL = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";
}

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李维山

帮到你就行 不差钱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值