1 package com.foxinmy.weixin4j.pay.api;
2
3 import com.alibaba.fastjson.JSON;
4 import com.alibaba.fastjson.TypeReference;
5 import com.foxinmy.weixin4j.exception.WeixinException;
6 import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
7 import com.foxinmy.weixin4j.http.weixin.XmlResult;
8 import com.foxinmy.weixin4j.pay.model.WeixinPayAccount;
9 import com.foxinmy.weixin4j.pay.payment.face.PayfaceAuthinfo;
10 import com.foxinmy.weixin4j.pay.payment.face.PayfaceAuthinfoRequest;
11 import com.foxinmy.weixin4j.pay.payment.mch.*;
12 import com.foxinmy.weixin4j.pay.type.mch.BillType;
13 import com.foxinmy.weixin4j.pay.type.mch.RefundAccountType;
14 import com.foxinmy.weixin4j.pay.type.*;
15 import com.foxinmy.weixin4j.util.*;
16 import com.foxinmy.weixin4j.xml.ListsuffixResultDeserializer;
17 import com.foxinmy.weixin4j.xml.XmlStream;
18
19 import java.io.*;
20 import java.net.URLEncoder;
21 import java.util.Calendar;
22 import java.util.Date;
23 import java.util.HashMap;
24 import java.util.Map;
25
26
27
28
29
30
31
32
33
34 public class PayApi extends MchApi {
35
36 private final static String Y = "Y";
37
38 public PayApi(WeixinPayAccount weixinAccount) {
39 super(weixinAccount);
40 }
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 public PrePay createPrePay(MchPayPackage payPackage) throws WeixinException {
57 super.declareMerchant(payPackage);
58 payPackage.setSign(weixinSignature.sign(payPackage));
59 String payJsRequestXml = XmlStream.toXML(payPackage);
60 WeixinResponse response = weixinExecutor.post(
61 getRequestUri("order_create_uri"), payJsRequestXml);
62 return response.getAsObject(new TypeReference<PrePay>() {
63 });
64 }
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79 public MchPayRequest createPayRequest(MchPayPackage payPackage)
80 throws WeixinException {
81 if (StringUtil.isBlank(payPackage.getTradeType())) {
82 throw new WeixinException("tradeType not be empty");
83 }
84 String tradeType = payPackage.getTradeType().toUpperCase();
85 if (TradeType.MICROPAY.name().equals(tradeType) || TradeType.FACEPAY.name().equals(tradeType)) {
86 MchPayPackage _payPackage = new MchPayPackage(payPackage.getBody(),
87 payPackage.getDetail(), payPackage.getOutTradeNo(),
88 DateUtil.formatFee2Yuan(payPackage.getTotalFee()), null,
89 null, payPackage.getCreateIp(), null, payPackage.getOpenId(),
90 payPackage.getAuthCode(), null, payPackage.getAttach(),
91 null, null, payPackage.getGoodsTag(),
92 payPackage.getLimitPay(), payPackage.getSubAppId(), payPackage.getReceipt(),
93 payPackage.getDeposit(), payPackage.getProfitSharing());
94
95 SignType signType= SignType.MD5;
96 super.declareMerchant(_payPackage);
97
98 String url = getRequestUri("micropay_uri");
99 if(Y.equals(payPackage.getDeposit())){
100
101 signType = SignType.HMAC$SHA256;
102 _payPackage.setSignType("HMAC-SHA256");
103
104 url = TradeType.MICROPAY.name().equals(tradeType) ? getRequestUri("deposit_micropay_uri") :
105 getRequestUri("deposit_facepay_uri");
106 }else if(TradeType.FACEPAY.name().equals(tradeType)){
107 url = getRequestUri("facepay_url");
108 }
109 _payPackage.setSign(weixinSignature.sign(_payPackage, signType));
110 String para = XmlStream.toXML(_payPackage);
111
112 WeixinResponse response = weixinExecutor.post(url, para);
113 MICROPayRequest microPayRequest = response.getAsObject(new TypeReference<MICROPayRequest>() {});
114 microPayRequest.setPaymentAccount(weixinAccount);
115 return microPayRequest;
116 }
117 PrePay prePay = createPrePay(payPackage);
118 if (TradeType.APP.name().equals(tradeType)) {
119 return new APPPayRequest(prePay.getPrepayId(), weixinAccount);
120 } else if (TradeType.JSAPI.name().equals(tradeType)) {
121 return new JSAPIPayRequest(prePay.getPrepayId(), weixinAccount);
122 } else if (TradeType.NATIVE.name().equals(tradeType)) {
123 return new NATIVEPayRequest(prePay.getPrepayId(),
124 prePay.getPayUrl(), weixinAccount);
125 } else if (TradeType.MWEB.name().equals(tradeType)) {
126 return new WAPPayRequest(prePay.getPrepayId(), prePay.getPayUrl(),
127 weixinAccount);
128 } else {
129 throw new WeixinException("unknown tradeType:" + tradeType);
130 }
131 }
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154 public MchPayRequest createJSPayRequest(String openId, String body,
155 String outTradeNo, double totalFee, String notifyUrl,
156 String createIp, String attach) throws WeixinException {
157 MchPayPackage payPackage = new MchPayPackage(body, outTradeNo,
158 totalFee, notifyUrl, createIp, TradeType.JSAPI, openId, null,
159 null, attach);
160 return createPayRequest(payPackage);
161 }
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176 public String createNativePayRequest(String productId) {
177 Map<String, String> map = new HashMap<String, String>();
178 String timestamp = DateUtil.timestamp2string();
179 String noncestr = RandomUtil.generateString(16);
180 map.put("appid", weixinAccount.getId());
181 map.put("mch_id", weixinAccount.getMchId());
182 map.put("time_stamp", timestamp);
183 map.put("nonce_str", noncestr);
184 map.put("product_id", productId);
185 String sign = weixinSignature.sign(map);
186 return String.format(getRequestUri("native_pay_uri"), sign,
187 weixinAccount.getId(), weixinAccount.getMchId(), productId,
188 timestamp, noncestr);
189 }
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218 public NativePayResponse createNativePayResponse(String productId,
219 String body, String outTradeNo, double totalFee, String notifyUrl,
220 String createIp, String attach) throws WeixinException {
221 MchPayPackage payPackage = new MchPayPackage(body, outTradeNo,
222 totalFee, notifyUrl, createIp, TradeType.NATIVE, null, null,
223 productId, attach);
224 PrePay prePay = createPrePay(payPackage);
225 return new NativePayResponse(weixinAccount, prePay.getPrepayId());
226 }
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255 public MchPayRequest createNativePayRequest(String productId, String body,
256 String outTradeNo, double totalFee, String notifyUrl,
257 String createIp, String attach) throws WeixinException {
258 MchPayPackage payPackage = new MchPayPackage(body, outTradeNo,
259 totalFee, notifyUrl, createIp, TradeType.NATIVE, null, null,
260 productId, attach);
261 return createPayRequest(payPackage);
262 }
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289 public MchPayRequest createAppPayRequest(String body, String outTradeNo,
290 double totalFee, String notifyUrl, String createIp, String attach,
291 SceneInfoStore store) throws WeixinException {
292 MchPayPackage payPackage = new MchPayPackage(body, outTradeNo,
293 totalFee, notifyUrl, createIp, TradeType.APP, null, null, null,
294 attach);
295 return createPayRequest(payPackage);
296 }
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324 public MchPayRequest createWapPayRequest(String body, String outTradeNo,
325 double totalFee, String notifyUrl, String createIp, String attach,
326 SceneInfoApp app) throws WeixinException {
327 MchPayPackage payPackage = new MchPayPackage(body, outTradeNo,
328 totalFee, notifyUrl, createIp, TradeType.MWEB, null, null,
329 null, attach);
330 if (app != null) {
331 payPackage.setSceneInfo(app.toJson());
332 }
333 return createPayRequest(payPackage);
334 }
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362 public MchPayRequest createMicroPayRequest(String authCode, String body,
363 String outTradeNo, double totalFee, String createIp, String attach,
364 SceneInfoStore store) throws WeixinException {
365 MchPayPackage payPackage = new MchPayPackage(body, outTradeNo,
366 totalFee, null, createIp, TradeType.MICROPAY, null, authCode,
367 null, attach);
368 if (store != null) {
369 payPackage.setSceneInfo(store.toJson());
370 }
371 return createPayRequest(payPackage);
372 }
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392 public Order queryOrder(IdQuery idQuery) throws WeixinException {
393 Map<String, String> map = createBaseRequestMap(idQuery);
394 map.put("sign", weixinSignature.sign(map));
395 String param = XmlStream.map2xml(map);
396 WeixinResponse response = weixinExecutor.post(
397 getRequestUri("order_query_uri"), param);
398 return ListsuffixResultDeserializer.deserialize(response.getAsString(),
399 Order.class);
400 }
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449 public RefundResult applyRefund(IdQuery idQuery, String outRefundNo,
450 double totalFee, double refundFee, CurrencyType refundFeeType,
451 String opUserId, String refundDesc,
452 RefundAccountType refundAccountType) throws WeixinException {
453 Map<String, String> map = createBaseRequestMap(idQuery);
454 map.put("out_refund_no", outRefundNo);
455 map.put("total_fee",
456 Integer.toString(DateUtil.formatYuan2Fen(totalFee)));
457 map.put("refund_fee",
458 Integer.toString(DateUtil.formatYuan2Fen(refundFee)));
459 if (StringUtil.isBlank(opUserId)) {
460 opUserId = weixinAccount.getMchId();
461 }
462 map.put("op_user_id", opUserId);
463 if (refundFeeType == null) {
464 refundFeeType = CurrencyType.CNY;
465 }
466 if (refundAccountType == null) {
467 refundAccountType = RefundAccountType.REFUND_SOURCE_UNSETTLED_FUNDS;
468 }
469 if (StringUtil.isNotBlank(refundDesc)) {
470 map.put("refund_desc", refundDesc);
471 }
472 map.put("refund_fee_type", refundFeeType.name());
473 map.put("refund_account", refundAccountType.name());
474 map.put("sign", weixinSignature.sign(map));
475 String param = XmlStream.map2xml(map);
476 WeixinResponse response = getWeixinSSLExecutor().post(
477 getRequestUri("refund_apply_uri"), param);
478 return response.getAsObject(new TypeReference<RefundResult>() {
479 });
480 }
481
482
483
484
485
486
487
488
489
490
491
492
493
494 public RefundResult applyRefund(IdQuery idQuery, String outRefundNo,
495 double totalFee) throws WeixinException {
496 return applyRefund(idQuery, outRefundNo, totalFee, totalFee, null,
497 null, null, null);
498 }
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513 public MerchantResult reverseOrder(IdQuery idQuery) throws WeixinException {
514 Map<String, String> map = createBaseRequestMap(idQuery);
515 map.put("sign", weixinSignature.sign(map));
516 String param = XmlStream.map2xml(map);
517 WeixinResponse response = getWeixinSSLExecutor().post(
518 getRequestUri("order_reverse_uri"), param);
519 return response.getAsObject(new TypeReference<MerchantResult>() {
520 });
521 }
522
523
524
525
526
527
528
529
530
531
532
533
534
535 public String getShorturl(String url) throws WeixinException {
536 Map<String, String> map = createBaseRequestMap(null);
537 try {
538 map.put("long_url", URLEncoder.encode(url, Consts.UTF_8.name()));
539 } catch (UnsupportedEncodingException e) {
540 ;
541 }
542 map.put("sign", weixinSignature.sign(map));
543 String param = XmlStream.map2xml(map);
544 WeixinResponse response = weixinExecutor.post(
545 getRequestUri("longurl_convert_uri"), param);
546 map = XmlStream.xml2map(response.getAsString());
547 return map.get("short_url");
548 }
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566 public MerchantResult closeOrder(String outTradeNo) throws WeixinException {
567 Map<String, String> map = createBaseRequestMap(new IdQuery(outTradeNo,
568 IdType.TRADENO));
569 map.put("sign", weixinSignature.sign(map));
570 String param = XmlStream.map2xml(map);
571 WeixinResponse response = weixinExecutor.post(
572 getRequestUri("order_close_uri"), param);
573 return response.getAsObject(new TypeReference<MerchantResult>() {
574 });
575 }
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599 public void downloadBill(Date billDate, BillType billType,
600 OutputStream outputStream, TarType tarType) throws WeixinException {
601 if (billDate == null) {
602 Calendar now = Calendar.getInstance();
603 now.add(Calendar.DAY_OF_MONTH, -1);
604 billDate = now.getTime();
605 }
606 if (billType == null) {
607 billType = BillType.ALL;
608 }
609 String formatBillDate = DateUtil.fortmat2yyyyMMdd(billDate);
610 Map<String, String> map = createBaseRequestMap(null);
611 map.put("bill_date", formatBillDate);
612 map.put("bill_type", billType.name());
613 if (tarType != null) {
614 map.put("tar_type", tarType.name());
615 }
616 map.put("sign", weixinSignature.sign(map));
617 String param = XmlStream.map2xml(map);
618 WeixinResponse response = weixinExecutor.post(
619 getRequestUri("downloadbill_uri"), param);
620
621 if (TarType.GZIP == tarType) {
622 try {
623 IOUtil.copy(response.getBody(), outputStream);
624 } catch (IOException e) {
625 ;
626 }
627 } else {
628 BufferedReader reader = null;
629 BufferedWriter writer = null;
630 try {
631 writer = new BufferedWriter(new OutputStreamWriter(
632 outputStream, Consts.UTF_8));
633 reader = new BufferedReader(new InputStreamReader(
634 response.getBody(), Consts.UTF_8));
635 String line = null;
636 while ((line = reader.readLine()) != null) {
637 writer.write(line);
638 writer.newLine();
639 }
640 } catch (IOException e) {
641 throw new WeixinException(e);
642 } finally {
643 try {
644 if (reader != null) {
645 reader.close();
646 }
647 if (writer != null) {
648 writer.close();
649 }
650 } catch (IOException ignore) {
651 ;
652 }
653 }
654 }
655 }
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677 public RefundRecord queryRefund(IdQuery idQuery) throws WeixinException {
678 Map<String, String> map = createBaseRequestMap(idQuery);
679 map.put("sign", weixinSignature.sign(map));
680 String param = XmlStream.map2xml(map);
681 WeixinResponse response = weixinExecutor.post(
682 getRequestUri("refund_query_uri"), param);
683 return ListsuffixResultDeserializer.deserialize(response.getAsString(),
684 RefundRecord.class);
685 }
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709 @SuppressWarnings("unchecked")
710 public XmlResult reportInterface(String interfaceUrl, int executeTime,
711 String outTradeNo, String ip, Date time, XmlResult returnXml)
712 throws WeixinException {
713 Map<String, String> map = createBaseRequestMap(null);
714 map.put("interface_url", interfaceUrl);
715 map.put("execute_time_", Integer.toString(executeTime));
716 map.put("out_trade_no", outTradeNo);
717 map.put("user_ip", ip);
718 map.put("time", DateUtil.fortmat2yyyyMMddHHmmss(time));
719 map.putAll((Map<String, String>) JSON.toJSON(returnXml));
720 map.put("sign", weixinSignature.sign(map));
721 String param = XmlStream.map2xml(map);
722 WeixinResponse response = weixinExecutor.post(
723 getRequestUri("interface_report_uri"), param);
724 return response.getAsXml();
725 }
726
727
728
729
730
731
732
733
734
735
736
737
738
739 public OpenIdResult authCode2openId(String authCode) throws WeixinException {
740 Map<String, String> map = createBaseRequestMap(null);
741 map.put("auth_code", authCode);
742 map.put("sign", weixinSignature.sign(map));
743 String param = XmlStream.map2xml(map);
744 WeixinResponse response = weixinExecutor.post(
745 getRequestUri("authcode_openid_uri"), param);
746 return response.getAsObject(new TypeReference<OpenIdResult>() {
747 });
748 }
749
750
751
752
753
754
755
756
757
758
759 public PayfaceAuthinfo getWxPayfaceAuthinfo(PayfaceAuthinfoRequest request) throws WeixinException {
760 WeixinResponse response = weixinExecutor.post(
761 getRequestUri("get_wxpayface_authinfo_uri"), request.toRequestString());
762 return response.getAsObject(new TypeReference<PayfaceAuthinfo>() {});
763 }
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782 public MchPayRequest createDepositPayRequest(String code, String body, String outTradeNo, double totalFee,
783 String createIp, String openId, String attach, SceneInfoStore store,
784 boolean isFacePay) throws WeixinException {
785 MchPayPackage payPackage;
786 if(isFacePay) {
787 payPackage = new MchPayPackage(body, outTradeNo, totalFee, null, createIp, TradeType.FACEPAY,
788 openId, null, null, attach);
789 payPackage.setAuthCode(code);
790 payPackage.setDeposit(Y);
791 return createPayRequest(payPackage);
792 }else{
793 payPackage = new MchPayPackage(body, outTradeNo, totalFee, null, createIp, TradeType.MICROPAY,
794 openId, code, null, attach);
795 payPackage.setDeposit(Y);
796 if (store != null) {
797 payPackage.setSceneInfo(store.toJson());
798 }
799 return createPayRequest(payPackage);
800 }
801 }
802 }