微信 企業付款到零錢

微信相關配置

一、公衆平臺

受權域名回調

二、商戶平臺

路徑:商戶平臺:帳戶中心 》 帳戶設置 》API安全
一、api 安全配置 (指的是:容許調用接口的白名單配置)
二、證書下載 (本次代碼主要使用的是 p12 證書)

企業付款到零錢,是須要 open_id 參數的,open_id 參數的獲取,參考其餘文章,此處不作記錄java

主要發起支付的代碼

工具類

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");
    }
相關文章
相關標籤/搜索