一、使用微信sdk的Xml转换工具类
import org.w3c.dom.Document;import javax.xml.XMLConstants;import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;import javax.xml.parsers.ParserConfigurationException;/*** /7/3*/public final class WXPayXmlUtil {public static DocumentBuilder newDocumentBuilder() throws ParserConfigurationException {DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();documentBuilderFactory.setFeature("/xml/features/disallow-doctype-decl", true);documentBuilderFactory.setFeature("/sax/features/external-general-entities", false);documentBuilderFactory.setFeature("/sax/features/external-parameter-entities", false);documentBuilderFactory.setFeature("/xml/features/nonvalidating/load-external-dtd", false);documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);documentBuilderFactory.setXIncludeAware(false);documentBuilderFactory.setExpandEntityReferences(false);return documentBuilderFactory.newDocumentBuilder();}public static Document newDocument() throws ParserConfigurationException {return newDocumentBuilder().newDocument();}}
二、进行携带证书的http的请求,获取公钥
package co.ganxiang.mp.test;import java.io.*;import java.security.KeyStore;import java.security.MessageDigest;import java.security.PublicKey;import java.security.SecureRandom;import java.util.*;import .ssl.SSLContext;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 co.ganxiang.mp.utils.Base64;import co.ganxiang.mp.utils.RSAUtil;import org.apache.http.HttpEntity;import org.apache.http.client.methods.CloseableHttpResponse;import org.apache.http.client.methods.HttpPost;import org.apache.http.conn.ssl.SSLConnectionSocketFactory;import org.apache.http.entity.StringEntity;import org.apache.http.impl.client.CloseableHttpClient;import org.apache.http.impl.client.HttpClients;import org.apache.http.ssl.SSLContexts;import org.apache.http.util.EntityUtils;import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;public class HttpClientSSL {Logger log = LogManager.getLogger(HttpClientSSL.class);private static String payUrl = "https://fraud.mch./risk/getpublickey";//商户keyprivate static String KEY = "xxxxxxxxxx";//商户mch_idprivate static String mchId = "xxxxxxxxx";public static void main(String[] args) throws Exception {Map<String, String> parameterMap = new HashMap<>();parameterMap.put("mch_id", mchId);parameterMap.put("nonce_str", generateNonceStr());try{parameterMap.put("sign_type", "MD5");parameterMap.put("sign", HttpClientSSL.generateSignature(parameterMap,KEY,"MD5"));//要以xml格式传递String postDataXML = HttpClientSSL.mapToXml(parameterMap);String result = HttpClientSSL.wxRefundLink(postDataXML, mchId );System.out.println(result);}catch (Exception e){e.printStackTrace();}}/*** 将Map转换为XML格式的字符串** @param data Map类型数据* @return XML格式的字符串* @throws Exception*/public static String mapToXml(Map<String, String> data) throws Exception {org.w3c.dom.Document document = WXPayXmlUtil.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;}private static final String SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";private static final Random RANDOM = new SecureRandom();/*** 获取随机字符串 Nonce Str** @return String 随机字符串*/public static String generateNonceStr() {char[] nonceChars = new char[32];for (int index = 0; index < nonceChars.length; ++index) {nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length()));}return new String(nonceChars);}public static String generateSignature(Map<String, String> data, String key, String signType) throws Exception {Set<String> keySet = data.keySet();String[] keyArray = keySet.toArray(new String[keySet.size()]);Arrays.sort(keyArray);StringBuilder sb = new StringBuilder();for (String k : keyArray) {if (k.equals("sign")) {continue;}if (data.get(k).trim().length() > 0) // 参数值为空,则不参与签名sb.append(k).append("=").append(data.get(k).trim()).append("&");}sb.append("key=").append(key);if ("MD5".equals(signType)) {return MD5(sb.toString()).toUpperCase();}else {throw new Exception(String.format("Invalid sign_type: %s", signType));}}/*** 生成 MD5** @param data 待处理数据* @return MD5结果*/public static String MD5(String data) throws Exception {java.security.MessageDigest md = MessageDigest.getInstance("MD5");byte[] array = md.digest(data.getBytes("UTF-8"));StringBuilder sb = new StringBuilder();for (byte item : array) {sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));}return sb.toString().toUpperCase();}private static String wxRefundLink(String postDataXML,String mch_id) throws Exception{CloseableHttpClient httpClient = null;CloseableHttpResponse httpResponse = null;try{//获取微信支付api证书KeyStore keyStore = getCertificate(mch_id);SSLContext sslContext = SSLContexts.custom().loadKeyMaterial(keyStore, mch_id.toCharArray()).build();SSLConnectionSocketFactory sslf = new SSLConnectionSocketFactory(sslContext);httpClient = HttpClients.custom().setSSLSocketFactory(sslf).build();HttpPost httpPost = new HttpPost(payUrl);StringEntity reqEntity = new StringEntity(postDataXML);// 设置类型reqEntity.setContentType("application/x-www-form-urlencoded");httpPost.setEntity(reqEntity);String result = null;httpResponse = httpClient.execute(httpPost);HttpEntity httpEntity = httpResponse.getEntity();result = EntityUtils.toString(httpEntity, "UTF8");EntityUtils.consume(httpEntity);return result;}finally {//关流httpClient.close();httpResponse.close();}}/**** @description: 获取微信支付api证书*/private static KeyStore getCertificate(String mch_id){//try-with-resources 关流try (FileInputStream inputStream = new FileInputStream(new File("C:\\Users\\Administrator\\Desktop\\apiclient_cert.p12"))//证书文件位置) {KeyStore keyStore = KeyStore.getInstance("PKCS12");keyStore.load(inputStream, mch_id.toCharArray());return keyStore;} catch (Exception e) {throw new RuntimeException(e.getMessage(), e);}}}
三、打印出来的公钥可以到SSL在线工具-在线RSA公私钥格式转换|公钥PKCS1与PKCS8转换|私钥PKCS1与PKCS8转换-SSLeye官网进行转换