Compare commits

...

49 Commits

Author SHA1 Message Date
  xhxu 8f9f1a1cf2 //wxscheme 1 year ago
  xhxu 6299762a76 //log 2 years ago
  xhxu 1a6643cd5a //log 2 years ago
  xhxu e9b9fb33ff //log 2 years ago
  xhxu 4687a8e54c //会员卡 商圈相关——1 2 years ago
  zhengfangyuan 49f54f239e Merge branch 'formao-live' of https://git.malls.iformall.com/server/wxJava-final into formao-live 2 years ago
  zhengfangyuan 5e9242ea8f fix pay v3 2 years ago
  xhxu 4d49ffa35a Merge remote-tracking branch 'origin/formao-live' into formao-live 2 years ago
  xhxu 3c001cbb09 // test 2 years ago
  zhengfangyuan 4d1021d026 fix log 2 years ago
  zhengfangyuan 454a851bab fix bug 2 years ago
  zhengfangyuan 32a868fc43 add log 2 years ago
  zhengfangyuan e3ddc82a26 add log 2 years ago
  zhengfangyuan 2b66930cbf fix pay v3 2 years ago
  xhxu 232425a094 // add bank shar 2 years ago
  xhxu 7db21daa4b // add shar app 2 years ago
  xhxu 06d0d8f8ac // add shar 2 years ago
  xhxu 2ee4a96ab5 // add api 2 years ago
  xhxu 51aa930547 // add api 2 years ago
  zhengfangyuan 50c93fa40b fix v3 pay 2 years ago
  zhengfangyuan 4b255c3cb3 fix v3 bug 2 years ago
  zhengfangyuan e56b4b52f3 fix 2 years ago
  zhengfangyuan 376d493b80 add log 2 years ago
  xhxu 678166a7fe //tt coupon order 2 years ago
  xhxu 1c43527d4a //tt log 2 years ago
  xhxu b8ae64b4f9 //tt log 2 years ago
  xhxu 0e8887a176 //tt log 2 years ago
  xhxu a2f35198f7 //tt pay v2 2 years ago
  xhxu 5aebf46bb7 //ttpayv2 2 years ago
  xhxu cd0f61acab //update test 2 years ago
  xhxu 0601ec89f6 //add ttweb 2 years ago
  xhxu e38443e08d /、qrcode 3 years ago
  xhxu 94b1cc1658 /、qrcode 3 years ago
  xhxu 27642b8878 update 3 years ago
  xhxu 7fda673d11 jiemi 会员 3 years ago
  xhxu 1249ecf317 ceshi jiemi 会员 3 years ago
  xhxu d1ca9fb57d ceshi jiemi会员 3 years ago
  xhxu ae2990d0f9 还原 3 years ago
  xhxu 43abd63272 3 years ago
  xhxu 11b43728cc wxbusiness 3 years ago
  xhxu dd3240f8de update weixin pay 3 years ago
  xiaohanzi bea32490b5 Merge branch 'formao-live' of https://git.youlane.cn/server/wxJava-final into formao-live 4 years ago
  xiaohanzi fc2098c6d9 更改直播接口地址 4 years ago
  xhxu ff1d40d438 WxMaLiveService.java 4 years ago
  xiaohanzi be1e361cd1 添加微信日志信息 4 years ago
  xiaohanzi de0e9c4dc5 添加微信调用url日志信息 4 years ago
  Burce 1e8e731d93 增加小程序直播类相关接口 4 years ago
  yjwang 976e9aaf89 🐛 #1512 修复小程序直播官方文档live_satus字段拼错问题,调整为live_status 4 years ago
  yjwang d744cd5dd8 🆕 #1429 增加小程序直播类相关接口 4 years ago
100 changed files with 5718 additions and 83 deletions
Split View
  1. +3
    -4
      pom.xml
  2. +1
    -1
      spring-boot-starters/pom.xml
  3. +1
    -1
      spring-boot-starters/wx-java-miniapp-spring-boot-starter/pom.xml
  4. +1
    -1
      spring-boot-starters/wx-java-mp-spring-boot-starter/pom.xml
  5. +1
    -1
      spring-boot-starters/wx-java-open-spring-boot-starter/pom.xml
  6. +1
    -1
      spring-boot-starters/wx-java-pay-spring-boot-starter/pom.xml
  7. +8
    -0
      spring-boot-starters/wx-java-pay-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/pay/config/WxPayAutoConfiguration.java
  8. +30
    -0
      spring-boot-starters/wx-java-pay-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/pay/properties/WxPayProperties.java
  9. +1
    -1
      weixin-graal/pom.xml
  10. +1
    -1
      weixin-java-common/pom.xml
  11. +6
    -0
      weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java
  12. +1
    -1
      weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxError.java
  13. +23
    -0
      weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxRuntimeException.java
  14. +11
    -0
      weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheHttpClientSimpleGetRequestExecutor.java
  15. +3
    -2
      weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddHttpMediaDownloadRequestExecutor.java
  16. +2
    -2
      weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddHttpMediaUploadRequestExecutor.java
  17. +2
    -2
      weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddHttpSimpleGetRequestExecutor.java
  18. +2
    -2
      weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddHttpSimplePostRequestExecutor.java
  19. +26
    -0
      weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/GsonParser.java
  20. +9
    -0
      weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxErrorAdapter.java
  21. +1
    -1
      weixin-java-cp/pom.xml
  22. +2
    -2
      weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceJoddHttpImpl.java
  23. +1
    -1
      weixin-java-miniapp/pom.xml
  24. +62
    -0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaLiveService.java
  25. +36
    -0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaSchemeService.java
  26. +14
    -0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaService.java
  27. +100
    -0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaLiveServiceImpl.java
  28. +56
    -0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaSchemeServiceImpl.java
  29. +12
    -0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceImpl.java
  30. +88
    -0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaGetLiveInfo.java
  31. +1
    -0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaPhoneNumberInfo.java
  32. +75
    -0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/scheme/WxMaGenerateNfcSchemeRequest.java
  33. +94
    -0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/scheme/WxMaGenerateSchemeRequest.java
  34. +55
    -0
      weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaLiveServiceImplTest.java
  35. +1
    -1
      weixin-java-mp/pom.xml
  36. +1
    -1
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceJoddHttpImpl.java
  37. +2
    -2
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialDeleteJoddHttpRequestExecutor.java
  38. +2
    -2
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialNewsInfoJoddHttpRequestExecutor.java
  39. +2
    -2
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialUploadJoddHttpRequestExecutor.java
  40. +2
    -2
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVideoInfoJoddHttpRequestExecutor.java
  41. +1
    -1
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVoiceAndImageDownloadJoddHttpRequestExecutor.java
  42. +2
    -2
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/media/MediaImgUploadHttpRequestExecutor.java
  43. +3
    -3
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/qrcode/QrCodeJoddHttpRequestExecutor.java
  44. +1
    -1
      weixin-java-open/pom.xml
  45. +2
    -0
      weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenComponentServiceImpl.java
  46. +29
    -0
      weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/message/WxOpenXmlMessage.java
  47. +3
    -3
      weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/MaQrCodeJoddHttpRequestExecutor.java
  48. +13
    -1
      weixin-java-pay/pom.xml
  49. +87
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/ApplymentStateQueryResult.java
  50. +62
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/ModifySettlementRequest.java
  51. +62
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/SettlementInfoResult.java
  52. +1196
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/WxPayApplyment4SubCreateRequest.java
  53. +31
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/WxPayApplymentCreateResult.java
  54. +18
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/enums/AccountTypeEnum.java
  55. +42
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/enums/ApplymentStateEnum.java
  56. +18
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/enums/BankAccountTypeEnum.java
  57. +64
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/enums/CertTypeEnum.java
  58. +17
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/enums/ContactTypeEnum.java
  59. +20
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/enums/IdHolderEnum.java
  60. +41
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/enums/IdTypeEnum.java
  61. +20
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/enums/MicroBizTypeEnum.java
  62. +32
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/enums/SalesScenesTypeEnum.java
  63. +23
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/enums/SettlementVerifyResultEnum.java
  64. +34
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/enums/SubjectTypeEnum.java
  65. +28
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/BankAccountResult.java
  66. +176
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/BankBranchesResult.java
  67. +39
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/BankInfo.java
  68. +64
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/BankingResult.java
  69. +80
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/CitiesResult.java
  70. +59
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/PageLink.java
  71. +81
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/ProvincesResult.java
  72. +93
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/BusinessCircleNotifyData.java
  73. +52
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/MemberCardAuthorizeNotifyResult.java
  74. +53
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/MemberCardAuthorizeResult.java
  75. +112
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/PaidResult.java
  76. +103
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/ParkingNotifyRequest.java
  77. +31
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/PointsCommitStatusResult.java
  78. +154
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/PointsNotifyRequest.java
  79. +121
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/RefundResult.java
  80. +35
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/SignatureHeader.java
  81. +28
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/media/ImageUploadResult.java
  82. +29
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/media/MarketingImageUploadResult.java
  83. +82
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/membercard/MemberCardActivateResult.java
  84. +93
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/membercard/MemberCardNotifyData.java
  85. +360
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/membercard/MemberCardResult.java
  86. +104
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/membercard/MemberCardRightsRequest.java
  87. +95
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/membercard/MemberCardUpdRequest.java
  88. +178
    -34
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/config/WxPayConfig.java
  89. +74
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/Applyment4SubService.java
  90. +121
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/BankService.java
  91. +59
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/BusinessCircleService.java
  92. +50
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/MemberCardService.java
  93. +46
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/MerchantMediaService.java
  94. +120
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java
  95. +66
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/Applyment4SubServiceImpl.java
  96. +68
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BankServiceImpl.java
  97. +31
    -4
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java
  98. +125
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BusinessCircleServiceImpl.java
  99. +87
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/MemberCardServiceImpl.java
  100. +60
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/MerchantMediaServiceImpl.java

+ 3
- 4
pom.xml View File

@@ -6,7 +6,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java</artifactId>
<version>3.7.0</version>
<version>3.7.0.B</version>
<packaging>pom</packaging>
<name>WxJava - Weixin/Wechat Java SDK</name>
<description>微信开发Java SDK</description>
@@ -126,11 +126,10 @@
<artifactId>qrcode-utils</artifactId>
<version>1.1</version>
</dependency>
<!-- 由于jodd-http较新的3.8版本需要jdk8,故而此处采用较低版本 -->
<dependency>
<groupId>org.jodd</groupId>
<artifactId>jodd-http</artifactId>
<version>3.7.1</version>
<version>5.2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -163,7 +162,7 @@
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.5</version>
<version>3.10</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>


+ 1
- 1
spring-boot-starters/pom.xml View File

@@ -6,7 +6,7 @@
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java</artifactId>
<version>3.7.0</version>
<version>3.7.0.B</version>
</parent>
<packaging>pom</packaging>
<artifactId>wx-java-spring-boot-starters</artifactId>


+ 1
- 1
spring-boot-starters/wx-java-miniapp-spring-boot-starter/pom.xml View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>wx-java-spring-boot-starters</artifactId>
<groupId>com.github.binarywang</groupId>
<version>3.7.0</version>
<version>3.7.0.B</version>
</parent>
<modelVersion>4.0.0</modelVersion>



+ 1
- 1
spring-boot-starters/wx-java-mp-spring-boot-starter/pom.xml View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>wx-java-spring-boot-starters</artifactId>
<groupId>com.github.binarywang</groupId>
<version>3.7.0</version>
<version>3.7.0.B</version>
</parent>
<modelVersion>4.0.0</modelVersion>



+ 1
- 1
spring-boot-starters/wx-java-open-spring-boot-starter/pom.xml View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>wx-java-spring-boot-starters</artifactId>
<groupId>com.github.binarywang</groupId>
<version>3.7.0</version>
<version>3.7.0.B</version>
</parent>
<modelVersion>4.0.0</modelVersion>



+ 1
- 1
spring-boot-starters/wx-java-pay-spring-boot-starter/pom.xml View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>wx-java-spring-boot-starters</artifactId>
<groupId>com.github.binarywang</groupId>
<version>3.7.0</version>
<version>3.7.0.B</version>
</parent>
<modelVersion>4.0.0</modelVersion>



+ 8
- 0
spring-boot-starters/wx-java-pay-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/pay/config/WxPayAutoConfiguration.java View File

@@ -50,6 +50,14 @@ public class WxPayAutoConfiguration {
payConfig.setSubMchId(StringUtils.trimToNull(this.properties.getSubMchId()));
payConfig.setKeyPath(StringUtils.trimToNull(this.properties.getKeyPath()));

//以下是apiv3以及支付分相关
payConfig.setServiceId(StringUtils.trimToNull(this.properties.getServiceId()));
payConfig.setPayScoreNotifyUrl(StringUtils.trimToNull(this.properties.getPayScoreNotifyUrl()));
payConfig.setPrivateKeyPath(StringUtils.trimToNull(this.properties.getPrivateKeyPath()));
payConfig.setPrivateCertPath(StringUtils.trimToNull(this.properties.getPrivateCertPath()));
payConfig.setCertSerialNo(StringUtils.trimToNull(this.properties.getCertSerialNo()));
payConfig.setApiV3Key(StringUtils.trimToNull(this.properties.getApiv3Key()));

wxPayService.setConfig(payConfig);
return wxPayService;
}


+ 30
- 0
spring-boot-starters/wx-java-pay-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/pay/properties/WxPayProperties.java View File

@@ -43,4 +43,34 @@ public class WxPayProperties {
* apiclient_cert.p12文件的绝对路径,或者如果放在项目中,请以classpath:开头指定.
*/
private String keyPath;

/**
* 微信支付分serviceId
*/
private String serviceId;

/**
* 证书序列号
*/
private String certSerialNo;

/**
* apiV3秘钥
*/
private String apiv3Key;

/**
* 微信支付分回调地址
*/
private String payScoreNotifyUrl;

/**
* apiv3 商户apiclient_key.pem
*/
private String privateKeyPath;

/**
* apiv3 商户apiclient_cert.pem
*/
private String privateCertPath;
}

+ 1
- 1
weixin-graal/pom.xml View File

@@ -6,7 +6,7 @@
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java</artifactId>
<version>3.7.0</version>
<version>3.7.0.B</version>
</parent>

<artifactId>weixin-graal</artifactId>


+ 1
- 1
weixin-java-common/pom.xml View File

@@ -6,7 +6,7 @@
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java</artifactId>
<version>3.7.0</version>
<version>3.7.0.B</version>
</parent>

<artifactId>weixin-java-common</artifactId>


+ 6
- 0
weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java View File

@@ -9,6 +9,12 @@ import java.util.Map;
* @author Daniel Qian & binarywang
*/
public class WxConsts {

/**
* 微信接口返回的参数errcode.
*/
public static final String ERR_CODE = "errcode";

/**
* 微信推送过来的消息的类型,和发送给微信xml格式消息的消息类型.
*/


+ 1
- 1
weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxError.java View File

@@ -88,7 +88,7 @@ public class WxError implements Serializable {
return "错误代码:" + this.errorCode + ", 错误信息:" + this.errorMsg;
}

return "错误代码:" + this.errorCode + ", 错误信息:" + this.errorMsg + ",微信原始报文:" + this.json;
return "错误代码:" + this.errorCode + ", 错误信息:" + this.errorMsg + ",原始报文:" + this.json;
}

}

+ 23
- 0
weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxRuntimeException.java View File

@@ -0,0 +1,23 @@
package me.chanjar.weixin.common.error;

/**
* WxJava专用的runtime exception.
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
* @date 2020-09-26
*/
public class WxRuntimeException extends RuntimeException {
private static final long serialVersionUID = 4881698471192264412L;

public WxRuntimeException(Throwable e) {
super(e);
}

public WxRuntimeException(String msg) {
super(msg);
}

public WxRuntimeException(String msg, Throwable e) {
super(msg, e);
}
}

+ 11
- 0
weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheHttpClientSimpleGetRequestExecutor.java View File

@@ -1,15 +1,20 @@
package me.chanjar.weixin.common.util.http.apache;

import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.http.RequestHttp;
import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor;
import me.chanjar.weixin.common.util.http.WxDnsResolver;
import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

@@ -20,6 +25,7 @@ import java.io.IOException;
* @date 2017/5/4
*/
public class ApacheHttpClientSimpleGetRequestExecutor extends SimpleGetRequestExecutor<CloseableHttpClient, HttpHost> {
protected final Logger log = LoggerFactory.getLogger(this.getClass());
public ApacheHttpClientSimpleGetRequestExecutor(RequestHttp requestHttp) {
super(requestHttp);
}
@@ -39,6 +45,11 @@ public class ApacheHttpClientSimpleGetRequestExecutor extends SimpleGetRequestEx
}

