88import me .chanjar .weixin .mp .api .WxMpPayService ;
99import me .chanjar .weixin .mp .api .WxMpService ;
1010import me .chanjar .weixin .mp .bean .pay .WxPayJsSDKCallback ;
11- import me .chanjar .weixin .mp .bean .pay .result .WxPayOrderCloseResult ;
1211import me .chanjar .weixin .mp .bean .pay .request .*;
1312import me .chanjar .weixin .mp .bean .pay .result .*;
1413import org .apache .commons .codec .digest .DigestUtils ;
4241 */
4342public class WxMpPayServiceImpl implements WxMpPayService {
4443
45- protected final Logger log = LoggerFactory .getLogger (this .getClass ());
46-
4744 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" ,
5047 "REFUND_SOURCE_UNSETTLED_FUNDS" };
51-
48+ protected final Logger log = LoggerFactory . getLogger ( this . getClass ());
5249 private WxMpService wxMpService ;
5350
5451 public WxMpPayServiceImpl (WxMpService wxMpService ) {
@@ -57,7 +54,7 @@ public WxMpPayServiceImpl(WxMpService wxMpService) {
5754
5855 @ Override
5956 public WxPayRefundResult refund (WxPayRefundRequest request , File keyFile )
60- throws WxErrorException {
57+ throws WxErrorException {
6158 checkParameters (request );
6259
6360 XStream xstream = XStreamInitializer .getInstance ();
@@ -67,7 +64,7 @@ public WxPayRefundResult refund(WxPayRefundRequest request, File keyFile)
6764 request .setAppid (this .wxMpService .getWxMpConfigStorage ().getAppId ());
6865 String partnerId = this .wxMpService .getWxMpConfigStorage ().getPartnerId ();
6966 request .setMchId (partnerId );
70- request .setNonceStr ( System .currentTimeMillis () + "" );
67+ request .setNonceStr (System .currentTimeMillis () + "" );
7168 request .setOpUserId (partnerId );
7269 String sign = this .createSign (BeanUtils .xmlBean2Map (request ), this .wxMpService .getWxMpConfigStorage ().getPartnerKey ());
7370 request .setSign (sign );
@@ -79,11 +76,45 @@ public WxPayRefundResult refund(WxPayRefundRequest request, File keyFile)
7976 return result ;
8077 }
8178
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+
82113 private void checkResult (WxPayBaseResult result ) throws WxErrorException {
83114 if (!"SUCCESS" .equalsIgnoreCase (result .getReturnCode ())
84115 || !"SUCCESS" .equalsIgnoreCase (result .getResultCode ())) {
85116 throw new WxErrorException (WxError .newBuilder ().setErrorCode (-1 )
86- .setErrorMsg ("返回代码:" + result .getReturnCode () + ", 返回信息: "
117+ .setErrorMsg ("返回代码: " + result .getReturnCode () + ", 返回信息: "
87118 + result .getReturnMsg () + ", 结果代码: " + result .getResultCode () + ", 错误代码: "
88119 + result .getErrCode () + ", 错误详情: " + result .getErrCodeDes ())
89120 .build ());
@@ -94,7 +125,7 @@ private void checkParameters(WxPayRefundRequest request) throws WxErrorException
94125 BeanUtils .checkRequiredFields (request );
95126
96127 if (StringUtils .isNotBlank (request .getRefundAccount ())) {
97- if (!ArrayUtils .contains (REFUND_ACCOUNT , request .getRefundAccount ())){
128+ if (!ArrayUtils .contains (REFUND_ACCOUNT , request .getRefundAccount ())) {
98129 throw new IllegalArgumentException ("refund_account目前必须为" + Arrays .toString (REFUND_ACCOUNT ) + "其中之一" );
99130 }
100131 }
@@ -118,14 +149,14 @@ public WxPayJsSDKCallback getJSSDKCallbackData(String xmlData) throws WxErrorExc
118149
119150 @ Override
120151 public boolean checkJSSDKCallbackDataSignature (Map <String , String > kvm ,
121- String signature ) {
152+ String signature ) {
122153 return signature .equals (this .createSign (kvm ,
123- this .wxMpService .getWxMpConfigStorage ().getPartnerKey ()));
154+ this .wxMpService .getWxMpConfigStorage ().getPartnerKey ()));
124155 }
125156
126157 @ Override
127158 public WxPaySendRedpackResult sendRedpack (WxPaySendRedpackRequest request , File keyFile )
128- throws WxErrorException {
159+ throws WxErrorException {
129160 XStream xstream = XStreamInitializer .getInstance ();
130161 xstream .processAnnotations (WxPaySendRedpackRequest .class );
131162 xstream .processAnnotations (WxPaySendRedpackResult .class );
@@ -136,7 +167,7 @@ public WxPaySendRedpackResult sendRedpack(WxPaySendRedpackRequest request, File
136167 request .setNonceStr (System .currentTimeMillis () + "" );
137168
138169 String sign = this .createSign (BeanUtils .xmlBean2Map (request ),
139- this .wxMpService .getWxMpConfigStorage ().getPartnerKey ());
170+ this .wxMpService .getWxMpConfigStorage ().getPartnerKey ());
140171 request .setSign (sign );
141172
142173 String url = PAY_BASE_URL + "/mmpaymkttransfers/sendredpack" ;
@@ -147,15 +178,16 @@ public WxPaySendRedpackResult sendRedpack(WxPaySendRedpackRequest request, File
147178
148179 String responseContent = this .executeRequestWithKeyFile (url , keyFile , xstream .toXML (request ), mchId );
149180 WxPaySendRedpackResult result = (WxPaySendRedpackResult ) xstream
150- .fromXML (responseContent );
181+ .fromXML (responseContent );
151182 this .checkResult (result );
152183 return result ;
153184 }
154185
155186 /**
156187 * 微信公众号支付签名算法(详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=4_3)
188+ *
157189 * @param packageParams 原始参数
158- * @param signKey 加密Key(即 商户Key)
190+ * @param signKey 加密Key(即 商户Key)
159191 * @return 签名字符串
160192 */
161193 private String createSign (Map <String , String > packageParams , String signKey ) {
@@ -165,7 +197,7 @@ private String createSign(Map<String, String> packageParams, String signKey) {
165197 for (String key : sortedMap .keySet ()) {
166198 String value = packageParams .get (key );
167199 if (null != value && !"" .equals (value ) && !"sign" .equals (key )
168- && !"key" .equals (key )) {
200+ && !"key" .equals (key )) {
169201 toSign .append (key + "=" + value + "&" );
170202 }
171203 }
@@ -237,7 +269,7 @@ public WxPayOrderCloseResult closeOrder(String outTradeNo) throws WxErrorExcepti
237269
238270 @ Override
239271 public WxPayUnifiedOrderResult unifiedOrder (WxPayUnifiedOrderRequest request )
240- throws WxErrorException {
272+ throws WxErrorException {
241273 checkParameters (request );
242274
243275 XStream xstream = XStreamInitializer .getInstance ();
@@ -249,22 +281,22 @@ public WxPayUnifiedOrderResult unifiedOrder(WxPayUnifiedOrderRequest request)
249281 request .setNonceStr (System .currentTimeMillis () + "" );
250282
251283 String sign = this .createSign (BeanUtils .xmlBean2Map (request ),
252- this .wxMpService .getWxMpConfigStorage ().getPartnerKey ());
284+ this .wxMpService .getWxMpConfigStorage ().getPartnerKey ());
253285 request .setSign (sign );
254286
255287 String url = PAY_BASE_URL + "/pay/unifiedorder" ;
256288
257289 String responseContent = this .executeRequest (url , xstream .toXML (request ));
258290 WxPayUnifiedOrderResult result = (WxPayUnifiedOrderResult ) xstream
259- .fromXML (responseContent );
291+ .fromXML (responseContent );
260292 this .checkResult (result );
261293 return result ;
262294 }
263295
264296 private void checkParameters (WxPayUnifiedOrderRequest request ) throws WxErrorException {
265297 BeanUtils .checkRequiredFields (request );
266298
267- if (! ArrayUtils .contains (TRADE_TYPES , request .getTradeType ())) {
299+ if (!ArrayUtils .contains (TRADE_TYPES , request .getTradeType ())) {
268300 throw new IllegalArgumentException ("trade_type目前必须为" + Arrays .toString (TRADE_TYPES ) + "其中之一" );
269301 }
270302
@@ -283,7 +315,7 @@ public Map<String, String> getPayInfo(WxPayUnifiedOrderRequest request) throws W
283315 String prepayId = unifiedOrderResult .getPrepayId ();
284316 if (StringUtils .isBlank (prepayId )) {
285317 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 ()));
287319 }
288320
289321 Map <String , String > payInfo = new HashMap <>();
@@ -347,7 +379,7 @@ public WxEntPayQueryResult queryEntPay(String partnerTradeNo, File keyFile) thro
347379 return result ;
348380 }
349381
350- private String executeRequest ( String url , String requestStr ) throws WxErrorException {
382+ private String executeRequest (String url , String requestStr ) throws WxErrorException {
351383 HttpPost httpPost = new HttpPost (url );
352384 if (this .wxMpService .getHttpProxy () != null ) {
353385 httpPost .setConfig (RequestConfig .custom ().setProxy (this .wxMpService .getHttpProxy ()).build ());
@@ -358,25 +390,25 @@ private String executeRequest( String url, String requestStr) throws WxErrorExce
358390
359391 try (CloseableHttpResponse response = httpclient .execute (httpPost )) {
360392 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 );
362394 return result ;
363395 }
364396 } catch (IOException e ) {
365397 this .log .error ("\n [URL]: {}\n [PARAMS]: {}\n [EXCEPTION]: {}" , url , requestStr , e .getMessage ());
366398 throw new WxErrorException (WxError .newBuilder ().setErrorCode (-1 ).setErrorMsg (e .getMessage ()).build (), e );
367- }finally {
399+ } finally {
368400 httpPost .releaseConnection ();
369401 }
370402 }
371403
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 {
373405 try (FileInputStream inputStream = new FileInputStream (keyFile )) {
374406 KeyStore keyStore = KeyStore .getInstance ("PKCS12" );
375407 keyStore .load (inputStream , mchId .toCharArray ());
376408
377409 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 ());
380412
381413 HttpPost httpPost = new HttpPost (url );
382414 if (this .wxMpService .getHttpProxy () != null ) {
@@ -387,10 +419,10 @@ private String executeRequestWithKeyFile( String url, File keyFile, String reque
387419 httpPost .setEntity (new StringEntity (new String (requestStr .getBytes ("UTF-8" ), "ISO-8859-1" )));
388420 try (CloseableHttpResponse response = httpclient .execute (httpPost )) {
389421 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 );
391423 return result ;
392424 }
393- }finally {
425+ } finally {
394426 httpPost .releaseConnection ();
395427 }
396428 } catch (Exception e ) {
0 commit comments