java读取双向证书(p12)证书向微信发送请求

对有些微信接口为保证安全,需要p12证书进行请求,
获取证书:


获取证书的方式.png

PHP用到的证书.png

证书使用说明.png

加载证书的相关请求方式代码:

private static RequestConfig config;
private static HttpUtil httpUtil;

public static HttpUtil createHttpClientUtil(int connTimeout, int reqTimeout) {
        config = RequestConfig.custom().setConnectTimeout(connTimeout).setSocketTimeout(reqTimeout)
                .build();
        httpUtil = new HttpUtil();
        return httpUtil;
    }

private HttpUtil() {
    }
public static String requestWithHttpsWithP12(String url, String reqXml, String mchId, String cerPath) {
        try {
            ContentType contentType = ContentType.create("application/xml", "UTF-8");
            HttpUtil httpClient = createHttpClientUtil(8000, 8000);
            return httpClient.invokeRequestWithP12(url, reqXml, true, contentType, mchId, cerPath);
        } catch (Exception e) {
            log.error("执行http请求异常:", e);
            throw new ServiceException(GatewayErrorEnum.BF_CNCT_SENDFAIL);
        }

    }
    
    /**
     * 执行后台Http请求
     *
     * @param reqUrl      请求URl
     * @param params      请求参数
     * @param contentType contentType
     * @param sslFlg      是否需要ssl加密
     * @return
     */
    public String invokeRequestWithP12(String reqUrl, String params, boolean sslFlg,
                                       ContentType contentType, String mchId, String cerPath) {
        CloseableHttpClient httpClient = new DefaultHttpClient();
        KeyStore keyStore = null;
        try {
            keyStore = initCert(mchId, cerPath);

        } catch (Exception e) {
            e.printStackTrace();
        }
        if (sslFlg) {
            try {
                registerSSlp12(httpClient, keyStore, mchId);
            } catch (NoSuchAlgorithmException e) {
                log.error("注册SSL失败", e);
            } catch (KeyManagementException e) {
                log.error("注册SSL失败", e);
            }
        }
        HttpPost httpPost = new HttpPost(reqUrl);
        CloseableHttpResponse response = null;
        try {
            httpPost.setConfig(config);
            httpPost.setEntity(new StringEntity(params, contentType));
            response = httpClient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            String value = EntityUtils.toString(entity, contentType.getCharset());
            EntityUtils.consume(entity);
            return value;
        } catch (Exception e) {
            log.error("http请求异常", e);
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    log.error("response IOException", e);
                }
            }
            httpPost.releaseConnection();
            try {
                httpClient.close();
            } catch (IOException e) {
                log.error("httpClient IOException", e);
            }
        }
    }

上面代码中用到的两个方法:
1.加载p12证书的方法:

    /**
     * 加载证书
     *
     * @param mchId    商户ID
     * @param certPath 证书位置
     * @throws Exception
     */
    private static KeyStore initCert(String mchId, String certPath) throws Exception {

        // 证书密码,默认为商户ID
        String key = mchId;
        // 证书的路径
        String path = certPath;
        // 指定读取证书格式为PKCS12
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        // 读取本机存放的PKCS12证书文件
        String currentPath = Thread.currentThread().getContextClassLoader().getResource(certPath).getPath();
        log.info("路径:{}", currentPath);
        FileInputStream instream = new FileInputStream(new File(currentPath));

        try {
            // 指定PKCS12的密码(商户ID)
            keyStore.load(instream, key.toCharArray());

        } catch (Exception e) {
            log.error("keyStoreException", e);
        } finally {
            instream.close();
        }
        return keyStore;
    }

2.registerSSlp12方法:

private static void registerSSlp12(HttpClient httpclient, KeyStore keyStore, String mch) throws NoSuchAlgorithmException,
            KeyManagementException {
        SSLContext sslcontext = SSLContext.getInstance("SSL");
        X509TrustManager tm = new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] arg0,
                                           String arg1) throws CertificateException {
            }

            @Override
            public void checkServerTrusted(X509Certificate[] arg0,
                                           String arg1) throws CertificateException {
            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };
        String alg = KeyManagerFactory.getDefaultAlgorithm();
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(alg);
        try {
            keyManagerFactory.init(keyStore, mch.toCharArray());
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (UnrecoverableKeyException e) {
            e.printStackTrace();
        }
        KeyManager[] kms = keyManagerFactory.getKeyManagers();

        sslcontext.init(kms, new TrustManager[]{tm}, null);
        SSLSocketFactory sf = new SSLSocketFactory(sslcontext,
                SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        Scheme https = new Scheme("https", 443, sf);
        httpclient.getConnectionManager().getSchemeRegistry().register(https);
    }

相关链接:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=4_3

你可能感兴趣的:(java读取双向证书(p12)证书向微信发送请求)