菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
42
0

微信 企业付款到零钱

原创
05/13 14:22
阅读数 1351

微信相关配置

1、公众平台

授权域名回调

2、商户平台

路径:商户平台:账户中心 》 账户设置 》API安全
1、api 安全配置 (指的是:允许调用接口的白名单配置)
2、证书下载 (本次代码主要使用的是 p12 证书)

企业付款到零钱,是需要 open_id 参数的,open_id 参数的获取,参考其他文章,此处不做记录

主要发起支付的代码

工具类

import com.alibaba.fastjson.JSONObject;
import com.hoohui.project.richeng.model.WeChatEntity;
import com.hoohui.project.richeng.util.PathUtil;
import com.hoohui.util.http.HttpRequestUtils;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

public class WeChatUtils {
    private byte[] certData;

    public InputStream getCertStream() {
        FileInputStream instream = null;
        try {
            //此处为 p12 证书文件路径
            instream = new FileInputStream(new File(PathUtil.getClassResources() + "/weChat/apiclient_cert.p12"));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return instream;
    }
    /**
    * 随机串
    */
    public static String getNonceStr() {
        UUID uuid = UUID.randomUUID();
        return uuid.toString().replace("-", "");
    }
    /**
     * 方法用途: 对所有传入参数按照字段名的Unicode码从小到大排序(字典序),并且生成url参数串<br>
     * 实现步骤: <br>
     *
     * @param paraMap    要排序的Map对象
     * @param urlEncode  是否需要URLENCODE
     * @param keyToLower 是否需要将Key转换为全小写
     *                   true:key转化成小写,false:不转化
     * @return
     */
    public static String formatUrlMap(Map<String, String> paraMap, boolean urlEncode, boolean keyToLower) {
        String buff = "";
        Map<String, String> tmpMap = paraMap;
        try {
            List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(tmpMap.entrySet());
            // 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序)
            Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {
                @Override
                public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
                    return (o1.getKey()).toString().compareTo(o2.getKey());
                }
            });
            // 构造URL 键值对的格式
            StringBuilder buf = new StringBuilder();
            for (Map.Entry<String, String> item : infoIds) {
                if (StringUtils.isNotBlank(item.getKey())) {
                    String key = item.getKey();
                    String val = item.getValue();
                    if (urlEncode) {
                        val = URLEncoder.encode(val, "utf-8");
                    }
                    if (keyToLower) {
                        buf.append(key.toLowerCase() + "=" + val);
                    } else {
                        buf.append(key + "=" + val);
                    }
                    buf.append("&");
                }

            }
            buff = buf.toString();
            if (buff.isEmpty() == false) {
                buff = buff.substring(0, buff.length() - 1);
            }
        } catch (Exception e) {
            return null;
        }
        return buff;
    }
}