try (CloseableHttpResponse response = requestHttp.getRequestHttpClient().execute(httpGet)) {
// Header[] allHeaders = response.getAllHeaders();
// for (Header header:allHeaders) {
// log.info("\n【header】:"+header.getName()+"="+header.getValue());
// }

String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
WxError error = WxError.fromJson(responseContent, wxType);
if (error.getErrorCode() != 0) {


+ 3
- 2
weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddHttpMediaDownloadRequestExecutor.java View File

@@ -4,7 +4,6 @@ import jodd.http.HttpConnectionProvider;
import jodd.http.HttpRequest;
import jodd.http.HttpResponse;
import jodd.http.ProxyInfo;
import jodd.util.StringPool;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
@@ -19,6 +18,8 @@ import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;


/**
* .
@@ -47,7 +48,7 @@ public class JoddHttpMediaDownloadRequestExecutor extends BaseMediaDownloadReque
request.withConnectionProvider(requestHttp.getRequestHttpClient());

HttpResponse response = request.send();
response.charset(StringPool.UTF_8);
response.charset(StandardCharsets.UTF_8.name());

String contentType = response.header("Content-Type");
if (contentType != null && contentType.startsWith("application/json")) {


+ 2
- 2
weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddHttpMediaUploadRequestExecutor.java View File

@@ -4,7 +4,6 @@ import jodd.http.HttpConnectionProvider;
import jodd.http.HttpRequest;
import jodd.http.HttpResponse;
import jodd.http.ProxyInfo;
import jodd.util.StringPool;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.error.WxError;
@@ -14,6 +13,7 @@ import me.chanjar.weixin.common.util.http.RequestHttp;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
* .
@@ -35,7 +35,7 @@ public class JoddHttpMediaUploadRequestExecutor extends MediaUploadRequestExecut
request.withConnectionProvider(requestHttp.getRequestHttpClient());
request.form("media", file);
HttpResponse response = request.send();
response.charset(StringPool.UTF_8);
response.charset(StandardCharsets.UTF_8.name());

String responseContent = response.bodyText();
WxError error = WxError.fromJson(responseContent, wxType);


+ 2
- 2
weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddHttpSimpleGetRequestExecutor.java View File

@@ -4,7 +4,6 @@ import jodd.http.HttpConnectionProvider;
import jodd.http.HttpRequest;
import jodd.http.HttpResponse;
import jodd.http.ProxyInfo;
import jodd.util.StringPool;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
@@ -12,6 +11,7 @@ import me.chanjar.weixin.common.util.http.RequestHttp;
import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
* .
@@ -39,7 +39,7 @@ public class JoddHttpSimpleGetRequestExecutor extends SimpleGetRequestExecutor<H
}
request.withConnectionProvider(requestHttp.getRequestHttpClient());
HttpResponse response = request.send();
response.charset(StringPool.UTF_8);
response.charset(StandardCharsets.UTF_8.name());

String responseContent = response.bodyText();



+ 2
- 2
weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddHttpSimplePostRequestExecutor.java View File

@@ -4,7 +4,6 @@ import jodd.http.HttpConnectionProvider;
import jodd.http.HttpRequest;
import jodd.http.HttpResponse;
import jodd.http.ProxyInfo;
import jodd.util.StringPool;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
@@ -12,6 +11,7 @@ import me.chanjar.weixin.common.util.http.RequestHttp;
import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
* .
@@ -38,7 +38,7 @@ public class JoddHttpSimplePostRequestExecutor extends SimplePostRequestExecutor
request.bodyText(postEntity);
}
HttpResponse response = request.send();
response.charset(StringPool.UTF_8);
response.charset(StandardCharsets.UTF_8.name());

String responseContent = response.bodyText();
if (responseContent.isEmpty()) {


+ 26
- 0
weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/GsonParser.java View File

@@ -0,0 +1,26 @@
package me.chanjar.weixin.common.util.json;

import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.stream.JsonReader;

import java.io.Reader;

/**
* @author niefy
*/
public class GsonParser {
private static final JsonParser JSON_PARSER = new JsonParser();

public static JsonObject parse(String json) {
return JSON_PARSER.parse(json).getAsJsonObject();
}

public static JsonObject parse(Reader json) {
return JSON_PARSER.parse(json).getAsJsonObject();
}

public static JsonObject parse(JsonReader json) {
return JSON_PARSER.parse(json).getAsJsonObject();
}
}

+ 9
- 0
weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxErrorAdapter.java View File

@@ -18,9 +18,18 @@ public class WxErrorAdapter implements JsonDeserializer<WxError> {

if (wxErrorJsonObject.get("errcode") != null && !wxErrorJsonObject.get("errcode").isJsonNull()) {
errorBuilder.errorCode(GsonHelper.getAsPrimitiveInt(wxErrorJsonObject.get("errcode")));
} else if(wxErrorJsonObject.get("err_no") != null && !wxErrorJsonObject.get("err_no").isJsonNull()) {
errorBuilder.errorCode(GsonHelper.getAsPrimitiveInt(wxErrorJsonObject.get("err_no")));
} else if(wxErrorJsonObject.get("error_code") != null && !wxErrorJsonObject.get("error_code").isJsonNull()){
errorBuilder.errorCode(GsonHelper.getAsPrimitiveInt(wxErrorJsonObject.get("error_code")));
}

if (wxErrorJsonObject.get("errmsg") != null && !wxErrorJsonObject.get("errmsg").isJsonNull()) {
errorBuilder.errorMsg(GsonHelper.getAsString(wxErrorJsonObject.get("errmsg")));
} else if (wxErrorJsonObject.get("err_tips") != null && !wxErrorJsonObject.get("err_tips").isJsonNull()) {
errorBuilder.errorMsg(GsonHelper.getAsString(wxErrorJsonObject.get("err_tips")));
} else if (wxErrorJsonObject.get("description") != null && !wxErrorJsonObject.get("description").isJsonNull()) {
errorBuilder.errorMsg(GsonHelper.getAsString(wxErrorJsonObject.get("description")));
}

errorBuilder.json(json.toString());


+ 1
- 1
weixin-java-cp/pom.xml View File

@@ -7,7 +7,7 @@
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java</artifactId>
<version>3.7.0</version>
<version>3.7.0.B</version>
</parent>

<artifactId>weixin-java-cp</artifactId>


+ 2
- 2
weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceJoddHttpImpl.java View File

@@ -3,8 +3,8 @@ package me.chanjar.weixin.cp.api.impl;
import jodd.http.HttpConnectionProvider;
import jodd.http.HttpRequest;
import jodd.http.HttpResponse;
import jodd.http.JoddHttp;
import jodd.http.ProxyInfo;
import jodd.http.net.SocketHttpConnectionProvider;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.common.error.WxError;
@@ -68,7 +68,7 @@ public class WxCpServiceJoddHttpImpl extends BaseWxCpServiceImpl<HttpConnectionP
configStorage.getHttpProxyPort(), configStorage.getHttpProxyUsername(), configStorage.getHttpProxyPassword());
}

httpClient = JoddHttp.httpConnectionProvider;
httpClient = new SocketHttpConnectionProvider();
}

@Override


+ 1
- 1
weixin-java-miniapp/pom.xml View File

@@ -7,7 +7,7 @@
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java</artifactId>
<version>3.7.0</version>
<version>3.7.0.B</version>
</parent>

<artifactId>weixin-java-miniapp</artifactId>


+ 62
- 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaLiveService.java View File

@@ -0,0 +1,62 @@
package cn.binarywang.wx.miniapp.api;

import cn.binarywang.wx.miniapp.bean.WxMaGetLiveInfo;
import me.chanjar.weixin.common.error.WxErrorException;

import java.util.List;

/**
* <pre>
* 直播相关操作接口.
* Created by yjwang on 2020/4/5.
* </pre>
*
* @author <a href="https://github.com/yjwang3300300">yjwang</a>
*/
public interface WxMaLiveService {
String GET_LIVE_INFO = "https://api.weixin.qq.com/wxa/business/getliveinfo";

/**
* 获取直播房间列表.(分页)
*
* @param start 起始拉取房间,start = 0 表示从第 1 个房间开始拉取
* @param limit 每次拉取的个数上限,不要设置过大,建议 100 以内
* @return .
* @throws WxErrorException .
*/
WxMaGetLiveInfo getLiveInfo(Integer start, Integer limit) throws WxErrorException;

/**
* 获取所有直播间信息(没有分页直接获取全部)
* @return
* @throws WxErrorException
*/
List<WxMaGetLiveInfo.RoomInfo> getLiveinfos() throws WxErrorException;

/**
*
* 获取直播房间回放数据信息.
*
* @param action 获取回放
* @param room_id 直播间 id
* @param start 起始拉取视频,start = 0 表示从第 1 个视频片段开始拉取
* @param limit 每次拉取的个数上限,不要设置过大,建议 100 以内
* @return
* @throws WxErrorException
*/
WxMaGetLiveInfo getLiveReplay(String action, Integer room_id, Integer start, Integer limit) throws WxErrorException;

/**
*
* 获取直播房间回放数据信息.
*
* 获取回放 (默认:get_replay)
* @param room_id 直播间 id
* @param start 起始拉取视频,start = 0 表示从第 1 个视频片段开始拉取
* @param limit 每次拉取的个数上限,不要设置过大,建议 100 以内
* @return
* @throws WxErrorException
*/
WxMaGetLiveInfo getLiveReplay(Integer room_id, Integer start, Integer limit) throws WxErrorException;

}

+ 36
- 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaSchemeService.java View File

@@ -0,0 +1,36 @@
package cn.binarywang.wx.miniapp.api;

import cn.binarywang.wx.miniapp.bean.scheme.WxMaGenerateNfcSchemeRequest;
import cn.binarywang.wx.miniapp.bean.scheme.WxMaGenerateSchemeRequest;
import me.chanjar.weixin.common.error.WxErrorException;

/**
* <pre>
* 小程序Scheme码相关操作接口.
*
*
* </pre>
*
* @author : cofedream
* created on : 2021-01-26
*/
public interface WxMaSchemeService {

String GENERATE_SCHEME_URL = "https://api.weixin.qq.com/wxa/generatescheme";
String GENERATE_NFC_SCHEME_URL = "https://api.weixin.qq.com/wxa/generatenfcscheme";

/**
* 获取小程序scheme码
*文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/url-scheme/urlscheme.generate.html
* @param request 请求参数
* @throws WxErrorException 生成失败时抛出,具体错误码请看文档
*/
String generate(WxMaGenerateSchemeRequest request) throws WxErrorException;
/**
* 获取NFC 的小程序 scheme
*文档地址:https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/qrcode-link/url-scheme/generateNFCScheme.html
* @param request 请求参数
* @throws WxErrorException 生成失败时抛出,具体错误码请看文档
*/
String generateNFC(WxMaGenerateNfcSchemeRequest request) throws WxErrorException;
}

+ 14
- 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaService.java View File

@@ -156,6 +156,13 @@ public interface WxMaService {
*/
WxMaQrcodeService getQrcodeService();

/**
* 返回获取小程序scheme码实现对象,以方便调用其各个接口.
*
* @return WxMaSchemeService wx ma scheme service
*/
WxMaSchemeService getWxMaSchemeService();

/**
* 返回模板配置相关接口方法的实现类对象, 以方便调用其各个接口.
*
@@ -247,4 +254,11 @@ public interface WxMaService {
* 获取云开发接口服务对象
*/
WxMaCloudService getCloudService();

/**
* 获取直播接口服务对象
*
* @return .
*/
WxMaLiveService getLiveService();
}

+ 100
- 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaLiveServiceImpl.java View File

@@ -0,0 +1,100 @@
package cn.binarywang.wx.miniapp.api.impl;

import cn.binarywang.wx.miniapp.api.WxMaLiveService;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaGetLiveInfo;
import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import lombok.AllArgsConstructor;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* <pre>
* Created by yjwang on 2020/4/5.
* </pre>
*
* @author <a href="https://github.com/yjwang3300300">yjwang</a>
*/
@AllArgsConstructor
public class WxMaLiveServiceImpl implements WxMaLiveService {
private static final JsonParser JSON_PARSER = new JsonParser();
private WxMaService service;

@Override
public WxMaGetLiveInfo getLiveInfo(Integer start, Integer limit) throws WxErrorException {
JsonObject jsonObject = getJsonObject(start, limit, null);
return WxMaGetLiveInfo.fromJson(jsonObject.toString());
}

@Override
public List<WxMaGetLiveInfo.RoomInfo> getLiveinfos() throws WxErrorException {
List<WxMaGetLiveInfo.RoomInfo> results = new ArrayList<>();
Integer start = 0;
Integer limit = 80;
Integer tatal = 0;
WxMaGetLiveInfo liveInfo = null;
do {
if (tatal != 0 && tatal <= start) {
break;
}
liveInfo = getLiveInfo(start, limit);
if (liveInfo == null) {
return null;
}
results.addAll(liveInfo.getRoomInfos());
tatal = liveInfo.getTotal();
start = results.size();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
} while (results.size() <= tatal);
return results;
}

@Override
public WxMaGetLiveInfo getLiveReplay(String action, Integer room_id, Integer start, Integer limit) throws WxErrorException {
Map<String, Object> map = new HashMap(4);
map.put("action", action);
map.put("room_id", room_id);
JsonObject jsonObject = getJsonObject(start, limit, map);
return WxMaGetLiveInfo.fromJson(jsonObject.toString());
}

@Override
public WxMaGetLiveInfo getLiveReplay(Integer room_id, Integer start, Integer limit) throws WxErrorException {
return getLiveReplay("get_replay", room_id, start, limit);
}

/**
* 包装一下
*
* @param start
* @param limit
* @param map
* @return
* @throws WxErrorException
*/
private JsonObject getJsonObject(Integer start, Integer limit, Map<String, Object> map) throws WxErrorException {
if (map == null) {
map = new HashMap(2);
}
map.put("start", start);
map.put("limit", limit);
String responseContent = service.post(GET_LIVE_INFO, WxMaGsonBuilder.create().toJson(map));
JsonObject jsonObject = JSON_PARSER.parse(responseContent).getAsJsonObject();
if (jsonObject.get("errcode").getAsInt() != 0) {
throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp));
}
return jsonObject;
}
}

+ 56
- 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaSchemeServiceImpl.java View File

@@ -0,0 +1,56 @@
package cn.binarywang.wx.miniapp.api.impl;

import cn.binarywang.wx.miniapp.api.WxMaSchemeService;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.scheme.WxMaGenerateNfcSchemeRequest;
import cn.binarywang.wx.miniapp.bean.scheme.WxMaGenerateSchemeRequest;
import com.google.gson.JsonObject;
import lombok.AllArgsConstructor;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.json.GsonParser;

/**
* @author : cofedream
* created on : 2021-01-28
*/
@AllArgsConstructor
public class WxMaSchemeServiceImpl implements WxMaSchemeService {
private final WxMaService wxMaService;

/**
* 获取小程序scheme码
* 文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/url-scheme/urlscheme.generate.html
*
* @param request 请求参数
* @throws WxErrorException 生成失败时抛出,具体错误码请看文档
*/
@Override
public String generate(WxMaGenerateSchemeRequest request) throws WxErrorException {
String responseContent = this.wxMaService.post(GENERATE_SCHEME_URL, request.toJson());
JsonObject jsonObject = GsonParser.parse(responseContent);
if (jsonObject.get(WxConsts.ERR_CODE).getAsInt() != 0) {
throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp));
}
return jsonObject.get("openlink").getAsString();
}

/**
* 获取NFC 的小程序 scheme
* 文档地址:https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/qrcode-link/url-scheme/generateNFCScheme.html
*
* @param request 请求参数
* @throws WxErrorException 生成失败时抛出,具体错误码请看文档
*/
@Override
public String generateNFC(WxMaGenerateNfcSchemeRequest request) throws WxErrorException {
String responseContent = this.wxMaService.post(GENERATE_NFC_SCHEME_URL, request.toJson());
JsonObject jsonObject = GsonParser.parse(responseContent);
if (jsonObject.get(WxConsts.ERR_CODE).getAsInt() != 0) {
throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp));
}
return jsonObject.get("openlink").getAsString();
}
}

+ 12
- 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceImpl.java View File

@@ -46,6 +46,7 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl
private WxMaMediaService materialService = new WxMaMediaServiceImpl(this);
private WxMaUserService userService = new WxMaUserServiceImpl(this);
private WxMaQrcodeService qrCodeService = new WxMaQrcodeServiceImpl(this);
private WxMaSchemeService schemeService = new WxMaSchemeServiceImpl(this);
private WxMaTemplateService templateService = new WxMaTemplateServiceImpl(this);
private WxMaAnalysisService analysisService = new WxMaAnalysisServiceImpl(this);
private WxMaCodeService codeService = new WxMaCodeServiceImpl(this);
@@ -58,6 +59,7 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl
private WxMaExpressService expressService = new WxMaExpressServiceImpl(this);
private WxMaSubscribeService subscribeService = new WxMaSubscribeServiceImpl(this);
private WxMaCloudService cloudService = new WxMaCloudServiceImpl(this);
private WxMaLiveService liveService = new WxMaLiveServiceImpl(this);

private int retrySleepMillis = 1000;
private int maxRetryTimes = 5;
@@ -330,6 +332,11 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl
return this.qrCodeService;
}

@Override
public WxMaSchemeService getWxMaSchemeService() {
return schemeService;
}

@Override
public WxMaTemplateService getTemplateService() {
return this.templateService;
@@ -389,4 +396,9 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl
public WxMaCloudService getCloudService() {
return this.cloudService;
}

@Override
public WxMaLiveService getLiveService() {
return this.liveService;
}
}

+ 88
- 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaGetLiveInfo.java View File

@@ -0,0 +1,88 @@
package cn.binarywang.wx.miniapp.bean;

import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder;
import com.google.gson.annotations.SerializedName;
import lombok.Data;

import java.io.Serializable;
import java.util.List;

/**
* 获取直播房间列表
*
* @author yjwang
* @date 2020/4/5
*/
@Data
public class WxMaGetLiveInfo implements Serializable {
private static final long serialVersionUID = 7285263767524755887L;
private Integer errcode;
private String errmsg;
private Integer total;
/**
* 直播间列表
*/
@SerializedName("room_info")
private List<RoomInfo> roomInfos;
/**
* 获取回放源视频列表
*/
@SerializedName("live_replay")
private List<LiveReplay> liveReplay;

public static WxMaGetLiveInfo fromJson(String json) {
return WxMaGsonBuilder.create().fromJson(json, WxMaGetLiveInfo.class);
}

/**
* 直播列表
*/
@Data
public static class RoomInfo implements Serializable {
private static final long serialVersionUID = 7745775280267417154L;
private String name;
private Integer roomid;
@SerializedName("cover_img")
private String coverImg;
@SerializedName("live_status")
private Integer liveStatus;
@SerializedName("start_time")
private Long startTime;
@SerializedName("end_time")
private Long endTime;
@SerializedName("anchor_name")
private String anchorName;
@SerializedName("anchor_img")
private String anchorImg;
private List<Goods> goods;
}

/**
* 商品列表
*/
@Data
public static class Goods implements Serializable {
private static final long serialVersionUID = 5769245932149287574L;
@SerializedName("cover_img")
private String coverImg;
private String url;
private String price;
private String name;
}

/**
* 回放数据列表
*/
@Data
public static class LiveReplay implements Serializable {
private static final long serialVersionUID = 7683927205627536320L;
@SerializedName("expire_time")
private String expireTime;
@SerializedName("create_time")
private String createTime;
@SerializedName("media_url")
private String mediaUrl;
}


}

+ 1
- 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaPhoneNumberInfo.java View File

@@ -4,6 +4,7 @@ import java.io.Serializable;

import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

/**
* 微信用户绑定的手机号相关信息


+ 75
- 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/scheme/WxMaGenerateNfcSchemeRequest.java View File

@@ -0,0 +1,75 @@
package cn.binarywang.wx.miniapp.bean.scheme;

import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder;
import com.google.gson.annotations.SerializedName;
import lombok.Builder;
import lombok.Data;

/**
* @author : lyt
* created on : 2023-07-31
*/
@Data
@Builder(builderMethodName = "newBuilder")
public class WxMaGenerateNfcSchemeRequest {
/**
* 跳转到的目标小程序信息。
* <pre>
* 是否必填:否
* </pre>
*/
@SerializedName("jump_wxa")
private JumpWxa jumpWxa;

/**
* scheme对应的设备model_id
* <pre>
* 是否必填:是
* </pre>
*/
@SerializedName("model_id")
private String modelId;

/**
* scheme对应的设备sn,仅一机一码时填写
* <pre>
* 是否必填:否
* </pre>
*/
@SerializedName("sn")
private String sn;

@Data
@Builder(builderMethodName = "newBuilder")
public static class JumpWxa {
/**
* 通过scheme码进入的小程序页面路径,必须是已经发布的小程序存在的页面,不可携带query。path为空时会跳转小程序主页。
* <pre>
* 是否必填:是
* </pre>
*/
@SerializedName("path")
private String path;

/**
* 通过scheme码进入小程序时的query,最大128个字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~
* 返回值
* <pre>
* 是否必填:是
* </pre>
*/
@SerializedName("query")
private String query;

/**
* 要打开的小程序版本。正式版为"release",体验版为"trial",开发版为"develop"默认值:release
*/
@SerializedName("env_version")
private String envVersion = "release";
}

public String toJson() {
return WxMaGsonBuilder.create().toJson(this);
}

}

+ 94
- 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/scheme/WxMaGenerateSchemeRequest.java View File

@@ -0,0 +1,94 @@
package cn.binarywang.wx.miniapp.bean.scheme;

import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder;
import com.google.gson.annotations.SerializedName;
import lombok.Builder;
import lombok.Data;

/**
* @author : cofedream
* created on : 2021-01-26
*/
@Data
@Builder(builderMethodName = "newBuilder")
public class WxMaGenerateSchemeRequest {
/**
* 跳转到的目标小程序信息。
* <pre>
* 是否必填:否
* </pre>
*/
@SerializedName("jump_wxa")
private JumpWxa jumpWxa;

/**
* 生成的scheme码类型,到期失效:true,永久有效:false。
* <pre>
* 是否必填:否
* </pre>
*/
@SerializedName("is_expire")
private Boolean isExpire;

/**
* 到期失效的scheme码的失效时间,为Unix时间戳。生成的到期失效scheme码在该时间前有效。最长有效期为1年。生成到期失效的scheme时必填。
* <pre>
* 是否必填:否
* </pre>
*/
@SerializedName("expire_time")
private Long expireTime;

/**
* 到期失效的 scheme 码失效类型,失效时间:0,失效间隔天数:1
* <pre>
* 是否必填:否
* </pre>
*/
@SerializedName("expire_type")
private Integer expireType;

/**
* 到期失效的 scheme 码的失效间隔天数。
* <pre>
* 生成的到期失效 scheme 码在该间隔时间到达前有效。最长间隔天数为365天。is_expire 为 true 且 expire_type 为 1 时必填 * <pre>
* 是否必填:否
* </pre>
*/
@SerializedName("expire_interval")
private Integer expireInterval;

@Data
@Builder(builderMethodName = "newBuilder")
public static class JumpWxa {
/**
* 通过scheme码进入的小程序页面路径,必须是已经发布的小程序存在的页面,不可携带query。path为空时会跳转小程序主页。
* <pre>
* 是否必填:是
* </pre>
*/
@SerializedName("path")
private String path;

/**
* 通过scheme码进入小程序时的query,最大128个字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~
* 返回值
* <pre>
* 是否必填:是
* </pre>
*/
@SerializedName("query")
private String query;

/**
* 要打开的小程序版本。正式版为"release",体验版为"trial",开发版为"develop"默认值:release
*/
@SerializedName("env_version")
private String envVersion = "release";
}

public String toJson() {
return WxMaGsonBuilder.create().toJson(this);
}

}

