锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

微信企业账户提现到微信用户钱包零钱(通过openid)

时间:2022-09-15 04:00:00 kmf磁感应直线位移传感器

快速完成开发

1. apiclient_cert.p12:微信商户支付证书,一份配置在项目或服务器中的文件

2.工具类

  import org.apache.commons.codec.digest.DigestUtils;  import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.util.*;  public class CommonUtil {     /**      * 获取一定长度的随机字符串,范围0-9,a-z      * @param length:指定字符串的长度      * @return 一定长度的随机字符串      */     public static String getRandomStringByLength(int length) {         String base = "abcdefghijklmnopqrstuvwxyz0123456789";         Random random = new Random();         StringBuffer sb = new StringBuffer();         for (int i = 0; i < length; i  ) {             int number = random.nextInt(base.length());             sb.append(base.charAt(number));         }         return sb.toString();     }     /**      * 除去数组中的空值和签名参数      *      * @param sArray 签名参数组      * @return 去除空值和签名参数后的新签名参数组      */     public static Map paraFilter(Map sArray) {         Map result = new HashMap();         if (sArray == null || sArray.size() <= 0) {             return result;         }         for (String key : sArray.keySet()) {             String value = sArray.get(key);             if (value == null || value.equals("") || key.equalsIgnoreCase("sign")                     || key.equalsIgnoreCase("sign_type")) {                 continue;             }             result.put(key, value);         }         return result;     }     /**      * 排序数组的所有元素,并按参数=参数值模式采用参数值模式&将字符拼接成字符串      *      * @param params 参数组需要排序并参与字符拼接      * @return 字符串拼接后      */     public static String createLinkString(Map params) {         List keys = new ArrayList(params.keySet());         Collections.sort(keys);         String prestr = "";         for (int i = 0; i < keys.size(); i  ) {             String key = keys.get(i);             String value = params.get(key);             if (i == keys.size() - 1) {// 拼接时,不包括最后一个&字符                 prestr = prestr   key   "="   value;             } else {                 prestr = prestr   key   "="   value   "&";             }         }         return prestr;     }     /**      * 签名字符串      *      * @param text          需要签名的字符串      * @param key           密钥      * @param input_charset 编码格式      * @return 签名结果      */     public static String sign(String text, String key, String input_charset) {         text = text   "&key="   key;         return DigestUtils.md5Hex(getContentBytes(text, input_charset));     }     public static byte[] getContentBytes(String content, String charset) {         if (charset == null || "".equals(charset)) {             return content.getBytes();         }         try {             return content.getBytes(charset);         } catch (UnsupportedEncodingException e) {             throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:"   charset);         }     }     /**      * 将Map转换为XML字符串的格式      *      * @param data Map类型数据      * @return XML字符串的格式      * @throws Exception      */     public static String mapToXml(Map data) throws Exception {         DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();         DocumentBuilder documentBuilder= documentBuilderFactory.newDocumentBuilder();         org.w3c.dom.Document document = documentBuilder.newDocument();         org.w3c.dom.Element root = document.createElement("xml");         document.appendChild(root);         for (String key: data.keySet()) {             String value = data.get(key);             if (value == null) {                 value = "";             }             value = value.trim();             org.w3c.dom.Element filed = document.createElement(key);             filed.appendChild(document.createTextNode(value));             root.appendChild(filed);         }         TransformerFactory tf = TransformerFactory.newInstance();         Transformer transformer = tf.newTransformer();         DOMSource source = new DOMSource(document);         transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");         transformer.setOutputProperty(OutputKeys.INDENT, "yes");         StringWriter writer = new StringWriter();         StreamResult result = new StreamResult(writer);         transformer.transform(source, result);         String output = writer.getBuffer().toString(); //.replaceAll("\n|\r", "");         try {             writer.close();        }
        catch (Exception ex) {
        }
        return output;
    }
 /**
     * 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。
     *
     * @param strxml
     * @return
     * @throws IOException
     */
    public static Map doXMLParse(String strxml) throws Exception {
        if (null == strxml || "".equals(strxml)) {
            return null;
        }

        Map m = new HashMap();
        InputStream in = String2Inputstream(strxml);
        SAXBuilder builder = new SAXBuilder();
        Document doc = builder.build(in);
        Element root = doc.getRootElement();
        List list = root.getChildren();
        Iterator it = list.iterator();
        while (it.hasNext()) {
            Element e = (Element) it.next();
            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;
    }
}

3.结果实体

        


import lombok.Data;

/**
 * @author ljchen
 */
@Data
public class TransferResultDto{
    /**
     * 转账结果:成功或失败(SUCCESS/FAIL)
     */
    private String resultCode;
    /**
     * 商户转账订单号
     */
    private String partnerTradeNo;
    /**
     * 微信订单号
     */
    private String paymentNo;
    /**
     * 微信支付成功时间
     */
    private  String paymentTime;

    /**
     * 错误代码
     */
    private String errorCode;
   
    /**
     * 错误代码描述
     */
    private  String errorCodeDes;
}

4.实现代码


import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
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.HttpClientBuilder;
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.springframework.util.CollectionUtils;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.security.*;
import java.util.*;

/**
 * 微信提现
 * @author
 */
public class WxPayServiceImpl{


    /**
     * 企业微信提现到用户
     * @param amount  提现金额  整数 单位分
     * @param openId  微信用户 openid
     * @param transactionNo   自定义 提现记录全局唯一标识
     * @param request
     * @param msg         企业付款操作说明
     * @throws Exception
     */

    public TransferResultDto wxWithdrawalTransferSample(HttpServletRequest request, String openId,String amount,String transactionNo,String msg) throws Exception {
        //封装提现请求参数map
        Map packageParams = handleInputParamMap(request,openId, amount, transactionNo,msg);
        //将map转成xml
        String mapToXml = CommonUtil.mapToXml(packageParams);
        //调用接口
        String result = requestOnce("https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers", mapToXml, 30000, 30000, true);
        //调用提现请求接口,返回结果是xml格式
        log.info("提现接口{}",result);
        //处理微信提现接口返回结果
        return handleTransferResultDto(result);
    }

    private Map handleInputParamMap(HttpServletRequest request,String openId,String amount,String transactionNo,String msg) throws Exception {
        Map packageParams = new HashMap();

        //1.0 拼凑企业支付需要的参数
        //微信小程序的appid
        String mchAppId ="微信小程序的appid";
        //商户号
        String mchId = "商户号";
        //生成随机数
        String nonceStr =CommonUtil.getRandomStringByLength(32);
        //是否验证真实姓名呢:NO_CHECK:不校验真实姓名; FORCE_CHECK:强校验真实姓名
        String checkName = "NO_CHECK";
        //企业付款操作说明信息, 默认为提现到微信零钱
        //获取调用接口的机器ip
        String spbillCreateIp = request.getRemoteHost();
        //微信小程序的appid
        packageParams.put("mch_appid", mchAppId);
        //商户号
        packageParams.put("mchid", mchId);
        //随机生成后数字,保证安全性
        packageParams.put("nonce_str", nonceStr);
        //生成商户订单号
        packageParams.put("partner_trade_no", transactionNo);
        // 支付给用户openid
        packageParams.put("openid", openId);
        //是否验证真实姓名呢
        packageParams.put("check_name", checkName);
        //企业付款金额,单位为分
        packageParams.put("amount",amount);
        //企业付款操作说明信息。必填。
        packageParams.put("desc", msg);
        //调用接口的机器Ip地址
        packageParams.put("spbill_create_ip", spbillCreateIp);
        //3.0 生成自己的签名
        // 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
        packageParams=CommonUtil.paraFilter(packageParams);

        String prestr = CommonUtil.createLinkString(packageParams);
        //签名
        String sign = CommonUtil.sign(prestr,mchAppId,"utf-8").toUpperCase();
        //封装入参map
        packageParams.put("sign", sign);
        return packageParams;
    }

    private TransferResultDto handleTransferResultDto(String resultXml) throws Exception {
        TransferResultDto resultDto = new TransferResultDto();

        Map resultMap = CommonUtil.doXMLParse(resultXml);
        if (!CollectionUtils.isEmpty(resultMap) && "SUCCESS".equals(resultMap.get("result_code"))&&"SUCCESS".equals(resultMap.get("return_code"))) {
            log.info("转账成功");
            resultDto.setResultCode(resultMap.get("result_code"));
            // 商户转账订单号
            resultDto.setPartnerTradeNo(resultMap.get("partner_trade_no"));
            // 微信订单号
            resultDto.setPaymentNo(resultMap.get("payment_no"));
            // 微信支付成功时间
            resultDto.setPaymentTime(resultMap.get("payment_time"));
        } else {
            resultDto.setResultCode(resultMap.get("result_code"));
            //错误代码
            resultDto.setErrorCode(resultMap.get("err_code"));
            //错误代码描述
            resultDto.setErrorCodeDes(resultMap.get("err_code_des"));
        }
        return resultDto;
    }
    /**
     * @param data
     * @param connectTimeoutMs
     * @param readTimeoutMs
     * @param useCert 是否使用证书,针对退款、撤销等操作
     * @return
     * @throws Exception
     */
    private String requestOnce(String url,String data, int connectTimeoutMs, int readTimeoutMs, boolean useCert) throws Exception {
        //证书路径
        String path = "你的证书路径";
        BasicHttpClientConnectionManager connManager;
        if (useCert) {
            //商户id
            char[] password = "小程序商户id".toCharArray();

            //加载证书
            FileInputStream certStream = new FileInputStream(new File(path));
            KeyStore ks = KeyStore.getInstance("PKCS12");
            ks.load(certStream, password);

            // 实例化密钥库 & 初始化密钥工厂
            KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            kmf.init(ks, password);

            // 创建 SSLContext
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(kmf.getKeyManagers(), null, new SecureRandom());

            SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(
                    sslContext,
                    new String[]{"TLSv1"},
                    null,
                    new DefaultHostnameVerifier());

            connManager = new BasicHttpClientConnectionManager(
                    RegistryBuilder.create()
                            .register("http", PlainConnectionSocketFactory.getSocketFactory())
                            .register("https", sslConnectionSocketFactory)
                            .build(),
                    null,
                    null,
                    null
            );
        }
        else {
            connManager = new BasicHttpClientConnectionManager(
                    RegistryBuilder.create()
                            .register("http", PlainConnectionSocketFactory.getSocketFactory())
                            .register("https", SSLConnectionSocketFactory.getSocketFactory())
                            .build(),
                    null,
                    null,
                    null
            );
        }

        HttpClient httpClient = HttpClientBuilder.create()
                .setConnectionManager(connManager)
                .build();

        HttpPost httpPost = new HttpPost(url);

        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(readTimeoutMs).setConnectTimeout(connectTimeoutMs).build();
        httpPost.setConfig(requestConfig);

        StringEntity postEntity = new StringEntity(data, "UTF-8");
        httpPost.addHeader("Content-Type", "text/xml");
        httpPost.addHeader("User-Agent",  "WXPaySDK/3.0.9" +
                " (" + System.getProperty("os.arch") + " " + System.getProperty("os.name") + " " + System.getProperty("os.version") +
                ") Java/" + System.getProperty("java.version") + " HttpClient/" + HttpClient.class.getPackage().getImplementationVersion() + " " + path);
        httpPost.setEntity(postEntity);
        HttpResponse httpResponse = httpClient.execute(httpPost);
        HttpEntity httpEntity = httpResponse.getEntity();
        return EntityUtils.toString(httpEntity, "UTF-8");

    }

}

小结:代码需要更换参数 具体位置请自行查找(有点乱,请自行配置修改在同一个位置)

依赖:


    org.jdom
    jdom2
2.0.6

锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章