Showing
3 changed files
with
383 additions
and
1 deletions
@@ -25,6 +25,11 @@ | @@ -25,6 +25,11 @@ | ||
25 | <dependency> | 25 | <dependency> |
26 | <groupId>javax.servlet</groupId> | 26 | <groupId>javax.servlet</groupId> |
27 | <artifactId>javax.servlet-api</artifactId> | 27 | <artifactId>javax.servlet-api</artifactId> |
28 | - </dependency> | 28 | + </dependency> |
29 | + <!-- 测试用 --> | ||
30 | + <dependency> | ||
31 | + <groupId>junit</groupId> | ||
32 | + <artifactId>junit</artifactId> | ||
33 | + </dependency> | ||
29 | </dependencies> | 34 | </dependencies> |
30 | </project> | 35 | </project> |
1 | +package com.yoho.pay; | ||
2 | + | ||
3 | +import org.apache.http.HttpStatus; | ||
4 | +import org.apache.http.NameValuePair; | ||
5 | +import org.apache.http.client.config.RequestConfig; | ||
6 | +import org.apache.http.client.entity.UrlEncodedFormEntity; | ||
7 | +import org.apache.http.client.methods.CloseableHttpResponse; | ||
8 | +import org.apache.http.client.methods.HttpGet; | ||
9 | +import org.apache.http.client.methods.HttpPost; | ||
10 | +import org.apache.http.client.methods.HttpUriRequest; | ||
11 | +import org.apache.http.config.Registry; | ||
12 | +import org.apache.http.config.RegistryBuilder; | ||
13 | +import org.apache.http.conn.socket.ConnectionSocketFactory; | ||
14 | +import org.apache.http.conn.socket.PlainConnectionSocketFactory; | ||
15 | +import org.apache.http.conn.ssl.NoopHostnameVerifier; | ||
16 | +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; | ||
17 | +import org.apache.http.entity.StringEntity; | ||
18 | +import org.apache.http.impl.client.CloseableHttpClient; | ||
19 | +import org.apache.http.impl.client.HttpClientBuilder; | ||
20 | +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; | ||
21 | +import org.apache.http.message.BasicNameValuePair; | ||
22 | +import org.apache.http.ssl.SSLContextBuilder; | ||
23 | +import org.apache.http.ssl.TrustStrategy; | ||
24 | +import org.apache.http.util.EntityUtils; | ||
25 | +import org.slf4j.Logger; | ||
26 | +import org.slf4j.LoggerFactory; | ||
27 | +import javax.net.ssl.HostnameVerifier; | ||
28 | +import javax.net.ssl.SSLContext; | ||
29 | +import java.security.cert.CertificateException; | ||
30 | +import java.security.cert.X509Certificate; | ||
31 | +import java.util.ArrayList; | ||
32 | +import java.util.List; | ||
33 | +import java.util.Map; | ||
34 | + | ||
35 | +public class HttpClient { | ||
36 | + private Logger logger = LoggerFactory.getLogger(getClass()); | ||
37 | + | ||
38 | + protected static final int connectionRequestTimeout = 6000; | ||
39 | + protected static final int connectionTimeout = 3000; | ||
40 | + protected static final int socketTimeout = 2000; | ||
41 | + | ||
42 | + //最大总数 | ||
43 | + private final int maxTotal = 30; | ||
44 | + | ||
45 | + //默认并发数 | ||
46 | + private final int defaultMaxPerRoute = 10; | ||
47 | + | ||
48 | + protected CloseableHttpClient httpClient; | ||
49 | + | ||
50 | + public void init() throws Exception{ | ||
51 | + HttpClientBuilder b = HttpClientBuilder.create(); | ||
52 | + | ||
53 | + // setup a Trust Strategy that allows all certificates. | ||
54 | + // | ||
55 | + SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, | ||
56 | + new TrustStrategy() { | ||
57 | + @Override | ||
58 | + public boolean isTrusted(X509Certificate[] arg0, String arg1) | ||
59 | + throws CertificateException { | ||
60 | + return true; | ||
61 | + } | ||
62 | + }).build(); | ||
63 | + b.setSSLContext(sslContext); | ||
64 | + | ||
65 | + // don't check Hostnames, either. | ||
66 | + // -- use SSLConnectionSocketFactory.getDefaultHostnameVerifier(), if | ||
67 | + // you don't want to weaken | ||
68 | + HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE; | ||
69 | + | ||
70 | + // here's the special part: | ||
71 | + // -- need to create an SSL Socket Factory, to use our weakened | ||
72 | + // "trust strategy"; | ||
73 | + // -- and create a Registry, to register it. | ||
74 | + // | ||
75 | + SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory( | ||
76 | + sslContext, hostnameVerifier); | ||
77 | + Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder | ||
78 | + .<ConnectionSocketFactory> create() | ||
79 | + .register("http", | ||
80 | + PlainConnectionSocketFactory.getSocketFactory()) | ||
81 | + .register("https", sslSocketFactory).build(); | ||
82 | + | ||
83 | + // now, we create connection-manager using our Registry. | ||
84 | + // -- allows multi-threaded use | ||
85 | + PoolingHttpClientConnectionManager connMgr = new PoolingHttpClientConnectionManager( | ||
86 | + socketFactoryRegistry); | ||
87 | + connMgr.setMaxTotal(maxTotal); | ||
88 | + connMgr.setDefaultMaxPerRoute(defaultMaxPerRoute); | ||
89 | + b.setConnectionManager(connMgr); | ||
90 | + | ||
91 | + //request config | ||
92 | + RequestConfig requestConfig = RequestConfig.custom() | ||
93 | + .setConnectionRequestTimeout(connectionRequestTimeout) | ||
94 | + .setConnectTimeout(connectionTimeout) | ||
95 | + .setSocketTimeout(socketTimeout) | ||
96 | + .build(); | ||
97 | + b.setDefaultRequestConfig(requestConfig); | ||
98 | + | ||
99 | + // finally, build the HttpClient; | ||
100 | + // -- done! | ||
101 | + httpClient = b.build(); | ||
102 | + } | ||
103 | + | ||
104 | + public void destroy() { | ||
105 | + if(httpClient != null) | ||
106 | + httpClient.getConnectionManager().shutdown(); | ||
107 | + } | ||
108 | + | ||
109 | + /** | ||
110 | + * Get请求 | ||
111 | + * @param url | ||
112 | + * @return | ||
113 | + * @throws Exception | ||
114 | + */ | ||
115 | + public String get(String url) throws Exception { | ||
116 | + HttpGet httpget = new HttpGet(url); | ||
117 | + return sendHttpRequest(httpget); | ||
118 | + } | ||
119 | + | ||
120 | + /** | ||
121 | + * Post请求 | ||
122 | + * @param url | ||
123 | + * @param body | ||
124 | + * @return | ||
125 | + * @throws Exception | ||
126 | + */ | ||
127 | + public String post(String url, String body) throws Exception { | ||
128 | + HttpPost httpPost = new HttpPost(url); | ||
129 | + httpPost.addHeader("Content-Type", "application/json;charset=UTF-8"); | ||
130 | + httpPost.setEntity(new StringEntity(body, "UTF-8")); | ||
131 | + return sendHttpRequest(httpPost); | ||
132 | + } | ||
133 | + | ||
134 | + /** | ||
135 | + * 提交form-data | ||
136 | + * @param url | ||
137 | + * @param formDataMap | ||
138 | + * @return | ||
139 | + * @throws Exception | ||
140 | + */ | ||
141 | + public String postFormData(String url, Map<String, String> formDataMap) throws Exception { | ||
142 | + HttpPost httpPost = new HttpPost(url); | ||
143 | + //httpPost.addHeader("Content-Type", "multipart/form-data;charset=UTF-8"); | ||
144 | + List <NameValuePair> nvps = new ArrayList <NameValuePair>(); | ||
145 | + if(formDataMap != null) { | ||
146 | + for(Map.Entry<String, String> data : formDataMap.entrySet()) { | ||
147 | + nvps.add(new BasicNameValuePair(data.getKey(), data.getValue())); | ||
148 | + } | ||
149 | + } | ||
150 | + httpPost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8")); | ||
151 | + return sendHttpRequest(httpPost); | ||
152 | + } | ||
153 | + | ||
154 | + /** | ||
155 | + * http发送请求 | ||
156 | + * @param httpRequest | ||
157 | + * @return | ||
158 | + * @throws Exception | ||
159 | + */ | ||
160 | + private String sendHttpRequest(HttpUriRequest httpRequest) throws Exception { | ||
161 | + CloseableHttpResponse response = null; | ||
162 | + try { | ||
163 | + response = httpClient.execute(httpRequest); | ||
164 | + int statusCode = response.getStatusLine().getStatusCode(); | ||
165 | + if (statusCode != HttpStatus.SC_OK) { | ||
166 | + logger.error("http response code: {}, request: {}", statusCode, httpRequest.getURI()); | ||
167 | + throw new RuntimeException("http response status: " + statusCode); | ||
168 | + } | ||
169 | + | ||
170 | + return EntityUtils.toString(response.getEntity(), "UTF-8"); | ||
171 | + } | ||
172 | + finally { | ||
173 | + if (response != null) { | ||
174 | + try { | ||
175 | + response.close(); | ||
176 | + } catch (Exception e) { | ||
177 | + logger.error("pay httpclient resp close failed: {}", e.getMessage()); | ||
178 | + } | ||
179 | + } | ||
180 | + if(httpRequest != null) { | ||
181 | + try { | ||
182 | + httpRequest.abort(); | ||
183 | + } catch (Exception e) { | ||
184 | + logger.error("pay httpclient req abort failed: {}", e.getMessage()); | ||
185 | + } | ||
186 | + } | ||
187 | + } | ||
188 | + } | ||
189 | + | ||
190 | +} |
payment/test/java/com/yoho/pay/PayTest.java
0 → 100644
1 | +package com.yoho.pay; | ||
2 | + | ||
3 | +import com.alibaba.fastjson.JSON; | ||
4 | +import com.alibaba.fastjson.JSONObject; | ||
5 | +import com.google.common.collect.Lists; | ||
6 | +import com.yoho.core.common.utils.DateUtil; | ||
7 | +import com.yoho.core.common.utils.MD5; | ||
8 | +import org.junit.Test; | ||
9 | + | ||
10 | + | ||
11 | +import java.util.Collections; | ||
12 | +import java.util.Date; | ||
13 | +import java.util.List; | ||
14 | +import java.util.stream.Collectors; | ||
15 | + | ||
16 | + | ||
17 | +public class PayTest { | ||
18 | + | ||
19 | + | ||
20 | + public static final String url = "https://qr-test2.chinaums.com/netpay-route-server/api/"; | ||
21 | + | ||
22 | + /** | ||
23 | + * 预支付=下单接口 支付宝 | ||
24 | + */ | ||
25 | + @Test | ||
26 | + public void testPrepay() throws Exception { | ||
27 | + | ||
28 | + JSONObject data = new JSONObject(); | ||
29 | + data.put("msgSrc","WWW.TEST.COM"); | ||
30 | + // 支付宝 | ||
31 | + data.put("msgType", "trade.precreate"); // 微信:wx.unifiedOrder, 支付宝:trade.precreate, 全民付:qmf.order, 银联云闪付:uac.appOrder | ||
32 | + data.put("requestTimestamp", DateUtil.date2String(new Date(), "yyyy-MM-dd HH:mm:ss")); | ||
33 | + // 支付宝- 31945075157 | ||
34 | + data.put("merOrderId", "31945075157"); | ||
35 | + data.put("mid", "898310148160568"); //商户号 仅用于支付宝和云闪付 | ||
36 | + data.put("tid","00000001"); //终端号 | ||
37 | + data.put("instMid", "APPDEFAULT"); // 机构商户号 | ||
38 | + data.put("totalAmount", 1); | ||
39 | + | ||
40 | + | ||
41 | + data.put("sign", getSign(data)); | ||
42 | + | ||
43 | + HttpClient httpClient = new HttpClient(); | ||
44 | + httpClient.init(); | ||
45 | + String result = httpClient.post(url, JSON.toJSONString(data)); | ||
46 | + System.out.println(result); | ||
47 | + | ||
48 | + | ||
49 | + } | ||
50 | + | ||
51 | + /** | ||
52 | + * 预支付=下单接口 微信 | ||
53 | + */ | ||
54 | + @Test | ||
55 | + public void testPrepayWx() throws Exception { | ||
56 | + | ||
57 | + JSONObject data = new JSONObject(); | ||
58 | + data.put("msgSrc","WWW.TEST.COM"); | ||
59 | + // 支付宝 | ||
60 | + data.put("msgType", "wx.unifiedOrder"); // 微信:wx.unifiedOrder, 支付宝:trade.precreate, 全民付:qmf.order, 银联云闪付:uac.appOrder | ||
61 | + data.put("requestTimestamp", DateUtil.date2String(new Date(), "yyyy-MM-dd HH:mm:ss")); | ||
62 | + // 支付宝- 31945075157 | ||
63 | + data.put("merOrderId", "3194"+"24253748565"); | ||
64 | + data.put("mid", "898310148160568"); //商户号 仅用于支付宝和云闪付 | ||
65 | + data.put("tid","00000001"); //终端号 | ||
66 | + data.put("instMid", "APPDEFAULT"); // 机构商户号 | ||
67 | + data.put("totalAmount", 1); | ||
68 | + data.put("tradeType","APP"); | ||
69 | + | ||
70 | + | ||
71 | + data.put("sign", getSign(data)); | ||
72 | + | ||
73 | + HttpClient httpClient = new HttpClient(); | ||
74 | + httpClient.init(); | ||
75 | + String result = httpClient.post(url, JSON.toJSONString(data)); | ||
76 | + System.out.println(result); | ||
77 | + | ||
78 | + } | ||
79 | + | ||
80 | + /** | ||
81 | + * 预支付=下单接口 微信 | ||
82 | + */ | ||
83 | + @Test | ||
84 | + public void testPrepayQmf() throws Exception { | ||
85 | + | ||
86 | + JSONObject data = new JSONObject(); | ||
87 | + data.put("msgSrc","WWW.TEST.COM"); | ||
88 | + // 支付宝 | ||
89 | + data.put("msgType", "uac.appOrder"); // 微信:wx.unifiedOrder, 支付宝:trade.precreate, 全民付:qmf.order, 银联云闪付:uac.appOrder | ||
90 | + data.put("requestTimestamp", DateUtil.date2String(new Date(), "yyyy-MM-dd HH:mm:ss")); | ||
91 | + // 支付宝- 31945075157 | ||
92 | + data.put("merOrderId", "3194"+"24253748567"); | ||
93 | + data.put("mid", "898310148160568"); //商户号 仅用于支付宝和云闪付 | ||
94 | + data.put("tid","00000001"); //终端号 | ||
95 | + data.put("instMid", "APPDEFAULT"); // 机构商户号 | ||
96 | + data.put("totalAmount", 1); | ||
97 | + data.put("tradeType","APP"); | ||
98 | + | ||
99 | + | ||
100 | + data.put("sign", getSign(data)); | ||
101 | + | ||
102 | + HttpClient httpClient = new HttpClient(); | ||
103 | + httpClient.init(); | ||
104 | + String result = httpClient.post(url, JSON.toJSONString(data)); | ||
105 | + System.out.println(result); | ||
106 | + | ||
107 | + } | ||
108 | + | ||
109 | + | ||
110 | + public static String getSign(JSONObject data){ | ||
111 | + List<String> list = Lists.newArrayList(); | ||
112 | + for (String str: data.keySet()){ | ||
113 | + list.add(str+"="+data.getString(str)); | ||
114 | + } | ||
115 | + | ||
116 | + Collections.sort(list); | ||
117 | + String param = list.stream().collect(Collectors.joining("&")); | ||
118 | + | ||
119 | + String sign = MD5.md5(param+"fcAmtnx7MwismjWNhNKdHC44mNXtnEQeJkRrhKJwyrW2ysRR"); | ||
120 | + return sign; | ||
121 | + } | ||
122 | + | ||
123 | + | ||
124 | + | ||
125 | + /** | ||
126 | + * 订单查询接口 | ||
127 | + */ | ||
128 | + @Test | ||
129 | + public void testQuary(){ | ||
130 | + | ||
131 | + JSONObject data = new JSONObject(); | ||
132 | + data.put("msgSrc","WWW.TEST.COM"); | ||
133 | + // 支付宝 | ||
134 | + data.put("msgType", "query"); // 微信:wx.unifiedOrder, 支付宝:trade.precreate, 全民付:qmf.order, 银联云闪付:uac.appOrder | ||
135 | + data.put("requestTimestamp", DateUtil.date2String(new Date(), "yyyy-MM-dd HH:mm:ss")); | ||
136 | + data.put("merOrderId", "24455075157"); | ||
137 | + data.put("mid", "898310148160568"); //商户号 仅用于支付宝和云闪付 | ||
138 | + data.put("tid","00000001"); //终端号 | ||
139 | + data.put("instMid", "APPDEFAULT"); // 机构商户号 | ||
140 | + | ||
141 | + data.put("sign", getSign(data)); | ||
142 | + } | ||
143 | + | ||
144 | + | ||
145 | + /** | ||
146 | + * 订单退款 | ||
147 | + */ | ||
148 | + @Test | ||
149 | + public void testRefund(){ | ||
150 | + | ||
151 | + JSONObject data = new JSONObject(); | ||
152 | + data.put("msgSrc","WWW.TEST.COM"); | ||
153 | + // 支付宝 | ||
154 | + data.put("msgType", "refund"); // 微信:wx.unifiedOrder, 支付宝:trade.precreate, 全民付:qmf.order, 银联云闪付:uac.appOrder | ||
155 | + data.put("requestTimestamp", DateUtil.date2String(new Date(), "yyyy-MM-dd HH:mm:ss")); | ||
156 | + data.put("merOrderId", "24455075157"); | ||
157 | + data.put("mid", "898310148160568"); //商户号 仅用于支付宝和云闪付 | ||
158 | + data.put("tid","00000001"); //终端号 | ||
159 | + data.put("instMid", "APPDEFAULT"); // 机构商户号 | ||
160 | + data.put("refundAmount",1); | ||
161 | + | ||
162 | + data.put("sign", getSign(data)); | ||
163 | + } | ||
164 | + | ||
165 | + /** | ||
166 | + * 订单关闭 | ||
167 | + */ | ||
168 | + @Test | ||
169 | + public void testClose(){ | ||
170 | + | ||
171 | + JSONObject data = new JSONObject(); | ||
172 | + data.put("msgSrc","WWW.TEST.COM"); | ||
173 | + // 支付宝 | ||
174 | + data.put("msgType", "close"); // 微信:wx.unifiedOrder, 支付宝:trade.precreate, 全民付:qmf.order, 银联云闪付:uac.appOrder | ||
175 | + data.put("requestTimestamp", DateUtil.date2String(new Date(), "yyyy-MM-dd HH:mm:ss")); | ||
176 | + data.put("merOrderId", "24455075157"); | ||
177 | + data.put("mid", "898310148160568"); //商户号 仅用于支付宝和云闪付 | ||
178 | + data.put("tid","00000001"); //终端号 | ||
179 | + data.put("instMid", "APPDEFAULT"); // 机构商户号 | ||
180 | + data.put("refundAmount",1); | ||
181 | + | ||
182 | + data.put("sign", getSign(data)); | ||
183 | + } | ||
184 | + | ||
185 | + // 回调接口 | ||
186 | + | ||
187 | +} |
-
Please register or login to post a comment