+ 55
- 0
weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaLiveServiceImplTest.java View File

@@ -0,0 +1,55 @@
package cn.binarywang.wx.miniapp.api.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaGetLiveInfo;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import cn.binarywang.wx.miniapp.test.ApiTestModule;
import cn.binarywang.wx.miniapp.test.TestConfig;
import com.google.common.collect.ImmutableMap;
import com.google.gson.JsonObject;
import com.google.inject.Inject;
import me.chanjar.weixin.common.error.WxErrorException;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;

import java.util.List;
import java.util.stream.Collectors;

import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;

/**
* 测试直播相关的接口
*
* @author <a href="https://github.com/yjwang3300300">yjwang</a>
*/
@Test
@Guice(modules = ApiTestModule.class)
public class WxMaLiveServiceImplTest {

@Inject
private WxMaService wxService;

@Test
public void getLiveInfo() throws Exception {
WxMaGetLiveInfo list = this.wxService.getLiveService().getLiveInfo(0,10);
assertNotNull(list);
System.out.println(list.toString());
}

@Test
public void getLiveReplay() throws Exception {
// [12, 11, 10, 9, 8, 7, 6, 5, 3, 2]
WxMaGetLiveInfo list = this.wxService.getLiveService().getLiveReplay(11,0,10);
assertNotNull(list);
System.out.println(list.toString());
}

@Test
public void getLiveinfos() throws Exception {
List<WxMaGetLiveInfo.RoomInfo> list = this.wxService.getLiveService().getLiveinfos();
assertNotNull(list);
System.out.println(list.toString());
}
}

+ 1
- 1
weixin-java-mp/pom.xml View File

@@ -7,7 +7,7 @@
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java</artifactId>
<version>3.7.0</version>
<version>3.7.0.B</version>
</parent>

<artifactId>weixin-java-mp</artifactId>


+ 1
- 1
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceJoddHttpImpl.java View File

@@ -46,7 +46,7 @@ public class WxMpServiceJoddHttpImpl extends BaseWxMpServiceImpl<HttpConnectionP
httpProxy = new ProxyInfo(ProxyInfo.ProxyType.HTTP, configStorage.getHttpProxyHost(), configStorage.getHttpProxyPort(), configStorage.getHttpProxyUsername(), configStorage.getHttpProxyPassword());
}

httpClient = JoddHttp.httpConnectionProvider;
httpClient = new SocketHttpConnectionProvider();
}

@Override


+ 2
- 2
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialDeleteJoddHttpRequestExecutor.java View File

@@ -4,7 +4,6 @@ import jodd.http.HttpConnectionProvider;
import jodd.http.HttpRequest;
import jodd.http.HttpResponse;
import jodd.http.ProxyInfo;
import jodd.util.StringPool;

import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.error.WxError;
@@ -12,6 +11,7 @@ import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.http.RequestHttp;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
* Created by ecoolper on 2017/5/5.
@@ -31,7 +31,7 @@ public class MaterialDeleteJoddHttpRequestExecutor extends MaterialDeleteRequest

request.query("media_id", materialId);
HttpResponse response = request.send();
response.charset(StringPool.UTF_8);
response.charset(StandardCharsets.UTF_8.name());
String responseContent = response.bodyText();
WxError error = WxError.fromJson(responseContent, WxType.MP);
if (error.getErrorCode() != 0) {


+ 2
- 2
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialNewsInfoJoddHttpRequestExecutor.java View File

@@ -5,7 +5,6 @@ import jodd.http.HttpConnectionProvider;
import jodd.http.HttpRequest;
import jodd.http.HttpResponse;
import jodd.http.ProxyInfo;
import jodd.util.StringPool;

import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.error.WxError;
@@ -18,6 +17,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
* Created by ecoolper on 2017/5/5.
@@ -38,7 +38,7 @@ public class MaterialNewsInfoJoddHttpRequestExecutor extends MaterialNewsInfoReq
.withConnectionProvider(requestHttp.getRequestHttpClient())
.body(WxGsonBuilder.create().toJson(ImmutableMap.of("media_id", materialId)));
HttpResponse response = request.send();
response.charset(StringPool.UTF_8);
response.charset(StandardCharsets.UTF_8.name());

String responseContent = response.bodyText();
this.logger.debug("响应原始数据:{}", responseContent);


+ 2
- 2
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialUploadJoddHttpRequestExecutor.java View File

@@ -4,7 +4,6 @@ import jodd.http.HttpConnectionProvider;
import jodd.http.HttpRequest;
import jodd.http.HttpResponse;
import jodd.http.ProxyInfo;
import jodd.util.StringPool;

import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.error.WxError;
@@ -17,6 +16,7 @@ import me.chanjar.weixin.mp.bean.material.WxMpMaterialUploadResult;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Map;

/**
@@ -50,7 +50,7 @@ public class MaterialUploadJoddHttpRequestExecutor extends MaterialUploadRequest
}

HttpResponse response = request.send();
response.charset(StringPool.UTF_8);
response.charset(StandardCharsets.UTF_8.name());
String responseContent = response.bodyText();
WxError error = WxError.fromJson(responseContent, WxType.MP);
if (error.getErrorCode() != 0) {


+ 2
- 2
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVideoInfoJoddHttpRequestExecutor.java View File

@@ -4,7 +4,6 @@ import jodd.http.HttpConnectionProvider;
import jodd.http.HttpRequest;
import jodd.http.HttpResponse;
import jodd.http.ProxyInfo;
import jodd.util.StringPool;

import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.error.WxError;
@@ -13,6 +12,7 @@ import me.chanjar.weixin.common.util.http.RequestHttp;
import me.chanjar.weixin.mp.bean.material.WxMpMaterialVideoInfoResult;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
* Created by ecoolper on 2017/5/5.
@@ -32,7 +32,7 @@ public class MaterialVideoInfoJoddHttpRequestExecutor extends MaterialVideoInfoR

request.query("media_id", materialId);
HttpResponse response = request.send();
response.charset(StringPool.UTF_8);
response.charset(StandardCharsets.UTF_8.name());
String responseContent = response.bodyText();
WxError error = WxError.fromJson(responseContent, WxType.MP);
if (error.getErrorCode() != 0) {


+ 1
- 1
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVoiceAndImageDownloadJoddHttpRequestExecutor.java View File

@@ -37,7 +37,7 @@ public class MaterialVoiceAndImageDownloadJoddHttpRequestExecutor extends Materi

request.query("media_id", materialId);
HttpResponse response = request.send();
response.charset(StringPool.UTF_8);
response.charset(StandardCharsets.UTF_8.name());
try (InputStream inputStream = new ByteArrayInputStream(response.bodyBytes())) {
// 下载媒体文件出错
byte[] responseContent = IOUtils.toByteArray(inputStream);


+ 2
- 2
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/media/MediaImgUploadHttpRequestExecutor.java View File

@@ -4,7 +4,6 @@ import jodd.http.HttpConnectionProvider;
import jodd.http.HttpRequest;
import jodd.http.HttpResponse;
import jodd.http.ProxyInfo;
import jodd.util.StringPool;

import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.error.WxError;
@@ -14,6 +13,7 @@ import me.chanjar.weixin.mp.bean.material.WxMediaImgUploadResult;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
* Created by ecoolper on 2017/5/5.
@@ -39,7 +39,7 @@ public class MediaImgUploadHttpRequestExecutor extends MediaImgUploadRequestExec

request.form("media", data);
HttpResponse response = request.send();
response.charset(StringPool.UTF_8);
response.charset(StandardCharsets.UTF_8.name());
String responseContent = response.bodyText();
WxError error = WxError.fromJson(responseContent, WxType.MP);
if (error.getErrorCode() != 0) {


+ 3
- 3
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/qrcode/QrCodeJoddHttpRequestExecutor.java View File

@@ -4,9 +4,8 @@ import jodd.http.HttpConnectionProvider;
import jodd.http.HttpRequest;
import jodd.http.HttpResponse;
import jodd.http.ProxyInfo;
import jodd.util.MimeTypes;
import jodd.util.StringPool;

import jodd.net.MimeTypes;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
@@ -19,6 +18,7 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.UUID;

/**
@@ -47,7 +47,7 @@ public class QrCodeJoddHttpRequestExecutor extends QrCodeRequestExecutor<HttpCon
request.withConnectionProvider(requestHttp.getRequestHttpClient());

HttpResponse response = request.send();
response.charset(StringPool.UTF_8);
response.charset(StandardCharsets.UTF_8.name());
String contentTypeHeader = response.header("Content-Type");
if (MimeTypes.MIME_TEXT_PLAIN.equals(contentTypeHeader)) {
String responseContent = response.bodyText();


+ 1
- 1
weixin-java-open/pom.xml View File

@@ -7,7 +7,7 @@
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java</artifactId>
<version>3.7.0</version>
<version>3.7.0.B</version>
</parent>

<artifactId>weixin-java-open</artifactId>


+ 2
- 0
weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenComponentServiceImpl.java View File

@@ -166,6 +166,7 @@ public class WxOpenComponentServiceImpl implements WxOpenComponentService {
String componentAccessToken = getComponentAccessToken(false);
String uriWithComponentAccessToken = uri + (uri.contains("?") ? "&" : "?") + accessTokenKey + "=" + componentAccessToken;
try {
this.log.info("wxopencomponent excute url:"+uriWithComponentAccessToken);
return getWxOpenService().get(uriWithComponentAccessToken, null);
} catch (WxErrorException e) {
WxError error = e.getError();
@@ -246,6 +247,7 @@ public class WxOpenComponentServiceImpl implements WxOpenComponentService {

@Override
public String route(final WxOpenXmlMessage wxMessage) throws WxErrorException {
log.info("wxopencomponent route :"+wxMessage);
if (wxMessage == null) {
throw new NullPointerException("message is empty");
}


+ 29
- 0
weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/message/WxOpenXmlMessage.java View File

@@ -8,6 +8,7 @@ import me.chanjar.weixin.common.util.xml.XStreamCDataConverter;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.chanjar.weixin.open.api.WxOpenConfigStorage;
import me.chanjar.weixin.open.api.impl.WxOpenInMemoryConfigStorage;
import me.chanjar.weixin.open.util.WxOpenCryptUtil;
import me.chanjar.weixin.open.util.xml.XStreamTransformer;
import org.apache.commons.io.IOUtils;
@@ -140,6 +141,7 @@ public class WxOpenXmlMessage implements Serializable {
String timestamp, String nonce, String msgSignature) {
WxOpenCryptUtil cryptUtil = new WxOpenCryptUtil(wxOpenConfigStorage);
String plainText = cryptUtil.decrypt(msgSignature, timestamp, nonce, encryptedXml);
log.debug("解密后的原始xml消息内容:{}", plainText);
return WxMpXmlMessage.fromXml(plainText);
}

@@ -152,4 +154,31 @@ public class WxOpenXmlMessage implements Serializable {
throw new RuntimeException(e);
}
}

public static void main(String[] args) {
WxOpenInMemoryConfigStorage wxOpenConfigStorage = new WxOpenInMemoryConfigStorage();
wxOpenConfigStorage.setComponentAesKey("");
wxOpenConfigStorage.setComponentToken("");
wxOpenConfigStorage.setComponentAppId("");

WxOpenCryptUtil cryptUtil = new WxOpenCryptUtil(wxOpenConfigStorage);
/**
* 接收微信APP回调:[appId=[wx3cb90ab25f132468], openid=[ok9Xtt7rErEqlQKBjaluwroxsHaM], signature=[50e3ddd2d2817cbc309ed0a4b9b6eafe6e4c8648], encType=[aes], msgSignature=[00c9b32600e67276a56e2092fe3dfe1c486318f5], timestamp=[1653534263], nonce=[897774971], requestBody=[
* <xml>
* <ToUserName><![CDATA[gh_ddfa54d85724]]></ToUserName>
* <Encrypt><![CDATA[EUzw+5L2Vsqs6fxq4ZGw1S/Hu/4Gx04Z4v2ZqE45OM5OHvK/6z0K21D2wdVv20YmswbsxW7bThe2vvoMqf8dktp4MbOqLMACpYt9B1UeQBoG0tnwiQo1PggTLr3iomBVxRERVpLcyIRZHbyGW0sg3zKjecVGlvMgL4fQFCZmi5swzuR8zXsHQ9LlPiB0jSaF37cj0g7YMyYlzZ1GRyleGljLER3P+Plqa727bpJjGwRgSkBBco8vm4bEcOyTiO0Yy5gARMHC2bcQkhqgUgp6XRyz5YM9jW6DwXPhVCY+X/vvTL1gPm/UAZpwY+YUNh+1o+xm45MX+FjHXN/kbdeVV6NqO8VGF0sP0XYBlenBm4a3CmxU5AjNTauM1f6KSpoLV0R1c02l2hbvpwZ32CEgD5uriOh2NWOnWuLD58AScA8xyIUzdENUsYlq60H9tRd4KRbSydcwp2ALCcm0B1KS/GDT/587TntnL+Ai2VrUSnlZej/ByV8D4dvEuAU+5/ky]]></Encrypt>
* </xml>
*
* ]
*/
String msgSignature = "50e3ddd2d2817cbc309ed0a4b9b6eafe6e4c8648";
String timestamp = "1653534263";
String nonce = "897774971";
String encryptedXml = "<xml>\n" +
" <ToUserName><![CDATA[gh_ddfa54d85724]]></ToUserName>\n" +
" <Encrypt><![CDATA[EUzw+5L2Vsqs6fxq4ZGw1S/Hu/4Gx04Z4v2ZqE45OM5OHvK/6z0K21D2wdVv20YmswbsxW7bThe2vvoMqf8dktp4MbOqLMACpYt9B1UeQBoG0tnwiQo1PggTLr3iomBVxRERVpLcyIRZHbyGW0sg3zKjecVGlvMgL4fQFCZmi5swzuR8zXsHQ9LlPiB0jSaF37cj0g7YMyYlzZ1GRyleGljLER3P+Plqa727bpJjGwRgSkBBco8vm4bEcOyTiO0Yy5gARMHC2bcQkhqgUgp6XRyz5YM9jW6DwXPhVCY+X/vvTL1gPm/UAZpwY+YUNh+1o+xm45MX+FjHXN/kbdeVV6NqO8VGF0sP0XYBlenBm4a3CmxU5AjNTauM1f6KSpoLV0R1c02l2hbvpwZ32CEgD5uriOh2NWOnWuLD58AScA8xyIUzdENUsYlq60H9tRd4KRbSydcwp2ALCcm0B1KS/GDT/587TntnL+Ai2VrUSnlZej/ByV8D4dvEuAU+5/ky]]></Encrypt>\n" +
"</xml>";
String plainText = cryptUtil.decrypt(msgSignature, timestamp, nonce, encryptedXml);
System.out.println(plainText);
}
}

+ 3
- 3
weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/MaQrCodeJoddHttpRequestExecutor.java View File

@@ -4,8 +4,7 @@ import jodd.http.HttpConnectionProvider;
import jodd.http.HttpRequest;
import jodd.http.HttpResponse;
import jodd.http.ProxyInfo;
import jodd.util.MimeTypes;
import jodd.util.StringPool;
import jodd.net.MimeTypes;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
@@ -19,6 +18,7 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.UUID;

/**
@@ -49,7 +49,7 @@ public class MaQrCodeJoddHttpRequestExecutor extends MaQrCodeRequestExecutor<Htt
request.withConnectionProvider(requestHttp.getRequestHttpClient());

HttpResponse response = request.send();
response.charset(StringPool.UTF_8);
response.charset(StandardCharsets.UTF_8.name());
String contentTypeHeader = response.header("Content-Type");
if (MimeTypes.MIME_TEXT_PLAIN.equals(contentTypeHeader)) {
String responseContent = response.bodyText();


+ 13
- 1
weixin-java-pay/pom.xml View File

@@ -5,13 +5,25 @@
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java</artifactId>
<version>3.7.0</version>
<version>3.7.0.B</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>weixin-java-pay</artifactId>
<name>WxJava - PAY Java SDK</name>
<description>微信支付 Java SDK</description>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>

<dependencies>
<dependency>


+ 87
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/ApplymentStateQueryResult.java View File

@@ -0,0 +1,87 @@
package com.github.binarywang.wxpay.bean.applyment;

import com.github.binarywang.wxpay.bean.applyment.enums.ApplymentStateEnum;
import com.google.gson.annotations.SerializedName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import java.io.Serializable;
import java.util.List;

/**
* 查询申请单状态返回对象信息
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class ApplymentStateQueryResult implements Serializable {
private static final long serialVersionUID = 6539090917423486409L;
/**
* 业务申请编号
*/
@SerializedName("business_code")
private String businessCode;
/**
* 微信支付申请单号
*/
@SerializedName("applyment_id")
private String applymentId;
/**
* 特约商户号
*/
@SerializedName("sub_mchid")
private String subMchid;
/**
* 超级管理员签约链接
*/
@SerializedName("sign_url")
private String signUrl;

/**
* 申请单状态
*/
@SerializedName("applyment_state")
private ApplymentStateEnum applymentState;
/**
* 申请状态描述
*/
@SerializedName("applyment_state_msg")
private String applymentStateMsg;
/**
* 驳回原因详情
*/
@SerializedName("audit_detail")
private List<AuditDetail> auditDetail;

/**
* 驳回原因详情
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public static class AuditDetail {
/**
* 字段名
*/
@SerializedName("field")
private String field;
/**
* 字段名称
*/
@SerializedName("field_name")
private String fieldName;
/**
* 驳回原因
*/
@SerializedName("reject_reason")
private String rejectReason;

}
}

+ 62
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/ModifySettlementRequest.java View File

@@ -0,0 +1,62 @@
package com.github.binarywang.wxpay.bean.applyment;

import com.github.binarywang.wxpay.bean.applyment.enums.AccountTypeEnum;
import com.github.binarywang.wxpay.v3.SpecEncrypt;
import com.google.gson.annotations.SerializedName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import java.io.Serializable;

/**
* 修改结算账户请求对象
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class ModifySettlementRequest implements Serializable {
private static final long serialVersionUID = 4568552340365230872L;
/**
* 账户类型
*/
@SerializedName("account_type")
private AccountTypeEnum accountType;
/**
* 开户名称
*/
@SpecEncrypt
@SerializedName("account_name")
private String accountName;
/**
* 开户银行
*/
@SerializedName("account_bank")
private String accountBank;
/**
* 开户银行省市编码
*/
@SerializedName("bank_address_code")
private String bankAddressCode;
/**
* 开户银行全称(含支行)
*/
@SerializedName("bank_name")
private String bankName;
/**
* 开户银行联行号
*/
@SerializedName("bank_branch_id")
private String bankBranchId;

/**
* 银行账号
*/
@SpecEncrypt
@SerializedName("account_number")
private String accountNumber;
}

+ 62
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/SettlementInfoResult.java View File

@@ -0,0 +1,62 @@
package com.github.binarywang.wxpay.bean.applyment;

