8
8
import me .chanjar .weixin .mp .api .WxMpPayService ;
9
9
import me .chanjar .weixin .mp .api .WxMpService ;
10
10
import me .chanjar .weixin .mp .bean .pay .WxPayJsSDKCallback ;
11
- import me .chanjar .weixin .mp .bean .pay .result .WxPayOrderCloseResult ;
12
11
import me .chanjar .weixin .mp .bean .pay .request .*;
13
12
import me .chanjar .weixin .mp .bean .pay .result .*;
14
13
import org .apache .commons .codec .digest .DigestUtils ;
42
41
*/
43
42
public class WxMpPayServiceImpl implements WxMpPayService {
44
43
45
- protected final Logger log = LoggerFactory .getLogger (this .getClass ());
46
-
47
44
private static final String PAY_BASE_URL = "https://api.mch.weixin.qq.com" ;
48
- private static final String [] TRADE_TYPES = new String []{"JSAPI" ,"NATIVE" , "APP" };
49
- private static final String [] REFUND_ACCOUNT = new String []{"REFUND_SOURCE_RECHARGE_FUNDS" ,
45
+ private static final String [] TRADE_TYPES = new String []{"JSAPI" , "NATIVE" , "APP" };
46
+ private static final String [] REFUND_ACCOUNT = new String []{"REFUND_SOURCE_RECHARGE_FUNDS" ,
50
47
"REFUND_SOURCE_UNSETTLED_FUNDS" };
51
-
48
+ protected final Logger log = LoggerFactory . getLogger ( this . getClass ());
52
49
private WxMpService wxMpService ;
53
50
54
51
public WxMpPayServiceImpl (WxMpService wxMpService ) {
@@ -57,7 +54,7 @@ public WxMpPayServiceImpl(WxMpService wxMpService) {
57
54
58
55
@ Override
59
56
public WxPayRefundResult refund (WxPayRefundRequest request , File keyFile )
60
- throws WxErrorException {
57
+ throws WxErrorException {
61
58
checkParameters (request );
62
59
63
60
XStream xstream = XStreamInitializer .getInstance ();
@@ -67,7 +64,7 @@ public WxPayRefundResult refund(WxPayRefundRequest request, File keyFile)
67
64
request .setAppid (this .wxMpService .getWxMpConfigStorage ().getAppId ());
68
65
String partnerId = this .wxMpService .getWxMpConfigStorage ().getPartnerId ();
69
66
request .setMchId (partnerId );
70
- request .setNonceStr ( System .currentTimeMillis () + "" );
67
+ request .setNonceStr (System .currentTimeMillis () + "" );
71
68
request .setOpUserId (partnerId );
72
69
String sign = this .createSign (BeanUtils .xmlBean2Map (request ), this .wxMpService .getWxMpConfigStorage ().getPartnerKey ());
73
70
request .setSign (sign );
@@ -79,11 +76,45 @@ public WxPayRefundResult refund(WxPayRefundRequest request, File keyFile)
79
76
return result ;
80
77
}
81
78
79
+ @ Override
80
+ public WxPayRefundQueryResult refundQuery (String transactionId , String outTradeNo , String outRefundNo , String refundId ) throws WxErrorException {
81
+ if ((StringUtils .isBlank (transactionId ) && StringUtils .isBlank (outTradeNo ) && StringUtils .isBlank (outRefundNo ) && StringUtils .isBlank (refundId )) ||
82
+ (StringUtils .isNotBlank (transactionId ) && StringUtils .isNotBlank (outTradeNo ) && StringUtils .isNotBlank (outRefundNo ) && StringUtils .isNotBlank (refundId ))) {
83
+ throw new IllegalArgumentException ("transaction_id , out_trade_no,out_refund_no, refund_id 必须四选一" );
84
+ }
85
+
86
+ XStream xstream = XStreamInitializer .getInstance ();
87
+ xstream .processAnnotations (WxPayRefundQueryRequest .class );
88
+ xstream .processAnnotations (WxPayRefundQueryResult .class );
89
+
90
+ WxPayRefundQueryRequest request = new WxPayRefundQueryRequest ();
91
+ request .setOutTradeNo (StringUtils .trimToNull (outTradeNo ));
92
+ request .setTransactionId (StringUtils .trimToNull (transactionId ));
93
+ request .setOutRefundNo (StringUtils .trimToNull (outRefundNo ));
94
+ request .setRefundId (StringUtils .trimToNull (refundId ));
95
+
96
+ request .setAppid (this .wxMpService .getWxMpConfigStorage ().getAppId ());
97
+ request .setMchId (this .wxMpService .getWxMpConfigStorage ().getPartnerId ());
98
+ request .setNonceStr (System .currentTimeMillis () + "" );
99
+
100
+ String sign = this .createSign (BeanUtils .xmlBean2Map (request ),
101
+ this .wxMpService .getWxMpConfigStorage ().getPartnerKey ());
102
+ request .setSign (sign );
103
+
104
+ String url = PAY_BASE_URL + "/pay/refundquery" ;
105
+
106
+ String responseContent = this .executeRequest (url , xstream .toXML (request ));
107
+ WxPayRefundQueryResult result = (WxPayRefundQueryResult ) xstream .fromXML (responseContent );
108
+ result .composeRefundRecords (responseContent );
109
+ this .checkResult (result );
110
+ return result ;
111
+ }
112
+
82
113
private void checkResult (WxPayBaseResult result ) throws WxErrorException {
83
114
if (!"SUCCESS" .equalsIgnoreCase (result .getReturnCode ())
84
115
|| !"SUCCESS" .equalsIgnoreCase (result .getResultCode ())) {
85
116
throw new WxErrorException (WxError .newBuilder ().setErrorCode (-1 )
86
- .setErrorMsg ("返回代码:" + result .getReturnCode () + ", 返回信息: "
117
+ .setErrorMsg ("返回代码: " + result .getReturnCode () + ", 返回信息: "
87
118
+ result .getReturnMsg () + ", 结果代码: " + result .getResultCode () + ", 错误代码: "
88
119
+ result .getErrCode () + ", 错误详情: " + result .getErrCodeDes ())
89
120
.build ());
@@ -94,7 +125,7 @@ private void checkParameters(WxPayRefundRequest request) throws WxErrorException
94
125
BeanUtils .checkRequiredFields (request );
95
126
96
127
if (StringUtils .isNotBlank (request .getRefundAccount ())) {
97
- if (!ArrayUtils .contains (REFUND_ACCOUNT , request .getRefundAccount ())){
128
+ if (!ArrayUtils .contains (REFUND_ACCOUNT , request .getRefundAccount ())) {
98
129
throw new IllegalArgumentException ("refund_account目前必须为" + Arrays .toString (REFUND_ACCOUNT ) + "其中之一" );
99
130
}
100
131
}
@@ -118,14 +149,14 @@ public WxPayJsSDKCallback getJSSDKCallbackData(String xmlData) throws WxErrorExc
118
149
119
150
@ Override
120
151
public boolean checkJSSDKCallbackDataSignature (Map <String , String > kvm ,
121
- String signature ) {
152
+ String signature ) {
122
153
return signature .equals (this .createSign (kvm ,
123
- this .wxMpService .getWxMpConfigStorage ().getPartnerKey ()));
154
+ this .wxMpService .getWxMpConfigStorage ().getPartnerKey ()));
124
155
}
125
156
126
157
@ Override
127
158
public WxPaySendRedpackResult sendRedpack (WxPaySendRedpackRequest request , File keyFile )
128
- throws WxErrorException {
159
+ throws WxErrorException {
129
160
XStream xstream = XStreamInitializer .getInstance ();
130
161
xstream .processAnnotations (WxPaySendRedpackRequest .class );
131
162
xstream .processAnnotations (WxPaySendRedpackResult .class );
@@ -136,7 +167,7 @@ public WxPaySendRedpackResult sendRedpack(WxPaySendRedpackRequest request, File
136
167
request .setNonceStr (System .currentTimeMillis () + "" );
137
168
138
169
String sign = this .createSign (BeanUtils .xmlBean2Map (request ),
139
- this .wxMpService .getWxMpConfigStorage ().getPartnerKey ());
170
+ this .wxMpService .getWxMpConfigStorage ().getPartnerKey ());
140
171
request .setSign (sign );
141
172
142
173
String url = PAY_BASE_URL + "/mmpaymkttransfers/sendredpack" ;
@@ -147,15 +178,16 @@ public WxPaySendRedpackResult sendRedpack(WxPaySendRedpackRequest request, File
147
178
148
179
String responseContent = this .executeRequestWithKeyFile (url , keyFile , xstream .toXML (request ), mchId );
149
180
WxPaySendRedpackResult result = (WxPaySendRedpackResult ) xstream
150
- .fromXML (responseContent );
181
+ .fromXML (responseContent );
151
182
this .checkResult (result );
152
183
return result ;
153
184
}
154
185
155
186
/**
156
187
* 微信公众号支付签名算法(详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=4_3)
188
+ *
157
189
* @param packageParams 原始参数
158
- * @param signKey 加密Key(即 商户Key)
190
+ * @param signKey 加密Key(即 商户Key)
159
191
* @return 签名字符串
160
192
*/
161
193
private String createSign (Map <String , String > packageParams , String signKey ) {
@@ -165,7 +197,7 @@ private String createSign(Map<String, String> packageParams, String signKey) {
165
197
for (String key : sortedMap .keySet ()) {
166
198
String value = packageParams .get (key );
167
199
if (null != value && !"" .equals (value ) && !"sign" .equals (key )
168
- && !"key" .equals (key )) {
200
+ && !"key" .equals (key )) {
169
201
toSign .append (key + "=" + value + "&" );
170
202
}
171
203
}
@@ -237,7 +269,7 @@ public WxPayOrderCloseResult closeOrder(String outTradeNo) throws WxErrorExcepti
237
269
238
270
@ Override
239
271
public WxPayUnifiedOrderResult unifiedOrder (WxPayUnifiedOrderRequest request )
240
- throws WxErrorException {
272
+ throws WxErrorException {
241
273
checkParameters (request );
242
274
243
275
XStream xstream = XStreamInitializer .getInstance ();
@@ -249,22 +281,22 @@ public WxPayUnifiedOrderResult unifiedOrder(WxPayUnifiedOrderRequest request)
249
281
request .setNonceStr (System .currentTimeMillis () + "" );
250
282
251
283
String sign = this .createSign (BeanUtils .xmlBean2Map (request ),
252
- this .wxMpService .getWxMpConfigStorage ().getPartnerKey ());
284
+ this .wxMpService .getWxMpConfigStorage ().getPartnerKey ());
253
285
request .setSign (sign );
254
286
255
287
String url = PAY_BASE_URL + "/pay/unifiedorder" ;
256
288
257
289
String responseContent = this .executeRequest (url , xstream .toXML (request ));
258
290
WxPayUnifiedOrderResult result = (WxPayUnifiedOrderResult ) xstream
259
- .fromXML (responseContent );
291
+ .fromXML (responseContent );
260
292
this .checkResult (result );
261
293
return result ;
262
294
}
263
295
264
296
private void checkParameters (WxPayUnifiedOrderRequest request ) throws WxErrorException {
265
297
BeanUtils .checkRequiredFields (request );
266
298
267
- if (! ArrayUtils .contains (TRADE_TYPES , request .getTradeType ())) {
299
+ if (!ArrayUtils .contains (TRADE_TYPES , request .getTradeType ())) {
268
300
throw new IllegalArgumentException ("trade_type目前必须为" + Arrays .toString (TRADE_TYPES ) + "其中之一" );
269
301
}
270
302
@@ -283,7 +315,7 @@ public Map<String, String> getPayInfo(WxPayUnifiedOrderRequest request) throws W
283
315
String prepayId = unifiedOrderResult .getPrepayId ();
284
316
if (StringUtils .isBlank (prepayId )) {
285
317
throw new RuntimeException (String .format ("Failed to get prepay id due to error code '%s'(%s)." ,
286
- unifiedOrderResult .getErrCode (), unifiedOrderResult .getErrCodeDes ()));
318
+ unifiedOrderResult .getErrCode (), unifiedOrderResult .getErrCodeDes ()));
287
319
}
288
320
289
321
Map <String , String > payInfo = new HashMap <>();
@@ -347,7 +379,7 @@ public WxEntPayQueryResult queryEntPay(String partnerTradeNo, File keyFile) thro
347
379
return result ;
348
380
}
349
381
350
- private String executeRequest ( String url , String requestStr ) throws WxErrorException {
382
+ private String executeRequest (String url , String requestStr ) throws WxErrorException {
351
383
HttpPost httpPost = new HttpPost (url );
352
384
if (this .wxMpService .getHttpProxy () != null ) {
353
385
httpPost .setConfig (RequestConfig .custom ().setProxy (this .wxMpService .getHttpProxy ()).build ());
@@ -358,25 +390,25 @@ private String executeRequest( String url, String requestStr) throws WxErrorExce
358
390
359
391
try (CloseableHttpResponse response = httpclient .execute (httpPost )) {
360
392
String result = EntityUtils .toString (response .getEntity (), Consts .UTF_8 );
361
- this .log .debug ("\n [URL]: {}\n [PARAMS]: {}\n [RESPONSE]: {}" ,url , requestStr , result );
393
+ this .log .debug ("\n [URL]: {}\n [PARAMS]: {}\n [RESPONSE]: {}" , url , requestStr , result );
362
394
return result ;
363
395
}
364
396
} catch (IOException e ) {
365
397
this .log .error ("\n [URL]: {}\n [PARAMS]: {}\n [EXCEPTION]: {}" , url , requestStr , e .getMessage ());
366
398
throw new WxErrorException (WxError .newBuilder ().setErrorCode (-1 ).setErrorMsg (e .getMessage ()).build (), e );
367
- }finally {
399
+ } finally {
368
400
httpPost .releaseConnection ();
369
401
}
370
402
}
371
403
372
- private String executeRequestWithKeyFile ( String url , File keyFile , String requestStr , String mchId ) throws WxErrorException {
404
+ private String executeRequestWithKeyFile (String url , File keyFile , String requestStr , String mchId ) throws WxErrorException {
373
405
try (FileInputStream inputStream = new FileInputStream (keyFile )) {
374
406
KeyStore keyStore = KeyStore .getInstance ("PKCS12" );
375
407
keyStore .load (inputStream , mchId .toCharArray ());
376
408
377
409
SSLContext sslcontext = SSLContexts .custom ().loadKeyMaterial (keyStore , mchId .toCharArray ()).build ();
378
- SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory (sslcontext , new String [] { "TLSv1" }, null ,
379
- new DefaultHostnameVerifier ());
410
+ SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory (sslcontext , new String []{ "TLSv1" }, null ,
411
+ new DefaultHostnameVerifier ());
380
412
381
413
HttpPost httpPost = new HttpPost (url );
382
414
if (this .wxMpService .getHttpProxy () != null ) {
@@ -387,10 +419,10 @@ private String executeRequestWithKeyFile( String url, File keyFile, String reque
387
419
httpPost .setEntity (new StringEntity (new String (requestStr .getBytes ("UTF-8" ), "ISO-8859-1" )));
388
420
try (CloseableHttpResponse response = httpclient .execute (httpPost )) {
389
421
String result = EntityUtils .toString (response .getEntity (), Consts .UTF_8 );
390
- this .log .debug ("\n [URL]: {}\n [PARAMS]: {}\n [RESPONSE]: {}" ,url , requestStr , result );
422
+ this .log .debug ("\n [URL]: {}\n [PARAMS]: {}\n [RESPONSE]: {}" , url , requestStr , result );
391
423
return result ;
392
424
}
393
- }finally {
425
+ } finally {
394
426
httpPost .releaseConnection ();
395
427
}
396
428
} catch (Exception e ) {
0 commit comments