From 48086312b60159a1212fc5d2afbca2d445bc3ae9 Mon Sep 17 00:00:00 2001 From: jinyu Date: Wed, 19 Aug 2015 14:14:57 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=AD=A3SSL=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../weixin4j/http/factory/HttpComponent3.java | 17 +- .../http/factory/HttpComponent3Response.java | 2 + .../weixin4j/http/factory/HttpComponent4.java | 36 ++++ .../http/factory/HttpComponent4_1.java | 9 +- .../http/factory/HttpComponent4_2.java | 8 + .../http/weixin/WeixinRequestExecutor.java | 26 +-- .../weixin4j/http/weixin/WeixinResponse.java | 1 - .../http/weixin/WeixinSSLRequestExecutor.java | 2 - .../com/foxinmy/weixin4j/mp/test/PayTest.java | 198 +++--------------- 9 files changed, 102 insertions(+), 197 deletions(-) diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent3.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent3.java index 79a952ae..564c199e 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent3.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent3.java @@ -31,7 +31,7 @@ import org.apache.commons.httpclient.methods.TraceMethod; import org.apache.commons.httpclient.params.HttpConnectionParams; import org.apache.commons.httpclient.protocol.ControllerThreadSocketFactory; import org.apache.commons.httpclient.protocol.Protocol; -import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; +import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory; import com.foxinmy.weixin4j.http.AbstractHttpClient; import com.foxinmy.weixin4j.http.HttpClient; @@ -97,10 +97,8 @@ public class HttpComponent3 extends AbstractHttpClient implements HttpClient { } SSLContext sslContext = params.getSSLContext(); if (sslContext != null) { - Protocol protocol = new Protocol("https", - new SSLProtocolSocketFactory(sslContext), 443); - httpClient.getHostConfiguration().setHost(uri.getHost(), - uri.getPort(), protocol); + Protocol.registerProtocol("https", new Protocol("https", + new SSLProtocolSocketFactory(sslContext), 443)); } httpClient.getHttpConnectionManager().getParams() .setConnectionTimeout(params.getConnectTimeout()); @@ -169,7 +167,7 @@ public class HttpComponent3 extends AbstractHttpClient implements HttpClient { } private static class SSLProtocolSocketFactory implements - ProtocolSocketFactory { + SecureProtocolSocketFactory { private final SSLContext sslContext; @@ -207,5 +205,12 @@ public class HttpComponent3 extends AbstractHttpClient implements HttpClient { UnknownHostException { return sslContext.getSocketFactory().createSocket(host, port); } + + @Override + public Socket createSocket(Socket socket, String host, int port, + boolean autoClose) throws IOException, UnknownHostException { + return sslContext.getSocketFactory().createSocket(socket, host, + port, autoClose); + } } } diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent3Response.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent3Response.java index 0fe3bb42..499153cf 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent3Response.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent3Response.java @@ -6,6 +6,7 @@ import java.io.InputStream; import org.apache.commons.httpclient.Header; import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.protocol.Protocol; import com.foxinmy.weixin4j.http.HttpClientException; import com.foxinmy.weixin4j.http.HttpHeaders; @@ -86,5 +87,6 @@ public class HttpComponent3Response implements HttpResponse { @Override public void close() { httpMethod.releaseConnection(); + Protocol.unregisterProtocol("https"); } } diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent4.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent4.java index 5e90d1f9..1f9fcc0a 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent4.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent4.java @@ -2,12 +2,18 @@ package com.foxinmy.weixin4j.http.factory; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.security.cert.X509Certificate; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLException; +import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLSocket; + import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; import org.apache.http.client.methods.HttpGet; @@ -17,6 +23,7 @@ import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.client.methods.HttpTrace; +import org.apache.http.conn.ssl.X509HostnameVerifier; import org.apache.http.entity.AbstractHttpEntity; import org.apache.http.entity.InputStreamEntity; @@ -86,4 +93,33 @@ public abstract class HttpComponent4 extends AbstractHttpClient { ((HttpEntityEnclosingRequestBase) uriRequest).setEntity(httpEntity); } } + + protected static class CustomHostnameVerifier implements + X509HostnameVerifier { + + private final HostnameVerifier hostnameVerifier; + + public CustomHostnameVerifier(HostnameVerifier hostnameVerifier) { + this.hostnameVerifier = hostnameVerifier; + } + + @Override + public boolean verify(String hostname, SSLSession session) { + return hostnameVerifier.verify(hostname, session); + } + + @Override + public void verify(String host, SSLSocket ssl) throws IOException { + } + + @Override + public void verify(String host, X509Certificate cert) + throws SSLException { + } + + @Override + public void verify(String host, String[] cns, String[] subjectAlts) + throws SSLException { + } + } } diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent4_1.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent4_1.java index bc1db10f..15211c9d 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent4_1.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent4_1.java @@ -8,6 +8,7 @@ import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.conn.params.ConnRoutePNames; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.ssl.SSLSocketFactory; +import org.apache.http.conn.ssl.X509HostnameVerifier; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.params.CoreConnectionPNames; import org.apache.http.params.CoreProtocolPNames; @@ -71,7 +72,13 @@ public class HttpComponent4_1 extends HttpComponent4 implements HttpClient { if (params.getSSLContext() != null) { SSLSocketFactory socketFactory = new SSLSocketFactory( params.getSSLContext()); - Scheme scheme = new Scheme("https", socketFactory, 433); + X509HostnameVerifier hostnameVerifier = SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER; + if (params.getHostnameVerifier() != null) { + hostnameVerifier = new CustomHostnameVerifier( + params.getHostnameVerifier()); + } + socketFactory.setHostnameVerifier(hostnameVerifier); + Scheme scheme = new Scheme("https", socketFactory, 443); httpClient.getConnectionManager().getSchemeRegistry() .register(scheme); } diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent4_2.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent4_2.java index aeec3093..49f03b2e 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent4_2.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent4_2.java @@ -8,6 +8,8 @@ import org.apache.http.client.config.RequestConfig; import org.apache.http.client.config.RequestConfig.Builder; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.conn.ssl.X509HostnameVerifier; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; @@ -54,7 +56,13 @@ public class HttpComponent4_2 extends HttpComponent4 implements HttpClient { requestConfig.setProxy(proxy); } if (params.getSSLContext() != null) { + X509HostnameVerifier hostnameVerifier = SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER; + if (params.getHostnameVerifier() != null) { + hostnameVerifier = new CustomHostnameVerifier( + params.getHostnameVerifier()); + } httpClient = HttpClients.custom() + .setHostnameVerifier(hostnameVerifier) .setSslcontext(params.getSSLContext()).build(); } uriRequest.setConfig(requestConfig.build()); diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/weixin/WeixinRequestExecutor.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/weixin/WeixinRequestExecutor.java index a540ea2e..9af976e5 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/weixin/WeixinRequestExecutor.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/weixin/WeixinRequestExecutor.java @@ -20,7 +20,6 @@ import com.foxinmy.weixin4j.http.entity.FormUrlEntity; import com.foxinmy.weixin4j.http.entity.HttpEntity; import com.foxinmy.weixin4j.http.entity.StringEntity; import com.foxinmy.weixin4j.http.factory.HttpClientFactory; -import com.foxinmy.weixin4j.http.factory.SimpleHttpClientFactory; import com.foxinmy.weixin4j.model.Consts; import com.foxinmy.weixin4j.util.StringUtil; import com.foxinmy.weixin4j.util.WeixinErrorUtil; @@ -45,7 +44,6 @@ public class WeixinRequestExecutor { } public WeixinRequestExecutor(HttpParams params) { - HttpClientFactory.setDefaultFactory(new SimpleHttpClientFactory()); this.httpClient = HttpClientFactory.getInstance(); this.params = params; } @@ -153,32 +151,30 @@ public class WeixinRequestExecutor { } protected void checkXml(WeixinResponse response) throws WeixinException { - XmlResult xmlResult = null; - try { - xmlResult = response.getAsXmlResult(); - } catch (IllegalArgumentException ex) { + String xmlContent = response.getAsString(); + if (xmlContent.length() != xmlContent.replaceFirst("", + "").length()) { // - String newXml = response.getAsString() - .replaceFirst("", "") + xmlContent = xmlContent.replaceFirst("", "") .replaceFirst("", "") .replaceFirst("", "") .replaceFirst("", "") .replaceFirst("", "") .replaceFirst("", ""); - xmlResult = XmlStream.fromXML(newXml, XmlResult.class); - response.setText(newXml); } + XmlResult xmlResult = XmlStream.fromXML(xmlContent, XmlResult.class); + response.setText(xmlContent); response.setXmlResult(true); - if (xmlResult.getReturnCode().equals("0")) { + if ("0".equals(xmlResult.getReturnCode())) { return; } - if (!xmlResult.getReturnCode().equalsIgnoreCase( - com.foxinmy.weixin4j.model.Consts.SUCCESS)) { + if (!com.foxinmy.weixin4j.model.Consts.SUCCESS + .equalsIgnoreCase(xmlResult.getReturnCode())) { throw new WeixinException(xmlResult.getReturnCode(), xmlResult.getReturnMsg()); } - if (!xmlResult.getResultCode().equalsIgnoreCase( - com.foxinmy.weixin4j.model.Consts.SUCCESS)) { + if (!com.foxinmy.weixin4j.model.Consts.SUCCESS + .equalsIgnoreCase(xmlResult.getResultCode())) { throw new WeixinException(xmlResult.getErrCode(), xmlResult.getErrCodeDes()); } diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/weixin/WeixinResponse.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/weixin/WeixinResponse.java index 55b06cc0..1e17d5b6 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/weixin/WeixinResponse.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/weixin/WeixinResponse.java @@ -42,7 +42,6 @@ public class WeixinResponse { try { text = StringUtil.newStringUtf8(IOUtil.toByteArray(body)); } catch (IOException e) { - e.printStackTrace(); ; } } diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/weixin/WeixinSSLRequestExecutor.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/weixin/WeixinSSLRequestExecutor.java index 98be4304..2bf1ebe5 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/weixin/WeixinSSLRequestExecutor.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/weixin/WeixinSSLRequestExecutor.java @@ -1,9 +1,7 @@ package com.foxinmy.weixin4j.http.weixin; import java.io.InputStream; -import java.security.KeyManagementException; import java.security.KeyStore; -import java.security.NoSuchAlgorithmException; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; diff --git a/weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/PayTest.java b/weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/PayTest.java index d9ddf7de..05f353a2 100644 --- a/weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/PayTest.java +++ b/weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/PayTest.java @@ -26,306 +26,160 @@ import com.foxinmy.weixin4j.type.IdType; import com.foxinmy.weixin4j.type.TradeType; import com.foxinmy.weixin4j.util.Weixin4jConfigUtil; -/** - * - * 支付相关测试 - * - * - * - * @className PayTest - * - * @author jy - * - * @date 2015年8月19日 - * - * @since JDK 1.7 - * - * @see - */ - public class PayTest { - protected final static Pay2Api PAY2; - protected final static WeixinPayProxy PAY3; - protected final static WeixinPayAccount ACCOUNT2; - protected final static WeixinPayAccount ACCOUNT3; - static { - - ACCOUNT2 = new WeixinPayAccount( - - "wxba294f2c6f330361", - - "8e33f5371a1afea1f7bce88088cb4bba", - - "gADrKITv3qYWu9JEg1NS0WPaU5yFgTwS9WfPueskfPpt3OZGpnUN1uBom36G2tP701vi2pPRJLZF9dEDFj9pqxidPn10Y91Lj8kK37Svz6S4MfeAHo9svFZmHkIKScGb", - - null, null, null, "1221928801", - - "8d1b26231827a965ef54fe6a3a151551"); - + ACCOUNT2 = new WeixinPayAccount("请填入v2版本的appid", "请填入v2版本的appSecret", + "请填入v2版本的paysignkey", null, null, null, "请填入v2版本的partnerId", + "请填入v2版本的partnerKey"); PAY2 = new Pay2Api(ACCOUNT2, new FileTokenStorager( - - Weixin4jConfigUtil - - .getValue("token_path", "/tmp/weixin4j/token"))); - - ACCOUNT3 = new WeixinPayAccount("wx0d1d598c0c03c999", - - "2513ac683f1beabdb6b98d9ddd9e5755", - - "GATFzDwbQdbbci3QEQxX2rUBvwTrsMiZ", "10020674"); - + Weixin4jConfigUtil + .getValue("token_path", "/tmp/weixin4j/token"))); + ACCOUNT3 = new WeixinPayAccount("请填入v3版本的appid", "请填入v3版本的appSecret", + "请填入v3版本的paysignkey", "请填入v3版本的mchid", null, null, null, null); PAY3 = new WeixinPayProxy(ACCOUNT3); - } - /** - * - * 商户的证书文件 + * 商户证书文件 */ - - protected final File caFile = new File( - - "/Users/jy/workspace/feican/canyi-weixin-parent/canyi-weixin-service/src/main/resources/10020674.p12"); + protected File caFile = new File("证书文件,如12333.p12"); @Test public void orderQueryV2() throws WeixinException { - System.err.println(PAY2.orderQuery(new IdQuery("D14110500021", - - IdType.REFUNDNO))); - + IdType.REFUNDNO))); } @Test public void refundV2() throws WeixinException { - - File caFile = new File( - - "/Users/jy/workspace/feican/canyi-weixin-parent/canyi-weixin-service/src/main/resources/1221928801.pfx"); - + File caFile = new File("证书文件,如12333.pfx"); IdQuery idQuery = new IdQuery("D15020300005", IdType.TRADENO); - System.err.println(PAY2.refundApply(caFile, idQuery, "1422925555037", - - 16d, 16d, "1221928801", "111111", null, null, null)); - + 16d, 16d, "1221928801", "111111", null, null, null)); } @Test public void refundQueryV2() throws WeixinException { - System.err.println(PAY2.refundQuery(new IdQuery("D14123000004", - - IdType.TRADENO))); - + IdType.TRADENO))); refundQueryV3(); - } @Test public void downbillV2() throws WeixinException { - Calendar c = Calendar.getInstance(); - c.set(Calendar.YEAR, 2014); - c.set(Calendar.MONTH, 11); - c.set(Calendar.DAY_OF_MONTH, 22); - File file = PAY2.downloadbill(c.getTime(), null); - System.err.println(file); - } @Test public void orderQueryV3() throws WeixinException { - Order order = PAY3.orderQuery(new IdQuery("T0002", IdType.TRADENO)); - System.err.println(order); - String sign = order.getSign(); - order.setSign(null); - String valiSign = PayUtil.paysignMd5(order, ACCOUNT3.getPaySignKey()); - System.err - - .println(String.format("sign=%s,valiSign=%s", sign, valiSign)); - + .println(String.format("sign=%s,valiSign=%s", sign, valiSign)); Assert.assertEquals(valiSign, sign); - } @Test public void refundQueryV3() throws WeixinException { - com.foxinmy.weixin4j.payment.mch.RefundRecord record = PAY3 - - .refundQueryV3(new IdQuery("TT_1427183696238", IdType.TRADENO)); - + .refundQueryV3(new IdQuery("TT_1427183696238", IdType.TRADENO)); System.err.println(record); - // 这里的验证签名需要把details循环拼接 - String sign = record.getSign(); - record.setSign(null); - String valiSign = PayUtil.paysignMd5(record, ACCOUNT3.getPaySignKey()); - System.err - - .println(String.format("sign=%s,valiSign=%s", sign, valiSign)); - + .println(String.format("sign=%s,valiSign=%s", sign, valiSign)); Assert.assertEquals(valiSign, sign); - } @Test public void downbillV3() throws WeixinException { - Calendar c = Calendar.getInstance(); - System.err.println(c.getTime()); - c.set(Calendar.YEAR, 2015); - c.set(Calendar.MONTH, 2); - c.set(Calendar.DAY_OF_MONTH, 24); - System.err.println(c.getTime()); - File file = PAY3.downloadbill(c.getTime(), null); - System.err.println(file); - } @Test public void refundV3() throws WeixinException, IOException { - + File caFile = new File("签名文件如123.p12"); IdQuery idQuery = new IdQuery("TT_1427183696238", IdType.TRADENO); - com.foxinmy.weixin4j.payment.mch.RefundResult result = PAY3 - - .refundApply(new FileInputStream(caFile), idQuery, "TT_R" - - + System.currentTimeMillis(), 0.01d, 0.01d, null, - - "10020674"); - + .refundApply(new FileInputStream(caFile), idQuery, "TT_R" + + System.currentTimeMillis(), 0.01d, 0.01d, null, + "10020674"); System.err.println(result); - String sign = result.getSign(); - result.setSign(null); - String valiSign = PayUtil.paysignMd5(result, ACCOUNT3.getPaySignKey()); - System.err - - .println(String.format("sign=%s,valiSign=%s", sign, valiSign)); - + .println(String.format("sign=%s,valiSign=%s", sign, valiSign)); Assert.assertEquals(valiSign, sign); - } @Test public void nativeV3() throws WeixinException { - MchPayPackage payPackageV3 = new MchPayPackage(ACCOUNT3, - - "oyFLst1bqtuTcxK-ojF8hOGtLQao", "native测试", "T0001", 0.1d, - - "127.0.0.1", TradeType.NATIVE); - + "oyFLst1bqtuTcxK-ojF8hOGtLQao", "native测试", "T0001", 0.1d, + "127.0.0.1", TradeType.NATIVE); payPackageV3.setProductId("0001"); - payPackageV3.setNotifyUrl("xxxx"); - PrePay prePay = null; - try { - prePay = PayUtil.createPrePay(payPackageV3, - - ACCOUNT3.getPaySignKey()); - + ACCOUNT3.getPaySignKey()); } catch (PayException e) { - e.printStackTrace(); - } - System.err.println(prePay); - } @Test public void closeOrder() throws WeixinException { - ApiResult result = PAY3.closeOrder("D111"); - System.err.println(result); - String sign = result.getSign(); - result.setSign(null); - String valiSign = PayUtil.paysignMd5(result, ACCOUNT3.getPaySignKey()); - System.err - - .println(String.format("sign=%s,valiSign=%s", sign, valiSign)); - + .println(String.format("sign=%s,valiSign=%s", sign, valiSign)); Assert.assertEquals(valiSign, sign); - } @Test public void shortUrl() throws WeixinException { - String url = "weixin://wxpay/bizpayurl?xxxxxx"; - String shortUrl = PAY3.getPayShorturl(url); - System.err.println(shortUrl); - } @Test public void interfaceReport() throws WeixinException { - String interfaceUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder"; - int executeTime = 2500; - String outTradeNo = null; - String ip = "127.0.0.1"; - Date time = new Date(); - XmlResult returnXml = new XmlResult("SUCCESS", ""); - returnXml.setResultCode("SUCCESS"); - returnXml = PAY3.interfaceReport(interfaceUrl, executeTime, outTradeNo, - - ip, time, returnXml); - + ip, time, returnXml); System.err.println(returnXml); - } - }