import com.github.binarywang.wxpay.bean.applyment.enums.AccountTypeEnum;
import com.github.binarywang.wxpay.bean.applyment.enums.SettlementVerifyResultEnum;
import com.google.gson.annotations.SerializedName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import java.io.Serializable;

/**
* 查询结算账户返回对象信息
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class SettlementInfoResult implements Serializable {
private static final long serialVersionUID = 4568552340365230872L;
/**
* 账户类型
*/
@SerializedName("account_type")
private AccountTypeEnum accountType;
/**
* 开户银行
*/
@SerializedName("account_bank")
private String accountBank;
/**
* 开户银行全称(含支行]
*/
@SerializedName("bank_name")
private String bankName;
/**
* 开户银行联行号
*/
@SerializedName("bank_branch_id")
private String bankBranchId;
/**
* 银行账号
*/
@SerializedName("account_number")
private String accountNumber;
/**
* 汇款验证结果
*
* @see com.github.binarywang.wxpay.bean.applyment.enums.SettlementVerifyResultEnum
*/
@SerializedName("verify_result")
private SettlementVerifyResultEnum verifyResult;

/**
* 汇款验证失败原因
*/
@SerializedName("verify_fail_reason")
private String verifyFailReason;
}

+ 1196
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/WxPayApplyment4SubCreateRequest.java
File diff suppressed because it is too large
View File


+ 31
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/WxPayApplymentCreateResult.java View File

@@ -0,0 +1,31 @@
package com.github.binarywang.wxpay.bean.applyment;

import com.google.gson.annotations.SerializedName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import java.io.Serializable;


/**
* 特约商户进件 提交申请结果响应
*
* @author zhouyongshen
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class WxPayApplymentCreateResult implements Serializable {
private static final long serialVersionUID = 1L;

/**
* 微信支付申请单号
*/
@SerializedName("applyment_id")
private String applymentId;
}

+ 18
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/enums/AccountTypeEnum.java View File

@@ -0,0 +1,18 @@
package com.github.binarywang.wxpay.bean.applyment.enums;


/**
* 银行结算账户枚举类
*/
public enum AccountTypeEnum {
/**
* 对公银行账户
*/
ACCOUNT_TYPE_BUSINESS,

/**
* 经营者个人银行卡
*/
ACCOUNT_TYPE_PRIVATE,
;
}

+ 42
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/enums/ApplymentStateEnum.java View File

@@ -0,0 +1,42 @@
package com.github.binarywang.wxpay.bean.applyment.enums;

/**
* 申请单状态枚举类
*
* @author zhouyongshen
*/
public enum ApplymentStateEnum {
/**
* (编辑中):提交申请发生错误导致,请尝试重新提交。
*/
APPLYMENT_STATE_EDITTING,
/**
* (审核中):申请单正在审核中,超级管理员用微信打开“签约链接”,完成绑定微信号后,申请单进度将通过微信公众号通知超级管理员,引导完成后续步骤。
*/
APPLYMENT_STATE_AUDITING,
/**
* (已驳回):请按照驳回原因修改申请资料,超级管理员用微信打开“签约链接”,完成绑定微信号,后续申请单进度将通过微信公众号通知超级管理员。
*/
APPLYMENT_STATE_REJECTED,
/**
* (待账户验证):请超级管理员使用微信打开返回的“签约链接”,根据页面指引完成账户验证。
*/
APPLYMENT_STATE_TO_BE_CONFIRMED,
/**
* (待签约):请超级管理员使用微信打开返回的“签约链接”,根据页面指引完成签约。
*/
APPLYMENT_STATE_TO_BE_SIGNED,
/**
* (开通权限中):系统开通相关权限中,请耐心等待。
*/
APPLYMENT_STATE_SIGNING,
/**
* (已完成):商户入驻申请已完成。
*/
APPLYMENT_STATE_FINISHED,
/**
* (已作废):申请单已被撤销。
*/
APPLYMENT_STATE_CANCELED

}

+ 18
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/enums/BankAccountTypeEnum.java View File

@@ -0,0 +1,18 @@
package com.github.binarywang.wxpay.bean.applyment.enums;


/**
* 银行结算账户枚举类
*/
public enum BankAccountTypeEnum {
/**
* 对公银行账户
*/
BANK_ACCOUNT_TYPE_CORPORATE,

/**
* 经营者个人银行卡
*/
BANK_ACCOUNT_TYPE_PERSONAL,
;
}

+ 64
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/enums/CertTypeEnum.java View File

@@ -0,0 +1,64 @@
package com.github.binarywang.wxpay.bean.applyment.enums;

/**
* 登记证书的类型枚举
*/
public enum CertTypeEnum {
/**
* 事业单位法人证书
*/
CERTIFICATE_TYPE_2388,
/**
* 统一社会信用代码证书
*/
CERTIFICATE_TYPE_2389,
/**
* 有偿服务许可证(军队医院适用)
*/
CERTIFICATE_TYPE_2390,
/**
* 医疗机构执业许可证(军队医院适用)
*/
CERTIFICATE_TYPE_2391,
/**
* 企业营业执照(挂靠企业的党组织适用)
*/
CERTIFICATE_TYPE_2392,
/**
* 组织机构代码证(政府机关适用)
*/
CERTIFICATE_TYPE_2393,
/**
* 社会团体法人登记证书
*/
CERTIFICATE_TYPE_2394,
/**
* 民办非企业单位登记证书
*/
CERTIFICATE_TYPE_2395,
/**
* 基金会法人登记证书
*/
CERTIFICATE_TYPE_2396,
/**
* 宗教活动场所登记证
*/
CERTIFICATE_TYPE_2399,
/**
* 其他证书/批文/证明
*/
CERTIFICATE_TYPE_2400,
/**
* 执业许可证/执业证
*/
CERTIFICATE_TYPE_2520,
/**
* 基层群众性自治组织特别法人统一社会信用代码证
*/
CERTIFICATE_TYPE_2521,
/**
* 农村集体经济组织登记证
*/
CERTIFICATE_TYPE_2522,
;
}

+ 17
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/enums/ContactTypeEnum.java View File

@@ -0,0 +1,17 @@
package com.github.binarywang.wxpay.bean.applyment.enums;

/**
* 1、主体为“个体工商户/企业/政府机关/事业单位/社会组织”,可选择:LEGAL:经营者/法人,SUPER:经办人 。(经办人:经商户授权办理微信支付业务的人员)。
* 枚举值
*/
public enum ContactTypeEnum {
/**
* 法人
*/
LEGAL,
/**
* 经办人
*/
SUPER,
;
}

+ 20
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/enums/IdHolderEnum.java View File

@@ -0,0 +1,20 @@
package com.github.binarywang.wxpay.bean.applyment.enums;

/**
* 1. 主体类型为政府机关、事业单位时选传:
* (1)若上传的是法人证件,则不需要上传该字段
* (2)若因特殊情况,无法提供法人证件时,可上传经办人。 (经办人:经商户授权办理微信支付业务的人员,授权范围包括但不限于签约,入驻过程需完成账户验证)。
* 2. 主体类型为企业、个体户、社会组织时,默认为经营者/法人,不需要上传该字段。
* 枚举值
*/
public enum IdHolderEnum {
/**
* 法人
*/
LEGAL,
/**
* 经办人
*/
SUPER,
;
}

+ 41
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/enums/IdTypeEnum.java View File

@@ -0,0 +1,41 @@
package com.github.binarywang.wxpay.bean.applyment.enums;

/**
* 个体户/企业/党政、机关及事业单位/其他组织:可选择任一证件类型。
* 枚举值
*/
public enum IdTypeEnum {
/**
* 中国大陆居民-身份证
*/
IDENTIFICATION_TYPE_IDCARD,
/**
* 其他国家或地区居民-护照
*/
IDENTIFICATION_TYPE_OVERSEA_PASSPORT,
/**
* 中国香港居民-来往内地通行证
*/
IDENTIFICATION_TYPE_HONGKONG_PASSPORT,
/**
* 中国澳门居民-来往内地通行证
*/
IDENTIFICATION_TYPE_MACAO_PASSPORT,
/**
* 中国台湾居民-来往大陆通行证
*/
IDENTIFICATION_TYPE_TAIWAN_PASSPORT,
/**
* 外国人居留证
*/
IDENTIFICATION_TYPE_FOREIGN_RESIDENT,
/**
* 港澳居民证
*/
IDENTIFICATION_TYPE_HONGKONG_MACAO_RESIDENT,
/**
* 台湾居民证
*/
IDENTIFICATION_TYPE_TAIWAN_RESIDENT,
;
}

+ 20
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/enums/MicroBizTypeEnum.java View File

@@ -0,0 +1,20 @@
package com.github.binarywang.wxpay.bean.applyment.enums;

/**
* 小微经营类型
*/
public enum MicroBizTypeEnum {
/**
* 门店场所
*/
MICRO_TYPE_STORE,
/**
* 流动经营/便民服务
*/
MICRO_TYPE_MOBILE,
/**
* 线上商品/服务交易
*/
MICRO_TYPE_ONLINE,
;
}

+ 32
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/enums/SalesScenesTypeEnum.java View File

@@ -0,0 +1,32 @@
package com.github.binarywang.wxpay.bean.applyment.enums;

/**
* 经营场景类型枚举值
*/
public enum SalesScenesTypeEnum {
/**
* 线下门店
*/
SALES_SCENES_STORE,
/**
* 公众号
*/
SALES_SCENES_MP,
/**
* 小程序
*/
SALES_SCENES_MINI_PROGRAM,
/**
* 互联网
*/
SALES_SCENES_WEB,
/**
* APP
*/
SALES_SCENES_APP,
/**
* 企业微信
*/
SALES_SCENES_WEWORK,
;
}

+ 23
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/enums/SettlementVerifyResultEnum.java View File

@@ -0,0 +1,23 @@
package com.github.binarywang.wxpay.bean.applyment.enums;

/**
* 返回特约商户的结算账户-汇款验证结果枚举类
*
* @author zhouyognshen
*/
public enum SettlementVerifyResultEnum {
/**
* 系统汇款验证中,商户可发起提现尝试。
*/
VERIFYING,
/**
* 系统成功汇款,该账户可正常发起提现。
*/
VERIFY_SUCCESS,
/**
* 系统汇款失败,该账户无法发起提现,请检查修改。
*/
VERIFY_FAIL,
;

}

+ 34
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/enums/SubjectTypeEnum.java View File

@@ -0,0 +1,34 @@
package com.github.binarywang.wxpay.bean.applyment.enums;

/**
* 主体类型枚举类
* <pre>
* 商户申请接入时如何选择主体类型? https://kf.qq.com/faq/180910IBZVnQ180910naQ77b.html
* </pre>
*
* @author zhouyongshen
*/
public enum SubjectTypeEnum {
/**
* (个体户):营业执照上的主体类型一般为个体户、个体工商户、个体经营;
*/
SUBJECT_TYPE_INDIVIDUAL,
/**
* (企业):营业执照上的主体类型一般为有限公司、有限责任公司;
*/
SUBJECT_TYPE_ENTERPRISE,
/**
* (党政、机关及事业单位):包括国内各级、各类政府机构、事业单位等(如:公安、党团、司法、交通、旅游、工商税务、市政、医疗、教育、学校等机构);
*/
SUBJECT_TYPE_INSTITUTIONS,
/**
* (其他组织):不属于企业、政府/事业单位的组织机构(如社会团体、民办非企业、基金会),要求机构已办理组织机构代码证。
*/
SUBJECT_TYPE_OTHERS,
/**
* (小微):无营业执照、免办理工商注册登记的实体商户
*/
SUBJECT_TYPE_MICRO,
;

}

+ 28
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/BankAccountResult.java View File

@@ -0,0 +1,28 @@
package com.github.binarywang.wxpay.bean.bank;

import com.google.gson.annotations.SerializedName;
import lombok.Data;

import java.io.Serializable;
import java.util.List;

/**
* 对私银行卡号开户银行信息
*
* @author zhongjun
**/
@Data
public class BankAccountResult implements Serializable {

private static final long serialVersionUID = -8226859146533243501L;

/**
* 根据卡号查询到的银行列表数据的总条数,未查询到对应银行列表时默认返回0,最大不超过两百条。
*/
@SerializedName("total_count")
private Integer totalCount;

@SerializedName("data")
private List<BankInfo> data;

}

+ 176
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/BankBranchesResult.java View File

@@ -0,0 +1,176 @@
package com.github.binarywang.wxpay.bean.bank;

import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;

import java.io.Serializable;
import java.util.List;

/**
* 支行列表
*
* @author hupeng
**/
@Data
public class BankBranchesResult implements Serializable {

private static final long serialVersionUID = -3500020131951579476L;

/**
* <pre>
* 字段名:查询数据总条数
* 变量名:total_count
* 是否必填:是
* 类型:int
* 描述:
* 经过条件筛选,查询到的支行总数
* 示例值:10
* </pre>
*/
@SerializedName("total_count")
private Integer totalCount;

/**
* <pre>
* 字段名:本次查询条数
* 变量名:count
* 是否必填:是
* 类型:int
* 描述:
* 本次查询到的支行数据条数
* 示例值:10
* </pre>
*/
@SerializedName("count")
private Integer count;

/**
* <pre>
* 字段名:支行列表
* 变量名:data
* 是否必填:否
* 类型:array
* 描述:
* 单次查询返回的支行列表结果数组
* </pre>
*/
@SerializedName("data")
private List<BankBranch> data;

/**
* <pre>
* 字段名:本次查询偏移量
* 变量名:offset
* 是否必填:是
* 类型:int
* 描述:
* 该次请求资源的起始位置,请求中包含偏移量时应答消息返回相同偏移量,否则返回默认值0
* 示例值:0
* </pre>
*/
@SerializedName("offset")
private Integer offset;

/**
* <pre>
* 字段名:分页链接
* 变量名:offset
* 是否必填:是
* 类型:object
* 描述:
* 返回前后页和当前页面的访问链接
* </pre>
*/
@SerializedName("links")
private PageLink links;

/**
* <pre>
* 字段名:开户银行
* 变量名:account_bank
* 是否必填:是
* 类型:string[1, 128]
* 描述:
* 查询到的支行所属开户银行的名称,非直连银行统一为其他银行
* 示例值:招商银行其他银行
* </pre>
*/
@SerializedName("account_bank")
private String accountBank;

/**
* <pre>
* 字段名:开户银行编码
* 变量名:account_bank_code
* 是否必填:是
* 类型:int
* 描述:
* 查询到的支行所属开户银行的开户银行编码,可用于付款到银行卡等场景中指定银行卡的开户银行
* 示例值:1001
* </pre>
*/
@SerializedName("account_bank_code")
private Integer accountBankCode;

/**
* <pre>
* 字段名:银行别名
* 变量名:bank_alias
* 是否必填:是
* 类型:string[1, 128]
* 描述:
* 查询到的支行所属银行的银行别名
* 示例值:工商银行深圳前海微众银行
* </pre>
*/
@SerializedName("bank_alias")
private String bankAlias;

/**
* <pre>
* 字段名:银行别名编码
* 变量名:bank_alias_code
* 是否必填:是
* 类型:string[1, 32]
* 描述:
* 查询到的支行所属银行的银行别名编码,用于校验回包
* 示例值:1000006247
* </pre>
*/
@SerializedName("bank_alias_code")
private String bankAliasCode;

@Getter
@Setter
public static class BankBranch {
/**
* <pre>
* 字段名:开户银行支行名称
* 变量名:bank_branch_name
* 是否必填:是
* 类型:string[1, 128]
* 描述:
* 开户银行支行名称,用于开户银行为其他银行的情况下,在入驻、修改结算银行卡、企业付款等场景下填写结算银行卡信息。
* 示例值:中国工商银行上海市周浦支行
* </pre>
*/
@SerializedName("bank_branch_name")
private String bankBranchName;

/**
* <pre>
* 字段名:开户银行支行联行号
* 变量名:bank_branch_id
* 是否必填:是
* 类型:string[1, 64]
* 描述:
* 开户银行支行的联行号,用于开户银行为其他银行的情况下,在入驻、修改结算银行卡、企业付款等场景下填写结算银行卡信息。
* 示例值:102290072311
* </pre>
*/
@SerializedName("bank_branch_id")
private String bankBranchId;
}
}

+ 39
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/BankInfo.java View File

@@ -0,0 +1,39 @@
package com.github.binarywang.wxpay.bean.bank;

import com.google.gson.annotations.SerializedName;
import lombok.Data;

/**
* 银行信息
*
* @author zhongjun
* @date 2022/5/12
**/
@Data
public class BankInfo {
/**
* 银行别名
*/
@SerializedName("bank_alias")
private String bankAlias;
/**
* 银行别名编码
*/
@SerializedName("bank_alias_code")
private String bankAliasCode;
/**
* 开户银行
*/
@SerializedName("account_bank")
private String accountBank;
/**
* 开户银行编码
*/
@SerializedName("account_bank_code")
private Integer accountBankCode;
/**
* 是否需要填写支行
*/
@SerializedName("need_bank_branch")
private Boolean needBankBranch;
}

+ 64
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/BankingResult.java View File

@@ -0,0 +1,64 @@
package com.github.binarywang.wxpay.bean.bank;

import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;

import java.io.Serializable;
import java.util.List;

/**
* 个人业务的银行列表
*
* @author zhongjun
**/
@Data
public class BankingResult implements Serializable {
private static final long serialVersionUID = -8372812998971715894L;

/**
* 银行列表数据的总条数,调用方需要根据总条数分页查询
*/
@SerializedName("total_count")
private Integer totalCount;

/**
* 本次查询银行列表返回的数据条数
*/
@SerializedName("count")
private Integer count;

/**
* 该次请求资源的起始位置,请求中包含偏移量时应答消息返回相同偏移量,否则返回默认值0。
*/
@SerializedName("offset")
private Integer offset;

@SerializedName("data")
private List<BankInfo> data;

@SerializedName("links")
private Link links;

@Getter
@Setter
public static class Link {
/**
* 下一页链接
*/
@SerializedName("next")
private String next;
/**
* 上一页链接
*/
@SerializedName("prev")
private String prev;
/**
* 当前链接
*/
@SerializedName("self")
private String self;
}

}

+ 80
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/CitiesResult.java View File

@@ -0,0 +1,80 @@
package com.github.binarywang.wxpay.bean.bank;

import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;

import java.io.Serializable;
import java.util.List;

/**
* 城市列表
*
* @author hupeng
**/
@Data
public class CitiesResult implements Serializable {

private static final long serialVersionUID = -6089905695087974693L;

/**
* <pre>
* 字段名:查询数据总条数
* 变量名:total_count
* 是否必填:是
* 类型:int
* 描述:
* 查询到的省份数据总条数
* 示例值:10
* </pre>
*/
@SerializedName("total_count")
private Integer totalCount;

/**
* <pre>
* 字段名:城市列表
* 变量名:data
* 是否必填:否
* 类型:array
* 描述:
* 查询返回的城市列表结果
* </pre>
*/
@SerializedName("data")
private List<CityInfo> data;

@Getter
@Setter
public static class CityInfo {
/**
* <pre>
* 字段名:城市名称
* 变量名:city_name
* 是否必填:是
* 类型:string[1, 256]
* 描述:
* 城市名称
* 示例值:北京市
* </pre>
*/
@SerializedName("city_name")
private String cityName;

/**
* <pre>
* 字段名:城市编码
* 变量名:city_code
* 是否必填:是
* 类型:int
* 描述:
* 城市编码,唯一标识一座城市,用于结合银行别名编码查询支行列表
* 示例值:10
* </pre>
*/
@SerializedName("city_code")
private Integer cityCode;
}

}

+ 59
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/PageLink.java View File

@@ -0,0 +1,59 @@
package com.github.binarywang.wxpay.bean.bank;

import com.google.gson.annotations.SerializedName;
import lombok.Data;

import java.io.Serializable;