发起打款的主要方法:

    public void toPay() throws Exception {
        //1. 调用发起支付的方法
        String str = mainPay(map, 3000, 3000, true);
        //2. xml 转成 map的 方法
        Map<String,String> resultMap = XmlUtil.xml2Map(str);
        //3. 根据 result_code 判断是否支付成功
        if(resultMap.containsKey("result_code") && StringUtils.equals("SUCCESS",resultMap.getOrDefault("result_code",""))){
            // TODO: 2019/9/19 表示支付成功 后进行的操作
          
        }else{
            // TODO: 2019/9/19表示支付失败
          
        }
    }

    /**
     * 主要发起支付的方法
     */
    public static String mainPay(Map<String,String> params, int connectTimeoutMs, int readTimeoutMs,boolean useCert) throws Exception{
        Map<String, String> paraMap = new HashMap<>();
        //微信 app_id
        paraMap.put("mch_appid", WeChatConfig.APP_ID);
        //微信 mch_id
        paraMap.put("mchid",WeChatConfig.MCH_ID);
        //随机字符串
        paraMap.put("nonce_str", WeChatUtils.getNonceStr());
        //订单号 可以按照自己的规则生成,不重复即可
        paraMap.put("partner_trade_no","wx"+params.getOrDefault("id","")+ DateUtils.getDate("yyyyMMddHHmmss"));
        //用户的 open_id 
        paraMap.put("openid",params.getOrDefault("openid",""));
        // 校验用户姓名选项 NO_CHECK:不校验真实姓名  FORCE_CHECK:强校验真实姓名
        paraMap.put("check_name","FORCE_CHECK");
        // 微信的真实姓名
        paraMap.put("re_user_name",params.getOrDefault("re_user_name",""));
        //金额值,单位为 分
        paraMap.put("amount",params.getOrDefault("amount",""));
        //企业付款操作说明信息
        paraMap.put("desc",params.getOrDefault("desc",""));
        //跟白名单没有关系 ,这样写就可以
        paraMap.put("spbill_create_ip", InetAddress.getLocalHost().getHostAddress());
        //将参数排序,并 拼接成字符串
        String url = WeChatUtils.formatUrlMap(paraMap, false, false);
        //最后加上  商户 api_key
        url = url + "&key=" + WeChatConfig.API_KEY; //生成签名 使用商户 key
        //md5 加密,转大写
        String sign = Md5Utils.md5(url).toUpperCase();
        //拼接成xml
        StringBuffer xml = new StringBuffer();
        xml.append("<xml>");
        for (Map.Entry<String, String> entry : paraMap.entrySet()) {
            xml.append("<" + entry.getKey() + ">");
            xml.append(entry.getValue());
            xml.append("</" + entry.getKey() + ">" + "\n");
        }
        xml.append("<sign>");
        xml.append(sign);
        xml.append("</sign>");
        xml.append("</xml>");
        logger.info("xml {} ", xml.toString());
        BasicHttpClientConnectionManager connManager;
        if (useCert) {
            // 证书
            char[] password = WeChatConfig.MCH_ID.toCharArray();
            //这一步调用获取证书内容
            InputStream certStream =  new WeChatUtils().getCertStream();
            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 org.apache.http.conn.ssl.DefaultHostnameVerifier());

            connManager = new BasicHttpClientConnectionManager(
                    RegistryBuilder.<ConnectionSocketFactory>create()
                            .register("http", PlainConnectionSocketFactory.getSocketFactory())
                            .register("https", sslConnectionSocketFactory)
                            .build(),
                    null,
                    null,
                    null
            );
        } else {
            connManager = new BasicHttpClientConnectionManager(
                    RegistryBuilder.<ConnectionSocketFactory>create()
                            .register("http", PlainConnectionSocketFactory.getSocketFactory())
                            .register("https", SSLConnectionSocketFactory.getSocketFactory())
                            .build(),
                    null,
                    null,
                    null
            );
        }
        org.apache.http.client.HttpClient httpClient = HttpClientBuilder.create()
                .setConnectionManager(connManager)
                .build();
        HttpPost httpPost = new HttpPost(WeChatConfig.MACH_PAY_URL);
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(readTimeoutMs).setConnectTimeout(connectTimeoutMs).build();
        httpPost.setConfig(requestConfig);

        StringEntity postEntity = new StringEntity(xml.toString(), "UTF-8");
        httpPost.addHeader("Content-Type", "text/xml");
        httpPost.addHeader("User-Agent", "wxpay sdk java v1.0 " + WeChatConfig.MCH_ID);  // TODO: 很重要,用来检测 sdk 的使用情况,要不要加上商户信息?
        httpPost.setEntity(postEntity);
        HttpResponse httpResponse = httpClient.execute(httpPost);
        HttpEntity httpEntity = httpResponse.getEntity();
        return EntityUtils.toString(httpEntity, "UTF-8");
    }

发表评论

0/200
42 点赞
0 评论
收藏
为你推荐 换一批