/**
* 支行列表
*
* @author hupeng
**/
@Data
public class PageLink implements Serializable {

private static final long serialVersionUID = -2624233403271204837L;

/**
* <pre>
* 字段名:下一页链接
* 变量名:next
* 是否必填:否
* 类型:string[1, 2048]
* 描述:
* 使用同样的limit进行下一页查询时的相对请求链接,使用方需要自行根据当前域名进行拼接。如果已经到最后时,为空
* 示例值:/v3/capital/capitallhh/banks/1001/branches?offset=10&limit=5
* </pre>
*/
@SerializedName("next")
private String next;

/**
* <pre>
* 字段名:上一页链接
* 变量名:prev
* 是否必填:否
* 类型:string[1, 2048]
* 描述:
* 使用同样的limit进行上一页查询时的相对请求链接,使用方需要自行根据当前域名进行拼接。如果是第一页,为空
* 示例值:/v3/capital/capitallhh/banks/1001/branchesoffset=0&limit=5
* </pre>
*/
@SerializedName("prev")
private String prev;

/**
* <pre>
* 字段名:当前链接
* 变量名:self
* 是否必填:否
* 类型:string[1, 2048]
* 描述:
* 当前的相对请求链接,使用方需要自行根据当前域名进行拼接
* 示例值:/v3/capital/capitallhh/banks/1001/branches?offset=5&limit=5
* </pre>
*/
@SerializedName("self")
private String self;
}

+ 81
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/ProvincesResult.java View File

@@ -0,0 +1,81 @@
package com.github.binarywang.wxpay.bean.bank;

import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;

import java.io.Serializable;
import java.util.List;

/**
* 省份列表
*
* @author hupeng
**/
@Data
public class ProvincesResult implements Serializable {

private static final long serialVersionUID = -4118613374545722650L;

/**
* <pre>
* 字段名:查询数据总条数
* 变量名:total_count
* 是否必填:是
* 类型:int
* 描述:
* 查询到的省份数据总条数
* 示例值:10
* </pre>
*/
@SerializedName("total_count")
private Integer totalCount;

/**
* <pre>
* 字段名:省份列表
* 变量名:data
* 是否必填:否
* 类型:array
* 描述:
* 查询到的省份列表数组
* </pre>
*/
@SerializedName("data")
private List<ProvinceInfo> data;

@Getter
@Setter
public static class ProvinceInfo {

/**
* <pre>
* 字段名:省份名称
* 变量名:province_name
* 是否必填:是
* 类型:string[1, 256]
* 描述:
* 省份名称
* 示例值:广东省
* </pre>
*/
@SerializedName("province_name")
private String provinceName;

/**
* <pre>
* 字段名:省份编码
* 变量名:province_code
* 是否必填:是
* 类型:int
* 描述:
* 省份编码,唯一标识一个省份,用于根据省份编码查询省份下的城市列表数据
* 示例值:22
* </pre>
*/
@SerializedName("province_code")
private Integer provinceCode;
}

}

+ 93
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/BusinessCircleNotifyData.java View File

@@ -0,0 +1,93 @@
package com.github.binarywang.wxpay.bean.businesscircle;

import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
* 智慧商圈回调通知对象
* <pre>
* 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/businesscircle/chapter3_1.shtml
* https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/businesscircle/chapter3_3.shtml
* </pre>
*
* @author thinsstar
*/
@NoArgsConstructor
@Data
public class BusinessCircleNotifyData implements Serializable {
private static final long serialVersionUID = 1L;

/**
* 通知ID
*/
@SerializedName("id")
private String id;

/**
* 通知创建时间
*/
@SerializedName("create_time")
private String createTime;

/**
* 通知类型
*/
@SerializedName("event_type")
private String eventType;

/**
* 通知数据类型
*/
@SerializedName("resource_type")
private String resourceType;

/**
* 回调摘要
* summary
*/
@SerializedName("summary")
private String summary;

/**
* 通知数据
*/
@SerializedName("resource")
private Resource resource;

@Data
public static class Resource implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 加密算法类型
*/
@SerializedName("algorithm")
private String algorithm;

/**
* 数据密文
*/
@SerializedName("ciphertext")
private String cipherText;

/**
* 附加数据
*/
@SerializedName("associated_data")
private String associatedData;

/**
* 随机串
*/
@SerializedName("nonce")
private String nonce;

/**
* 原始回调类型
*/
@SerializedName("original_type")
private String originalType;
}
}

+ 52
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/MemberCardAuthorizeNotifyResult.java View File

@@ -0,0 +1,52 @@
package com.github.binarywang.wxpay.bean.businesscircle;

import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
* 商圈授权结果通知内容
* <pre>
* 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter8_6_6.shtml
* </pre>
*
* @author thinsstar
*/
@NoArgsConstructor
@Data
public class MemberCardAuthorizeNotifyResult implements Serializable {

private static final long serialVersionUID = 1L;

/**
* 用户标识
* <p>
* 顾客授权时使用的小程序上的openid
* 示例值:oUpF8uMuAJ2pxb1Q9zNjWeS6o
*/
@SerializedName("openid")
private String openid;

/**
* 会员在card_id下的唯一标识,
*/
@SerializedName("code")
private String code;

/**
* 用户开会员卡时的商圈商户号
*/
@SerializedName("mchid")
private String mchid;

/**
* 用户授权类型
* REGISTERED_MODE :会员开卡(进卡包) + 未授权会员积分服务
* REGISTERED_AND_AUTHORIZATION_MODE:会员开卡(进卡包)+授权会员积分服务
*/
@SerializedName("auth_type")
private String authType;

}

+ 53
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/MemberCardAuthorizeResult.java View File

@@ -0,0 +1,53 @@
package com.github.binarywang.wxpay.bean.businesscircle;

import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
* 商圈授权结果查询内容
* <pre>
* 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter8_6_4.shtml
* </pre>
*
* @author thinsstar
*/
@NoArgsConstructor
@Data
public class MemberCardAuthorizeResult implements Serializable {

private static final long serialVersionUID = 1L;

/**
* 用户标识
* <p>
* 顾客授权时使用的小程序上的openid
* 示例值:oUpF8uMuAJ2pxb1Q9zNjWeS6o
*/
@SerializedName("openid")
private String openid;

/**
* 顾客授权商圈积分结果
* UNAUTHORIZED:未授权
* AUTHORIZED:已授权
* DEAUTHORIZED:已取消授权
*/
@SerializedName("authorize_state")
private String authorizeState;

/**
* 顾客成功授权商圈积分的时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss+TIMEZONE
*/
@SerializedName("authorize_time")
private String authorizeTime;

/**
* 顾客关闭授权商圈积分的时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss+TIMEZONE
*/
@SerializedName("deauthorize_time")
private String deauthorizeTime;

}

+ 112
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/PaidResult.java View File

@@ -0,0 +1,112 @@
package com.github.binarywang.wxpay.bean.businesscircle;

import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
* 商圈支付结果通知内容
* <pre>
* 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/businesscircle/chapter3_1.shtml
* </pre>
*
* @author thinsstar
*/
@NoArgsConstructor
@Data
public class PaidResult implements Serializable {

private static final long serialVersionUID = 1L;

/**
* 商户号
* <p>
* 微信支付分配的商户号
* 示例值:1230000109
*/
@SerializedName("mchid")
private String mchid;

/**
* 商圈商户名称
* <p>
* 商圈商户名称
* 示例值:微信支付
*/
@SerializedName("merchant_name")
private String merchantName;

/**
* 门店名称
* <p>
* 门店名称,商圈在商圈小程序上圈店时填写的门店名称
* 示例值:微信支付
*/
@SerializedName("shop_name")
private String shopName;

/**
* 门店编号
* <p>
* 门店编号,商圈在商圈小程序上圈店时填写的门店编号,用于跟商圈自身已有的商户识别码对齐
* 示例值:123456
*/
@SerializedName("shop_number")
private String shopNumber;

/**
* 小程序APPID
* <p>
* 顾客授权积分时使用的小程序的appid
* 示例值:wxd678efh567hg6787
*/
@SerializedName("appid")
private String appid;

/**
* 用户标识
* <p>
* 顾客授权时使用的小程序上的openid
* 示例值:oUpF8uMuAJ2pxb1Q9zNjWeS6o
*/
@SerializedName("openid")
private String openid;

/**
* 交易完成时间
* <p>
* 交易完成时间,遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示北京时间2015年05月20日13点29分35秒(需要增加所有跟时间有关的参数的描述)
* 示例值:2015-05-20T13:29:35+08:00
*/
@SerializedName("time_end")
private String timeEnd;

/**
* 金额
* <p>
* 用户实际消费金额,单位(分)
* 示例值:200
*/
@SerializedName("amount")
private Integer amount;

/**
* 微信支付订单号
* <p>
* 微信支付订单号
* 示例值:1234567890
*/
@SerializedName("transaction_id")
private String transactionId;

/**
* 手动提交积分标记
* <p>
* 手动提交积分标记,自动提交时无该字段,用于区分用户手动申请后推送的积分数据
* 示例值:oUpF8uMuAJ2pxb1Q9zNjWUHsd
*/
@SerializedName("commit_tag")
private String commitTag;
}

+ 103
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/ParkingNotifyRequest.java View File

@@ -0,0 +1,103 @@
package com.github.binarywang.wxpay.bean.businesscircle;

import com.google.gson.annotations.SerializedName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
* 商圈停车同步
* <pre>
* 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter8_6_5.shtml
* </pre>
*
* @author thinsstar
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ParkingNotifyRequest implements Serializable {

private static final long serialVersionUID = 1L;

/**
* <pre>
* 字段名:商圈商户ID
* 变量名:sub_mchid
* 是否必填:否
* 类型:string[1,64]
* 描述:
* 当以服务商模式管理商圈积分能力时,则要带上商圈商户ID,否则留空
* 示例值:1234567890
* </pre>
*/
@SerializedName(value = "sub_mchid")
private String subMchid;

/**
* <pre>
* 调用方商户号对应的品牌brandid,调用方商户号需为此品牌brandid的品牌主商户号或品牌服务商商户号
* </pre>
*/
@SerializedName(value = "brandid")
private String brandid;

/**
* <pre>
* 字段名:小程序appid
* 变量名:appid
* 是否必填:是
* 类型:string[1,128]
* 描述:
* 顾客授权积分时使用的小程序的appid
* 示例值:wx1234567890abcdef
* </pre>
*/
@SerializedName(value = "appid")
private String appid;

/**
* <pre>
* 字段名:用户标识
* 变量名:openid
* 是否必填:是
* 类型:string[1,64]
* 描述:
* 顾客授权时使用的小程序上的openid
* 示例值:oWmnN4xxxxxxxxxxe92NHIGf1xd8
* </pre>
*/
@SerializedName(value = "openid")
private String openid;

/**
* <pre>
* 首位需为省份的中文简称,第二位起支持大写字母、数字、中文
* </pre>
*/
@SerializedName(value = "plate_number")
private String plateNumber;

/**
* <pre>
* 停车状态,服务商模式下必传
* IN:入场,用户开车进入商圈
* OUT:离场,用户开车离开商圈
* </pre>
*/
@SerializedName(value = "state")
private String state;

/**
* <pre>
* 在场状态更新时间,按照使用rfc3339所定义的格式,格式为yyyy-MM-DDThh:mm:ss+TIMEZONE
* </pre>
*/
@SerializedName(value = "time")
private String time;

}

+ 31
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/PointsCommitStatusResult.java View File

@@ -0,0 +1,31 @@
package com.github.binarywang.wxpay.bean.businesscircle;

import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
* 商圈积分状态查询
* <pre>
* 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter8_6_7.shtml
* </pre>
*
* @author thinsstar
*/
@NoArgsConstructor
@Data
public class PointsCommitStatusResult implements Serializable {

private static final long serialVersionUID = 1L;

/**
* 商圈会员待积分状态
* PENDING:有积分待提交,商圈会员有待提交的积分记录,可引导会员跳转插件提交积分申请
* FINISHED:无积分可提交,商圈会员没有待提交的积分记录
*/
@SerializedName("points_commit_status")
private String pointsCommitStatus;

}

+ 154
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/PointsNotifyRequest.java View File

@@ -0,0 +1,154 @@
package com.github.binarywang.wxpay.bean.businesscircle;

import com.google.gson.annotations.SerializedName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
* 商圈积分同步
* <pre>
* 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/businesscircle/chapter3_2.shtml
* </pre>
*
* @author thinsstar
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PointsNotifyRequest implements Serializable {

private static final long serialVersionUID = 1L;

/**
* <pre>
* 字段名:商圈商户ID
* 变量名:sub_mchid
* 是否必填:否
* 类型:string[1,64]
* 描述:
* 当以服务商模式管理商圈积分能力时,则要带上商圈商户ID,否则留空
* 示例值:1234567890
* </pre>
*/
@SerializedName(value = "sub_mchid")
private String subMchid;

/**
* <pre>
* 字段名:微信订单号
* 变量名:transaction_id
* 是否必填:是
* 类型:string[1,64]
* 描述:
* 微信支付推送的商圈内交易通知里携带的微信订单号
* 示例值:1217752501201407033233368018
* </pre>
*/
@SerializedName(value = "transaction_id")
private String transactionId;

/**
* <pre>
* 字段名:小程序appid
* 变量名:appid
* 是否必填:是
* 类型:string[1,128]
* 描述:
* 顾客授权积分时使用的小程序的appid
* 示例值:wx1234567890abcdef
* </pre>
*/
@SerializedName(value = "appid")
private String appid;

/**
* <pre>
* 字段名:用户标识
* 变量名:openid
* 是否必填:是
* 类型:string[1,64]
* 描述:
* 顾客授权时使用的小程序上的openid
* 示例值:oWmnN4xxxxxxxxxxe92NHIGf1xd8
* </pre>
*/
@SerializedName(value = "openid")
private String openid;

/**
* <pre>
* 字段名:是否获得积分
* 变量名:earn_points
* 是否必填:是
* 类型:boolean
* 描述:
* 用于标明此单是否获得积分,
* true为获得积分,
* false为未获得
* 示例值:true
* </pre>
*/
@SerializedName(value = "earn_points")
private Boolean earnPoints;

/**
* <pre>
* 字段名:订单新增积分值
* 变量名:increased_points
* 是否必填:是
* 类型:int
* 描述:
* 顾客此笔交易新增的积分值
* 示例值:100
* </pre>
*/
@SerializedName(value = "increased_points")
private Integer increasedPoints;

/**
* <pre>
* 字段名:积分更新时间
* 变量名:points_update_time
* 是否必填:是
* 类型:string[1,32]
* 描述:
* 为顾客此笔交易成功积分的时间
* 示例值:2020-05-20T13:29:35.120+08:00
* </pre>
*/
@SerializedName(value = "points_update_time")
private String pointsUpdateTime;

/**
* <pre>
* 字段名:未获得积分的备注信息
* 变量名:no_points_remarks
* 是否必填:否
* 类型:string[1,128]
* 描述:
* 当未获得积分时,提供未获得积分的原因等备注信息
* 示例值:商品不参与积分活动
* </pre>
*/
@SerializedName(value = "no_points_remarks")
private String noPointsRemarks;

/**
* <pre>
* 字段名:顾客积分总额
* 变量名:total_points
* 是否必填:否
* 类型:int
* 描述:
* 当前顾客积分总额
* 示例值:888888
* </pre>
*/
@SerializedName(value = "total_points")
private Integer totalPoints;
}

+ 121
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/RefundResult.java View File

@@ -0,0 +1,121 @@
package com.github.binarywang.wxpay.bean.businesscircle;

import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
* 商圈退款成功通知内容
* <pre>
* 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/businesscircle/chapter3_3.shtml
* </pre>
*
* @author thinsstar
*/
@NoArgsConstructor
@Data
public class RefundResult implements Serializable {

private static final long serialVersionUID = 1L;

/**
* 商户号
* <p>
* 微信支付分配的商户号
* 示例值:1230000109
*/
@SerializedName("mchid")
private String mchid;

/**
* 商圈商户名称
* <p>
* 商圈商户名称
* 示例值:微信支付
*/
@SerializedName("merchant_name")
private String merchantName;

/**
* 门店名称
* <p>
* 门店名称,商圈在商圈小程序上圈店时填写的门店名称
* 示例值:微信支付
*/
@SerializedName("shop_name")
private String shopName;

/**
* 门店编号
* <p>
* 门店编号,商圈在商圈小程序上圈店时填写的门店编号,用于跟商圈自身已有的商户识别码对齐
* 示例值:123456
*/
@SerializedName("shop_number")
private String shopNumber;

/**
* 小程序APPID
* <p>
* 顾客授权积分时使用的小程序的appid
* 示例值:wxd678efh567hg6787
*/
@SerializedName("appid")
private String appid;

/**
* 用户标识
* <p>
* 顾客授权时使用的小程序上的openid
* 示例值:oUpF8uMuAJ2pxb1Q9zNjWeS6o
*/
@SerializedName("openid")
private String openid;

/**
* 退款完成时间
* <p>
* 退款完成时间,遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示北京时间2015年05月20日13点29分35秒(需要增加所有跟时间有关的参数的描述)
* 示例值:2015-05-20T13:29:35+08:00
*/
@SerializedName("refund_time")
private String refundTime;

/**
* 消费金额
* <p>
* 用户实际消费金额,单位(分)
* 示例值:100
*/
@SerializedName("pay_amount")
private Integer payAmount;

/**
* 退款金额
* <p>
* 用户退款金额,单位(分)
* 示例值:100
*/
@SerializedName("refund_amount")
private Integer refundAmount;

/**
* 微信支付订单号
* <p>
* 微信支付订单号
* 示例值:1234567890
*/
@SerializedName("transaction_id")
private String transactionId;

/**
* 微信支付退款单号
* <p>
* 微信支付退款单号
* 示例值:1217752501201407033233368999
*/
@SerializedName("refund_id")
private String refundId;
}

+ 35
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/SignatureHeader.java View File

@@ -0,0 +1,35 @@
package com.github.binarywang.wxpay.bean.ecommerce;

import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
* 微信通知接口头部信息,需要做签名验证
* 文档地址: https://wechatpay-api.gitbook.io/wechatpay-api-v3/qian-ming-zhi-nan-1/qian-ming-yan-zheng
*/
@Data
@NoArgsConstructor
public class SignatureHeader implements Serializable {
private static final long serialVersionUID = -6958015499416059949L;
/**
* 时间戳
*/
private String timeStamp;

/**
* 随机串
*/
private String nonce;

/**
* 已签名字符串
*/
private String signed;

/**
* 证书序列号
*/
private String serialNo;
}

+ 28
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/media/ImageUploadResult.java View File

@@ -0,0 +1,28 @@
package com.github.binarywang.wxpay.bean.media;

import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;

/**
* 媒体文件上传返回结果对象
* @author zhouyongshen
*/
@NoArgsConstructor
@Data
public class ImageUploadResult {

public static ImageUploadResult fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, ImageUploadResult.class);
}
/**
* 媒体文件标识 Id
*
* 微信返回的媒体文件标识Id。
* 示例值:6uqyGjGrCf2GtyXP8bxrbuH9-aAoTjH-rKeSl3Lf4_So6kdkQu4w8BYVP3bzLtvR38lxt4PjtCDXsQpzqge_hQEovHzOhsLleGFQVRF-U_0
*
*/
@SerializedName("media_id")
private String mediaId;
}

+ 29
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/media/MarketingImageUploadResult.java View File

@@ -0,0 +1,29 @@
package com.github.binarywang.wxpay.bean.media;

import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;

/**
* 媒体文件上传返回结果对象
*
* @author thinsstar
*/
@NoArgsConstructor
@Data
public class MarketingImageUploadResult {

public static MarketingImageUploadResult fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, MarketingImageUploadResult.class);
}

/**
* 媒体文件URL地址
* <p>
* 微信返回的媒体文件标识url。有效期为永久
* 示例值:https://qpic.cn/xxx
*/
@SerializedName("media_url")
private String mediaUrl;
}

+ 82
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/membercard/MemberCardActivateResult.java View File

@@ -0,0 +1,82 @@
package com.github.binarywang.wxpay.bean.membercard;

import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
* 商圈支付结果通知内容
* <pre>
* 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_9_32.shtml
* </pre>
*
* @author thinsstar
*/
@NoArgsConstructor
@Data
public class MemberCardActivateResult implements Serializable {

private static final long serialVersionUID = 1L;

/**
* 业务细分事件类型,枚举值:
* MEMBER_CARD_ACTIVATE:激活会员卡
*
* USER_VIEW_MEMBERCARD:用户查看会员卡详情
* USER_DELETE_MEMBERCARD:用户删除会员卡
* USER_MODIFY_INFORMATION:用户修改个人信息
*/
@SerializedName("event_type")
private String eventType;

/**
* 商户创建微信会员卡模板成功后系统返回的会员卡模板id
*/
@SerializedName("card_id")
private String cardId;

/**
* 会员在card_id下的唯一标识,
*/
@SerializedName("code")
private String code;

/**
* 事件发生时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss.sss+TIMEZONE
*/
@SerializedName("event_time")
private String eventTime;

/**
* 激活场景,用于区分用户新开卡激活或删卡后重新领取激活。枚举值:
* NEW_ACTIVATE 新开卡激活
* RECOVER 删卡后重新领取激活
*/
@SerializedName("activate_scene")
private String activateScene;

/**
* 用户标识
* <p>
* 顾客授权时使用的小程序上的openid
* 示例值:oUpF8uMuAJ2pxb1Q9zNjWeS6o
*/
@SerializedName("openid")
private String openid;

/**
* 微信用户在同一个微信开放平台账号下的唯一用户标识,unionid获取方式请参见《UnionID机制说明》文档。
*/
@SerializedName("unionid")
private String unionid;

/**
* 自定义场景值,商户可以用于标记投放场景,如门店/来源等。只能录入数字及中英文/半角标点
* 匹配正则表达式: ^[0-9a-zA-Z\u0000-\u00FF\u4e00-\u9fa5]+$
*/
@SerializedName("outer_str")
private String outerStr;

}

+ 93
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/membercard/MemberCardNotifyData.java View File

@@ -0,0 +1,93 @@
package com.github.binarywang.wxpay.bean.membercard;

import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
* 会员卡回调通知对象
* <pre>
* 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_9_32.shtml
* https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_9_33.shtml
* </pre>
*
* @author thinsstar
*/
@NoArgsConstructor
@Data
public class MemberCardNotifyData implements Serializable {
private static final long serialVersionUID = 1L;

/**
* 通知ID
*/
@SerializedName("id")
private String id;

/**
* 通知创建时间
*/
@SerializedName("create_time")
private String createTime;

/**
* 通知类型
*/
@SerializedName("event_type")
private String eventType;

/**
* 通知数据类型
*/
@SerializedName("resource_type")
private String resourceType;

/**
* 回调摘要
* summary
*/
@SerializedName("summary")
private String summary;

/**
* 通知数据
*/
@SerializedName("resource")
private Resource resource;

@Data
public static class Resource implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 加密算法类型
*/
@SerializedName("algorithm")
private String algorithm;

/**
* 数据密文
*/
@SerializedName("ciphertext")
private String cipherText;

/**
* 附加数据
*/
@SerializedName("associated_data")
private String associatedData;

/**
* 随机串
*/
@SerializedName("nonce")
private String nonce;

/**
* 原始回调类型
*/
@SerializedName("original_type")
private String originalType;
}
}

+ 360
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/membercard/MemberCardResult.java View File

@@ -0,0 +1,360 @@
package com.github.binarywang.wxpay.bean.membercard;

import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.util.List;

/**
* 查询用户会员卡信息API
* <pre>
* 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_9_6.shtml
* </pre>
*
* @author thinsstar
*/
@NoArgsConstructor
@Data
public class MemberCardResult implements Serializable {
private static final long serialVersionUID = 1L;

/**
* 商户创建微信会员卡模板成功后系统返回的会员卡模板id
*/
@SerializedName("card_id")
private String cardId;

/**
* 会员在card_id下的唯一标识,用户领取会员卡后获得的code
*/
@SerializedName("code")
private String code;

/**
* 用户在会员卡绑定品牌appid下的唯一标识,如通过手机号同步会员身份且用户未领取到卡包,无法查询该字段
*/
@SerializedName("openid")
private String openid;

/**
* 在用户会员卡上展示的会员卡编号,默认使用会员卡code作为membership_number。只能录入数字/英文/半角标点。商家可通过修改用户单张会员卡信息更新
*/
@SerializedName("membership_number")
private String membershipNumber;

/**
* 用户会员等级
*/
@SerializedName("level")
private String level;

/**
* 用户的微信昵称,如通过手机号同步会员身份且用户未领取到卡包,无法查询该字段
*/
@SerializedName("nickname")
private String nickname;

/**
* 用户的微信头像url,如通过手机号同步会员身份且用户未领取到卡包,无法查询该字段
*/
@SerializedName("head_image_url")
private String headImageUrl;

/**
* 商家给当前用户设置的会员卡背景图。仅支持通过《图片上传API》接口获取的图片URL地址。支持JPG/JPEG/PNG格式,且图片小于1M。
*/
@SerializedName("background_picture_url")
private String backgroundPictureUrl;

/**
* 用户储值的最新余额,单位分
*/
@SerializedName("balance")
private Integer balance;

/**
* 用户当前的卡状态:
* NOT_ACTIVATE:未激活
* EFFECTIVE:生效中
* EXPIRE:已过期
* UNAVAILABLE:已失效
* DELETE:已删除
* IMPORTED:已导入
*/
@SerializedName("user_card_status")
private String userCardStatus;

/**
* 用户开卡时填写的个人信息
*/
@SerializedName("user_information")
private UserInformation userInformation;

/**
* 用户当前的积分值
*/
@SerializedName("bonus_value")
private Integer bonusValue;

/**
* 用户当前的积分值
*/
@SerializedName("service_modules")
private List<ServiceModule> serviceModules;

/**
* 用户会员卡详情页会员优惠栏目中的会员专享价文案
*/
@SerializedName("member_price_word")
private String memberPriceWord;

/**
*发票栏跳转小程序的引导文案
*/
@SerializedName("fapiao_jump_word")
private String fapiaoJumpWord;

/**
*设置商家联系人员的名字、头像和联系方式
*/
@SerializedName("guide")
private List<Guide> guide;

@Data
public static class UserInformation implements Serializable {
private static final long serialVersionUID = 1L;

/**
* 平台提供的通用开卡信息字段
* 包含性别、手机、头像、昵称、姓名等基本信息字段
*/
@SerializedName("common_field_list")
private List<CommonField> commonFieldList;

/**
* 商户自定义的开卡信息字段
*/
@SerializedName("custom_field_list")
private List<CustomField> customFieldList;

}

@Data
public static class CommonField implements Serializable {
private static final long serialVersionUID = 1L;

/**
* 平台提供了一些通用的开卡字段供开发者选用
* USER_FORM_FLAG_MOBILE:手机号
* USER_FORM_FLAG_SEX:性别
* USER_FORM_FLAG_NAME:姓名
* USER_FORM_FLAG_BIRTHDAY:生日
* USER_FORM_FLAG_ADDRESS:地址
* USER_FORM_FLAG_EMAIL:邮箱
* USER_FORM_FLAG_CITY:城市
*/
@SerializedName("name")
private String name;

/**
* 平台提供的通用开卡信息字段,用户在开卡时填写的信息
*/
@SerializedName("value")
private String value;
}

@Data
public static class CustomField implements Serializable {
private static final long serialVersionUID = 1L;

/**
* 商户自定义的开卡信息字段名称
*/
@SerializedName("name")
private String name;

/**
* 商户自定义的开卡信息字段值,用户在开卡时需填写。填写项目为单选时的返回
*/
@SerializedName("value")
private String value;

/**
* 商户自定义的开卡信息字段值,用户在开卡时需填写。填写项目为多选时的返回
* 特殊规则:列表最多支持10个,单个列表限制8个字符
*/
@SerializedName("value_list")
private List<String> valueList;
}

@Data
public static class ServiceModule implements Serializable {
private static final long serialVersionUID = 1L;

/**
* 会员服务项的唯一识别ID,创建服务项后由微信支付生成的服务项ID。商户可通过服务项id查询服务项的配置信息及用途。
*/
@SerializedName("service_module_id")
private String serviceModuleId;

/**
* 用户的服务状态设置,这些设置会展示在用户的会员卡详情页。可设置状态的内容字段、按钮、消息内容等
*/
@SerializedName("state_setting")
private StateSetting stateSetting;

}

@Data
public static class StateSetting implements Serializable {
private static final long serialVersionUID = 1L;

/**
* 状态的id。一个服务项通常包含多个状态,商户可根据服务流程选择其中的状态进行设置,模板内容展示在用户的会员卡详情页,并支持通过公众号给用户发送触达消息
*/
@SerializedName("state_id")
private String stateId;

/**
* 用户的服务内容模板设置,这些设置会展示在用户的会员卡详情页。可设置状态的内容字段、按钮等
*/
@SerializedName("content_template_data")
private ContentTemplateData contentTemplateData;

/**
* 公众号模板消息设置。部分服务项支持给用户发送触达消息,商户可通过模板id选择模板消息样式,并设置字段值。API调用成功后会通过微信公众号自动给用户发送此模板消息。不填则默认不发消息
*/
@SerializedName("message_template_setting")
private MessageTemplateSetting messageTemplateSetting;
}

@Data
public static class ContentTemplateData implements Serializable {
private static final long serialVersionUID = 1L;

/**
* 当前服务状态下,可以设置的内容字段列表
*/
@SerializedName("field_list")
private List<Field> fieldList;

/**
* 服务状态对应的操作设置,可配置跳转文案和跳转小程序路径
* 需配置跳转文案及跳转小程序路径时必填
*/
@SerializedName("action_setting")
private ActionSetting actionSetting;

}

@Data
public static class Field implements Serializable {
private static final long serialVersionUID = 1L;

/**
* 服务内容列表,最多包含5条内容
*/
@SerializedName("field_id")
private String fieldId;

/**
* 服务状态字段的值
*/
@SerializedName("field_value")
private String fieldValue;

}

@Data
public static class ActionSetting implements Serializable {
private static final long serialVersionUID = 1L;

/**
* 操作名称
*/
@SerializedName("action_name")
private String actionName;

/**
* 服务状态指定跳转小程序
*/
@SerializedName("jump_miniprogram")
private JumpMiniprogram jumpMiniprogram;

}

@Data
public static class JumpMiniprogram implements Serializable {
private static final long serialVersionUID = 1L;

/**
* 小程序的appid
*/
@SerializedName("appid")
private String appid;

/**
* 小程序的页面path
* 示例值:pages/index/index
*/
@SerializedName("path")
private String path;

}

@Data
public static class MessageTemplateSetting implements Serializable {
private static final long serialVersionUID = 1L;

/**
* 公众号模板消息的id
*/
@SerializedName("message_template_id")
private String messageTemplateId;

/**
* 模板消息字段列表。商户在此设置模板消息每个字段需展示的内容
* 特殊规则:限制最多可提交9条
*/
@SerializedName("field_list")
private List<Field> fieldList;

}

@Data
public static class Guide implements Serializable {
private static final long serialVersionUID = 1L;

/**
* 设置商家咨询联系人的名称
*/
@SerializedName("staff_name")
private String staffName;

/**
* 设置商家咨询联系人的头像。仅支持通过《图片上传API》接口获取的图片URL地址。
*/
@SerializedName("head_image_url")
private String headImageUrl;

/**
* 展示说明商家咨询联系人的联系方式,例如“微信号”“企业微信号”
*/
@SerializedName("contact_information_name")
private String contactInformationName;

/**
* 展示说明商家咨询联系人的联系方式信息,例如“weixin123”“135266664”
*/
@SerializedName("contact_information_value")
private String contactInformationValue;

/**
* 商家咨询联系人的联系电话
*/
@SerializedName("phone_number")
private String phoneNumber;
}
}

+ 104
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/membercard/MemberCardRightsRequest.java View File

@@ -0,0 +1,104 @@
package com.github.binarywang.wxpay.bean.membercard;

import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
* 设置用户会员权益信息api
* <pre>
* 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_9_23.shtml
* </pre>
*
* @author thinsstar
*/
@NoArgsConstructor
@Data
public class MemberCardRightsRequest implements Serializable {
private static final long serialVersionUID = 1L;

/**
* 变更前的用户的积分值
*/
@SerializedName("before_bonus_value")
private Integer beforeBonusValue;

/**
* 变更后的用户最新积分值,该值会展示在会员卡详页上
*/
@SerializedName("bonus_value")
private Integer bonusValue;

/**
* 本次变更的积分值
*/
@SerializedName("add_bonus_value")
private Integer addBonusValue;

/**
* 商户凭据号。商户自定义,注意保持唯一性,仅供参考的格式:商户id+日期+流水号。可包含英文字母,数字,|,_,*,-等内容,不允许出现其他不合法符号。
*/
@SerializedName("out_request_no")
private String outRequestNo;

/**
* 积分变更时是否触发系统模板消息,默认为true
*/
@SerializedName("need_inform_bonus")
private Boolean needInformBonus;

/**
* 用户会员卡详情页会员优惠栏目中的会员专享价文案
*/
@SerializedName("member_price_word")
private String memberPriceWord;

/**
*发票栏跳转小程序的引导文案
*/
@SerializedName("fapiao_jump_word")
private String fapiaoJumpWord;

/**
*设置商家联系人员的名字、头像和联系方式
*/
@SerializedName("guide")
private Guide guide;

@Data
public static class Guide implements Serializable {
private static final long serialVersionUID = 1L;

/**
* 设置商家咨询联系人的名称
*/
@SerializedName("staff_name")
private String staffName;

/**
* 设置商家咨询联系人的头像。仅支持通过《图片上传API》接口获取的图片URL地址。
*/
@SerializedName("head_image_url")
private String headImageUrl;

/**
* 展示说明商家咨询联系人的联系方式,例如“微信号”“企业微信号”
*/
@SerializedName("contact_information_name")
private String contactInformationName;

/**
* 展示说明商家咨询联系人的联系方式信息,例如“weixin123”“135266664”
*/
@SerializedName("contact_information_value")
private String contactInformationValue;

/**
* 商家咨询联系人的联系电话
*/
@SerializedName("phone_number")
private String phoneNumber;
}
}

+ 95
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/membercard/MemberCardUpdRequest.java View File

@@ -0,0 +1,95 @@
package com.github.binarywang.wxpay.bean.membercard;

import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.util.List;

/**
* 修改用户会员卡信息API
* <pre>
* 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_9_8.shtml
* </pre>
*
* @author thinsstar
*/
@NoArgsConstructor
@Data
public class MemberCardUpdRequest implements Serializable {
private static final long serialVersionUID = 1L;

/**
* 在用户会员卡上展示的会员卡编号,默认使用会员卡code作为membership_number。只能录入数字/英文/半角标点。商家可通过修改用户单张会员卡信息更新
*/
@SerializedName("membership_number")
private String membershipNumber;

/**
* 商家给当前用户设置的会员卡背景图。仅支持通过《图片上传API》接口获取的图片URL地址。支持JPG/JPEG/PNG格式,且图片小于1M。
*/
@SerializedName("background_picture_url")
private String backgroundPictureUrl;

/**
* 用户会员等级
*/
@SerializedName("level")
private String level;

/**
* 商户据号。商户自定义,注意保持唯一性,仅供参考的格式:商户id+日期+流水号。可包含英文字母,数字,|,_,*,-等内容,不允许出现其他不合法符号。
*/
@SerializedName("out_request_no")
private String outRequestNo;

/**
* 用户储值变更信息
*/
@SerializedName("balance_information")
private BalanceInformation balanceInformation;

/**
* 用户储值变更信息
*/
@SerializedName("need_inform_balance")
private Boolean needInformBalance;

/**
* 用户储值变更信息
*/
@SerializedName("need_inform_level")
private Boolean needInformLevel;


@Data
public static class BalanceInformation implements Serializable {
private static final long serialVersionUID = 1L;

/**
* 用户储值的更新前余额,单位分
*/
@SerializedName("before_balance")
private Integer beforeBalance;

/**
* 用户储值的更新后余额,单位分
*/
@SerializedName("balance")
private Integer balance;

/**
* 用户储值余额本次的变动值,单位分,等于balance减去before_balance,传入正数表示余额增加,传入负数表示余额减少
*/
@SerializedName("add_balance")
private Integer addBalance;

/**
* 商家自定义储值金额消耗记录,不超过30个字
*/
@SerializedName("balance_remark")
private String balanceRemark;

}
}

+ 178
- 34
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/config/WxPayConfig.java View File

@@ -1,15 +1,27 @@
package com.github.binarywang.wxpay.config;

import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.v3.WxPayV3HttpClientBuilder;
import com.github.binarywang.wxpay.v3.auth.*;
import com.github.binarywang.wxpay.v3.util.PemUtils;
import jodd.util.ResourcesUtil;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.SneakyThrows;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.RegExUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.ssl.SSLContexts;

import javax.net.ssl.SSLContext;
import java.io.*;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.Collections;

/**
* 微信支付配置
@@ -17,8 +29,11 @@ import java.security.KeyStore;
* @author Binary Wang (https://github.com/binarywang)
*/
@Data
@EqualsAndHashCode(exclude = "verifier")
public class WxPayConfig {
private static final String DEFAULT_PAY_BASE_URL = "https://api.mch.weixin.qq.com";
private static final String PROBLEM_MSG = "证书文件【%s】有问题,请核实!";
private static final String NOT_FOUND_MSG = "证书文件【%s】不存在,请核实!";

/**
* 微信支付接口请求地址域名部分.
@@ -85,6 +100,52 @@ public class WxPayConfig {
*/
private String keyPath;

/**
* apiclient_key.pem证书文件的绝对路径或者以classpath:开头的类路径.
*/
private String privateKeyPath;
/**
* apiclient_cert.pem证书文件的绝对路径或者以classpath:开头的类路径.
*/
private String privateCertPath;

/**
* apiV3 秘钥值.
*/
private String apiV3Key;

/**
* apiV3 证书序列号值
*/
private String certSerialNo;
/**
* 微信支付分serviceId
*/
private String serviceId;

/**
* 微信支付分回调地址
*/
private String payScoreNotifyUrl;


/**
* 微信支付分授权回调地址
*/
private String payScorePermissionNotifyUrl;


private CloseableHttpClient apiV3HttpClient;
/**
* 私钥信息
*/
private PrivateKey privateKey;

/**
* 证书自动更新时间差(分钟),默认一分钟
*/
private int certAutoUpdateTime = 60;

/**
* p12证书文件内容的字节数组.
*/
@@ -106,8 +167,15 @@ public class WxPayConfig {
private String httpProxyUsername;
private String httpProxyPassword;

/**
* v3接口下证书检验对象,通过改对象可以获取到X509Certificate,进一步对敏感信息加密
* 文档见 https://wechatpay-api.gitbook.io/wechatpay-api-v3/qian-ming-zhi-nan-1/min-gan-xin-xi-jia-mi
*/
private Verifier verifier;

/**
* 返回所设置的微信支付接口请求地址域名.
*
* @return 微信支付接口请求地址域名
*/
public String getPayBaseUrl() {
@@ -118,6 +186,15 @@ public class WxPayConfig {
return this.payBaseUrl;
}

@SneakyThrows
public Verifier getVerifier() {
if (verifier == null) {
//当改对象为null时,初始化api v3的请求头
initApiV3HttpClient();
}
return verifier;
}

/**
* 初始化ssl.
*
@@ -136,40 +213,7 @@ public class WxPayConfig {
if (StringUtils.isBlank(this.getKeyPath())) {
throw new WxPayException("请确保证书文件地址keyPath已配置");
}

final String prefix = "classpath:";
String fileHasProblemMsg = "证书文件【" + this.getKeyPath() + "】有问题,请核实!";
String fileNotFoundMsg = "证书文件【" + this.getKeyPath() + "】不存在,请核实!";
if (this.getKeyPath().startsWith(prefix)) {
String path = StringUtils.removeFirst(this.getKeyPath(), prefix);
if (!path.startsWith("/")) {
path = "/" + path;
}
inputStream = WxPayConfig.class.getResourceAsStream(path);
if (inputStream == null) {
throw new WxPayException(fileNotFoundMsg);
}
} else if (this.getKeyPath().startsWith("http://") || this.getKeyPath().startsWith("https://")) {
try {
inputStream = new URL(this.keyPath).openStream();
if (inputStream == null) {
throw new WxPayException(fileNotFoundMsg);
}
} catch (IOException e) {
throw new WxPayException(fileNotFoundMsg, e);
}
} else {
try {
File file = new File(this.getKeyPath());
if (!file.exists()) {
throw new WxPayException(fileNotFoundMsg);
}

inputStream = new FileInputStream(file);
} catch (IOException e) {
throw new WxPayException(fileHasProblemMsg, e);
}
}
inputStream = this.loadConfigInputStream(this.getKeyPath());
}

try {
@@ -185,4 +229,104 @@ public class WxPayConfig {
}
}

/**
* 初始化api v3请求头 自动签名验签
* 方法参照微信官方https://github.com/wechatpay-apiv3/wechatpay-apache-httpclient
*
* @return org.apache.http.impl.client.CloseableHttpClient
* @author doger.wang
**/
public CloseableHttpClient initApiV3HttpClient() throws WxPayException {
String privateKeyPath = this.getPrivateKeyPath();
String privateCertPath = this.getPrivateCertPath();
String serialNo = this.getCertSerialNo();
String apiV3Key = this.getApiV3Key();
if (StringUtils.isBlank(privateKeyPath)) {
throw new WxPayException("请确保privateKeyPath已设置");
}
if (StringUtils.isBlank(privateCertPath)) {
throw new WxPayException("请确保privateCertPath已设置");
}
// if (StringUtils.isBlank(certSerialNo)) {
// throw new WxPayException("请确保certSerialNo证书序列号已设置");
// }
if (StringUtils.isBlank(apiV3Key)) {
throw new WxPayException("请确保apiV3Key值已设置");
}

InputStream keyInputStream = this.loadConfigInputStream(privateKeyPath);
InputStream certInputStream = this.loadConfigInputStream(privateCertPath);
try {
PrivateKey merchantPrivateKey = PemUtils.loadPrivateKey(keyInputStream);
X509Certificate certificate = PemUtils.loadCertificate(certInputStream);
if(StringUtils.isBlank(serialNo)){
this.certSerialNo = certificate.getSerialNumber().toString(16).toUpperCase();
}

AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(
new WxPayCredentials(mchId, new PrivateKeySigner(certSerialNo, merchantPrivateKey)),
apiV3Key.getBytes(StandardCharsets.UTF_8), this.getCertAutoUpdateTime());

CloseableHttpClient httpClient = WxPayV3HttpClientBuilder.create()
.withMerchant(mchId, certSerialNo, merchantPrivateKey)
.withWechatpay(Collections.singletonList(certificate))
.withValidator(new WxPayValidator(verifier))
.build();
this.apiV3HttpClient = httpClient;
this.verifier=verifier;
this.privateKey = merchantPrivateKey;

return httpClient;
} catch (Exception e) {
throw new WxPayException("v3请求构造异常!", e);
}
}

/**
* 从配置路径 加载配置 信息(支持 classpath、本地路径、网络url)
* @param configPath 配置路径
* @return
* @throws WxPayException
*/
private InputStream loadConfigInputStream(String configPath) throws WxPayException {
InputStream inputStream;
final String prefix = "classpath:";
String fileHasProblemMsg = String.format(PROBLEM_MSG, configPath);
String fileNotFoundMsg = String.format(NOT_FOUND_MSG, configPath);
if (configPath.startsWith(prefix)) {
String path = RegExUtils.removeFirst(configPath, prefix);
if (!path.startsWith("/")) {
path = "/" + path;
}
try {
inputStream = ResourcesUtil.getResourceAsStream(path);
if (inputStream == null) {
throw new WxPayException(fileNotFoundMsg);
}
} catch (Exception e) {
throw new WxPayException(fileNotFoundMsg, e);
}
} else if (configPath.startsWith("http://") || configPath.startsWith("https://")) {
try {
inputStream = new URL(configPath).openStream();
if (inputStream == null) {
throw new WxPayException(fileNotFoundMsg);
}
} catch (IOException e) {
throw new WxPayException(fileNotFoundMsg, e);
}
} else {
try {
File file = new File(configPath);
if (!file.exists()) {
throw new WxPayException(fileNotFoundMsg);
}

inputStream = new FileInputStream(file);
} catch (IOException e) {
throw new WxPayException(fileHasProblemMsg, e);
}
}
return inputStream;
}
}

+ 74
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/Applyment4SubService.java View File

@@ -0,0 +1,74 @@
package com.github.binarywang.wxpay.service;

import com.github.binarywang.wxpay.bean.applyment.*;
import com.github.binarywang.wxpay.exception.WxPayException;

/**
* 特约商户进件
* 产品介绍:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/tool/applyment4sub/chapter1_1.shtml
*
* @author zhouyongshen
*/
public interface Applyment4SubService {
/**
* 提交申请单API
* 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/tool/applyment4sub/chapter3_1.shtml
* 接口链接:https://api.mch.weixin.qq.com/v3/applyment4sub/applyment/
*
* @param request 请求对象
* @return WxPayApplymentCreateResult 响应结果
* @throws WxPayException the wx pay exception
*/
WxPayApplymentCreateResult createApply(WxPayApplyment4SubCreateRequest request) throws WxPayException;

/**
* 通过业务申请编号查询申请状态
* 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/tool/applyment4sub/chapter3_2.shtml
* 接口链接:https://api.mch.weixin.qq.com/v3/applyment4sub/applyment/business_code/{business_code}
*
* @param businessCode 业务申请编号
* 1、只能由数字、字母或下划线组成,建议前缀为服务商商户号。
* 2、服务商自定义的唯一编号。
* 3、每个编号对应一个申请单,每个申请单审核通过后生成一个微信支付商户号。
* 4、若申请单被驳回,可填写相同的“业务申请编号”,即可覆盖修改原申请单信息。
* 示例值:1900013511_10000
* @return the applyment state query result
* @throws WxPayException the wx pay exception
*/
ApplymentStateQueryResult queryApplyStatusByBusinessCode(String businessCode) throws WxPayException;

/**
* 通过申请单号查询申请状态
* 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/tool/applyment4sub/chapter3_2.shtml
* 接口链接:https://api.mch.weixin.qq.com/v3/applyment4sub/applyment/applyment_id/{applyment_id}
*
* @param applymentId 微信支付分的申请单号。示例值:2000001234567890
* @return the applyment state query result
* @throws WxPayException the wx pay exception
*/
ApplymentStateQueryResult queryApplyStatusByApplymentId(String applymentId) throws WxPayException;

/**
* 通过商户号查询结算帐号状态
* 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/tool/applyment4sub/chapter3_4.shtml
* 接口链接:https://api.mch.weixin.qq.com/v3/apply4sub/sub_merchants/{sub_mchid}/settlement
*
* @param subMchid 本服务商进件、已签约的特约商户号。
* @return the settlement info result
* @throws WxPayException the wx pay exception
*/
SettlementInfoResult querySettlementBySubMchid(String subMchid) throws WxPayException;

/**
* 修改结算帐号
* 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/tool/applyment4sub/chapter3_3.shtml
* 接口链接:https://api.mch.weixin.qq.com/v3/apply4sub/sub_merchants/{sub_mchid}/modify-settlement
*
* @param subMchid 特约商户号
* @param request 修改结算账户请求对象信息
* @throws WxPayException the wx pay exception
* @return
*/
String modifySettlement(String subMchid, ModifySettlementRequest request) throws WxPayException;

}

+ 121
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/BankService.java View File

@@ -0,0 +1,121 @@
package com.github.binarywang.wxpay.service;

import com.github.binarywang.wxpay.bean.bank.*;
import com.github.binarywang.wxpay.exception.WxPayException;

/**
* <pre>
* 微信支付-银行组件
* </pre>
*
* @author zhongjun
**/
public interface BankService {
/**
* <pre>
*
* 获取对私银行卡号开户银行
*
* 请求方式:GET(HTTPS)
* 请求地址:<a href="https://api.mch.weixin.qq.com/v3/capital/capitallhh/banks/search-banks-by-bank-account">https://api.mch.weixin.qq.com/v3/capital/capitallhh/banks/search-banks-by-bank-account</a>
*
* 文档地址:<a href="https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter11_2_1.shtml">https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter11_2_1.shtml</a>
* </pre>
*
* @param accountNumber 银行卡号 该字段需进行加密处理,加密方法详见敏感信息加密说明。(提醒:必须在HTTP头中上送Wechatpay-Serial)
* @return BankAccountResult 对私银行卡号开户银行信息
* @throws WxPayException .
*/
BankAccountResult searchBanksByBankAccount(String accountNumber) throws WxPayException;

/**
* <pre>
*
* 查询支持个人业务的银行列表
*
* 请求方式:GET(HTTPS)
* 请求地址:<a href="https://api.mch.weixin.qq.com/v3/capital/capitallhh/banks/personal-banking">https://api.mch.weixin.qq.com/v3/capital/capitallhh/banks/personal-banking</a>
*
* 文档地址:<a href="https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter11_2_2.shtml">https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter11_2_2.shtml</a>
* </pre>
*
* @param offset 本次查询偏移量
* @param limit 本次请求最大查询条数,最大值为200
* @return PersonalBankingResult 支持个人业务的银行列表信息
* @throws WxPayException .
*/
BankingResult personalBanking(Integer offset, Integer limit) throws WxPayException;

/**
* <pre>
*
* 支持对公业务的银行列表
*
* 请求方式:GET(HTTPS)
* 请求地址:<a href="https://api.mch.weixin.qq.com/v3/capital/capitallhh/banks/corporate-banking">https://api.mch.weixin.qq.com/v3/capital/capitallhh/banks/corporate-banking</a>
*
* 文档地址:<a href="https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter11_2_3.shtml">https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter11_2_3.shtml</a>
* </pre>
*
* @param offset 本次查询偏移量
* @param limit 本次请求最大查询条数,最大值为200
* @return BankingResult 支持对公业务的银行列表信息
* @throws WxPayException .
*/
BankingResult corporateBanking(Integer offset, Integer limit) throws WxPayException;

/**
* <pre>
*
* 查询省份列表API
* 通过本接口获取省份列表数据(不包含中国港澳台地区),可用于省份下的城市数据查询
*
* 请求方式:GET(HTTPS)
* 请求地址:<a href="https://api.mch.weixin.qq.com/v3/capital/capitallhh/areas/provinces">https://api.mch.weixin.qq.com/v3/capital/capitallhh/areas/provinces</a>
*
* 文档地址:<a href="https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter11_2_4.shtml">https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter11_2_4.shtml</a>
* </pre>
*
* @return ProvincesResult 省份列表信息
* @throws WxPayException .
*/
ProvincesResult areasProvinces() throws WxPayException;

/**
* <pre>
*
* 查询城市列表API
* 通过本接口根据省份编码获取省份下的城市列表信息,不包含中国港澳台地区城市信息,可用于支行数据过滤查询
*
* 请求方式:GET(HTTPS)
* 请求地址:<a href="https://api.mch.weixin.qq.com/v3/capital/capitallhh/areas/provinces/{province_code}/cities">https://api.mch.weixin.qq.com/v3/capital/capitallhh/areas/provinces/{province_code}/cities</a>
*
* 文档地址:<a href="https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter11_2_5.shtml">https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter11_2_5.shtml</a>
* </pre>
*
* @return CitiesResult 城市列表信息
* @throws WxPayException .
*/
CitiesResult areasCities(Integer provinceCode) throws WxPayException;

/**
* <pre>
*
* 查询支行列表API
* 本接口可以用于根据银行别名编码(仅支持需要填写支行的银行别名编码)和城市编码过滤查询支行列表数据
*
* 请求方式:GET(HTTPS)
* 请求地址:<a href="https://api.mch.weixin.qq.com/v3/capital/capitallhh/banks/{bank_alias_code}/branches">https://api.mch.weixin.qq.com/v3/capital/capitallhh/banks/{bank_alias_code}/branches</a>
*
* 文档地址:<a href="https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter11_2_5.shtml">https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter11_2_5.shtml</a>
* </pre>
*
* @param bankAliasCode 银行别名的编码,查询支行接口仅支持需要填写支行的银行别名编码。示例值:1000006247
* @param cityCode 城市编码,唯一标识一座城市,用于结合银行别名编码查询支行列表。示例值:536
* @param offset 非负整数,表示该次请求资源的起始位置,从0开始计数。调用方选填,默认为0。offset为20,limit为100时,查询第21-120条数据
* @param limit 非0非负的整数,该次请求可返回的最大资源条数。示例值:200
* @return BankBranchesResult 城市列表信息
* @throws WxPayException .
*/
BankBranchesResult bankBranches(String bankAliasCode, Integer cityCode, Integer offset, Integer limit) throws WxPayException;
}

+ 59
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/BusinessCircleService.java View File

@@ -0,0 +1,59 @@
package com.github.binarywang.wxpay.service;

import com.github.binarywang.wxpay.bean.businesscircle.*;
import com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader;
import com.github.binarywang.wxpay.exception.WxPayException;

/**
* <pre>
* 微信支付智慧商圈API
* </pre>
*
* @author thinsstar
*/
public interface BusinessCircleService {
/**
* <pre>
* 智慧商圈接口-商圈积分同步API
* 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/businesscircle/chapter3_2.shtml
* 接口链接:https://api.mch.weixin.qq.com/v3/businesscircle/points/notify
* </pre>
*
* @param request 请求对象
* @throws WxPayException the wx pay exception
*/
String notifyPoints(PointsNotifyRequest request) throws WxPayException;

BusinessCircleNotifyData parseNotifyData(String data, SignatureHeader header) throws WxPayException;

PaidResult decryptPaidNotifyDataResource(BusinessCircleNotifyData data) throws WxPayException;

RefundResult decryptRefundNotifyDataResource(BusinessCircleNotifyData data) throws WxPayException;

MemberCardAuthorizeNotifyResult decryptMemberCardAuthorizeNotifyDataResource(BusinessCircleNotifyData data) throws WxPayException;

/**
* 授权查询
* https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter8_6_4.shtml
* @return
* @throws WxPayException
*/
MemberCardAuthorizeResult getAuthorizations(String openid) throws WxPayException;

/**
* 查询待积分状态
* @param brandid
* @param openid
* @return
* @throws WxPayException
*/
PointsCommitStatusResult getPointsCommitStatus(String brandid,String openid) throws WxPayException;

/**
* 停车状态同步
* https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter8_6_5.shtml
* @param request
* @throws WxPayException
*/
void notifyParkings(ParkingNotifyRequest request) throws WxPayException;
}

+ 50
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/MemberCardService.java View File

@@ -0,0 +1,50 @@
package com.github.binarywang.wxpay.service;

import com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader;
import com.github.binarywang.wxpay.bean.membercard.*;
import com.github.binarywang.wxpay.exception.WxPayException;

/**
* <pre>
* 会员卡相关接口
* </pre>
*
* @author thinsstar
*/
public interface MemberCardService {

MemberCardNotifyData parseNotifyData(String data, SignatureHeader header) throws WxPayException;

MemberCardActivateResult decryptActivateNotifyDataResource(MemberCardNotifyData data) throws WxPayException;

/**
* 查询会员卡信息
* https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_9_6.shtml
* @param card_id
* @param code
* @return
* @throws WxPayException
*/
MemberCardResult getMemberCard(String card_id,String code) throws WxPayException;

/**
* 修改用户会员卡信息API
* https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_9_8.shtml
* @param card_id
* @param code
* @param request
* @throws WxPayException
*/
void updMemberCard(String card_id, String code, MemberCardUpdRequest request) throws WxPayException;

/**
* 设置用户会员权益信息api
* https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_9_23.shtml
* @param card_id
* @param code
* @param request
* @throws WxPayException
*/
void setMemberCardRights(String card_id,String code,MemberCardRightsRequest request) throws WxPayException;

}

+ 46
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/MerchantMediaService.java View File

@@ -0,0 +1,46 @@
package com.github.binarywang.wxpay.service;

import com.github.binarywang.wxpay.bean.media.ImageUploadResult;
import com.github.binarywang.wxpay.exception.WxPayException;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;

/**
* <pre>
* 微信支付通用媒体接口.
* </pre>
*
* @author zhouyongshen
*/
public interface MerchantMediaService {
/**
* <pre>
* 通用接口-图片上传API
* 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/tool/chapter3_1.shtml
* 接口链接:https://api.mch.weixin.qq.com/v3/merchant/media/upload
* </pre>
*
* @param imageFile 需要上传的图片文件
* @return ImageUploadResult 微信返回的媒体文件标识Id。示例值:6uqyGjGrCf2GtyXP8bxrbuH9-aAoTjH-rKeSl3Lf4_So6kdkQu4w8BYVP3bzLtvR38lxt4PjtCDXsQpzqge_hQEovHzOhsLleGFQVRF-U_0
* @throws WxPayException the wx pay exception
*/
ImageUploadResult imageUploadV3(File imageFile) throws WxPayException, IOException;

/**
* <pre>
* 通用接口-图片上传API
* 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/tool/chapter3_1.shtml
* 接口链接:https://api.mch.weixin.qq.com/v3/merchant/media/upload
* </pre>
*
* @param inputStream 需要上传的图片文件流
* @param fileName 需要上传的图片文件名
* @return ImageUploadResult 微信返回的媒体文件标识Id。示例值:6uqyGjGrCf2GtyXP8bxrbuH9-aAoTjH-rKeSl3Lf4_So6kdkQu4w8BYVP3bzLtvR38lxt4PjtCDXsQpzqge_hQEovHzOhsLleGFQVRF-U_0
* @throws WxPayException the wx pay exception
*/
ImageUploadResult imageUploadV3(InputStream inputStream, String fileName) throws WxPayException, IOException;


}

+ 120
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java View File

@@ -9,8 +9,11 @@ import com.github.binarywang.wxpay.bean.request.*;
import com.github.binarywang.wxpay.bean.result.*;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.exception.WxPayException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;

import java.io.File;
import java.io.InputStream;
import java.util.Date;
import java.util.Map;

@@ -53,6 +56,87 @@ public interface WxPayService {
*/
String post(String url, String requestStr, boolean useKey) throws WxPayException;

/**
* 发送post请求,得到响应字符串.
*
* @param url 请求地址
* @param requestStr 请求信息
* @return 返回请求结果字符串 string
* @throws WxPayException the wx pay exception
*/
String postV3(String url, String requestStr) throws WxPayException;

/**
* 发送patch请求,得到响应字符串.
*
* @param url 请求地址
* @param requestStr 请求信息
* @return 返回请求结果字符串 string
* @throws WxPayException the wx pay exception
*/
String patchV3(String url, String requestStr) throws WxPayException;

/**
* 发送post请求,得到响应字符串.
* <p>
* 部分字段会包含敏感信息,所以在提交前需要在请求头中会包含"Wechatpay-Serial"信息
*
* @param url 请求地址
* @param requestStr 请求信息
* @return 返回请求结果字符串 string
* @throws WxPayException the wx pay exception
*/
String postV3WithWechatpaySerial(String url, String requestStr) throws WxPayException;

/**
* 发送post请求,得到响应字符串.
*
* @param url 请求地址
* @param httpPost 请求信息
* @return 返回请求结果字符串 string
* @throws WxPayException the wx pay exception
*/
String postV3(String url, HttpPost httpPost) throws WxPayException;

/**
* 发送http请求,得到响应字符串.
*
* @param url 请求地址
* @param httpRequest 请求信息,可以是put,post,get,delete等请求
* @return 返回请求结果字符串 string
* @throws WxPayException the wx pay exception
*/
String requestV3(String url, HttpRequestBase httpRequest) throws WxPayException;

/**
* 发送get V3请求,得到响应字符串.
*
* @param url 请求地址
* @return 返回请求结果字符串 string
* @throws WxPayException the wx pay exception
*/
String getV3(String url) throws WxPayException;

/**
* 发送get请求,得到响应字符串.
* <p>
* 部分字段会包含敏感信息,所以在提交前需要在请求头中会包含"Wechatpay-Serial"信息
*
* @param url 请求地址
* @return 返回请求结果字符串 string
* @throws WxPayException the wx pay exception
*/
String getV3WithWechatPaySerial(String url) throws WxPayException;

/**
* 发送下载 V3请求,得到响应流.
*
* @param url 请求地址
* @return 返回请求响应流 input stream
* @throws WxPayException the wx pay exception
*/
InputStream downloadV3(String url) throws WxPayException;

/**
* 获取企业付款服务类.
*
@@ -74,6 +158,41 @@ public interface WxPayService {
*/
ProfitSharingService getProfitSharingService();

/**
* 获取微信支付智慧商圈服务类
*
* @return the business circle service
*/
BusinessCircleService getBusinessCircleService();

/**
* 获取会员卡服务类
*
* @return the business circle service
*/
MemberCardService getMemberCardService();

/**
* 特约商户进件服务
*
* @return
*/
Applyment4SubService getApplyment4SubService();

/**
* 媒体上传服务
*
* @return
*/
MerchantMediaService getMerchantMediaService();

/**
* 获取银行组件服务
*
* @return 银行组件服务
*/
BankService getBankService();

/**
* 设置企业付款服务类,允许开发者自定义实现类.
*
@@ -81,6 +200,7 @@ public interface WxPayService {
*/
void setEntPayService(EntPayService entPayService);


/**
* <pre>
* 查询订单.


+ 66
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/Applyment4SubServiceImpl.java View File

@@ -0,0 +1,66 @@
package com.github.binarywang.wxpay.service.impl;

import com.github.binarywang.wxpay.bean.applyment.*;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.Applyment4SubService;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.v3.util.RsaCryptoUtil;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.security.cert.X509Certificate;

@Slf4j
@RequiredArgsConstructor
public class Applyment4SubServiceImpl implements Applyment4SubService {
private static final Gson GSON = new GsonBuilder().create();
private final WxPayService payService;

private void encryptFiled(Object request) throws WxPayException {

X509Certificate validCertificate = payService.getConfig().getVerifier().getValidCertificate();

RsaCryptoUtil.encryptFields(request, validCertificate);
}


@Override
public WxPayApplymentCreateResult createApply(WxPayApplyment4SubCreateRequest request) throws WxPayException {
String url = String.format("%s/v3/applyment4sub/applyment/", this.payService.getPayBaseUrl());

encryptFiled(request);

String result = payService.postV3WithWechatpaySerial(url, GSON.toJson(request));
return GSON.fromJson(result, WxPayApplymentCreateResult.class);
}

@Override
public ApplymentStateQueryResult queryApplyStatusByBusinessCode(String businessCode) throws WxPayException {
String url = String.format("%s/v3/applyment4sub/applyment/business_code/%s", this.payService.getPayBaseUrl(), businessCode);
String result = payService.getV3(url);
return GSON.fromJson(result, ApplymentStateQueryResult.class);
}

@Override
public ApplymentStateQueryResult queryApplyStatusByApplymentId(String applymentId) throws WxPayException {
String url = String.format("%s/v3/applyment4sub/applyment/applyment_id/%s", this.payService.getPayBaseUrl(), applymentId);
String result = payService.getV3(url);
return GSON.fromJson(result, ApplymentStateQueryResult.class);
}

@Override
public SettlementInfoResult querySettlementBySubMchid(String subMchid) throws WxPayException {
String url = String.format("%s/v3/apply4sub/sub_merchants/%s/settlement", this.payService.getPayBaseUrl(), subMchid);
String result = payService.getV3(url);
return GSON.fromJson(result, SettlementInfoResult.class);
}

@Override
public String modifySettlement(String subMchid, ModifySettlementRequest request) throws WxPayException {
String url = String.format("%s/v3/apply4sub/sub_merchants/%s/modify-settlement", this.payService.getPayBaseUrl(), subMchid);
encryptFiled(request);
return payService.postV3WithWechatpaySerial(url, GSON.toJson(request));
}
}

+ 68
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BankServiceImpl.java View File

@@ -0,0 +1,68 @@
package com.github.binarywang.wxpay.service.impl;

import com.github.binarywang.wxpay.bean.bank.*;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.BankService;
import com.github.binarywang.wxpay.service.WxPayService;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import lombok.RequiredArgsConstructor;

/**
* 微信支付-银行组件
*
* @author zhongjun
**/
@RequiredArgsConstructor
public class BankServiceImpl implements BankService {
private final WxPayService payService;
private static final Gson GSON = new GsonBuilder().create();

@Override
public BankAccountResult searchBanksByBankAccount(String accountNumber) throws WxPayException {
String url = String.format("%s/v3/capital/capitallhh/banks/search-banks-by-bank-account?account_number=%s", this.payService.getPayBaseUrl(), accountNumber);
String response = payService.getV3WithWechatPaySerial(url);
return GSON.fromJson(response, BankAccountResult.class);
}

@Override
public BankingResult personalBanking(Integer offset, Integer limit) throws WxPayException {
offset = offset == null ? 0 : offset;
limit = limit == null ? 200 : limit;
String url = String.format("%s/v3/capital/capitallhh/banks/personal-banking?offset=%s&limit=%s", this.payService.getPayBaseUrl(), offset, limit);
String response = payService.getV3(url);
return GSON.fromJson(response, BankingResult.class);
}

@Override
public BankingResult corporateBanking(Integer offset, Integer limit) throws WxPayException {
offset = offset == null ? 0 : offset;
limit = limit == null ? 200 : limit;
String url = String.format("%s/v3/capital/capitallhh/banks/corporate-banking?offset=%s&limit=%s", this.payService.getPayBaseUrl(), offset, limit);
String response = payService.getV3(url);
return GSON.fromJson(response, BankingResult.class);
}

@Override
public ProvincesResult areasProvinces() throws WxPayException {
String url = String.format("%s/v3/capital/capitallhh/areas/provinces", this.payService.getPayBaseUrl());
String response = payService.getV3WithWechatPaySerial(url);
return GSON.fromJson(response, ProvincesResult.class);
}

@Override
public CitiesResult areasCities(Integer provinceCode) throws WxPayException {
String url = String.format("%s/v3/capital/capitallhh/areas/provinces/%s/cities", this.payService.getPayBaseUrl(), provinceCode);
String response = payService.getV3WithWechatPaySerial(url);
return GSON.fromJson(response, CitiesResult.class);
}

@Override
public BankBranchesResult bankBranches(String bankAliasCode, Integer cityCode, Integer offset, Integer limit) throws WxPayException {
offset = offset == null ? 0 : offset;
limit = limit == null ? 200 : limit;
String url = String.format("%s/v3/capital/capitallhh/banks/%s/branches?city_code=%s&offset=%s&limit=%s", this.payService.getPayBaseUrl(), bankAliasCode, cityCode, offset, limit);
String response = payService.getV3(url);
return GSON.fromJson(response, BankBranchesResult.class);
}
}

+ 31
- 4
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java View File

@@ -16,10 +16,7 @@ import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.constant.WxPayConstants.SignType;
import com.github.binarywang.wxpay.constant.WxPayConstants.TradeType;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.EntPayService;
import com.github.binarywang.wxpay.service.ProfitSharingService;
import com.github.binarywang.wxpay.service.RedpackService;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.*;
import com.github.binarywang.wxpay.util.SignUtils;
import com.github.binarywang.wxpay.util.XmlConfig;
import com.google.common.base.Joiner;
@@ -63,6 +60,11 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
private EntPayService entPayService = new EntPayServiceImpl(this);
private ProfitSharingService profitSharingService = new ProfitSharingServiceImpl(this);
private RedpackService redpackService = new RedpackServiceImpl(this);
private BusinessCircleService businessCircleService = new BusinessCircleServiceImpl(this);
private MemberCardService memberCardServiceService = new MemberCardServiceImpl(this);
private Applyment4SubService applyment4SubService = new Applyment4SubServiceImpl(this);
private MerchantMediaService merchantMediaService = new MerchantMediaServiceImpl(this);
private BankService bankService = new BankServiceImpl(this);

/**
* The Config.
@@ -79,11 +81,36 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
return profitSharingService;
}

@Override
public BusinessCircleService getBusinessCircleService() {
return this.businessCircleService;
}

@Override
public MemberCardService getMemberCardService(){
return this.memberCardServiceService;
}

@Override
public RedpackService getRedpackService() {
return this.redpackService;
}

@Override
public Applyment4SubService getApplyment4SubService() {
return applyment4SubService;
}

@Override
public MerchantMediaService getMerchantMediaService() {
return merchantMediaService;
}

@Override
public BankService getBankService() {
return bankService;
}

@Override
public void setEntPayService(EntPayService entPayService) {
this.entPayService = entPayService;


+ 125
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BusinessCircleServiceImpl.java View File

@@ -0,0 +1,125 @@
package com.github.binarywang.wxpay.service.impl;

import com.github.binarywang.wxpay.bean.businesscircle.*;
import com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.BusinessCircleService;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.v3.util.AesUtils;
import com.github.binarywang.wxpay.v3.util.RsaCryptoUtil;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.util.Objects;

/**
* 微信支付-微信支付智慧商圈service
*
* @author thinsstar
*/
@Slf4j
@RequiredArgsConstructor
public class BusinessCircleServiceImpl implements BusinessCircleService {
private static final Gson GSON = new GsonBuilder().create();
private final WxPayService payService;

@Override
public String notifyPoints(PointsNotifyRequest request) throws WxPayException {
String url = String.format("%s/v3/businesscircle/points/notify", this.payService.getPayBaseUrl());
RsaCryptoUtil.encryptFields(request, this.payService.getConfig().getVerifier().getValidCertificate());
return this.payService.postV3WithWechatpaySerial(url, GSON.toJson(request));
}

/**
* 校验通知签名
*
* @param header 通知头信息
* @param data 通知数据
* @return true:校验通过 false:校验不通过
*/
private boolean verifyNotifySign(SignatureHeader header, String data) {
String beforeSign = String.format("%s%n%s%n%s%n", header.getTimeStamp(), header.getNonce(), data);
return payService.getConfig().getVerifier().verify(header.getSerialNo(),
beforeSign.getBytes(StandardCharsets.UTF_8), header.getSigned());
}

@Override
public BusinessCircleNotifyData parseNotifyData(String data, SignatureHeader header) throws WxPayException {
if (Objects.nonNull(header) && !this.verifyNotifySign(header, data)) {
throw new WxPayException("非法请求,头部信息验证失败");
}
return GSON.fromJson(data, BusinessCircleNotifyData.class);
}

@Override
public PaidResult decryptPaidNotifyDataResource(BusinessCircleNotifyData data) throws WxPayException {
BusinessCircleNotifyData.Resource resource = data.getResource();
String cipherText = resource.getCipherText();
String associatedData = resource.getAssociatedData();
String nonce = resource.getNonce();
String apiV3Key = this.payService.getConfig().getApiV3Key();
try {
return GSON.fromJson(AesUtils.decryptToString(associatedData, nonce, cipherText, apiV3Key), PaidResult.class);
} catch (GeneralSecurityException | IOException e) {
throw new WxPayException("解析报文异常!", e);
}
}

@Override
public RefundResult decryptRefundNotifyDataResource(BusinessCircleNotifyData data) throws WxPayException {
BusinessCircleNotifyData.Resource resource = data.getResource();
String cipherText = resource.getCipherText();
String associatedData = resource.getAssociatedData();
String nonce = resource.getNonce();
String apiV3Key = this.payService.getConfig().getApiV3Key();
try {
return GSON.fromJson(AesUtils.decryptToString(associatedData, nonce, cipherText, apiV3Key), RefundResult.class);
} catch (GeneralSecurityException | IOException e) {
throw new WxPayException("解析报文异常!", e);
}
}

@Override
public MemberCardAuthorizeNotifyResult decryptMemberCardAuthorizeNotifyDataResource(BusinessCircleNotifyData data) throws WxPayException {
BusinessCircleNotifyData.Resource resource = data.getResource();
String cipherText = resource.getCipherText();
String associatedData = resource.getAssociatedData();
String nonce = resource.getNonce();
String apiV3Key = this.payService.getConfig().getApiV3Key();
try {
return GSON.fromJson(AesUtils.decryptToString(associatedData, nonce, cipherText, apiV3Key), MemberCardAuthorizeNotifyResult.class);
} catch (GeneralSecurityException | IOException e) {
throw new WxPayException("解析报文异常!", e);
}
}

@Override
public MemberCardAuthorizeResult getAuthorizations(String openid) throws WxPayException {
String url = String.format("%s/v3/businesscircle/user-authorizations/%s?sub_mchid=%s&appid=%s",
this.payService.getPayBaseUrl(),openid,this.payService.getConfig().getSubMchId(),this.payService.getConfig().getAppId());
String response = this.payService.getV3WithWechatPaySerial(url);
return GSON.fromJson(response,MemberCardAuthorizeResult.class);
}

@Override
public PointsCommitStatusResult getPointsCommitStatus(String brandid, String openid) throws WxPayException {
String url = String.format("%s/v3/businesscircle/user/%s/points/commit_status?sub_mchid=%s&brandid=%s&appid=%s",
this.payService.getPayBaseUrl(),openid,this.payService.getConfig().getSubMchId(),brandid,this.payService.getConfig().getAppId());
String response = this.payService.getV3WithWechatPaySerial(url);
return GSON.fromJson(response,PointsCommitStatusResult.class);
}

@Override
public void notifyParkings(ParkingNotifyRequest request) throws WxPayException {
request.setAppid(this.payService.getConfig().getAppId());
request.setSubMchid(this.payService.getConfig().getSubMchId());
String url = String.format("%s/v3/businesscircle/parkings", this.payService.getPayBaseUrl());
RsaCryptoUtil.encryptFields(request, this.payService.getConfig().getVerifier().getValidCertificate());
this.payService.postV3WithWechatpaySerial(url, GSON.toJson(request));
}
}

+ 87
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/MemberCardServiceImpl.java View File

@@ -0,0 +1,87 @@
package com.github.binarywang.wxpay.service.impl;

import com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader;
import com.github.binarywang.wxpay.bean.membercard.*;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.MemberCardService;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.v3.util.AesUtils;
import com.github.binarywang.wxpay.v3.util.RsaCryptoUtil;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.util.Objects;

/**
* 会员卡相关
*
* @author thinsstar
*/
@Slf4j
@RequiredArgsConstructor
public class MemberCardServiceImpl implements MemberCardService {
private static final Gson GSON = new GsonBuilder().create();
private final WxPayService payService;

/**
* 校验通知签名
*
* @param header 通知头信息
* @param data 通知数据
* @return true:校验通过 false:校验不通过
*/
private boolean verifyNotifySign(SignatureHeader header, String data) {
String beforeSign = String.format("%s%n%s%n%s%n", header.getTimeStamp(), header.getNonce(), data);
return payService.getConfig().getVerifier().verify(header.getSerialNo(),
beforeSign.getBytes(StandardCharsets.UTF_8), header.getSigned());
}

@Override
public MemberCardNotifyData parseNotifyData(String data, SignatureHeader header) throws WxPayException {
if (Objects.nonNull(header) && !this.verifyNotifySign(header, data)) {
throw new WxPayException("非法请求,头部信息验证失败");
}
return GSON.fromJson(data, MemberCardNotifyData.class);
}

@Override
public MemberCardActivateResult decryptActivateNotifyDataResource(MemberCardNotifyData data) throws WxPayException {
MemberCardNotifyData.Resource resource = data.getResource();
String cipherText = resource.getCipherText();
String associatedData = resource.getAssociatedData();
String nonce = resource.getNonce();
String apiV3Key = this.payService.getConfig().getApiV3Key();
try {
return GSON.fromJson(AesUtils.decryptToString(associatedData, nonce, cipherText, apiV3Key), MemberCardActivateResult.class);
} catch (GeneralSecurityException | IOException e) {
throw new WxPayException("解析报文异常!", e);
}
}

@Override
public MemberCardResult getMemberCard(String card_id, String code) throws WxPayException {
String url = String.format("%s/v3/marketing/membercard-open/cards/%s/codes/%s", this.payService.getPayBaseUrl(),card_id,code);
String response = this.payService.getV3WithWechatPaySerial(url);
return GSON.fromJson(response,MemberCardResult.class);
}

@Override
public void updMemberCard(String card_id, String code, MemberCardUpdRequest request) throws WxPayException {
String url = String.format("%s/v3/marketing/membercard-open/cards/%s/codes/%s", this.payService.getPayBaseUrl(),card_id,code);
RsaCryptoUtil.encryptFields(request, this.payService.getConfig().getVerifier().getValidCertificate());
this.payService.patchV3(url, GSON.toJson(request));
}

@Override
public void setMemberCardRights(String card_id, String code, MemberCardRightsRequest request) throws WxPayException {
String url = String.format("%s/v3/marketing/membercard-open/cards/%s/codes/%s/rights", this.payService.getPayBaseUrl(),card_id,code);
RsaCryptoUtil.encryptFields(request, this.payService.getConfig().getVerifier().getValidCertificate());
this.payService.patchV3(url, GSON.toJson(request));
}

}

+ 60
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/MerchantMediaServiceImpl.java View File

@@ -0,0 +1,60 @@
package com.github.binarywang.wxpay.service.impl;

import com.github.binarywang.wxpay.bean.media.ImageUploadResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.MerchantMediaService;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.v3.WechatPayUploadHttpPost;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;

import java.io.*;
import java.net.URI;

/**
* 微信支付-媒体文件上传service
* @author zhouyongshen
*/
@Slf4j
@RequiredArgsConstructor
public class MerchantMediaServiceImpl implements MerchantMediaService {
private final WxPayService payService;

@Override
public ImageUploadResult imageUploadV3(File imageFile) throws WxPayException,IOException {
String url = String.format("%s/v3/merchant/media/upload", this.payService.getPayBaseUrl());

try (FileInputStream s1 = new FileInputStream(imageFile)) {
String sha256 = DigestUtils.sha256Hex(s1);
try (InputStream s2 = new FileInputStream(imageFile)) {
WechatPayUploadHttpPost request = new WechatPayUploadHttpPost.Builder(URI.create(url))
.withImage(imageFile.getName(), sha256, s2)
.build();
String result = this.payService.postV3(url, request);
return ImageUploadResult.fromJson(result);
}
}
}

@Override
public ImageUploadResult imageUploadV3(InputStream inputStream, String fileName) throws WxPayException, IOException {
String url = String.format("%s/v3/merchant/media/upload", this.payService.getPayBaseUrl());
try(ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
byte[] buffer = new byte[2048];
int len;
while ((len = inputStream.read(buffer)) > -1) {
bos.write(buffer, 0, len);
}
bos.flush();
byte[] data = bos.toByteArray();
String sha256 = DigestUtils.sha256Hex(data);
WechatPayUploadHttpPost request = new WechatPayUploadHttpPost.Builder(URI.create(url))
.withImage(fileName, sha256, new ByteArrayInputStream(data))
.build();
String result = this.payService.postV3(url, request);
return ImageUploadResult.fromJson(result);
}
}

}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save