Browse Source

Merge pull request #12 from Wechat-Group/develop

合并
master
Jonk 8 years ago
committed by GitHub
parent
commit
9ac66af59b
88 changed files with 3047 additions and 1919 deletions
  1. +33
    -0
      CONTRIBUTION.md
  2. +34
    -67
      README.md
  3. +1
    -1
      build.gradle
  4. +4
    -11
      pom.xml
  5. +1
    -1
      weixin-java-common/pom.xml
  6. +10
    -11
      weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/WxJsapiSignature.java
  7. +3
    -1
      weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/menu/WxMenuButton.java
  8. +5
    -1
      weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/menu/WxMenuRule.java
  9. +48
    -46
      weixin-java-common/src/main/java/me/chanjar/weixin/common/util/BeanUtils.java
  10. +18
    -13
      weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxMenuGsonAdapter.java
  11. +67
    -61
      weixin-java-cp/pom.xml
  12. +3
    -3
      weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpServiceImpl.java
  13. +77
    -67
      weixin-java-mp/pom.xml
  14. +28
    -11
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpConfigStorage.java
  15. +77
    -46
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java
  16. +22
    -9
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMenuService.java
  17. +74
    -19
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java
  18. +14
    -14
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpQrcodeService.java
  19. +39
    -10
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMenuServiceImpl.java
  20. +172
    -117
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java
  21. +31
    -14
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpQrcodeServiceImpl.java
  22. +54
    -72
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImpl.java
  23. +15
    -0
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassTagMessage.java
  24. +10
    -0
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceAuthorize.java
  25. +92
    -0
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/menu/WxMpMenu.java
  26. +14
    -0
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlMessage.java
  27. +26
    -15
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayBaseRequest.java
  28. +123
    -0
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayDownloadBillRequest.java
  29. +1
    -3
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayRefundRequest.java
  30. +273
    -0
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayReportRequest.java
  31. +101
    -28
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayBaseResult.java
  32. +15
    -0
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayCommonResult.java
  33. +392
    -403
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayOrderNotifyResult.java
  34. +81
    -76
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayOrderQueryResult.java
  35. +6
    -5
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayRedpackQueryResult.java
  36. +60
    -16
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayRefundQueryResult.java
  37. +9
    -0
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayUnifiedOrderResult.java
  38. +1
    -1
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMassTagMessageGsonAdapter.java
  39. +4
    -4
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpBaseAPITest.java
  40. +5
    -6
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpBusyRetryTest.java
  41. +7
    -9
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpJsAPITest.java
  42. +11
    -13
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMassMessageAPITest.java
  43. +67
    -67
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMessageRouterTest.java
  44. +3
    -5
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMiscAPITest.java
  45. +3
    -3
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpShortUrlAPITest.java
  46. +4
    -4
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpCardServiceImplTest.java
  47. +43
    -52
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpDataCubeServiceImplTest.java
  48. +2
    -4
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpDeviceServiceImplTest.java
  49. +38
    -40
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java
  50. +34
    -40
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpMaterialServiceImplTest.java
  51. +101
    -52
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpMenuServiceImplTest.java
  52. +82
    -35
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImplTest.java
  53. +15
    -10
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpQrcodeServiceImplTest.java
  54. +6
    -7
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImplTest.java
  55. +8
    -9
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpStoreServiceImplTest.java
  56. +7
    -8
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpTemplateMsgServiceImplTest.java
  57. +7
    -8
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpUserBlacklistServiceImplTest.java
  58. +15
    -20
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpUserServiceImplTest.java
  59. +12
    -16
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpUserTagServiceImplTest.java
  60. +6
    -5
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/test/ApiTestModule.java
  61. +20
    -4
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/test/TestConfigStorage.java
  62. +9
    -9
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/kefu/WxMpKefuMessageTest.java
  63. +25
    -25
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfListTest.java
  64. +20
    -22
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfOnlineListTest.java
  65. +2
    -2
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlMessageTest.java
  66. +22
    -22
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutImageMessageTest.java
  67. +37
    -37
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutMusicMessageTest.java
  68. +50
    -50
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutNewsMessageTest.java
  69. +17
    -17
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutTextMessageTest.java
  70. +2
    -2
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutTransferKefuMessageTest.java
  71. +31
    -31
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutVideoMessageTest.java
  72. +17
    -17
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutVoiceMessageTest.java
  73. +49
    -0
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/pay/result/WxPayBaseResultTest.java
  74. +65
    -0
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/pay/result/WxPayOrderQueryResultTest.java
  75. +48
    -0
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/pay/result/WxPayRefundQueryResultTest.java
  76. +28
    -29
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/pay/result/WxPaySendRedpackResultTest.java
  77. +25
    -25
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoGuessNumberHandler.java
  78. +8
    -8
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoImageHandler.java
  79. +1
    -1
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoLogHandler.java
  80. +6
    -6
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoOAuth2Handler.java
  81. +3
    -3
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoTextHandler.java
  82. +6
    -7
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpDemoInMemoryConfigStorage.java
  83. +16
    -17
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpDemoServer.java
  84. +4
    -4
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpEndpointServlet.java
  85. +6
    -7
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpOAuth2Servlet.java
  86. +14
    -13
      weixin-java-mp/src/test/resources/test-config.sample.xml
  87. +1
    -1
      weixin-java-mp/src/test/resources/testng.xml
  88. +1
    -1
      weixin-java-osgi/pom.xml

+ 33
- 0
CONTRIBUTION.md View File

@@ -0,0 +1,33 @@
# 代码贡献指南
1. 非常欢迎和感谢对本项目发起Pull Request的同学,本项目代码风格为使用2个空格代表一个Tab,因此在提交代码时请注意一下,否则很容易在IDE格式化代码后与原代码产生大量diff,这样会给其他人阅读代码带来极大的困扰。为了便于设置,本项目引入editorconfig插件,请使用eclipse的同学在贡献代码前安装相关插件,IntelliJ IDEA新版本自带支持,如果没有可自行安装插件。
1. 本项目可以采用两种方式接受代码贡献:
* 第一种就是基于[Git Flow](https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow)开发流程,因此在发起Pull Request的时候请选择develop分支,详细步骤参考后文。
* 另外一种贡献代码的方式就是加入SDK Developers开发组,前提是对自己的代码足够自信就可以申请加入,加入之后可以随时直接提交代码,但要注意对所做的修改或新增的代码进行单元测试,保证提交代码没有明显问题,具体加入方式,请咨询QQ群管理员[![点击这里给我发消息](http://wpa.qq.com/pa?p=2:1211415707:51)](http://wpa.qq.com/msgrd?v=3&uin=1211415707&site=qq&menu=yes)。


### PR方式贡献代码步骤
* 在 GitHub 上 `fork` 到自己的仓库,如 `my_user/weixin-java-tools`,然后 `clone` 到本地,并设置用户信息。

```bash
$ git clone git@github.com:my_user/weixin-java-tools.git
$ cd weixin-java-tools
$ git config user.name "yourname"
$ git config user.email "your email"
```
* 修改代码后提交,并推送到自己的仓库。

```bash
$ #do some change on the content
$ git commit -am "Fix issue #1: change something"
$ git push
```
* 在 GitHub 网站上提交 Pull Request。
* 定期使用项目仓库内容更新自己仓库内容。

```bash
$ git remote add upstream https://github.com/wechat-group/weixin-java-tools
$ git fetch upstream
$ git checkout develop
$ git rebase upstream/develop
$ git push -f origin develop
```

+ 34
- 67
README.md View File

@@ -1,35 +1,51 @@
Weixin Java Tools 微信公众号/企业号开发Java SDK
Weixin Java Tools —— 微信公众号&企业号开发 Java SDK
===================================== =====================================
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.binarywang/weixin-java-parent/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.github.binarywang/weixin-java-parent) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.binarywang/weixin-java-parent/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.github.binarywang/weixin-java-parent)
[![Build Status](https://travis-ci.org/Wechat-Group/weixin-java-tools.svg?branch=develop)](https://travis-ci.org/Wechat-Group/weixin-java-tools) [![Build Status](https://travis-ci.org/Wechat-Group/weixin-java-tools.svg?branch=develop)](https://travis-ci.org/Wechat-Group/weixin-java-tools)


### 注意:
1. ***本项目Fork自chanjarster/weixin-java-tools,但由于原项目已停止维护,故单独维护和发布,且发布到maven上的groupId也会不同,详细信息见下文。***
1. ***自2.0.0版本以来,公众号的接口调整比较大,主要是为了解决主接口类过于庞大不方便管理的问题,将接口实现代码按模块进行拆分。***
1. 本SDK要求的最低JDK版本是7,为满足少量还在使用JDK6的用户的需求,特意抽出独立的代码分支项目,请参考 https://github.com/binarywang/weixin-java-tools-for-jdk6 ,其他更早的JDK版本则需要自己改造实现;
1. 最新更新:2016-11-30 发布2.4.0正式版!
### 注意事项:
1. 声明: ***本项目Fork自chanjarster/weixin-java-tools,但由于原项目已停止维护,故单独维护和发布,且发布到maven上的groupId也会不同,详细信息见下文。***
1. 最新更新:**2017-2-12 发布[【2.5.0正式版】](https://github.com/Wechat-Group/weixin-java-tools/releases)**!
1. 开源中国网站的本项目首页链接地址:https://www.oschina.net/p/weixin-java-tools-new
1. 自2.0.0版本以来,公众号的接口调整比较大,主要是为了解决主接口类过于庞大不方便管理的问题,将接口实现代码按模块进行拆分。
1. SDK详细开发文档请查阅 [【Wiki】](https://github.com/wechat-group/weixin-java-tools/wiki),部分文档可能未能及时更新,如有发现,可以及时上报或者自行修改。
1. 各个模块的Javadoc可以在线查看(有可能是最新的测试版本的,请注意观察版本号):[weixin-java-mp](https://binarywang.github.io/weixin-java-mp-javadoc/)、[weixin-java-common](https://binarywang.github.io/weixin-java-common-javadoc/)、[weixin-java-cp](https://binarywang.github.io/weixin-java-cp-javadoc/)
1. 本SDK要求的最低JDK版本是7,还在使用JDK6的用户请参考[【此项目】]( https://github.com/binarywang/weixin-java-tools-for-jdk6) ,而其他更早的JDK版本则需要自己改造实现。
1. 如有新功能需求,发现BUG,或者由于微信官方接口调整导致的代码问题,可以直接在[【Issues】](https://github.com/Wechat-Group/weixin-java-tools/issues)页提出issue,便于讨论追踪问题;
1. 如果想贡献代码,请阅读[【代码贡献指南】](CONTRIBUTION.md)。


=========== ===========


## 开发交流方式及注意事项:
1. QQ群:343954419(推荐点击按钮入群: [![Join QQ Group](http://pub.idqqimg.com/wpa/images/group.png)](http://shang.qq.com/wpa/qunwpa?idkey=731dc3e7ea31ebe25376cc1a791445468612c63fd0e9e05399b088ec81fd9e15) 或 [![Join QQ Group](http://pub.idqqimg.com/wpa/images/group.png)](http://jq.qq.com/?_wv=1027&k=40lRskK),如果无反应,可以自行搜索群号进行添加 )
## SDK使用交流方式说明
1. QQ群: [![加入QQ群](https://img.shields.io/badge/QQ群-343954419-blue.svg)](http://shang.qq.com/wpa/qunwpa?idkey=731dc3e7ea31ebe25376cc1a791445468612c63fd0e9e05399b088ec81fd9e15) 或 [![加入QQ群](https://img.shields.io/badge/QQ群-343954419-blue.svg)](http://jq.qq.com/?_wv=1027&k=40lRskK),推荐点击按钮入群,当然如果无法成功操作,请自行搜索群号343954419进行添加 )
1. 由于群容量有限,即将爆满,故开启付费入群模式以保证只有真实交流需求的人进入,并为保证群的活跃度,将不定期清理长时间不活跃的同学; 1. 由于群容量有限,即将爆满,故开启付费入群模式以保证只有真实交流需求的人进入,并为保证群的活跃度,将不定期清理长时间不活跃的同学;
1. 微信群: 因微信群已达到100人限制,故如有想加入微信群的,请入QQ群后联系管理员,提供微信号以便邀请加入; 1. 微信群: 因微信群已达到100人限制,故如有想加入微信群的,请入QQ群后联系管理员,提供微信号以便邀请加入;
1. 新手提问前,请先阅读此文章:http://t.cn/RV93MRB 1. 新手提问前,请先阅读此文章:http://t.cn/RV93MRB
1. 寻求帮助时需贴代码或大长串异常信息的,请利用http://paste.ubuntu.com 1. 寻求帮助时需贴代码或大长串异常信息的,请利用http://paste.ubuntu.com
1. 有功能需求或由于微信官方接口调整导致的代码问题,可以直接提出issue,便于讨论追踪问题;
1. 详细开发文档请看 [Wiki](https://github.com/wechat-group/weixin-java-tools/wiki),部分文档可能未能及时更新,如有发现,可以及时上报或者自行修改。
1. 微信公众号官方文档入口地址:http://mp.weixin.qq.com/wiki (注意,从网上搜到的文档有的虽然地址前面跟这个一样,但明显左侧菜单不一致,是旧的文档,注意不要看错文档)。
1. 各个模块的Javadoc可以在线查看:[weixin-java-mp](https://binarywang.github.io/weixin-java-mp-javadoc/)、[weixin-java-common](https://binarywang.github.io/weixin-java-common-javadoc/)、[weixin-java-cp](https://binarywang.github.io/weixin-java-cp-javadoc/)


=========== ===========


## 版本说明 ## 版本说明
1. 本项目定为每两个月发布一次正式版,版本号格式为X.X.0(如2.1.0,2.2.0等),月底发布新版本,遇到重大问题需修复会及时提交新版本,欢迎大家随时提交Pull Request;
1. BUG修复和新特性一般会先发布成小版本作为临时测试版本(如2.0.1-beta,2.0.2-beta等,即尾号不为0,并添加beta字样,以区别于正式版);
1. 本项目定为大约每两个月发布一次正式版,版本号格式为X.X.0(如2.1.0,2.2.0等),遇到重大问题需修复会及时提交新版本,欢迎大家随时提交Pull Request;
1. BUG修复和新特性一般会先发布成小版本作为临时测试版本(如2.4.5.BETA,2.4.6.BETA等,即尾号不为0,并添加BETA字样,以区别于正式版);
1. 目前最新版本号为 [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.binarywang/weixin-java-parent/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.github.binarywang/weixin-java-parent) ,也可以通过访问链接 [【公众号】](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.github.binarywang%22%20AND%20a%3A%22weixin-java-mp%22) 、[【企业号】](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.github.binarywang%22%20AND%20a%3A%22weixin-java-cp%22) 1. 目前最新版本号为 [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.binarywang/weixin-java-parent/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.github.binarywang/weixin-java-parent) ,也可以通过访问链接 [【公众号】](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.github.binarywang%22%20AND%20a%3A%22weixin-java-mp%22) 、[【企业号】](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.github.binarywang%22%20AND%20a%3A%22weixin-java-cp%22)
分别查看所有最新的版本。 分别查看所有最新的版本。


===========
#### 本项目在几个著名的代码托管网站同步更新,地址分别是:
* 码云:http://git.oschina.net/binary/weixin-java-tools
* GitHub: https://github.com/wechat-group/weixin-java-tools
* Bitbucket:https://bitbucket.org/binarywang/weixin-java-tools
* Coding: https://git.coding.net/binarywang/weixin-java-tools.git

===========
## 可参考的Demo项目
#### 目前都是公众号的,风格不同,欢迎提供更多的demo供新手参考:
* https://github.com/wechat-group/weixin-java-mp-demo
* https://github.com/wechat-group/weixin-java-mp-multi-demo (支持多公众号)
* https://github.com/wechat-group/weixin-java-tools-springmvc
* https://github.com/wechat-group/weixin-java-mp-demo-springboot

## Maven & Gradle 最新正式版本 ## Maven & Gradle 最新正式版本


* 公众号(订阅号、服务号): * 公众号(订阅号、服务号):
@@ -39,12 +55,12 @@ maven:
<dependency> <dependency>
<groupId>com.github.binarywang</groupId> <groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId> <artifactId>weixin-java-mp</artifactId>
<version>2.4.0</version>
<version>2.5.0</version>
</dependency> </dependency>
``` ```
gradle: gradle:
```groovy ```groovy
compile 'com.github.binarywang:weixin-java-mp:2.4.0'
compile 'com.github.binarywang:weixin-java-mp:2.5.0'
``` ```


* 企业号: * 企业号:
@@ -54,60 +70,11 @@ maven:
<dependency> <dependency>
<groupId>com.github.binarywang</groupId> <groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-cp</artifactId> <artifactId>weixin-java-cp</artifactId>
<version>2.4.0</version>
<version>2.5.0</version>
</dependency> </dependency>
``` ```
gradle: gradle:
```groovy ```groovy
compile 'com.github.binarywang:weixin-java-cp:2.4.0'
compile 'com.github.binarywang:weixin-java-cp:2.5.0'
``` ```


===========

#### 本项目主要存放在github上,地址为 :
* https://github.com/wechat-group/weixin-java-tools
* ===========但同时会在其他几个网站同步更新,地址分别是:
* https://bitbucket.org/binarywang/weixin-java-tools
* http://git.oschina.net/binary/weixin-java-tools
* https://git.coding.net/binarywang/weixin-java-tools.git

===========
## 可参考的Demo项目
#### 目前都是公众号的,风格不同,欢迎提供更多的demo供新手参考:
1. https://github.com/wechat-group/weixin-mp-demo
1. https://github.com/wechat-group/weixin-mp-multi-demo (支持多公众号)
1. https://github.com/wechat-group/weixin-java-tools-springmvc
1. https://github.com/wechat-group/weixin-mp-demo-springboot


===========
## 关于代码贡献
1. 非常欢迎和感谢对本项目发起Pull Request的同学,本项目代码风格为使用2个空格代表一个Tab,因此在提交代码时请注意一下,否则很容易在IDE格式化代码后与原代码产生大量diff,这样会给其他人阅读代码带来极大的困扰。
1. 为了便于设置,本项目引入editorconfig插件,请使用eclipse的同学在贡献代码前安装相关插件,IntelliJ IDEA则自带支持,无需额外安装插件。
1. 本项目可以采用两种方式接受代码贡献:
* 第一种就是基于[Git Flow](https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow)开发流程,因此在发起Pull Request的时候请选择develop分支,详细步骤参考后文。
* 另外一种贡献代码的方式就是加入SDK Developers开发组,前提是对自己的代码足够自信就可以申请加入,加入之后可以随时直接提交代码,但要注意对所做的修改或新增的代码进行单元测试,保证提交代码没有明显问题,具体加入方式,请咨询QQ群管理员[![点击这里给我发消息](http://wpa.qq.com/pa?p=2:1211415707:51)](http://wpa.qq.com/msgrd?v=3&uin=1211415707&site=qq&menu=yes)。

## PR方式贡献代码步骤
* 在 GitHub 上 `fork` 到自己的仓库,如 `my_user/weixin-java-tools`,然后 `clone` 到本地,并设置用户信息。
```
$ git clone git@github.com:my_user/weixin-java-tools.git
$ cd weixin-java-tools
$ git config user.name "yourname"
$ git config user.email "your email"
```
* 修改代码后提交,并推送到自己的仓库。
```
$ #do some change on the content
$ git commit -am "Fix issue #1: change something"
$ git push
```
* 在 GitHub 网站上提交 Pull Request。
* 定期使用项目仓库内容更新自己仓库内容。
```
$ git remote add upstream https://github.com/wechat-group/weixin-java-tools
$ git fetch upstream
$ git checkout develop
$ git rebase upstream/develop
$ git push -f origin develop
```

+ 1
- 1
build.gradle View File

@@ -2,7 +2,7 @@ allprojects {
apply plugin: 'maven' apply plugin: 'maven'


group = 'com.github.binarywang' group = 'com.github.binarywang'
version = '2.5.0-SNAPSHOT'
version = '2.6.0-SNAPSHOT'
} }


subprojects { subprojects {


+ 4
- 11
pom.xml View File

@@ -1,11 +1,11 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<project <project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.github.binarywang</groupId> <groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-parent</artifactId> <artifactId>weixin-java-parent</artifactId>
<version>2.4.4-beta</version>
<version>2.6.0-SNAPSHOT</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<name>WeiXin Java Tools - Parent</name> <name>WeiXin Java Tools - Parent</name>
<description>微信公众号、企业号上级POM</description> <description>微信公众号、企业号上级POM</description>
@@ -99,7 +99,6 @@
<httpclient.version>4.5</httpclient.version> <httpclient.version>4.5</httpclient.version>
<slf4j.version>1.7.10</slf4j.version> <slf4j.version>1.7.10</slf4j.version>
<logback.version>1.1.2</logback.version> <logback.version>1.1.2</logback.version>
<jedis.version>2.9.0</jedis.version>
<gson.version>2.7</gson.version> <gson.version>2.7</gson.version>
<guava.version>19.0</guava.version> <guava.version>19.0</guava.version>
<commons-lang3.version>3.5</commons-lang3.version> <commons-lang3.version>3.5</commons-lang3.version>
@@ -150,12 +149,6 @@
<artifactId>commons-lang3</artifactId> <artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version> <version>${commons-lang3.version}</version>
</dependency> </dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>${jedis.version}</version>
<optional>true</optional>
</dependency>
<dependency> <dependency>
<groupId>com.google.guava</groupId> <groupId>com.google.guava</groupId>
<artifactId>guava</artifactId> <artifactId>guava</artifactId>
@@ -307,7 +300,7 @@
<configuration> <configuration>
<serverId>ossrh</serverId> <serverId>ossrh</serverId>
<nexusUrl>https://oss.sonatype.org/</nexusUrl> <nexusUrl>https://oss.sonatype.org/</nexusUrl>
<autoReleaseAfterClose>false</autoReleaseAfterClose>
<autoReleaseAfterClose>true</autoReleaseAfterClose>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>


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

@@ -6,7 +6,7 @@
<parent> <parent>
<groupId>com.github.binarywang</groupId> <groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-parent</artifactId> <artifactId>weixin-java-parent</artifactId>
<version>2.4.4-beta</version>
<version>2.6.0-SNAPSHOT</version>
</parent> </parent>


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


+ 10
- 11
weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/WxJsapiSignature.java View File

@@ -8,9 +8,9 @@ import java.io.Serializable;
public class WxJsapiSignature implements Serializable { public class WxJsapiSignature implements Serializable {
private static final long serialVersionUID = -1116808193154384804L; private static final long serialVersionUID = -1116808193154384804L;


private String appid;
private String appId;


private String noncestr;
private String nonceStr;


private long timestamp; private long timestamp;


@@ -26,12 +26,12 @@ public class WxJsapiSignature implements Serializable {
this.signature = signature; this.signature = signature;
} }


public String getNoncestr() {
return this.noncestr;
public String getNonceStr() {
return nonceStr;
} }


public void setNoncestr(String noncestr) {
this.noncestr = noncestr;
public void setNonceStr(String nonceStr) {
this.nonceStr = nonceStr;
} }


public long getTimestamp() { public long getTimestamp() {
@@ -50,12 +50,11 @@ public class WxJsapiSignature implements Serializable {
this.url = url; this.url = url;
} }


public String getAppid() {
return this.appid;
public String getAppId() {
return appId;
} }


public void setAppid(String appid) {
this.appid = appid;
public void setAppId(String appId) {
this.appId = appId;
} }

} }

+ 3
- 1
weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/menu/WxMenuButton.java View File

@@ -2,10 +2,12 @@ package me.chanjar.weixin.common.bean.menu;


import me.chanjar.weixin.common.util.ToStringUtils; import me.chanjar.weixin.common.util.ToStringUtils;


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


public class WxMenuButton {
public class WxMenuButton implements Serializable {
private static final long serialVersionUID = -1070939403109776555L;


private String type; private String type;
private String name; private String name;


+ 5
- 1
weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/menu/WxMenuRule.java View File

@@ -2,7 +2,11 @@ package me.chanjar.weixin.common.bean.menu;


import me.chanjar.weixin.common.util.ToStringUtils; import me.chanjar.weixin.common.util.ToStringUtils;


public class WxMenuRule {
import java.io.Serializable;

public class WxMenuRule implements Serializable {
private static final long serialVersionUID = -4587181819499286670L;

private String tagId; private String tagId;
private String sex; private String sex;
private String country; private String country;


+ 48
- 46
weixin-java-common/src/main/java/me/chanjar/weixin/common/util/BeanUtils.java View File

@@ -1,21 +1,20 @@
package me.chanjar.weixin.common.util; package me.chanjar.weixin.common.util;


import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAlias;

import me.chanjar.weixin.common.annotation.Required; import me.chanjar.weixin.common.annotation.Required;
import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.bean.result.WxError;
import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.exception.WxErrorException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;


/** /**
* <pre> * <pre>
@@ -25,25 +24,28 @@ import me.chanjar.weixin.common.exception.WxErrorException;
* </pre> * </pre>
*/ */
public class BeanUtils { public class BeanUtils {
private static Logger log = LoggerFactory.getLogger(BeanUtils.class);
private static Logger log = LoggerFactory.getLogger(BeanUtils.class);


/** /**
* 检查bean里标记为@Required的field是否为空,为空则抛异常 * 检查bean里标记为@Required的field是否为空,为空则抛异常
*
* @param bean 要检查的bean对象 * @param bean 要检查的bean对象
* @throws WxErrorException * @throws WxErrorException
*/ */
public static void checkRequiredFields(Object bean) throws WxErrorException { public static void checkRequiredFields(Object bean) throws WxErrorException {
List<String> nullFields = Lists.newArrayList();
List<String> requiredFields = Lists.newArrayList();


List<Field> fields = new ArrayList<>( Arrays.asList(bean.getClass().getDeclaredFields()));
List<Field> fields = new ArrayList<>(Arrays.asList(bean.getClass().getDeclaredFields()));
fields.addAll(Arrays.asList(bean.getClass().getSuperclass().getDeclaredFields())); fields.addAll(Arrays.asList(bean.getClass().getSuperclass().getDeclaredFields()));
for (Field field : fields) { for (Field field : fields) {
try { try {
boolean isAccessible = field.isAccessible(); boolean isAccessible = field.isAccessible();
field.setAccessible(true); field.setAccessible(true);
if (field.isAnnotationPresent(Required.class)
&& field.get(bean) == null) {
nullFields.add(field.getName());
if (field.isAnnotationPresent(Required.class)) {
if (field.get(bean) == null || (field.get(bean) instanceof String && StringUtils.isBlank(field.get(bean).toString()))) {
//两种情况,一种是值为null,另外一种情况是类型为字符串,但是字符串内容为空的,都认为是没有提供值
requiredFields.add(field.getName());
}
} }
field.setAccessible(isAccessible); field.setAccessible(isAccessible);
} catch (SecurityException | IllegalArgumentException } catch (SecurityException | IllegalArgumentException
@@ -52,43 +54,43 @@ public class BeanUtils {
} }
} }


if (!nullFields.isEmpty()) {
String msg = "必填字段 " + nullFields + " 必须提供值";
if (!requiredFields.isEmpty()) {
String msg = "必填字段 " + requiredFields + " 必须提供值";
log.debug(msg); log.debug(msg);
throw new WxErrorException(WxError.newBuilder().setErrorMsg(msg).build()); throw new WxErrorException(WxError.newBuilder().setErrorMsg(msg).build());
} }
} }


/**
* 将bean按照@XStreamAlias标识的字符串内容生成以之为key的map对象
*
* @param bean 包含@XStreamAlias的xml bean对象
* @return map对象
*/
public static Map<String, String> xmlBean2Map(Object bean) {
Map<String, String> result = Maps.newHashMap();
List<Field> fields = new ArrayList<>(Arrays.asList(bean.getClass().getDeclaredFields()));
fields.addAll(Arrays.asList(bean.getClass().getSuperclass().getDeclaredFields()));
for (Field field : fields) {
try {
boolean isAccessible = field.isAccessible();
field.setAccessible(true);
if (field.get(bean) == null) {
field.setAccessible(isAccessible);
continue;
}
/**
* 将bean按照@XStreamAlias标识的字符串内容生成以之为key的map对象
*
* @param bean 包含@XStreamAlias的xml bean对象
* @return map对象
*/
public static Map<String, String> xmlBean2Map(Object bean) {
Map<String, String> result = Maps.newHashMap();
List<Field> fields = new ArrayList<>(Arrays.asList(bean.getClass().getDeclaredFields()));
fields.addAll(Arrays.asList(bean.getClass().getSuperclass().getDeclaredFields()));
for (Field field : fields) {
try {
boolean isAccessible = field.isAccessible();
field.setAccessible(true);
if (field.get(bean) == null) {
field.setAccessible(isAccessible);
continue;
}


if (field.isAnnotationPresent(XStreamAlias.class)) {
result.put(field.getAnnotation(XStreamAlias.class).value(), field.get(bean).toString());
}
if (field.isAnnotationPresent(XStreamAlias.class)) {
result.put(field.getAnnotation(XStreamAlias.class).value(), field.get(bean).toString());
}


field.setAccessible(isAccessible);
} catch (SecurityException | IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
field.setAccessible(isAccessible);
} catch (SecurityException | IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}


}
}


return result;
}
return result;
}
} }

+ 18
- 13
weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxMenuGsonAdapter.java View File

@@ -8,21 +8,13 @@
*/ */
package me.chanjar.weixin.common.util.json; package me.chanjar.weixin.common.util.json;


import java.lang.reflect.Type;

import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;

import com.google.gson.*;
import me.chanjar.weixin.common.bean.menu.WxMenu; import me.chanjar.weixin.common.bean.menu.WxMenu;
import me.chanjar.weixin.common.bean.menu.WxMenuButton; import me.chanjar.weixin.common.bean.menu.WxMenuButton;
import me.chanjar.weixin.common.bean.menu.WxMenuRule; import me.chanjar.weixin.common.bean.menu.WxMenuRule;


import java.lang.reflect.Type;



/** /**
* @author Daniel Qian * @author Daniel Qian
@@ -76,6 +68,20 @@ public class WxMenuGsonAdapter implements JsonSerializer<WxMenu>, JsonDeserializ
return matchRule; return matchRule;
} }


private WxMenuRule convertToRule(JsonObject json) {
WxMenuRule menuRule = new WxMenuRule();
//变态的微信接口,这里居然反人类的使用和序列化时不一样的名字
//menuRule.setTagId(GsonHelper.getString(json,"tag_id"));
menuRule.setTagId(GsonHelper.getString(json, "group_id"));
menuRule.setSex(GsonHelper.getString(json, "sex"));
menuRule.setCountry(GsonHelper.getString(json, "country"));
menuRule.setProvince(GsonHelper.getString(json, "province"));
menuRule.setCity(GsonHelper.getString(json, "city"));
menuRule.setClientPlatformType(GsonHelper.getString(json, "client_platform_type"));
menuRule.setLanguage(GsonHelper.getString(json, "language"));
return menuRule;
}

@Override @Override
public WxMenu deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { public WxMenu deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
/* /*
@@ -84,8 +90,7 @@ public class WxMenuGsonAdapter implements JsonSerializer<WxMenu>, JsonDeserializ
* 查询菜单时是 { menu : { button : ... } } * 查询菜单时是 { menu : { button : ... } }
*/ */
WxMenu menu = new WxMenu(); WxMenu menu = new WxMenu();
JsonObject menuJson = json.getAsJsonObject().get("menu").getAsJsonObject();
JsonArray buttonsJson = menuJson.get("button").getAsJsonArray();
JsonArray buttonsJson = json.getAsJsonObject().get("menu").getAsJsonObject().get("button").getAsJsonArray();
for (int i = 0; i < buttonsJson.size(); i++) { for (int i = 0; i < buttonsJson.size(); i++) {
JsonObject buttonJson = buttonsJson.get(i).getAsJsonObject(); JsonObject buttonJson = buttonsJson.get(i).getAsJsonObject();
WxMenuButton button = convertFromJson(buttonJson); WxMenuButton button = convertFromJson(buttonJson);


+ 67
- 61
weixin-java-cp/pom.xml View File

@@ -1,68 +1,74 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<project <project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-parent</artifactId>
<version>2.4.4-beta</version>
</parent>
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-parent</artifactId>
<version>2.6.0-SNAPSHOT</version>
</parent>


<artifactId>weixin-java-cp</artifactId>
<name>WeiXin Java Tools - CP</name>
<description>微信企业号Java SDK</description>
<artifactId>weixin-java-cp</artifactId>
<name>WeiXin Java Tools - CP</name>
<description>微信企业号Java SDK</description>


<dependencies>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencies>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
<optional>true</optional>
</dependency>
</dependencies>


<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>src/test/resources/testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
</plugins>
</build>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>src/test/resources/testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
</plugins>
</build>


</project> </project>

+ 3
- 3
weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpServiceImpl.java View File

@@ -166,12 +166,12 @@ public class WxCpServiceImpl implements WxCpService {
); );
WxJsapiSignature jsapiSignature = new WxJsapiSignature(); WxJsapiSignature jsapiSignature = new WxJsapiSignature();
jsapiSignature.setTimestamp(timestamp); jsapiSignature.setTimestamp(timestamp);
jsapiSignature.setNoncestr(noncestr);
jsapiSignature.setNonceStr(noncestr);
jsapiSignature.setUrl(url); jsapiSignature.setUrl(url);
jsapiSignature.setSignature(signature); jsapiSignature.setSignature(signature);


// Fixed bug // Fixed bug
jsapiSignature.setAppid(this.configStorage.getCorpId());
jsapiSignature.setAppId(this.configStorage.getCorpId());


return jsapiSignature; return jsapiSignature;
} }
@@ -491,7 +491,7 @@ public class WxCpServiceImpl implements WxCpService {
String responseText = get(url, null); String responseText = get(url, null);
JsonElement je = new JsonParser().parse(responseText); JsonElement je = new JsonParser().parse(responseText);
JsonObject jo = je.getAsJsonObject(); JsonObject jo = je.getAsJsonObject();
return new String[]{GsonHelper.getString(jo, "UserId"), GsonHelper.getString(jo, "DeviceId")};
return new String[]{GsonHelper.getString(jo, "UserId"), GsonHelper.getString(jo, "DeviceId"), GsonHelper.getString(jo, "OpenId")};
} }


@Override @Override


+ 77
- 67
weixin-java-mp/pom.xml View File

@@ -1,73 +1,83 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<project <project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-parent</artifactId>
<version>2.4.4-beta</version>
</parent>
<artifactId>weixin-java-mp</artifactId>
<name>WeiXin Java Tools - MP</name>
<description>微信公众号Java SDK</description>
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-parent</artifactId>
<version>2.6.0-SNAPSHOT</version>
</parent>
<artifactId>weixin-java-mp</artifactId>
<name>WeiXin Java Tools - MP</name>
<description>微信公众号Java SDK</description>


<dependencies>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.9.4</version>
<scope>test</scope>
</dependency>
</dependencies>
<dependencies>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.9.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>xml-path</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>qrcode-utils</artifactId>
<version>1.0</version>
</dependency>
</dependencies>


<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>src/test/resources/testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
</plugins>
</build>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>src/test/resources/testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
</plugins>
</build>


</project> </project>

+ 28
- 11
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpConfigStorage.java View File

@@ -4,14 +4,13 @@ import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.common.util.http.ApacheHttpClientBuilder; import me.chanjar.weixin.common.util.http.ApacheHttpClientBuilder;


import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;

import java.io.File; import java.io.File;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;


/** /**
* 微信客户端配置存储 * 微信客户端配置存储
* @author chanjarster
* *
* @author chanjarster
*/ */
public interface WxMpConfigStorage { public interface WxMpConfigStorage {


@@ -28,13 +27,15 @@ public interface WxMpConfigStorage {


/** /**
* 应该是线程安全的 * 应该是线程安全的
*
* @param accessToken 要更新的WxAccessToken对象 * @param accessToken 要更新的WxAccessToken对象
*/ */
void updateAccessToken(WxAccessToken accessToken); void updateAccessToken(WxAccessToken accessToken);


/** /**
* 应该是线程安全的 * 应该是线程安全的
* @param accessToken 新的accessToken值
*
* @param accessToken 新的accessToken值
* @param expiresInSeconds 过期时间,以秒为单位 * @param expiresInSeconds 过期时间,以秒为单位
*/ */
void updateAccessToken(String accessToken, int expiresInSeconds); void updateAccessToken(String accessToken, int expiresInSeconds);
@@ -52,7 +53,8 @@ public interface WxMpConfigStorage {


/** /**
* 应该是线程安全的 * 应该是线程安全的
* @param jsapiTicket 新的jsapi ticket值
*
* @param jsapiTicket 新的jsapi ticket值
* @param expiresInSeconds 过期时间,以秒为单位 * @param expiresInSeconds 过期时间,以秒为单位
*/ */
void updateJsapiTicket(String jsapiTicket, int expiresInSeconds); void updateJsapiTicket(String jsapiTicket, int expiresInSeconds);
@@ -70,7 +72,8 @@ public interface WxMpConfigStorage {


/** /**
* 应该是线程安全的 * 应该是线程安全的
* @param cardApiTicket 新的cardApi ticket值
*
* @param cardApiTicket 新的cardApi ticket值
* @param expiresInSeconds 过期时间,以秒为单位 * @param expiresInSeconds 过期时间,以秒为单位
*/ */
void updateCardApiTicket(String cardApiTicket, int expiresInSeconds); void updateCardApiTicket(String cardApiTicket, int expiresInSeconds);
@@ -82,21 +85,21 @@ public interface WxMpConfigStorage {
String getPartnerId(); String getPartnerId();


String getPartnerKey(); String getPartnerKey();
/** /**
* 微信支付异步回掉地址,通知url必须为直接可访问的url,不能携带参数。 * 微信支付异步回掉地址,通知url必须为直接可访问的url,不能携带参数。
*
* @since 2.5.0 * @since 2.5.0
* @return
*/ */
String getNotifyURL(); String getNotifyURL();
/** /**
* 交易类型 * 交易类型
* <pre> * <pre>
* JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付 * JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付
* </pre> * </pre>
*
* @since 2.5.0 * @since 2.5.0
* @return
*/ */
String getTradeType(); String getTradeType();


@@ -118,10 +121,20 @@ public interface WxMpConfigStorage {


File getTmpDirFile(); File getTmpDirFile();


SSLContext getSSLContext();
SSLContext getSslContext();

void setSslContext(SSLContext sslContext);

/**
* 在此之前,必须将partnerId进行赋值
*
* @param filePath apiclient_cert.p12的文件的绝对路径
*/
void setSslContextFilePath(String filePath) throws Exception;


/** /**
* http client builder * http client builder
*
* @return ApacheHttpClientBuilder * @return ApacheHttpClientBuilder
*/ */
ApacheHttpClientBuilder getApacheHttpClientBuilder(); ApacheHttpClientBuilder getApacheHttpClientBuilder();
@@ -130,5 +143,9 @@ public interface WxMpConfigStorage {
* 是否自动刷新token * 是否自动刷新token
*/ */
boolean autoRefreshToken(); boolean autoRefreshToken();

/**
* 微信支付是否使用仿真测试环境
*/
boolean useSandboxForWxPay();
} }

+ 77
- 46
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java View File

@@ -3,16 +3,19 @@ package me.chanjar.weixin.mp.api;
import me.chanjar.weixin.common.bean.WxAccessToken; import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.common.util.ToStringUtils; import me.chanjar.weixin.common.util.ToStringUtils;
import me.chanjar.weixin.common.util.http.ApacheHttpClientBuilder; import me.chanjar.weixin.common.util.http.ApacheHttpClientBuilder;
import org.apache.http.ssl.SSLContexts;


import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;


/** /**
* 基于内存的微信配置provider,在实际生产环境中应该将这些配置持久化 * 基于内存的微信配置provider,在实际生产环境中应该将这些配置持久化
* @author chanjarster
* *
* @author chanjarster
*/ */
public class WxMpInMemoryConfigStorage implements WxMpConfigStorage { public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {


@@ -58,6 +61,10 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
return this.accessToken; return this.accessToken;
} }


public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}

@Override @Override
public Lock getAccessTokenLock() { public Lock getAccessTokenLock() {
return this.accessTokenLock; return this.accessTokenLock;
@@ -89,15 +96,15 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
return this.jsapiTicket; return this.jsapiTicket;
} }


public void setJsapiTicket(String jsapiTicket) {
this.jsapiTicket = jsapiTicket;
}

@Override @Override
public Lock getJsapiTicketLock() { public Lock getJsapiTicketLock() {
return this.jsapiTicketLock; return this.jsapiTicketLock;
} }


public void setJsapiTicket(String jsapiTicket) {
this.jsapiTicket = jsapiTicket;
}

public long getJsapiTicketExpiresTime() { public long getJsapiTicketExpiresTime() {
return this.jsapiTicketExpiresTime; return this.jsapiTicketExpiresTime;
} }
@@ -158,31 +165,35 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
return this.appId; return this.appId;
} }


public void setAppId(String appId) {
this.appId = appId;
}

@Override @Override
public String getSecret() { public String getSecret() {
return this.secret; return this.secret;
} }


public void setSecret(String secret) {
this.secret = secret;
}

@Override @Override
public String getToken() { public String getToken() {
return this.token; return this.token;
} }


public void setToken(String token) {
this.token = token;
}

@Override @Override
public long getExpiresTime() { public long getExpiresTime() {
return this.expiresTime; return this.expiresTime;
} }


public void setAppId(String appId) {
this.appId = appId;
}

public void setSecret(String secret) {
this.secret = secret;
}

public void setToken(String token) {
this.token = token;
public void setExpiresTime(long expiresTime) {
this.expiresTime = expiresTime;
} }


@Override @Override
@@ -194,14 +205,6 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
this.aesKey = aesKey; this.aesKey = aesKey;
} }


public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}

public void setExpiresTime(long expiresTime) {
this.expiresTime = expiresTime;
}

@Override @Override
public String getOauth2redirectUri() { public String getOauth2redirectUri() {
return this.oauth2redirectUri; return this.oauth2redirectUri;
@@ -254,40 +257,40 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {


@Override @Override
public String getPartnerId() { public String getPartnerId() {
return this.partnerId;
return this.partnerId;
} }


public void setPartnerId(String partnerId) { public void setPartnerId(String partnerId) {
this.partnerId = partnerId;
this.partnerId = partnerId;
} }


@Override @Override
public String getPartnerKey() { public String getPartnerKey() {
return this.partnerKey;
return this.partnerKey;
} }


public void setPartnerKey(String partnerKey) { public void setPartnerKey(String partnerKey) {
this.partnerKey = partnerKey;
this.partnerKey = partnerKey;
} }
public String getNotifyURL() {
return notifyURL;
}


public void setNotifyURL(String notifyURL) {
this.notifyURL = notifyURL;
}


public String getTradeType() {
return tradeType;
}
public String getNotifyURL() {
return notifyURL;
}

public void setNotifyURL(String notifyURL) {
this.notifyURL = notifyURL;
}


public void setTradeType(String tradeType) {
this.tradeType = tradeType;
}
public String getTradeType() {
return tradeType;
}


@Override
public void setTradeType(String tradeType) {
this.tradeType = tradeType;
}

@Override
public File getTmpDirFile() { public File getTmpDirFile() {
return this.tmpDirFile; return this.tmpDirFile;
} }
@@ -297,25 +300,53 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
} }


@Override @Override
public SSLContext getSSLContext() {
public SSLContext getSslContext() {
return this.sslContext; return this.sslContext;
} }


public void setSSLContext(SSLContext context) {
@Override
public void setSslContext(SSLContext context) {
this.sslContext = context; this.sslContext = context;
} }


@Override
public void setSslContextFilePath(String filePath) {
if (null == partnerId) {
throw new IllegalArgumentException("请设置partnerId的值");
}

File file = new File(filePath);
if (!file.exists()) {
throw new RuntimeException("证书文件:【" + file.getPath() + "】不存在!");
}

try {
FileInputStream inputStream = new FileInputStream(file);
KeyStore keystore = KeyStore.getInstance("PKCS12");
char[] partnerId2charArray = partnerId.toCharArray();
keystore.load(inputStream, partnerId2charArray);
this.sslContext = SSLContexts.custom().loadKeyMaterial(keystore, partnerId2charArray).build();
} catch (Exception e) {
throw new RuntimeException("证书文件有问题,请核实!", e);
}
}

@Override @Override
public ApacheHttpClientBuilder getApacheHttpClientBuilder() { public ApacheHttpClientBuilder getApacheHttpClientBuilder() {
return this.apacheHttpClientBuilder; return this.apacheHttpClientBuilder;
} }


public void setApacheHttpClientBuilder(ApacheHttpClientBuilder apacheHttpClientBuilder) {
this.apacheHttpClientBuilder = apacheHttpClientBuilder;
}

@Override @Override
public boolean autoRefreshToken() { public boolean autoRefreshToken() {
return true; return true;
} }


public void setApacheHttpClientBuilder(ApacheHttpClientBuilder apacheHttpClientBuilder) {
this.apacheHttpClientBuilder = apacheHttpClientBuilder;
@Override
public boolean useSandboxForWxPay() {
return false;
} }
} }

+ 22
- 9
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMenuService.java View File

@@ -3,6 +3,7 @@ package me.chanjar.weixin.mp.api;
import me.chanjar.weixin.common.bean.menu.WxMenu; import me.chanjar.weixin.common.bean.menu.WxMenu;
import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.bean.menu.WxMpGetSelfMenuInfoResult; import me.chanjar.weixin.mp.bean.menu.WxMpGetSelfMenuInfoResult;
import me.chanjar.weixin.mp.bean.menu.WxMpMenu;


/** /**
* 菜单相关操作接口 * 菜单相关操作接口
@@ -14,17 +15,29 @@ public interface WxMpMenuService {
/** /**
* <pre> * <pre>
* 自定义菜单创建接口 * 自定义菜单创建接口
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=自定义菜单创建接口
* 详情请见:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141013&token=&lang=zh_CN
* 如果要创建个性化菜单,请设置matchrule属性 * 如果要创建个性化菜单,请设置matchrule属性
* 详情请见:http://mp.weixin.qq.com/wiki/0/c48ccd12b69ae023159b4bfaa7c39c20.html
* 详情请见:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455782296&token=&lang=zh_CN
* </pre> * </pre>
* @return 如果是个性化菜单,则返回menuid,否则返回null
*/ */
void menuCreate(WxMenu menu) throws WxErrorException;
String menuCreate(WxMenu menu) throws WxErrorException;

/**
* <pre>
* 自定义菜单创建接口
* 详情请见: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141013&token=&lang=zh_CN
* 如果要创建个性化菜单,请设置matchrule属性
* 详情请见:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455782296&token=&lang=zh_CN
* </pre>
* @return 如果是个性化菜单,则返回menuid,否则返回null
*/
String menuCreate(String json) throws WxErrorException;


/** /**
* <pre> * <pre>
* 自定义菜单删除接口 * 自定义菜单删除接口
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=自定义菜单删除接口
* 详情请见: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141015&token=&lang=zh_CN
* </pre> * </pre>
*/ */
void menuDelete() throws WxErrorException; void menuDelete() throws WxErrorException;
@@ -32,20 +45,20 @@ public interface WxMpMenuService {
/** /**
* <pre> * <pre>
* 删除个性化菜单接口 * 删除个性化菜单接口
* 详情请见: http://mp.weixin.qq.com/wiki/0/c48ccd12b69ae023159b4bfaa7c39c20.html
* 详情请见: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455782296&token=&lang=zh_CN
* </pre> * </pre>
* *
* @param menuid
* @param menuId 个性化菜单的menuid
*/ */
void menuDelete(String menuid) throws WxErrorException;
void menuDelete(String menuId) throws WxErrorException;


/** /**
* <pre> * <pre>
* 自定义菜单查询接口 * 自定义菜单查询接口
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=自定义菜单查询接口
* 详情请见: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141014&token=&lang=zh_CN
* </pre> * </pre>
*/ */
WxMenu menuGet() throws WxErrorException;
WxMpMenu menuGet() throws WxErrorException;


/** /**
* <pre> * <pre>


+ 74
- 19
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java View File

@@ -1,10 +1,7 @@
package me.chanjar.weixin.mp.api; package me.chanjar.weixin.mp.api;


import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.bean.pay.request.WxEntPayRequest;
import me.chanjar.weixin.mp.bean.pay.request.WxPayRefundRequest;
import me.chanjar.weixin.mp.bean.pay.request.WxPaySendRedpackRequest;
import me.chanjar.weixin.mp.bean.pay.request.WxPayUnifiedOrderRequest;
import me.chanjar.weixin.mp.bean.pay.request.*;
import me.chanjar.weixin.mp.bean.pay.result.*; import me.chanjar.weixin.mp.bean.pay.result.*;


import java.io.File; import java.io.File;
@@ -31,7 +28,7 @@ public interface WxMpPayService {
* </pre> * </pre>
* *
* @param transactionId 微信订单号 * @param transactionId 微信订单号
* @param outTradeNo 商户系统内部的订单号,当没提供transaction_id时需要传这个。
* @param outTradeNo 商户系统内部的订单号,当没提供transactionId时需要传这个。
*/ */
WxPayOrderQueryResult queryOrder(String transactionId, String outTradeNo) throws WxErrorException; WxPayOrderQueryResult queryOrder(String transactionId, String outTradeNo) throws WxErrorException;


@@ -47,7 +44,7 @@ public interface WxMpPayService {
* 是否需要证书: 不需要。 * 是否需要证书: 不需要。
* </pre> * </pre>
* *
* @param outTradeNo 商户系统内部的订单号,当没提供transaction_id时需要传这个。
* @param outTradeNo 商户系统内部的订单号
*/ */
WxPayOrderCloseResult closeOrder(String outTradeNo) throws WxErrorException; WxPayOrderCloseResult closeOrder(String outTradeNo) throws WxErrorException;


@@ -76,10 +73,9 @@ public interface WxMpPayService {
* </pre> * </pre>
* *
* @param request 请求对象 * @param request 请求对象
* @param keyFile 证书文件对象(即apiclient_cert.p12 商户证书文件,详细参考https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3)
* @return 退款操作结果 * @return 退款操作结果
*/ */
WxPayRefundResult refund(WxPayRefundRequest request, File keyFile) throws WxErrorException;
WxPayRefundResult refund(WxPayRefundRequest request) throws WxErrorException;


/** /**
* <pre> * <pre>
@@ -128,7 +124,7 @@ public interface WxMpPayService {
/** /**
* 微信公众号支付签名算法(详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=4_3) * 微信公众号支付签名算法(详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=4_3)
* *
* @param prams 参数信息,默认使用配置中的PartnerKey进行签名
* @param prams 参数信息,默认使用配置中的PartnerKey进行签名
* @return 签名字符串 * @return 签名字符串
* @see #createSign(Map, String) * @see #createSign(Map, String)
*/ */
@@ -176,14 +172,13 @@ public interface WxMpPayService {
/** /**
* 校验签名是否正确 * 校验签名是否正确
* *
* @param params 需要校验的参数Map
* @param params 需要校验的参数Map
* @param signKey 校验的签名Key * @param signKey 校验的签名Key
* @return true - 签名校验成功,false - 签名校验失败 * @return true - 签名校验成功,false - 签名校验失败
* @see #checkSign(Map, String) * @see #checkSign(Map, String)
*/ */
boolean checkSign(Map<String, String> params, String signKey); boolean checkSign(Map<String, String> params, String signKey);



/** /**
* 发送微信红包给个人用户 * 发送微信红包给个人用户
* <pre> * <pre>
@@ -195,9 +190,8 @@ public interface WxMpPayService {
* </pre> * </pre>
* *
* @param request 请求对象 * @param request 请求对象
* @param keyFile 证书文件对象(即apiclient_cert.p12 商户证书文件,详细参考https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3)
*/ */
WxPaySendRedpackResult sendRedpack(WxPaySendRedpackRequest request, File keyFile) throws WxErrorException;
WxPaySendRedpackResult sendRedpack(WxPaySendRedpackRequest request) throws WxErrorException;


/** /**
* <pre> * <pre>
@@ -209,9 +203,8 @@ public interface WxMpPayService {
* </pre> * </pre>
* *
* @param mchBillNo 商户发放红包的商户订单号,比如10000098201411111234567890 * @param mchBillNo 商户发放红包的商户订单号,比如10000098201411111234567890
* @param keyFile 证书文件对象(即apiclient_cert.p12 商户证书文件,详细参考https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3)
*/ */
WxPayRedpackQueryResult queryRedpack(String mchBillNo, File keyFile) throws WxErrorException;
WxPayRedpackQueryResult queryRedpack(String mchBillNo) throws WxErrorException;


/** /**
* <pre> * <pre>
@@ -224,9 +217,8 @@ public interface WxMpPayService {
* </pre> * </pre>
* *
* @param request 请求对象 * @param request 请求对象
* @param keyFile 证书文件对象(即apiclient_cert.p12 商户证书文件,详细参考https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3)
*/ */
WxEntPayResult entPay(WxEntPayRequest request, File keyFile) throws WxErrorException;
WxEntPayResult entPay(WxEntPayRequest request) throws WxErrorException;


/** /**
* <pre> * <pre>
@@ -237,8 +229,71 @@ public interface WxMpPayService {
* </pre> * </pre>
* *
* @param partnerTradeNo 商户订单号 * @param partnerTradeNo 商户订单号
* @param keyFile 证书文件对象(即apiclient_cert.p12 商户证书文件,详细参考https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3)
*/ */
WxEntPayQueryResult queryEntPay(String partnerTradeNo, File keyFile) throws WxErrorException;
WxEntPayQueryResult queryEntPay(String partnerTradeNo) throws WxErrorException;

/**
* <pre>
* 扫码支付模式一生成二维码的方法
* 二维码中的内容为链接,形式为:
* weixin://wxpay/bizpayurl?sign=XXXXX&appid=XXXXX&mch_id=XXXXX&product_id=XXXXXX&time_stamp=XXXXXX&nonce_str=XXXXX
* 其中XXXXX为商户需要填写的内容,商户将该链接生成二维码,如需要打印发布二维码,需要采用此格式。商户可调用第三方库生成二维码图片。
* 文档详见: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4
* </pre>
*
* @param productId 产品Id
* @param sideLength 要生成的二维码的边长,如果为空,则取默认值400
* @param logoFile 商户logo图片的文件对象,可以为空
* @return 生成的二维码的字节数组
*/
byte[] createScanPayQrcodeMode1(String productId, File logoFile, Integer sideLength);

/**
* <pre>
* 扫码支付模式二生成二维码的方法
* 对应链接格式:weixin://wxpay/bizpayurl?sr=XXXXX。请商户调用第三方库将code_url生成二维码图片。
* 该模式链接较短,生成的二维码打印到结账小票上的识别率较高。
* 文档详见: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5
* </pre>
*
* @param codeUrl 微信返回的交易会话的二维码链接
* @param logoFile 商户logo图片的文件对象,可以为空
* @param sideLength 要生成的二维码的边长,如果为空,则取默认值400
* @return 生成的二维码的字节数组
*/
byte[] createScanPayQrcodeMode2(String codeUrl, File logoFile, Integer sideLength);

/**
* <pre>
* 交易保障
* 应用场景:
* 商户在调用微信支付提供的相关接口时,会得到微信支付返回的相关信息以及获得整个接口的响应时间。
* 为提高整体的服务水平,协助商户一起提高服务质量,微信支付提供了相关接口调用耗时和返回信息的主动上报接口,
* 微信支付可以根据商户侧上报的数据进一步优化网络部署,完善服务监控,和商户更好的协作为用户提供更好的业务体验。
* 接口地址: https://api.mch.weixin.qq.com/payitil/report
* 是否需要证书:不需要
* </pre>
*/
void report(WxPayReportRequest request) throws WxErrorException;


/**
* <pre>
* 下载对账单
* 商户可以通过该接口下载历史交易清单。比如掉单、系统错误等导致商户侧和微信侧数据不一致,通过对账单核对后可校正支付状态。
* 注意:
* 1、微信侧未成功下单的交易不会出现在对账单中。支付成功后撤销的交易会出现在对账单中,跟原支付单订单号一致,bill_type为REVOKED;
* 2、微信在次日9点启动生成前一天的对账单,建议商户10点后再获取;
* 3、对账单中涉及金额的字段单位为“元”。
* 4、对账单接口只能下载三个月以内的账单。
* 接口链接:https://api.mch.weixin.qq.com/pay/downloadbill
* 详情请见: <a href="https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_6">下载对账单</a>
* </pre>
*
* @param billDate 对账单日期 bill_date 下载对账单的日期,格式:20140603
* @param billType 账单类型 bill_type ALL,返回当日所有订单信息,默认值,SUCCESS,返回当日成功支付的订单,REFUND,返回当日退款订单
* @param tarType 压缩账单 tar_type 非必传参数,固定值:GZIP,返回格式为.gzip的压缩包账单。不传则默认为数据流形式。
* @param deviceInfo 设备号 device_info 非必传参数,终端设备号
* @return 保存到本地的临时文件
*/
File downloadBill(String billDate, String billType, String tarType, String deviceInfo) throws WxErrorException;
} }

+ 14
- 14
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpQrcodeService.java View File

@@ -7,7 +7,7 @@ import java.io.File;


/** /**
* 二维码相关操作接口 * 二维码相关操作接口
*
* 文档地址:https://mp.weixin.qq.com/wiki?action=doc&id=mp1443433542&t=0.9274944716856435
* @author Binary Wang * @author Binary Wang
*/ */
public interface WxMpQrcodeService { public interface WxMpQrcodeService {
@@ -15,38 +15,38 @@ public interface WxMpQrcodeService {
/** /**
* <pre> * <pre>
* 换取临时二维码ticket * 换取临时二维码ticket
* 详情请见: <a href="http://mp.weixin.qq.com/wiki/18/167e7d94df85d8389df6c94a7a8f78ba.html">生成带参数的二维码</a>
* 详情请见: <a href="https://mp.weixin.qq.com/wiki?action=doc&id=mp1443433542&t=0.9274944716856435">生成带参数的二维码</a>
* </pre> * </pre>
* *
* @param scene_id 参数。
* @param expire_seconds 过期秒数,默认60秒,最小60秒,最大1800秒
* @param sceneId 场景值ID,临时二维码时为32位非0整型
* @param expireSeconds 该二维码有效时间,以秒为单位。 最大不超过2592000(即30天),此字段如果不填,则默认有效期为30秒。
*/ */
WxMpQrCodeTicket qrCodeCreateTmpTicket(int scene_id, Integer expire_seconds) throws WxErrorException;
WxMpQrCodeTicket qrCodeCreateTmpTicket(int sceneId, Integer expireSeconds) throws WxErrorException;


/** /**
* <pre> * <pre>
* 换取永久二维码ticket * 换取永久二维码ticket
* 详情请见: <a href="http://mp.weixin.qq.com/wiki/18/167e7d94df85d8389df6c94a7a8f78ba.html">生成带参数的二维码</a>
* 详情请见: <a href="https://mp.weixin.qq.com/wiki?action=doc&id=mp1443433542&t=0.9274944716856435">生成带参数的二维码</a>
* </pre> * </pre>
* *
* @param scene_id 参数。永久二维码时最大值为100000(目前参数只支持1--100000)
* @param sceneId 场景值ID,最大值为100000(目前参数只支持1--100000)
*/ */
WxMpQrCodeTicket qrCodeCreateLastTicket(int scene_id) throws WxErrorException;
WxMpQrCodeTicket qrCodeCreateLastTicket(int sceneId) throws WxErrorException;


/** /**
* <pre> * <pre>
* 换取永久字符串二维码ticket * 换取永久字符串二维码ticket
* 详情请见: <a href="http://mp.weixin.qq.com/wiki/18/167e7d94df85d8389df6c94a7a8f78ba.html">生成带参数的二维码</a>
* 详情请见: <a href="https://mp.weixin.qq.com/wiki?action=doc&id=mp1443433542&t=0.9274944716856435">生成带参数的二维码</a>
* </pre> * </pre>
* *
* @param scene_str 参数。字符串类型长度现在为1到64
* @param sceneStr 参数。字符串类型长度现在为1到64
*/ */
WxMpQrCodeTicket qrCodeCreateLastTicket(String scene_str) throws WxErrorException;
WxMpQrCodeTicket qrCodeCreateLastTicket(String sceneStr) throws WxErrorException;


/** /**
* <pre> * <pre>
* 换取二维码图片文件,jpg格式 * 换取二维码图片文件,jpg格式
* 详情请见: <a href="http://mp.weixin.qq.com/wiki/18/167e7d94df85d8389df6c94a7a8f78ba.html">生成带参数的二维码</a>
* 详情请见: <a href="https://mp.weixin.qq.com/wiki?action=doc&id=mp1443433542&t=0.9274944716856435">生成带参数的二维码</a>
* </pre> * </pre>
* *
* @param ticket 二维码ticket * @param ticket 二维码ticket
@@ -56,7 +56,7 @@ public interface WxMpQrcodeService {
/** /**
* <pre> * <pre>
* 换取二维码图片url地址(可以选择是否生成压缩的网址) * 换取二维码图片url地址(可以选择是否生成压缩的网址)
* 详情请见: <a href="http://mp.weixin.qq.com/wiki/18/167e7d94df85d8389df6c94a7a8f78ba.html">生成带参数的二维码</a>
* 详情请见: <a href="https://mp.weixin.qq.com/wiki?action=doc&id=mp1443433542&t=0.9274944716856435">生成带参数的二维码</a>
* </pre> * </pre>
* *
* @param ticket 二维码ticket * @param ticket 二维码ticket
@@ -67,7 +67,7 @@ public interface WxMpQrcodeService {
/** /**
* <pre> * <pre>
* 换取二维码图片url地址 * 换取二维码图片url地址
* 详情请见: <a href="http://mp.weixin.qq.com/wiki/18/167e7d94df85d8389df6c94a7a8f78ba.html">生成带参数的二维码</a>
* 详情请见: <a href="https://mp.weixin.qq.com/wiki?action=doc&id=mp1443433542&t=0.9274944716856435">生成带参数的二维码</a>
* </pre> * </pre>
* *
* @param ticket 二维码ticket * @param ticket 二维码ticket


+ 39
- 10
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMenuServiceImpl.java View File

@@ -1,10 +1,13 @@
package me.chanjar.weixin.mp.api.impl; package me.chanjar.weixin.mp.api.impl;


import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import me.chanjar.weixin.common.bean.menu.WxMenu; import me.chanjar.weixin.common.bean.menu.WxMenu;
import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpMenuService; import me.chanjar.weixin.mp.api.WxMpMenuService;
import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.menu.WxMpGetSelfMenuInfoResult; import me.chanjar.weixin.mp.bean.menu.WxMpGetSelfMenuInfoResult;
import me.chanjar.weixin.mp.bean.menu.WxMpMenu;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;


@@ -13,8 +16,7 @@ import org.slf4j.LoggerFactory;
*/ */
public class WxMpMenuServiceImpl implements WxMpMenuService { public class WxMpMenuServiceImpl implements WxMpMenuService {
private static final String API_URL_PREFIX = "https://api.weixin.qq.com/cgi-bin/menu"; private static final String API_URL_PREFIX = "https://api.weixin.qq.com/cgi-bin/menu";
private static Logger log = LoggerFactory
.getLogger(WxMpMenuServiceImpl.class);
private static Logger log = LoggerFactory.getLogger(WxMpMenuServiceImpl.class);


private WxMpService wxMpService; private WxMpService wxMpService;


@@ -23,7 +25,7 @@ public class WxMpMenuServiceImpl implements WxMpMenuService {
} }


@Override @Override
public void menuCreate(WxMenu menu) throws WxErrorException {
public String menuCreate(WxMenu menu) throws WxErrorException {
String menuJson = menu.toJson(); String menuJson = menu.toJson();
String url = API_URL_PREFIX + "/create"; String url = API_URL_PREFIX + "/create";
if (menu.getMatchRule() != null) { if (menu.getMatchRule() != null) {
@@ -34,6 +36,29 @@ public class WxMpMenuServiceImpl implements WxMpMenuService {


String result = this.wxMpService.post(url, menuJson); String result = this.wxMpService.post(url, menuJson);
log.debug("创建菜单:{},结果:{}", menuJson, result); log.debug("创建菜单:{},结果:{}", menuJson, result);

if (menu.getMatchRule() != null) {
return new JsonParser().parse(result).getAsJsonObject().get("menuid").getAsString();
}

return null;
}

@Override
public String menuCreate(String json) throws WxErrorException {
JsonParser jsonParser = new JsonParser();
JsonObject jsonObject = jsonParser.parse(json).getAsJsonObject();
String url = API_URL_PREFIX + "/create";
if (jsonObject.get("matchrule") != null) {
url = API_URL_PREFIX + "/addconditional";
}

String result = this.wxMpService.post(url, json);
if (jsonObject.get("matchrule") != null) {
return jsonParser.parse(result).getAsJsonObject().get("menuid").getAsString();
}

return null;
} }


@Override @Override
@@ -44,18 +69,20 @@ public class WxMpMenuServiceImpl implements WxMpMenuService {
} }


@Override @Override
public void menuDelete(String menuid) throws WxErrorException {
public void menuDelete(String menuId) throws WxErrorException {
String url = API_URL_PREFIX + "/delconditional"; String url = API_URL_PREFIX + "/delconditional";
String result = this.wxMpService.get(url, "menuid=" + menuid);
log.debug("根据MeunId({})删除菜单结果:{}", menuid, result);
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("menuid", menuId);
String result = this.wxMpService.post(url, jsonObject.toString());
log.debug("根据MeunId({})删除个性化菜单结果:{}", menuId, result);
} }


@Override @Override
public WxMenu menuGet() throws WxErrorException {
public WxMpMenu menuGet() throws WxErrorException {
String url = API_URL_PREFIX + "/get"; String url = API_URL_PREFIX + "/get";
try { try {
String resultContent = this.wxMpService.get(url, null); String resultContent = this.wxMpService.get(url, null);
return WxMenu.fromJson(resultContent);
return WxMpMenu.fromJson(resultContent);
} catch (WxErrorException e) { } catch (WxErrorException e) {
// 46003 不存在的菜单数据 // 46003 不存在的菜单数据
if (e.getError().getErrorCode() == 46003) { if (e.getError().getErrorCode() == 46003) {
@@ -68,11 +95,13 @@ public class WxMpMenuServiceImpl implements WxMpMenuService {
@Override @Override
public WxMenu menuTryMatch(String userid) throws WxErrorException { public WxMenu menuTryMatch(String userid) throws WxErrorException {
String url = API_URL_PREFIX + "/trymatch"; String url = API_URL_PREFIX + "/trymatch";
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("user_id", userid);
try { try {
String resultContent = this.wxMpService.get(url, "user_id=" + userid);
String resultContent = this.wxMpService.post(url, jsonObject.toString());
return WxMenu.fromJson(resultContent); return WxMenu.fromJson(resultContent);
} catch (WxErrorException e) { } catch (WxErrorException e) {
// 46003 不存在的菜单数据 46002 不存在的菜单版本
// 46003 不存在的菜单数据46002 不存在的菜单版本
if (e.getError().getErrorCode() == 46003 if (e.getError().getErrorCode() == 46003
|| e.getError().getErrorCode() == 46002) { || e.getError().getErrorCode() == 46002) {
return null; return null;


+ 172
- 117
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java View File

@@ -1,14 +1,13 @@
package me.chanjar.weixin.mp.api.impl; package me.chanjar.weixin.mp.api.impl;


import com.thoughtworks.xstream.XStream;
import com.github.binarywang.utils.qrcode.QrcodeUtils;
import com.google.common.collect.Maps;
import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.bean.result.WxError;
import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.util.BeanUtils; import me.chanjar.weixin.common.util.BeanUtils;
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
import me.chanjar.weixin.mp.api.WxMpConfigStorage; import me.chanjar.weixin.mp.api.WxMpConfigStorage;
import me.chanjar.weixin.mp.api.WxMpPayService; import me.chanjar.weixin.mp.api.WxMpPayService;
import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.pay.WxPayOrderNotifyResultConverter;
import me.chanjar.weixin.mp.bean.pay.request.*; import me.chanjar.weixin.mp.bean.pay.request.*;
import me.chanjar.weixin.mp.bean.pay.result.*; import me.chanjar.weixin.mp.bean.pay.result.*;
import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.DigestUtils;
@@ -23,16 +22,13 @@ import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity; import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils; import org.apache.http.util.EntityUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;


import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.security.KeyStore;
import java.util.*; import java.util.*;


/** /**
@@ -44,7 +40,8 @@ public class WxMpPayServiceImpl implements WxMpPayService {


private static final String PAY_BASE_URL = "https://api.mch.weixin.qq.com"; private static final String PAY_BASE_URL = "https://api.mch.weixin.qq.com";
private static final String[] TRADE_TYPES = new String[]{"JSAPI", "NATIVE", "APP"}; private static final String[] TRADE_TYPES = new String[]{"JSAPI", "NATIVE", "APP"};
private static final String[] REFUND_ACCOUNT = new String[]{"REFUND_SOURCE_RECHARGE_FUNDS","REFUND_SOURCE_UNSETTLED_FUNDS"};
private static final String[] REFUND_ACCOUNT = new String[]{"REFUND_SOURCE_RECHARGE_FUNDS", "REFUND_SOURCE_UNSETTLED_FUNDS"};
private static final String[] BILL_TYPE = new String[]{"ALL","REFUND","SUCCESS"};;
private final Logger log = LoggerFactory.getLogger(this.getClass()); private final Logger log = LoggerFactory.getLogger(this.getClass());
private WxMpService wxMpService; private WxMpService wxMpService;


@@ -56,22 +53,26 @@ public class WxMpPayServiceImpl implements WxMpPayService {
return wxMpService.getWxMpConfigStorage(); return wxMpService.getWxMpConfigStorage();
} }


private String getPayBaseUrl(){
if(this.getConfig().useSandboxForWxPay()){
return PAY_BASE_URL + "/sandboxnew";
}

return PAY_BASE_URL;
}

@Override @Override
public WxPayRefundResult refund(WxPayRefundRequest request, File keyFile) throws WxErrorException {
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxPayRefundRequest.class);
xstream.processAnnotations(WxPayRefundResult.class);
initRequest(request);
if(StringUtils.isBlank(request.getOpUserId())){
request.setOpUserId(getConfig().getPartnerId());
public WxPayRefundResult refund(WxPayRefundRequest request) throws WxErrorException {
this.initRequest(request);
if (StringUtils.isBlank(request.getOpUserId())) {
request.setOpUserId(this.getConfig().getPartnerId());
} }
checkParameters(request);
this.checkParameters(request);
request.setSign(this.createSign(request)); request.setSign(this.createSign(request));


String url = PAY_BASE_URL + "/secapi/pay/refund";
String responseContent = this.executeRequestWithKeyFile(url, keyFile, xstream.toXML(request), request.getMchId());
WxPayRefundResult result = (WxPayRefundResult) xstream.fromXML(responseContent);
String url = this.getPayBaseUrl() + "/secapi/pay/refund";
String responseContent = this.executeWithKey(url, request.toXML());
WxPayRefundResult result = WxPayRefundResult.fromXML(responseContent, WxPayRefundResult.class);
this.checkResult(result); this.checkResult(result);
return result; return result;
} }
@@ -83,22 +84,18 @@ public class WxMpPayServiceImpl implements WxMpPayService {
throw new IllegalArgumentException("transaction_id , out_trade_no,out_refund_no, refund_id 必须四选一"); throw new IllegalArgumentException("transaction_id , out_trade_no,out_refund_no, refund_id 必须四选一");
} }


XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxPayRefundQueryRequest.class);
xstream.processAnnotations(WxPayRefundQueryResult.class);

WxPayRefundQueryRequest request = new WxPayRefundQueryRequest(); WxPayRefundQueryRequest request = new WxPayRefundQueryRequest();
initRequest(request);
this.initRequest(request);
request.setOutTradeNo(StringUtils.trimToNull(outTradeNo)); request.setOutTradeNo(StringUtils.trimToNull(outTradeNo));
request.setTransactionId(StringUtils.trimToNull(transactionId)); request.setTransactionId(StringUtils.trimToNull(transactionId));
request.setOutRefundNo(StringUtils.trimToNull(outRefundNo)); request.setOutRefundNo(StringUtils.trimToNull(outRefundNo));
request.setRefundId(StringUtils.trimToNull(refundId)); request.setRefundId(StringUtils.trimToNull(refundId));
request.setSign(this.createSign(request)); request.setSign(this.createSign(request));


String url = PAY_BASE_URL + "/pay/refundquery";
String responseContent = this.executeRequest(url, xstream.toXML(request));
WxPayRefundQueryResult result = (WxPayRefundQueryResult) xstream.fromXML(responseContent);
result.composeRefundRecords(responseContent);
String url = this.getPayBaseUrl() + "/pay/refundquery";
String responseContent = this.executeRequest(url, request.toXML());
WxPayRefundQueryResult result = WxPayRefundQueryResult.fromXML(responseContent, WxPayRefundQueryResult.class);
result.composeRefundRecords();
this.checkResult(result); this.checkResult(result);
return result; return result;
} }
@@ -106,8 +103,9 @@ public class WxMpPayServiceImpl implements WxMpPayService {


private void checkResult(WxPayBaseResult result) throws WxErrorException { private void checkResult(WxPayBaseResult result) throws WxErrorException {
//校验返回结果签名 //校验返回结果签名
if (!checkSign(result.toMap())) {
log.debug("校验结果签名失败,参数:{}", result.toMap());
Map<String, String> map = result.toMap();
if (result.getSign() != null &&!this.checkSign(map)) {
log.debug("校验结果签名失败,参数:{}", map);
throw new WxErrorException(WxError.newBuilder().setErrorCode(-1).setErrorMsg("参数格式校验错误!").build()); throw new WxErrorException(WxError.newBuilder().setErrorCode(-1).setErrorMsg("参数格式校验错误!").build());
} }


@@ -119,11 +117,24 @@ public class WxMpPayServiceImpl implements WxMpPayService {
+ result.getReturnMsg() + ", 结果代码: " + result.getResultCode() + ", 错误代码: " + result.getReturnMsg() + ", 结果代码: " + result.getResultCode() + ", 错误代码: "
+ result.getErrCode() + ", 错误详情: " + result.getErrCodeDes()) + result.getErrCode() + ", 错误详情: " + result.getErrCodeDes())
.build(); .build();
log.error("结果业务代码异常,参数:{},详细:{}", result.toMap(), error);
log.error("结果业务代码异常,参数:{},详细:{}", map, error);
throw new WxErrorException(error); throw new WxErrorException(error);
} }
} }


private void checkParameters(WxPayDownloadBillRequest request) throws WxErrorException {
BeanUtils.checkRequiredFields(request);

if (StringUtils.isNotBlank(request.getTarType()) && !"GZIP".equals(request.getTarType())) {
throw new IllegalArgumentException("tar_type值如果存在,只能为GZIP");
}

if ( !ArrayUtils.contains(BILL_TYPE, request.getBillType())) {
throw new IllegalArgumentException("bill_tpye目前必须为" + Arrays.toString(BILL_TYPE) + "其中之一,实际值:" + request.getBillType());
}

}

private void checkParameters(WxPayRefundRequest request) throws WxErrorException { private void checkParameters(WxPayRefundRequest request) throws WxErrorException {
BeanUtils.checkRequiredFields(request); BeanUtils.checkRequiredFields(request);


@@ -142,10 +153,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
public WxPayOrderNotifyResult getOrderNotifyResult(String xmlData) throws WxErrorException { public WxPayOrderNotifyResult getOrderNotifyResult(String xmlData) throws WxErrorException {
try { try {
log.trace("微信支付回调参数详细:{}", xmlData); log.trace("微信支付回调参数详细:{}", xmlData);
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxPayOrderNotifyResult.class);
xstream.registerConverter(new WxPayOrderNotifyResultConverter(xstream.getMapper(), xstream.getReflectionProvider()));
WxPayOrderNotifyResult result = (WxPayOrderNotifyResult) xstream.fromXML(xmlData);
WxPayOrderNotifyResult result = WxPayOrderNotifyResult.fromXML(xmlData);
log.debug("微信支付回调结果对象:{}", result); log.debug("微信支付回调结果对象:{}", result);
this.checkResult(result); this.checkResult(result);
return result; return result;
@@ -158,43 +166,35 @@ public class WxMpPayServiceImpl implements WxMpPayService {
} }
} }



@Override @Override
public WxPaySendRedpackResult sendRedpack(WxPaySendRedpackRequest request, File keyFile)
public WxPaySendRedpackResult sendRedpack(WxPaySendRedpackRequest request)
throws WxErrorException { throws WxErrorException {
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxPaySendRedpackRequest.class);
xstream.processAnnotations(WxPaySendRedpackResult.class);

initRequest(request);
this.initRequest(request);
request.setSign(this.createSign(request)); request.setSign(this.createSign(request));


String url = PAY_BASE_URL + "/mmpaymkttransfers/sendredpack";
String url = this.getPayBaseUrl() + "/mmpaymkttransfers/sendredpack";
if (request.getAmtType() != null) { if (request.getAmtType() != null) {
//裂变红包 //裂变红包
url = PAY_BASE_URL + "/mmpaymkttransfers/sendgroupredpack";
url = this.getPayBaseUrl() + "/mmpaymkttransfers/sendgroupredpack";
} }
String responseContent = this.executeRequestWithKeyFile(url, keyFile, xstream.toXML(request), request.getMchId());
WxPaySendRedpackResult result = (WxPaySendRedpackResult) xstream.fromXML(responseContent);
this.checkResult(result);
String responseContent = this.executeWithKey(url, request.toXML());
WxPaySendRedpackResult result = WxPaySendRedpackResult.fromXML(responseContent, WxPaySendRedpackResult.class);
//毋须校验,因为没有返回签名信息
// this.checkResult(result);
return result; return result;
} }


@Override @Override
public WxPayRedpackQueryResult queryRedpack(String mchBillNo, File keyFile) throws WxErrorException {
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxPayRedpackQueryRequest.class);
xstream.processAnnotations(WxPayRedpackQueryResult.class);

public WxPayRedpackQueryResult queryRedpack(String mchBillNo) throws WxErrorException {
WxPayRedpackQueryRequest request = new WxPayRedpackQueryRequest(); WxPayRedpackQueryRequest request = new WxPayRedpackQueryRequest();
request.setMchBillNo(mchBillNo); request.setMchBillNo(mchBillNo);
request.setBillType("MCHT"); request.setBillType("MCHT");
initRequest(request); initRequest(request);
request.setSign(this.createSign(request)); request.setSign(this.createSign(request));


String url = PAY_BASE_URL + "/mmpaymkttransfers/gethbinfo";
String responseContent = this.executeRequestWithKeyFile(url, keyFile, xstream.toXML(request), request.getMchId());
WxPayRedpackQueryResult result = (WxPayRedpackQueryResult) xstream.fromXML(responseContent);
String url = this.getPayBaseUrl() + "/mmpaymkttransfers/gethbinfo";
String responseContent = this.executeWithKey(url, request.toXML());
WxPayRedpackQueryResult result = WxPayRedpackQueryResult.fromXML(responseContent, WxPayRedpackQueryResult.class);
this.checkResult(result); this.checkResult(result);
return result; return result;
} }
@@ -206,20 +206,16 @@ public class WxMpPayServiceImpl implements WxMpPayService {
throw new IllegalArgumentException("transaction_id 和 out_trade_no 不能同时存在或同时为空,必须二选一"); throw new IllegalArgumentException("transaction_id 和 out_trade_no 不能同时存在或同时为空,必须二选一");
} }


XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxPayOrderQueryRequest.class);
xstream.processAnnotations(WxPayOrderQueryResult.class);

WxPayOrderQueryRequest request = new WxPayOrderQueryRequest(); WxPayOrderQueryRequest request = new WxPayOrderQueryRequest();
request.setOutTradeNo(StringUtils.trimToNull(outTradeNo)); request.setOutTradeNo(StringUtils.trimToNull(outTradeNo));
request.setTransactionId(StringUtils.trimToNull(transactionId)); request.setTransactionId(StringUtils.trimToNull(transactionId));
initRequest(request); initRequest(request);
request.setSign(this.createSign(request)); request.setSign(this.createSign(request));


String url = PAY_BASE_URL + "/pay/orderquery";
String responseContent = this.executeRequest(url, xstream.toXML(request));
WxPayOrderQueryResult result = (WxPayOrderQueryResult) xstream.fromXML(responseContent);
result.composeCoupons(responseContent);
String url = this.getPayBaseUrl() + "/pay/orderquery";
String responseContent = this.executeRequest(url, request.toXML());
WxPayOrderQueryResult result = WxPayOrderQueryResult.fromXML(responseContent, WxPayOrderQueryResult.class);
result.composeCoupons();
this.checkResult(result); this.checkResult(result);
return result; return result;
} }
@@ -230,18 +226,14 @@ public class WxMpPayServiceImpl implements WxMpPayService {
throw new IllegalArgumentException("out_trade_no 不能为空"); throw new IllegalArgumentException("out_trade_no 不能为空");
} }


XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxPayOrderCloseRequest.class);
xstream.processAnnotations(WxPayOrderCloseResult.class);

WxPayOrderCloseRequest request = new WxPayOrderCloseRequest(); WxPayOrderCloseRequest request = new WxPayOrderCloseRequest();
request.setOutTradeNo(StringUtils.trimToNull(outTradeNo)); request.setOutTradeNo(StringUtils.trimToNull(outTradeNo));
initRequest(request); initRequest(request);
request.setSign(this.createSign(request)); request.setSign(this.createSign(request));


String url = PAY_BASE_URL + "/pay/closeorder";
String responseContent = this.executeRequest(url, xstream.toXML(request));
WxPayOrderCloseResult result = (WxPayOrderCloseResult) xstream.fromXML(responseContent);
String url = this.getPayBaseUrl() + "/pay/closeorder";
String responseContent = this.executeRequest(url, request.toXML());
WxPayOrderCloseResult result = WxPayOrderCloseResult.fromXML(responseContent, WxPayOrderCloseResult.class);
this.checkResult(result); this.checkResult(result);


return result; return result;
@@ -251,39 +243,35 @@ public class WxMpPayServiceImpl implements WxMpPayService {
public WxPayUnifiedOrderResult unifiedOrder(WxPayUnifiedOrderRequest request) public WxPayUnifiedOrderResult unifiedOrder(WxPayUnifiedOrderRequest request)
throws WxErrorException { throws WxErrorException {


XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxPayUnifiedOrderRequest.class);
xstream.processAnnotations(WxPayUnifiedOrderResult.class);
initRequest(request);
if(StringUtils.isBlank(request.getNotifyURL())){
this.initRequest(request);
if (StringUtils.isBlank(request.getNotifyURL())) {
request.setNotifyURL(getConfig().getNotifyURL()); request.setNotifyURL(getConfig().getNotifyURL());
} }
if(StringUtils.isBlank(request.getTradeType())){
if (StringUtils.isBlank(request.getTradeType())) {
request.setTradeType(getConfig().getTradeType()); request.setTradeType(getConfig().getTradeType());
} }
checkParameters(request);//校验参数 checkParameters(request);//校验参数
request.setSign(this.createSign(request)); request.setSign(this.createSign(request));
String url = PAY_BASE_URL + "/pay/unifiedorder";
String xmlParam = xstream.toXML(request);
String url = this.getPayBaseUrl() + "/pay/unifiedorder";
String xmlParam = request.toXML();
log.debug("微信统一下单接口,URL:{},参数:{}", url, xmlParam); log.debug("微信统一下单接口,URL:{},参数:{}", url, xmlParam);


String responseContent = this.executeRequest(url, xmlParam); String responseContent = this.executeRequest(url, xmlParam);
log.debug("微信统一下单接口,URL:{},结果:{}", url, responseContent); log.debug("微信统一下单接口,URL:{},结果:{}", url, responseContent);
WxPayUnifiedOrderResult result = (WxPayUnifiedOrderResult) xstream.fromXML(responseContent);
WxPayUnifiedOrderResult result = WxPayUnifiedOrderResult.fromXML(responseContent, WxPayUnifiedOrderResult.class);
this.checkResult(result); this.checkResult(result);
return result; return result;
} }
private void initRequest(WxPayBaseRequest request){
if(StringUtils.isBlank(request.getAppid())){
private void initRequest(WxPayBaseRequest request) {
if (StringUtils.isBlank(request.getAppid())) {
request.setAppid(getConfig().getAppId()); request.setAppid(getConfig().getAppId());
} }
if(StringUtils.isBlank(request.getMchId())){
if (StringUtils.isBlank(request.getMchId())) {
request.setMchId(getConfig().getPartnerId()); request.setMchId(getConfig().getPartnerId());
} }
if(StringUtils.isBlank(request.getNonceStr())){
if (StringUtils.isBlank(request.getNonceStr())) {
request.setNonceStr(String.valueOf(System.currentTimeMillis())); request.setNonceStr(String.valueOf(System.currentTimeMillis()));
} }
} }
@@ -328,40 +316,99 @@ public class WxMpPayServiceImpl implements WxMpPayService {
} }


@Override @Override
public WxEntPayResult entPay(WxEntPayRequest request, File keyFile) throws WxErrorException {
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxEntPayRequest.class);
xstream.processAnnotations(WxEntPayResult.class);
initRequest(request);
public WxEntPayResult entPay(WxEntPayRequest request) throws WxErrorException {
this.initRequest(request);
BeanUtils.checkRequiredFields(request); BeanUtils.checkRequiredFields(request);
request.setSign(this.createSign(request)); request.setSign(this.createSign(request));


String url = PAY_BASE_URL + "/mmpaymkttransfers/promotion/transfers";
String url = this.getPayBaseUrl() + "/mmpaymkttransfers/promotion/transfers";


String responseContent = this.executeRequestWithKeyFile(url, keyFile, xstream.toXML(request), request.getMchId());
WxEntPayResult result = (WxEntPayResult) xstream.fromXML(responseContent);
String responseContent = this.executeWithKey(url, request.toXML());
WxEntPayResult result = WxEntPayResult.fromXML(responseContent, WxEntPayResult.class);
this.checkResult(result); this.checkResult(result);
return result; return result;
} }


@Override @Override
public WxEntPayQueryResult queryEntPay(String partnerTradeNo, File keyFile) throws WxErrorException {
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxEntPayQueryRequest.class);
xstream.processAnnotations(WxEntPayQueryResult.class);

public WxEntPayQueryResult queryEntPay(String partnerTradeNo) throws WxErrorException {
WxEntPayQueryRequest request = new WxEntPayQueryRequest(); WxEntPayQueryRequest request = new WxEntPayQueryRequest();
initRequest(request);
this.initRequest(request);
request.setSign(this.createSign(request)); request.setSign(this.createSign(request));


String url = PAY_BASE_URL + "/mmpaymkttransfers/gettransferinfo";
String responseContent = this.executeRequestWithKeyFile(url, keyFile, xstream.toXML(request), request.getMchId());
WxEntPayQueryResult result = (WxEntPayQueryResult) xstream.fromXML(responseContent);
String url = this.getPayBaseUrl() + "/mmpaymkttransfers/gettransferinfo";
String responseContent = this.executeWithKey(url, request.toXML());
WxEntPayQueryResult result = WxEntPayQueryResult.fromXML(responseContent, WxEntPayQueryResult.class);
this.checkResult(result); this.checkResult(result);
return result; return result;
} }


@Override
public byte[] createScanPayQrcodeMode1(String productId, File logoFile, Integer sideLength) {
//weixin://wxpay/bizpayurl?sign=XXXXX&appid=XXXXX&mch_id=XXXXX&product_id=XXXXXX&time_stamp=XXXXXX&nonce_str=XXXXX
StringBuilder codeUrl = new StringBuilder("weixin://wxpay/bizpayurl?");
Map<String, String> params = Maps.newHashMap();
params.put("appid", this.getConfig().getAppId());
params.put("mch_id", this.getConfig().getPartnerId());
params.put("product_id", productId);
params.put("time_stamp", String.valueOf(System.currentTimeMillis()));
params.put("nonce_str", String.valueOf(System.currentTimeMillis()));

String sign = this.createSign(params);
params.put("sign", sign);

for (String key : params.keySet()) {
codeUrl.append(key + "=" + params.get(key) + "&");
}

String content = codeUrl.toString().substring(0, codeUrl.length() - 1);
if (sideLength == null || sideLength < 1) {
return QrcodeUtils.createQrcode(content, logoFile);
}

return QrcodeUtils.createQrcode(content, sideLength, logoFile);
}

@Override
public byte[] createScanPayQrcodeMode2(String codeUrl, File logoFile, Integer sideLength) {
if (sideLength == null || sideLength < 1) {
return QrcodeUtils.createQrcode(codeUrl, logoFile);
}

return QrcodeUtils.createQrcode(codeUrl, sideLength, logoFile);
}

public void report(WxPayReportRequest request) throws WxErrorException {
BeanUtils.checkRequiredFields(request);
this.initRequest(request);
request.setSign(this.createSign(request));

String url = this.getPayBaseUrl() + "/payitil/report";
String responseContent = this.wxMpService.post(url, request.toXML());
WxPayCommonResult result = WxPayBaseResult.fromXML(responseContent, WxPayCommonResult.class);
this.checkResult(result);
}

@Override
public File downloadBill(String billDate, String billType, String tarType, String deviceInfo) throws WxErrorException {
WxPayDownloadBillRequest request = new WxPayDownloadBillRequest();
this.initRequest(request);
request.setBillType(billType);
request.setBillDate(billDate);
request.setTarType(tarType);
request.setDeviceInfo(deviceInfo);
this.checkParameters(request);
request.setSign(this.createSign(request));

String url = this.getPayBaseUrl() + "/pay/downloadbill";
//TODO 返回的内容可能是文件流,也有可能是xml,需要区分对待
String responseContent = this.wxMpService.post(url, request.toXML());

WxPayCommonResult result = WxPayBaseResult.fromXML(responseContent, WxPayCommonResult.class);
this.checkResult(result);
//TODO 待实现,暂时无测试帐号,无法调试
return null;
}

private String executeRequest(String url, String requestStr) throws WxErrorException { private String executeRequest(String url, String requestStr) throws WxErrorException {
HttpPost httpPost = new HttpPost(url); HttpPost httpPost = new HttpPost(url);
if (this.wxMpService.getHttpProxy() != null) { if (this.wxMpService.getHttpProxy() != null) {
@@ -384,13 +431,14 @@ public class WxMpPayServiceImpl implements WxMpPayService {
} }
} }


private String executeRequestWithKeyFile(String url, File keyFile, String requestStr, String mchId) throws WxErrorException {
try (FileInputStream inputStream = new FileInputStream(keyFile)) {
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(inputStream, mchId.toCharArray());
private String executeWithKey(String url, String requestStr) throws WxErrorException {
try {
SSLContext sslContext = getConfig().getSslContext();
if (null == sslContext) {
throw new IllegalArgumentException("请先初始化配置类(即WxMpConfigStorage的实现类)中的SSLContext!");
}


SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mchId.toCharArray()).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1"}, null,
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new String[]{"TLSv1"}, null,
new DefaultHostnameVerifier()); new DefaultHostnameVerifier());


HttpPost httpPost = new HttpPost(url); HttpPost httpPost = new HttpPost(url);
@@ -413,24 +461,31 @@ public class WxMpPayServiceImpl implements WxMpPayService {
throw new WxErrorException(WxError.newBuilder().setErrorCode(-1).setErrorMsg(e.getMessage()).build(), e); throw new WxErrorException(WxError.newBuilder().setErrorCode(-1).setErrorMsg(e.getMessage()).build(), e);
} }
} }
@Override @Override
public String createSign(Object xmlBean) { public String createSign(Object xmlBean) {
return createSign(BeanUtils.xmlBean2Map(xmlBean), getConfig().getPartnerKey());
return this.createSign(BeanUtils.xmlBean2Map(xmlBean), getConfig().getPartnerKey());
} }


@Override @Override
public String createSign(Object xmlBean, String signKey) { public String createSign(Object xmlBean, String signKey) {
return createSign(BeanUtils.xmlBean2Map(xmlBean), signKey);
return this.createSign(BeanUtils.xmlBean2Map(xmlBean), signKey);
} }


@Override @Override
public String createSign(Map<String, String> params) { public String createSign(Map<String, String> params) {
return createSign(params, getConfig().getPartnerKey());
return this.createSign(params, this.getConfig().getPartnerKey());
} }


@Override @Override
public String createSign(Map<String, String> params, String signKey) { public String createSign(Map<String, String> params, String signKey) {
if(this.getConfig().useSandboxForWxPay()){
//使用仿真测试环境
//TODO 目前测试发现,以下两行代码都会出问题,所以暂不建议使用这个仿真测试环境
signKey = "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456";
//return "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456";
}

SortedMap<String, String> sortedMap = new TreeMap<>(params); SortedMap<String, String> sortedMap = new TreeMap<>(params);


StringBuilder toSign = new StringBuilder(); StringBuilder toSign = new StringBuilder();
@@ -447,17 +502,17 @@ public class WxMpPayServiceImpl implements WxMpPayService {


@Override @Override
public boolean checkSign(Object xmlBean) { public boolean checkSign(Object xmlBean) {
return checkSign(BeanUtils.xmlBean2Map(xmlBean), getConfig().getPartnerKey());
return this.checkSign(BeanUtils.xmlBean2Map(xmlBean), getConfig().getPartnerKey());
} }


@Override @Override
public boolean checkSign(Object xmlBean, String signKey) { public boolean checkSign(Object xmlBean, String signKey) {
return checkSign(BeanUtils.xmlBean2Map(xmlBean), signKey);
return this.checkSign(BeanUtils.xmlBean2Map(xmlBean), signKey);
} }


@Override @Override
public boolean checkSign(Map<String, String> params) { public boolean checkSign(Map<String, String> params) {
return checkSign(params, getConfig().getPartnerKey());
return this.checkSign(params, getConfig().getPartnerKey());
} }


@Override @Override


+ 31
- 14
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpQrcodeServiceImpl.java View File

@@ -3,7 +3,6 @@ package me.chanjar.weixin.mp.api.impl;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.bean.result.WxError;
import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor;
import me.chanjar.weixin.mp.api.WxMpQrcodeService; import me.chanjar.weixin.mp.api.WxMpQrcodeService;
import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
@@ -26,47 +25,65 @@ public class WxMpQrcodeServiceImpl implements WxMpQrcodeService {
} }


@Override @Override
public WxMpQrCodeTicket qrCodeCreateTmpTicket(int scene_id, Integer expire_seconds) throws WxErrorException {
public WxMpQrCodeTicket qrCodeCreateTmpTicket(int sceneId, Integer expireSeconds) throws WxErrorException {
if (sceneId == 0) {
throw new WxErrorException(WxError.newBuilder().setErrorCode(-1).setErrorMsg("临时二维码场景值不能为0!").build());
}

//expireSeconds 该二维码有效时间,以秒为单位。 最大不超过2592000(即30天),此字段如果不填,则默认有效期为30秒。
if (expireSeconds != null && expireSeconds > 2592000) {
throw new WxErrorException(WxError.newBuilder().setErrorCode(-1)
.setErrorMsg("临时二维码有效时间最大不能超过2592000(即30天)!").build());
}

if (expireSeconds == null) {
expireSeconds = 30;
}

String url = API_URL_PREFIX + "/create"; String url = API_URL_PREFIX + "/create";
JsonObject json = new JsonObject(); JsonObject json = new JsonObject();
json.addProperty("action_name", "QR_SCENE"); json.addProperty("action_name", "QR_SCENE");
if (expire_seconds != null) {
json.addProperty("expire_seconds", expire_seconds);
if (expireSeconds != null) {
json.addProperty("expire_seconds", expireSeconds);
} }
JsonObject actionInfo = new JsonObject(); JsonObject actionInfo = new JsonObject();
JsonObject scene = new JsonObject(); JsonObject scene = new JsonObject();
scene.addProperty("scene_id", scene_id);
scene.addProperty("scene_id", sceneId);
actionInfo.add("scene", scene); actionInfo.add("scene", scene);
json.add("action_info", actionInfo); json.add("action_info", actionInfo);
String responseContent = this.wxMpService.execute(new SimplePostRequestExecutor(), url, json.toString());
String responseContent = this.wxMpService.post(url, json.toString());
return WxMpQrCodeTicket.fromJson(responseContent); return WxMpQrCodeTicket.fromJson(responseContent);
} }


@Override @Override
public WxMpQrCodeTicket qrCodeCreateLastTicket(int scene_id) throws WxErrorException {
public WxMpQrCodeTicket qrCodeCreateLastTicket(int sceneId) throws WxErrorException {
if (sceneId < 1 || sceneId > 100000) {
throw new WxErrorException(WxError.newBuilder().setErrorCode(-1).setErrorMsg("永久二维码的场景值目前只支持1--100000!").build());
}

String url = API_URL_PREFIX + "/create"; String url = API_URL_PREFIX + "/create";
JsonObject json = new JsonObject(); JsonObject json = new JsonObject();
json.addProperty("action_name", "QR_LIMIT_SCENE"); json.addProperty("action_name", "QR_LIMIT_SCENE");
JsonObject actionInfo = new JsonObject(); JsonObject actionInfo = new JsonObject();
JsonObject scene = new JsonObject(); JsonObject scene = new JsonObject();
scene.addProperty("scene_id", scene_id);
scene.addProperty("scene_id", sceneId);
actionInfo.add("scene", scene); actionInfo.add("scene", scene);
json.add("action_info", actionInfo); json.add("action_info", actionInfo);
String responseContent = this.wxMpService.execute(new SimplePostRequestExecutor(), url, json.toString());
String responseContent = this.wxMpService.post(url, json.toString());
return WxMpQrCodeTicket.fromJson(responseContent); return WxMpQrCodeTicket.fromJson(responseContent);
} }


@Override @Override
public WxMpQrCodeTicket qrCodeCreateLastTicket(String scene_str) throws WxErrorException {
public WxMpQrCodeTicket qrCodeCreateLastTicket(String sceneStr) throws WxErrorException {
String url = API_URL_PREFIX + "/create"; String url = API_URL_PREFIX + "/create";
JsonObject json = new JsonObject(); JsonObject json = new JsonObject();
json.addProperty("action_name", "QR_LIMIT_STR_SCENE"); json.addProperty("action_name", "QR_LIMIT_STR_SCENE");
JsonObject actionInfo = new JsonObject(); JsonObject actionInfo = new JsonObject();
JsonObject scene = new JsonObject(); JsonObject scene = new JsonObject();
scene.addProperty("scene_str", scene_str);
scene.addProperty("scene_str", sceneStr);
actionInfo.add("scene", scene); actionInfo.add("scene", scene);
json.add("action_info", actionInfo); json.add("action_info", actionInfo);
String responseContent = this.wxMpService.execute(new SimplePostRequestExecutor(), url, json.toString());
String responseContent = this.wxMpService.post(url, json.toString());
return WxMpQrCodeTicket.fromJson(responseContent); return WxMpQrCodeTicket.fromJson(responseContent);
} }


@@ -81,7 +98,7 @@ public class WxMpQrcodeServiceImpl implements WxMpQrcodeService {
String url = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=%s"; String url = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=%s";
try { try {
String resultUrl = String.format(url, String resultUrl = String.format(url,
URLEncoder.encode(ticket, StandardCharsets.UTF_8.name()));
URLEncoder.encode(ticket, StandardCharsets.UTF_8.name()));
if (needShortUrl) { if (needShortUrl) {
return this.wxMpService.shortUrl(resultUrl); return this.wxMpService.shortUrl(resultUrl);
} }
@@ -89,7 +106,7 @@ public class WxMpQrcodeServiceImpl implements WxMpQrcodeService {
return resultUrl; return resultUrl;
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
WxError error = WxError.newBuilder().setErrorCode(-1) WxError error = WxError.newBuilder().setErrorCode(-1)
.setErrorMsg(e.getMessage()).build();
.setErrorMsg(e.getMessage()).build();
throw new WxErrorException(error); throw new WxErrorException(error);
} }
} }


+ 54
- 72
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImpl.java View File

@@ -20,8 +20,6 @@ import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig; import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.BasicResponseHandler; import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.CloseableHttpClient;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -30,55 +28,39 @@ import org.slf4j.LoggerFactory;
import java.io.IOException; import java.io.IOException;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;


//import org.apache.http.conn.ssl.DefaultHostnameVerifier;
//import org.apache.http.conn.ssl.SSLConnectionSocketFactory;

public class WxMpServiceImpl implements WxMpService { public class WxMpServiceImpl implements WxMpService {


private static final JsonParser JSON_PARSER = new JsonParser(); private static final JsonParser JSON_PARSER = new JsonParser();


protected final Logger log = LoggerFactory.getLogger(this.getClass()); protected final Logger log = LoggerFactory.getLogger(this.getClass());

private WxMpConfigStorage configStorage;

protected WxSessionManager sessionManager = new StandardSessionManager();
private WxMpConfigStorage wxMpConfigStorage;
private WxMpKefuService kefuService = new WxMpKefuServiceImpl(this); private WxMpKefuService kefuService = new WxMpKefuServiceImpl(this);

private WxMpMaterialService materialService = new WxMpMaterialServiceImpl(this); private WxMpMaterialService materialService = new WxMpMaterialServiceImpl(this);

private WxMpMenuService menuService = new WxMpMenuServiceImpl(this); private WxMpMenuService menuService = new WxMpMenuServiceImpl(this);

private WxMpUserService userService = new WxMpUserServiceImpl(this); private WxMpUserService userService = new WxMpUserServiceImpl(this);

private WxMpUserTagService tagService = new WxMpUserTagServiceImpl(this); private WxMpUserTagService tagService = new WxMpUserTagServiceImpl(this);

private WxMpQrcodeService qrCodeService = new WxMpQrcodeServiceImpl(this); private WxMpQrcodeService qrCodeService = new WxMpQrcodeServiceImpl(this);

private WxMpCardService cardService = new WxMpCardServiceImpl(this); private WxMpCardService cardService = new WxMpCardServiceImpl(this);

private WxMpPayService payService = new WxMpPayServiceImpl(this); private WxMpPayService payService = new WxMpPayServiceImpl(this);

private WxMpStoreService storeService = new WxMpStoreServiceImpl(this); private WxMpStoreService storeService = new WxMpStoreServiceImpl(this);

private WxMpDataCubeService dataCubeService = new WxMpDataCubeServiceImpl(this); private WxMpDataCubeService dataCubeService = new WxMpDataCubeServiceImpl(this);

private WxMpUserBlacklistService blackListService = new WxMpUserBlacklistServiceImpl(this); private WxMpUserBlacklistService blackListService = new WxMpUserBlacklistServiceImpl(this);

private WxMpTemplateMsgService templateMsgService = new WxMpTemplateMsgServiceImpl(this); private WxMpTemplateMsgService templateMsgService = new WxMpTemplateMsgServiceImpl(this);

private WxMpDeviceService deviceService = new WxMpDeviceServiceImpl(this); private WxMpDeviceService deviceService = new WxMpDeviceServiceImpl(this);

private CloseableHttpClient httpClient; private CloseableHttpClient httpClient;

private HttpHost httpProxy; private HttpHost httpProxy;

private int retrySleepMillis = 1000; private int retrySleepMillis = 1000;

private int maxRetryTimes = 5; private int maxRetryTimes = 5;


protected WxSessionManager sessionManager = new StandardSessionManager();

@Override @Override
public boolean checkSignature(String timestamp, String nonce, String signature) { public boolean checkSignature(String timestamp, String nonce, String signature) {
try { try {
return SHA1.gen(this.configStorage.getToken(), timestamp, nonce)
.equals(signature);
return SHA1.gen(this.wxMpConfigStorage.getToken(), timestamp, nonce)
.equals(signature);
} catch (Exception e) { } catch (Exception e) {
return false; return false;
} }
@@ -91,18 +73,18 @@ public class WxMpServiceImpl implements WxMpService {


@Override @Override
public String getAccessToken(boolean forceRefresh) throws WxErrorException { public String getAccessToken(boolean forceRefresh) throws WxErrorException {
Lock lock = this.configStorage.getAccessTokenLock();
Lock lock = this.wxMpConfigStorage.getAccessTokenLock();
try { try {
lock.lock(); lock.lock();


if (forceRefresh) { if (forceRefresh) {
this.configStorage.expireAccessToken();
this.wxMpConfigStorage.expireAccessToken();
} }


if (this.configStorage.isAccessTokenExpired()) {
if (this.wxMpConfigStorage.isAccessTokenExpired()) {
String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential" + String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential" +
"&appid=" + this.configStorage.getAppId() + "&secret="
+ this.configStorage.getSecret();
"&appid=" + this.wxMpConfigStorage.getAppId() + "&secret="
+ this.wxMpConfigStorage.getSecret();
try { try {
HttpGet httpGet = new HttpGet(url); HttpGet httpGet = new HttpGet(url);
if (this.httpProxy != null) { if (this.httpProxy != null) {
@@ -116,9 +98,9 @@ public class WxMpServiceImpl implements WxMpService {
throw new WxErrorException(error); throw new WxErrorException(error);
} }
WxAccessToken accessToken = WxAccessToken.fromJson(resultContent); WxAccessToken accessToken = WxAccessToken.fromJson(resultContent);
this.configStorage.updateAccessToken(accessToken.getAccessToken(),
accessToken.getExpiresIn());
}finally {
this.wxMpConfigStorage.updateAccessToken(accessToken.getAccessToken(),
accessToken.getExpiresIn());
} finally {
httpGet.releaseConnection(); httpGet.releaseConnection();
} }
} catch (IOException e) { } catch (IOException e) {
@@ -128,7 +110,7 @@ public class WxMpServiceImpl implements WxMpService {
} finally { } finally {
lock.unlock(); lock.unlock();
} }
return this.configStorage.getAccessToken();
return this.wxMpConfigStorage.getAccessToken();
} }


@Override @Override
@@ -138,27 +120,27 @@ public class WxMpServiceImpl implements WxMpService {


@Override @Override
public String getJsapiTicket(boolean forceRefresh) throws WxErrorException { public String getJsapiTicket(boolean forceRefresh) throws WxErrorException {
Lock lock = this.configStorage.getJsapiTicketLock();
Lock lock = this.wxMpConfigStorage.getJsapiTicketLock();
try { try {
lock.lock(); lock.lock();


if (forceRefresh) { if (forceRefresh) {
this.configStorage.expireJsapiTicket();
this.wxMpConfigStorage.expireJsapiTicket();
} }


if (this.configStorage.isJsapiTicketExpired()) {
if (this.wxMpConfigStorage.isJsapiTicketExpired()) {
String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi"; String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi";
String responseContent = execute(new SimpleGetRequestExecutor(), url, null); String responseContent = execute(new SimpleGetRequestExecutor(), url, null);
JsonElement tmpJsonElement = JSON_PARSER.parse(responseContent); JsonElement tmpJsonElement = JSON_PARSER.parse(responseContent);
JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject(); JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject();
String jsapiTicket = tmpJsonObject.get("ticket").getAsString(); String jsapiTicket = tmpJsonObject.get("ticket").getAsString();
int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt(); int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt();
this.configStorage.updateJsapiTicket(jsapiTicket, expiresInSeconds);
this.wxMpConfigStorage.updateJsapiTicket(jsapiTicket, expiresInSeconds);
} }
} finally { } finally {
lock.unlock(); lock.unlock();
} }
return this.configStorage.getJsapiTicket();
return this.wxMpConfigStorage.getJsapiTicket();
} }


@Override @Override
@@ -167,11 +149,11 @@ public class WxMpServiceImpl implements WxMpService {
String noncestr = RandomUtils.getRandomStr(); String noncestr = RandomUtils.getRandomStr();
String jsapiTicket = getJsapiTicket(false); String jsapiTicket = getJsapiTicket(false);
String signature = SHA1.genWithAmple("jsapi_ticket=" + jsapiTicket, String signature = SHA1.genWithAmple("jsapi_ticket=" + jsapiTicket,
"noncestr=" + noncestr, "timestamp=" + timestamp, "url=" + url);
"noncestr=" + noncestr, "timestamp=" + timestamp, "url=" + url);
WxJsapiSignature jsapiSignature = new WxJsapiSignature(); WxJsapiSignature jsapiSignature = new WxJsapiSignature();
jsapiSignature.setAppid(this.configStorage.getAppId());
jsapiSignature.setAppId(this.wxMpConfigStorage.getAppId());
jsapiSignature.setTimestamp(timestamp); jsapiSignature.setTimestamp(timestamp);
jsapiSignature.setNoncestr(noncestr);
jsapiSignature.setNonceStr(noncestr);
jsapiSignature.setUrl(url); jsapiSignature.setUrl(url);
jsapiSignature.setSignature(signature); jsapiSignature.setSignature(signature);
return jsapiSignature; return jsapiSignature;
@@ -234,7 +216,7 @@ public class WxMpServiceImpl implements WxMpService {
public String oauth2buildAuthorizationUrl(String redirectURI, String scope, String state) { public String oauth2buildAuthorizationUrl(String redirectURI, String scope, String state) {
StringBuilder url = new StringBuilder(); StringBuilder url = new StringBuilder();
url.append("https://open.weixin.qq.com/connect/oauth2/authorize?"); url.append("https://open.weixin.qq.com/connect/oauth2/authorize?");
url.append("appid=").append(this.configStorage.getAppId());
url.append("appid=").append(this.wxMpConfigStorage.getAppId());
url.append("&redirect_uri=").append(URIUtil.encodeURIComponent(redirectURI)); url.append("&redirect_uri=").append(URIUtil.encodeURIComponent(redirectURI));
url.append("&response_type=code"); url.append("&response_type=code");
url.append("&scope=").append(scope); url.append("&scope=").append(scope);
@@ -247,10 +229,10 @@ public class WxMpServiceImpl implements WxMpService {


@Override @Override
public String buildQrConnectUrl(String redirectURI, String scope, public String buildQrConnectUrl(String redirectURI, String scope,
String state) {
String state) {
StringBuilder url = new StringBuilder(); StringBuilder url = new StringBuilder();
url.append("https://open.weixin.qq.com/connect/qrconnect?"); url.append("https://open.weixin.qq.com/connect/qrconnect?");
url.append("appid=").append(this.configStorage.getAppId());
url.append("appid=").append(this.wxMpConfigStorage.getAppId());
url.append("&redirect_uri=").append(URIUtil.encodeURIComponent(redirectURI)); url.append("&redirect_uri=").append(URIUtil.encodeURIComponent(redirectURI));
url.append("&response_type=code"); url.append("&response_type=code");
url.append("&scope=").append(scope); url.append("&scope=").append(scope);
@@ -276,8 +258,8 @@ public class WxMpServiceImpl implements WxMpService {
public WxMpOAuth2AccessToken oauth2getAccessToken(String code) throws WxErrorException { public WxMpOAuth2AccessToken oauth2getAccessToken(String code) throws WxErrorException {
StringBuilder url = new StringBuilder(); StringBuilder url = new StringBuilder();
url.append("https://api.weixin.qq.com/sns/oauth2/access_token?"); url.append("https://api.weixin.qq.com/sns/oauth2/access_token?");
url.append("appid=").append(this.configStorage.getAppId());
url.append("&secret=").append(this.configStorage.getSecret());
url.append("appid=").append(this.wxMpConfigStorage.getAppId());
url.append("&secret=").append(this.wxMpConfigStorage.getSecret());
url.append("&code=").append(code); url.append("&code=").append(code);
url.append("&grant_type=authorization_code"); url.append("&grant_type=authorization_code");


@@ -288,7 +270,7 @@ public class WxMpServiceImpl implements WxMpService {
public WxMpOAuth2AccessToken oauth2refreshAccessToken(String refreshToken) throws WxErrorException { public WxMpOAuth2AccessToken oauth2refreshAccessToken(String refreshToken) throws WxErrorException {
StringBuilder url = new StringBuilder(); StringBuilder url = new StringBuilder();
url.append("https://api.weixin.qq.com/sns/oauth2/refresh_token?"); url.append("https://api.weixin.qq.com/sns/oauth2/refresh_token?");
url.append("appid=").append(this.configStorage.getAppId());
url.append("appid=").append(this.wxMpConfigStorage.getAppId());
url.append("&grant_type=refresh_token"); url.append("&grant_type=refresh_token");
url.append("&refresh_token=").append(refreshToken); url.append("&refresh_token=").append(refreshToken);


@@ -366,7 +348,7 @@ public class WxMpServiceImpl implements WxMpService {
do { do {
try { try {
T result = executeInternal(executor, uri, data); T result = executeInternal(executor, uri, data);
this.log.debug("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}",uri, data, result);
this.log.debug("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}", uri, data, result);
return result; return result;
} catch (WxErrorException e) { } catch (WxErrorException e) {
if (retryTimes + 1 > this.maxRetryTimes) { if (retryTimes + 1 > this.maxRetryTimes) {
@@ -415,8 +397,8 @@ public class WxMpServiceImpl implements WxMpService {
*/ */
if (error.getErrorCode() == 42001 || error.getErrorCode() == 40001) { if (error.getErrorCode() == 42001 || error.getErrorCode() == 40001) {
// 强制设置wxMpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token // 强制设置wxMpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token
this.configStorage.expireAccessToken();
if(this.configStorage.autoRefreshToken()){
this.wxMpConfigStorage.expireAccessToken();
if (this.wxMpConfigStorage.autoRefreshToken()) {
return this.execute(executor, uri, data); return this.execute(executor, uri, data);
} }
} }
@@ -441,33 +423,27 @@ public class WxMpServiceImpl implements WxMpService {
return this.httpClient; return this.httpClient;
} }


@Override
public void setWxMpConfigStorage(WxMpConfigStorage wxConfigProvider) {
this.configStorage = wxConfigProvider;
this.initHttpClient();
}

private void initHttpClient() { private void initHttpClient() {
ApacheHttpClientBuilder apacheHttpClientBuilder = this.configStorage
.getApacheHttpClientBuilder();
ApacheHttpClientBuilder apacheHttpClientBuilder = this.wxMpConfigStorage
.getApacheHttpClientBuilder();
if (null == apacheHttpClientBuilder) { if (null == apacheHttpClientBuilder) {
apacheHttpClientBuilder = DefaultApacheHttpClientBuilder.get(); apacheHttpClientBuilder = DefaultApacheHttpClientBuilder.get();
} }


apacheHttpClientBuilder.httpProxyHost(this.configStorage.getHttpProxyHost())
.httpProxyPort(this.configStorage.getHttpProxyPort())
.httpProxyUsername(this.configStorage.getHttpProxyUsername())
.httpProxyPassword(this.configStorage.getHttpProxyPassword());
apacheHttpClientBuilder.httpProxyHost(this.wxMpConfigStorage.getHttpProxyHost())
.httpProxyPort(this.wxMpConfigStorage.getHttpProxyPort())
.httpProxyUsername(this.wxMpConfigStorage.getHttpProxyUsername())
.httpProxyPassword(this.wxMpConfigStorage.getHttpProxyPassword());


if (this.configStorage.getSSLContext() != null) {
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
this.configStorage.getSSLContext(), new String[] { "TLSv1" }, null,
new DefaultHostnameVerifier());
apacheHttpClientBuilder.sslConnectionSocketFactory(sslsf);
}
// if (this.wxMpConfigStorage.getSSLContext() != null) {
// SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
// this.wxMpConfigStorage.getSSLContext(), new String[] { "TLSv1" }, null,
// new DefaultHostnameVerifier());
// apacheHttpClientBuilder.sslConnectionSocketFactory(sslsf);
// }


if (this.configStorage.getHttpProxyHost() != null && this.configStorage.getHttpProxyPort() > 0) {
this.httpProxy = new HttpHost(this.configStorage.getHttpProxyHost(), this.configStorage.getHttpProxyPort());
if (this.wxMpConfigStorage.getHttpProxyHost() != null && this.wxMpConfigStorage.getHttpProxyPort() > 0) {
this.httpProxy = new HttpHost(this.wxMpConfigStorage.getHttpProxyHost(), this.wxMpConfigStorage.getHttpProxyPort());
} }


this.httpClient = apacheHttpClientBuilder.build(); this.httpClient = apacheHttpClientBuilder.build();
@@ -475,7 +451,13 @@ public class WxMpServiceImpl implements WxMpService {


@Override @Override
public WxMpConfigStorage getWxMpConfigStorage() { public WxMpConfigStorage getWxMpConfigStorage() {
return this.configStorage;
return this.wxMpConfigStorage;
}

@Override
public void setWxMpConfigStorage(WxMpConfigStorage wxConfigProvider) {
this.wxMpConfigStorage = wxConfigProvider;
this.initHttpClient();
} }


@Override @Override


+ 15
- 0
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassTagMessage.java View File

@@ -16,6 +16,7 @@ public class WxMpMassTagMessage implements Serializable {
private String msgType; private String msgType;
private String content; private String content;
private String mediaId; private String mediaId;
private boolean isSendAll = false;
private boolean sendIgnoreReprint = false; private boolean sendIgnoreReprint = false;


public WxMpMassTagMessage() { public WxMpMassTagMessage() {
@@ -88,4 +89,18 @@ public class WxMpMassTagMessage implements Serializable {
this.sendIgnoreReprint = sendIgnoreReprint; this.sendIgnoreReprint = sendIgnoreReprint;
} }


/**
* 是否群发给所有用户
*/
public boolean isSendAll() {
return isSendAll;
}

public void setSendAll(boolean sendAll) {
if(sendAll){
this.tagId = null;
}

isSendAll = sendAll;
}
} }

+ 10
- 0
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceAuthorize.java View File

@@ -14,6 +14,8 @@ public class WxDeviceAuthorize extends AbstractDeviceBean {
private String deviceNum; private String deviceNum;
@SerializedName("op_type") @SerializedName("op_type")
private String opType; private String opType;
@SerializedName("product_id")
private String productId;
@SerializedName("device_list") @SerializedName("device_list")
private List<WxDevice> deviceList = new LinkedList<>(); private List<WxDevice> deviceList = new LinkedList<>();


@@ -33,6 +35,14 @@ public class WxDeviceAuthorize extends AbstractDeviceBean {
this.opType = opType; this.opType = opType;
} }


public String getProductId() {
return productId;
}

public void setProductId(String productId) {
this.productId = productId;
}

public List<WxDevice> getDeviceList() { public List<WxDevice> getDeviceList() {
return deviceList; return deviceList;
} }


+ 92
- 0
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/menu/WxMpMenu.java View File

@@ -0,0 +1,92 @@
package me.chanjar.weixin.mp.bean.menu;

import com.google.gson.annotations.SerializedName;
import me.chanjar.weixin.common.bean.menu.WxMenuButton;
import me.chanjar.weixin.common.bean.menu.WxMenuRule;
import me.chanjar.weixin.common.util.ToStringUtils;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;

import java.util.List;

/**
* <pre>
* 公众号专用的菜单类,可能包含个性化菜单
* Created by Binary Wang on 2017-1-17.
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
* </pre>
*/
public class WxMpMenu {
@SerializedName("menu")
private WxMpConditionalMenu menu;

@SerializedName("conditionalmenu")
private List<WxMpConditionalMenu> conditionalMenu;

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

public WxMpConditionalMenu getMenu() {
return menu;
}

public void setMenu(WxMpConditionalMenu menu) {
this.menu = menu;
}

public List<WxMpConditionalMenu> getConditionalMenu() {
return conditionalMenu;
}

public void setConditionalMenu(List<WxMpConditionalMenu> conditionalMenu) {
this.conditionalMenu = conditionalMenu;
}

@Override
public String toString() {
return ToStringUtils.toSimpleString(this);
}

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

public static class WxMpConditionalMenu {
@SerializedName("button")
private List<WxMenuButton> buttons;
@SerializedName("matchrule")
private WxMenuRule rule;
@SerializedName("menuid")
private String menuId;

@Override
public String toString() {
return ToStringUtils.toSimpleString(this);
}

public List<WxMenuButton> getButtons() {
return buttons;
}

public void setButtons(List<WxMenuButton> buttons) {
this.buttons = buttons;
}

public WxMenuRule getRule() {
return rule;
}

public void setRule(WxMenuRule rule) {
this.rule = rule;
}

public String getMenuId() {
return menuId;
}

public void setMenuId(String menuId) {
this.menuId = menuId;
}
}

}

+ 14
- 0
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlMessage.java View File

@@ -281,6 +281,12 @@ public class WxMpXmlMessage implements Serializable {
@XStreamConverter(value = XStreamCDataConverter.class) @XStreamConverter(value = XStreamCDataConverter.class)
private String deviceId; private String deviceId;


/**
* 微信用户账号的OpenID
*/
@XStreamAlias("OpenID")
@XStreamConverter(value = XStreamCDataConverter.class)
private String openId;


@XStreamAlias("HardWare") @XStreamAlias("HardWare")
private HardWare hardWare = new HardWare(); private HardWare hardWare = new HardWare();
@@ -375,6 +381,14 @@ public class WxMpXmlMessage implements Serializable {
this.deviceId = deviceId; this.deviceId = deviceId;
} }


public String getOpenId() {
return openId;
}

public void setOpenId(String openId) {
this.openId = openId;
}

public Long getExpiredTime() { public Long getExpiredTime() {
return this.expiredTime; return this.expiredTime;
} }


+ 26
- 15
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayBaseRequest.java View File

@@ -1,9 +1,11 @@
package me.chanjar.weixin.mp.bean.pay.request; package me.chanjar.weixin.mp.bean.pay.request;


import java.math.BigDecimal;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAlias;
import me.chanjar.weixin.common.util.ToStringUtils; import me.chanjar.weixin.common.util.ToStringUtils;
import me.chanjar.weixin.common.util.xml.XStreamInitializer;

import java.math.BigDecimal;


/** /**
* <pre> * <pre>
@@ -17,6 +19,7 @@ import me.chanjar.weixin.common.util.ToStringUtils;
* <li>示例值 * <li>示例值
* <li>描述 * <li>描述
* </pre> * </pre>
*
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a> * @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
*/ */
public abstract class WxPayBaseRequest { public abstract class WxPayBaseRequest {
@@ -69,13 +72,23 @@ public abstract class WxPayBaseRequest {
@XStreamAlias("sign") @XStreamAlias("sign")
protected String sign; protected String sign;


/**
* 将单位为元转换为单位为分
*
* @param yuan 将要转换的元的数值字符串
*/
public static Integer yuanToFee(String yuan) {
return new BigDecimal(yuan).setScale(2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).intValue();
}

public String getAppid() { public String getAppid() {
return this.appid; return this.appid;
} }


/** /**
* 如果配置中已经设置,可以不设置值 * 如果配置中已经设置,可以不设置值
* @param appid
*
* @param appid 微信公众号appid
*/ */
public void setAppid(String appid) { public void setAppid(String appid) {
this.appid = appid; this.appid = appid;
@@ -87,7 +100,8 @@ public abstract class WxPayBaseRequest {


/** /**
* 如果配置中已经设置,可以不设置值 * 如果配置中已经设置,可以不设置值
* @param mchId
*
* @param mchId 微信商户号
*/ */
public void setMchId(String mchId) { public void setMchId(String mchId) {
this.mchId = mchId; this.mchId = mchId;
@@ -99,7 +113,8 @@ public abstract class WxPayBaseRequest {


/** /**
* 默认采用时间戳为随机字符串,可以不设置 * 默认采用时间戳为随机字符串,可以不设置
* @param nonceStr
*
* @param nonceStr 随机字符串
*/ */
public void setNonceStr(String nonceStr) { public void setNonceStr(String nonceStr) {
this.nonceStr = nonceStr; this.nonceStr = nonceStr;
@@ -112,19 +127,15 @@ public abstract class WxPayBaseRequest {
public void setSign(String sign) { public void setSign(String sign) {
this.sign = sign; this.sign = sign;
} }
/**
* 将单位为元转换为单位为分
*
* @param yuan
* @return
*/
public static Integer yuanToFee(String yuan) {
return new BigDecimal(yuan).setScale(2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).intValue();
}


@Override @Override
public String toString() { public String toString() {
return ToStringUtils.toSimpleString(this); return ToStringUtils.toSimpleString(this);
} }

public String toXML() {
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(this.getClass());
return xstream.toXML(this);
}
} }

+ 123
- 0
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayDownloadBillRequest.java View File

@@ -0,0 +1,123 @@
package me.chanjar.weixin.mp.bean.pay.request;

import com.thoughtworks.xstream.annotations.XStreamAlias;
import me.chanjar.weixin.common.annotation.Required;

/**
* <pre>
* 微信支付下载对账单请求参数类
* Created by Binary Wang on 2017-01-11.
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
* </pre>
*/
@XStreamAlias("xml")
public class WxPayDownloadBillRequest extends WxPayBaseRequest {
/**
* <pre>
* 设备号
* device_info
* 否
* String(32)
* 13467007045764
* 终端设备号
* </pre>
*/
@XStreamAlias("device_info")
private String deviceInfo;

/**
* <pre>
* 签名类型
* sign_type
* 否
* String(32)
* HMAC-SHA256
* 签名类型,目前支持HMAC-SHA256和MD5,默认为MD5
* </pre>
*/
@XStreamAlias("sign_type")
private String signType;

/**
* <pre>
* 账单类型
* bill_type
* 是
* ALL
* String(8)
* --ALL,返回当日所有订单信息,默认值
* --SUCCESS,返回当日成功支付的订单
* --REFUND,返回当日退款订单
* </pre>
*/
@Required
@XStreamAlias("bill_type")
private String billType;

/**
* <pre>
* 对账单日期
* bill_date
* 是
* String(8)
* 20140603
* 下载对账单的日期,格式:20140603
* </pre>
*/
@Required
@XStreamAlias("bill_date")
private String billDate;

/**
* <pre>
* 压缩账单
* tar_type
* 否
* String(8)
* GZIP
* 非必传参数,固定值:GZIP,返回格式为.gzip的压缩包账单。不传则默认为数据流形式。
* </pre>
*/
@XStreamAlias("tar_type")
private String tarType;

public String getDeviceInfo() {
return deviceInfo;
}

public void setDeviceInfo(String deviceInfo) {
this.deviceInfo = deviceInfo;
}

public String getSignType() {
return signType;
}

public void setSignType(String signType) {
this.signType = signType;
}

public String getBillType() {
return billType;
}

public void setBillType(String billType) {
this.billType = billType;
}

public String getBillDate() {
return billDate;
}

public void setBillDate(String billDate) {
this.billDate = billDate;
}

public String getTarType() {
return tarType;
}

public void setTarType(String tarType) {
this.tarType = tarType;
}
}

+ 1
- 3
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayRefundRequest.java View File

@@ -1,7 +1,6 @@
package me.chanjar.weixin.mp.bean.pay.request; package me.chanjar.weixin.mp.bean.pay.request;


import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAlias;

import me.chanjar.weixin.common.annotation.Required; import me.chanjar.weixin.common.annotation.Required;


/** /**
@@ -144,8 +143,6 @@ public class WxPayRefundRequest extends WxPayBaseRequest {
@XStreamAlias("refund_account") @XStreamAlias("refund_account")
private String refundAccount; private String refundAccount;




public String getDeviceInfo() { public String getDeviceInfo() {
return this.deviceInfo; return this.deviceInfo;
} }
@@ -217,4 +214,5 @@ public class WxPayRefundRequest extends WxPayBaseRequest {
public void setRefundAccount(String refundAccount) { public void setRefundAccount(String refundAccount) {
this.refundAccount = refundAccount; this.refundAccount = refundAccount;
} }

} }

+ 273
- 0
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayReportRequest.java View File

@@ -0,0 +1,273 @@
package me.chanjar.weixin.mp.bean.pay.request;

import com.thoughtworks.xstream.annotations.XStreamAlias;
import me.chanjar.weixin.common.annotation.Required;

/**
* <pre>
* 微信支付-交易保障请求参数
* 注释中各行每个字段描述对应如下:
* <li>字段名
* <li>变量名
* <li>是否必填
* <li>类型
* <li>示例值
* <li>描述
* </pre>
*
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
*/
@XStreamAlias("xml")
public class WxPayReportRequest extends WxPayBaseRequest {
/**
* <pre>
* 设备号
* device_info
* 否
* String(32)
* 013467007045764
* 商户自定义的终端设备号,如门店编号、设备的ID等
* </pre>
*/
@XStreamAlias("device_info")
private String deviceInfo;

/**
* <pre>
* 签名类型
* sign_type
* 否
* String(32)
* HMAC-SHA256
* 签名类型,目前支持HMAC-SHA256和MD5,默认为MD5
* </pre>
*/
@XStreamAlias("sign_type")
private String signType;

/**
* <pre>
* 接口URL
* interface_url
* 是
* String(127)
* https://api.mch.weixin.qq.com/pay/unifiedorder
* 报对应的接口的完整URL,类似:https://api.mch.weixin.qq.com/pay/unifiedorder,
* 对于刷卡支付,为更好的和商户共同分析一次业务行为的整体耗时情况,
* 对于两种接入模式,请都在门店侧对一次刷卡支付进行一次单独的整体上报,
* 上报URL指定为:https://api.mch.weixin.qq.com/pay/micropay/total,关于两种接入模式具体可参考本文档章节:
* 刷卡支付商户接入模式,其它接口调用仍然按照调用一次,上报一次来进行。
* </pre>
*/
@Required
@XStreamAlias("interface_url")
private String interfaceUrl;
/**
* <pre>
* 接口耗时
* execute_time
* 是
* Int
* 1000
* 接口耗时情况,单位为毫秒
* </pre>
*/
@Required
@XStreamAlias("execute_time_")//估计是官方接口搞错了
private Integer executeTime;
/**
* <pre>
* 返回状态码
* return_code
* 是
* String(16)
* SUCCESS
* SUCCESS/FAIL,此字段是通信标识,非交易标识,交易是否成功需要查看trade_state来判断
* </pre>
*/
@Required
@XStreamAlias("return_code")
private String returnCode;
/**
* <pre>
* 返回信息
* return_msg
* 否
* String(128)
* 签名失败
* 返回信息,如非空,为错误原因,签名失败,参数格式校验错误
* </pre>
*/
@XStreamAlias("return_msg")
private String returnMsg;
/**
* <pre>
* 业务结果
* result_code
* 是
* String(16)
* SUCCESS
* SUCCESS/FAIL
* </pre>
*/
@Required
@XStreamAlias("result_code")
private String resultCode;
/**
* <pre>
* 错误代码
* err_code
* 否
* String(32)
* SYSTEMERROR
* ORDERNOTEXIST—订单不存在,SYSTEMERROR—系统错误
* </pre>
*/
@XStreamAlias("err_code")
private String errCode;
/**
* <pre>
* 错误代码描述
* err_code_des
* 否
* String(128)
* 系统错误
* 结果信息描述
* </pre>
*/
@XStreamAlias("err_code_des")
private String errCodeDes;
/**
* <pre>
* 商户订单号
* out_trade_no
* 否
* String(32)
* 1217752501201407033233368018
* 商户系统内部的订单号,商户可以在上报时提供相关商户订单号方便微信支付更好的提高服务质量。
* </pre>
*/
@XStreamAlias("out_trade_no")
private String outTradeNo;
/**
* <pre>
* 访问接口IP
* user_ip
* 是
* String(16)
* 8.8.8.8
* 发起接口调用时的机器IP
* </pre>
*/
@Required
@XStreamAlias("user_ip")
private String userIp;
/**
* <pre>
* 商户上报时间
* time
* 否
* String(14)
* 20091227091010
* 系统时间,格式为yyyyMMddHHmmss,如2009年12月27日9点10分10秒表示为20091227091010。其他详见时间规则
* </pre>
*/
@XStreamAlias("time")
private String time;

public String getDeviceInfo() {
return deviceInfo;
}

public void setDeviceInfo(String deviceInfo) {
this.deviceInfo = deviceInfo;
}

public String getSignType() {
return signType;
}

public void setSignType(String signType) {
this.signType = signType;
}

public String getInterfaceUrl() {
return interfaceUrl;
}

public void setInterfaceUrl(String interfaceUrl) {
this.interfaceUrl = interfaceUrl;
}

public Integer getExecuteTime() {
return executeTime;
}

public void setExecuteTime(Integer executeTime) {
this.executeTime = executeTime;
}

public String getReturnCode() {
return returnCode;
}

public void setReturnCode(String returnCode) {
this.returnCode = returnCode;
}

public String getReturnMsg() {
return returnMsg;
}

public void setReturnMsg(String returnMsg) {
this.returnMsg = returnMsg;
}

public String getResultCode() {
return resultCode;
}

public void setResultCode(String resultCode) {
this.resultCode = resultCode;
}

public String getErrCode() {
return errCode;
}

public void setErrCode(String errCode) {
this.errCode = errCode;
}

public String getErrCodeDes() {
return errCodeDes;
}

public void setErrCodeDes(String errCodeDes) {
this.errCodeDes = errCodeDes;
}

public String getOutTradeNo() {
return outTradeNo;
}

public void setOutTradeNo(String outTradeNo) {
this.outTradeNo = outTradeNo;
}

public String getUserIp() {
return userIp;
}

public void setUserIp(String userIp) {
this.userIp = userIp;
}

public String getTime() {
return time;
}

public void setTime(String time) {
this.time = time;
}
}

+ 101
- 28
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayBaseResult.java View File

@@ -1,12 +1,21 @@
package me.chanjar.weixin.mp.bean.pay.result; package me.chanjar.weixin.mp.bean.pay.result;


import java.math.BigDecimal;
import java.util.Map;

import com.google.common.collect.Maps;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAlias;

import me.chanjar.weixin.common.util.BeanUtils;
import io.restassured.internal.path.xml.NodeChildrenImpl;
import io.restassured.internal.path.xml.NodeImpl;
import io.restassured.path.xml.XmlPath;
import io.restassured.path.xml.element.Node;
import io.restassured.path.xml.exception.XmlPathException;
import me.chanjar.weixin.common.util.ToStringUtils; import me.chanjar.weixin.common.util.ToStringUtils;
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.util.Iterator;
import java.util.Map;


/** /**
* <pre> * <pre>
@@ -16,65 +25,90 @@ import me.chanjar.weixin.common.util.ToStringUtils;
* </pre> * </pre>
*/ */
public abstract class WxPayBaseResult { public abstract class WxPayBaseResult {
@Override
public String toString() {
return ToStringUtils.toSimpleString(this);
}

/** /**
* 返回状态码 * 返回状态码
*/ */
@XStreamAlias("return_code") @XStreamAlias("return_code")
protected String returnCode; protected String returnCode;

/** /**
* 返回信息 * 返回信息
*/ */
@XStreamAlias("return_msg") @XStreamAlias("return_msg")
protected String returnMsg; protected String returnMsg;
private String xmlString;
/** /**
* 业务结果 * 业务结果
*/ */
@XStreamAlias("result_code") @XStreamAlias("result_code")
private String resultCode; private String resultCode;

/** /**
* 错误代码 * 错误代码
*/ */
@XStreamAlias("err_code") @XStreamAlias("err_code")
private String errCode; private String errCode;

/** /**
* 错误代码描述 * 错误代码描述
*/ */
@XStreamAlias("err_code_des") @XStreamAlias("err_code_des")
private String errCodeDes; private String errCodeDes;

/** /**
* 公众账号ID * 公众账号ID
*/ */
@XStreamAlias("appid") @XStreamAlias("appid")
private String appid; private String appid;

/** /**
* 商户号 * 商户号
*/ */
@XStreamAlias("mch_id") @XStreamAlias("mch_id")
private String mchId; private String mchId;

/** /**
* 随机字符串 * 随机字符串
*/ */
@XStreamAlias("nonce_str") @XStreamAlias("nonce_str")
private String nonceStr; private String nonceStr;

/** /**
* 签名 * 签名
*/ */
@XStreamAlias("sign") @XStreamAlias("sign")
private String sign; private String sign;


/**
* 将单位分转换成单位圆
*
* @param fee 将要被转换为元的分的数值
*/
public static String feeToYuan(Integer fee) {
return new BigDecimal(Double.valueOf(fee) / 100).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString();
}

/**
* 从xml字符串创建bean对象
*/
public static <T extends WxPayBaseResult> T fromXML(String xmlString, Class<T> clz) {
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(clz);
T result = (T) xstream.fromXML(xmlString);
result.setXmlString(xmlString);
return result;
}

public String getXmlString() {
return this.xmlString;
}

public void setXmlString(String xmlString) {
this.xmlString = xmlString;
}

protected Logger getLogger() {
return LoggerFactory.getLogger(this.getClass());
}

@Override
public String toString() {
return ToStringUtils.toSimpleString(this);
}

public String getReturnCode() { public String getReturnCode() {
return this.returnCode; return this.returnCode;
} }
@@ -146,17 +180,56 @@ public abstract class WxPayBaseResult {
public void setSign(String sign) { public void setSign(String sign) {
this.sign = sign; this.sign = sign;
} }
/** /**
* 将单位分转换成单位圆
* @param fee
* @return
* 将bean通过保存的xml字符串转换成map
*/ */
public static String feeToYuan(Integer fee) {
return new BigDecimal(Double.valueOf(fee) / 100).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString();
}
public Map<String,String> toMap(){
return BeanUtils.xmlBean2Map(this);
public Map<String, String> toMap() {
Map<String, String> result = Maps.newHashMap();
XmlPath xmlPath = new XmlPath(this.xmlString);
NodeImpl rootNode = null;
try {
rootNode = xmlPath.get("xml");
} catch (XmlPathException e) {
throw new RuntimeException("xml数据有问题,请核实!");
}

if (rootNode == null) {
throw new RuntimeException("xml数据有问题,请核实!");
}

Iterator<Node> iterator = rootNode.children().nodeIterator();
while (iterator.hasNext()) {
Node node = iterator.next();
result.put(node.name(), node.value());
}

return result;
}

private String getXmlValue(XmlPath xmlPath, String path) {
if (xmlPath.get(path) instanceof NodeChildrenImpl) {
if (((NodeChildrenImpl) xmlPath.get(path)).size() == 0) {
return null;
}
}

return xmlPath.getString(path);
}

protected <T> T getXmlValue(XmlPath xmlPath, String path, Class<T> clz) {
String value = this.getXmlValue(xmlPath, path);
if (value == null) {
return null;
}

switch (clz.getSimpleName()) {
case "String":
return (T) value;
case "Integer":
return (T) Integer.valueOf(value);
}

throw new UnsupportedOperationException("暂时不支持此种类型的数据");
} }
} }

+ 15
- 0
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayCommonResult.java View File

@@ -0,0 +1,15 @@
package me.chanjar.weixin.mp.bean.pay.result;

import com.thoughtworks.xstream.annotations.XStreamAlias;

/**
* <pre>
* 微信支付结果仅包含有return 和result等相关信息的的属性类
* Created by Binary Wang on 2017-01-09.
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
* </pre>
*/

@XStreamAlias("xml")
public class WxPayCommonResult extends WxPayBaseResult {
}

+ 392
- 403
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayOrderNotifyResult.java View File

@@ -1,403 +1,392 @@
package me.chanjar.weixin.mp.bean.pay.result;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import me.chanjar.weixin.common.util.BeanUtils;
import me.chanjar.weixin.mp.bean.pay.WxPayOrderNotifyCoupon;
/**
* 支付结果通用通知 ,文档见:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7
* @author aimilin6688
* @since 2.5.0
*/
@XStreamAlias("xml")
public class WxPayOrderNotifyResult extends WxPayBaseResult implements Serializable {
/**
* @fields serialVersionUID
*/
private static final long serialVersionUID = 5389718115223345496L;
/**
* <pre>
* 设备号
* device_info
* 否
* String(32)
* 013467007045764
* 微信支付分配的终端设备号,
* </pre>
* @fields deviceInfo
*/
@XStreamAlias("device_info")
private String deviceInfo;
/**
* <pre>
* 用户标识
* openid
* 是
* String(128)
* wxd930ea5d5a258f4f
* 用户在商户appid下的唯一标识
* </pre>
* @fields openid
*/
@XStreamAlias("openid")
private String openid;
/**
* <pre>
* 是否关注公众账号
* is_subscribe
* 否
* String(1)
* Y
* 用户是否关注公众账号,Y-关注,N-未关注,仅在公众账号类型支付有效
* </pre>
* @fields isSubscribe
*/
@XStreamAlias("is_subscribe")
private String isSubscribe;
/**
* <pre>
* 交易类型
* trade_type
* 是
* String(16)
* JSAPI JSAPI、NATIVE、APP
* </pre>
* @fields tradeType
*/
@XStreamAlias("trade_type")
private String tradeType;
/**
* <pre>
* 付款银行
* bank_type
* 是
* String(16)
* CMC
* 银行类型,采用字符串类型的银行标识,银行类型见银行列表
* </pre>
* @fields bankType
*/
@XStreamAlias("bank_type")
private String bankType;
/**
* <pre>
* 订单金额
* total_fee
* 是
* Int
* 100
* 订单总金额,单位为分
* </pre>
* @fields totalFee
*/
@XStreamAlias("total_fee")
private Integer totalFee;
/**
* <pre>
* 应结订单金额
* settlement_total_fee
* 否
* Int
* 100
* 应结订单金额=订单金额-非充值代金券金额,应结订单金额<=订单金额。
* </pre>
* @fields settlementTotalFee
*/
@XStreamAlias("settlement_total_fee")
private Integer settlementTotalFee;
/**
* <pre>
* 货币种类
* fee_type
* 否
* String(8)
* CNY
* 货币类型,符合ISO4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型
* </pre>
* @fields feeType
*/
@XStreamAlias("fee_type")
private String feeType;
/**
* <pre>
* 现金支付金额
* cash_fee
* 是
* Int
* 100
* 现金支付金额订单现金支付金额,详见支付金额
* </pre>
* @fields cashFee
*/
@XStreamAlias("cash_fee")
private Integer cashFee;
/**
* <pre>
* 现金支付货币类型
* cash_fee_type
* 否
* String(16)
* CNY
* 货币类型,符合ISO4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型
* </pre>
* @fields cashFeeType
*/
@XStreamAlias("cash_fee_type")
private String cashFeeType;
/**
* <pre>
* 总代金券金额
* coupon_fee
* 否
* Int
* 10
* 代金券金额<=订单金额,订单金额-代金券金额=现金支付金额,详见支付金额
* </pre>
* @fields couponFee
*/
@XStreamAlias("coupon_fee")
private Integer couponFee;
/**
* <pre>
* 代金券使用数量
* coupon_count
* 否
* Int
* 1
* 代金券使用数量
*/
@XStreamAlias("coupon_count")
private Integer couponCount;
private List<WxPayOrderNotifyCoupon> couponList;
/**
* <pre>
* 微信支付订单号
* transaction_id
* 是
* String(32)
* 1217752501201407033233368018
* 微信支付订单号
* </pre>
* @fields transactionId
*/
@XStreamAlias("transaction_id")
private String transactionId;
/**
* <pre>
* 商户订单号
* out_trade_no
* 是
* String(32)
* 1212321211201407033568112322
* 商户系统的订单号,与请求一致。
* </pre>
* @fields outTradeNo
*/
@XStreamAlias("out_trade_no")
private String outTradeNo;
/**
* <pre>
* 商家数据包
* attach
* 否
* String(128)
* 123456
* 商家数据包,原样返回
* </pre>
* @fields
*/
@XStreamAlias("attach")
private String attach;
/**
* <pre>
* 支付完成时间
* time_end
* 是
* String(14)
* 20141030133525
* 支付完成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则
* </pre>
* @fields timeEnd
*/
@XStreamAlias("time_end")
private String timeEnd;
public Integer getCouponCount() {
return couponCount;
}
public void setCouponCount(Integer couponCount) {
this.couponCount = couponCount;
}
public List<WxPayOrderNotifyCoupon> getCouponList() {
return couponList;
}
public void setCouponList(List<WxPayOrderNotifyCoupon> couponList) {
this.couponList = couponList;
}
public String getDeviceInfo() {
return deviceInfo;
}
public void setDeviceInfo(String deviceInfo) {
this.deviceInfo = deviceInfo;
}
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public String getIsSubscribe() {
return isSubscribe;
}
public void setIsSubscribe(String isSubscribe) {
this.isSubscribe = isSubscribe;
}
public String getTradeType() {
return tradeType;
}
public void setTradeType(String tradeType) {
this.tradeType = tradeType;
}
public String getBankType() {
return bankType;
}
public void setBankType(String bankType) {
this.bankType = bankType;
}
public Integer getTotalFee() {
return totalFee;
}
public void setTotalFee(Integer totalFee) {
this.totalFee = totalFee;
}
public Integer getSettlementTotalFee() {
return settlementTotalFee;
}
public void setSettlementTotalFee(Integer settlementTotalFee) {
this.settlementTotalFee = settlementTotalFee;
}
public String getFeeType() {
return feeType;
}
public void setFeeType(String feeType) {
this.feeType = feeType;
}
public Integer getCashFee() {
return cashFee;
}
public void setCashFee(Integer cashFee) {
this.cashFee = cashFee;
}
public String getCashFeeType() {
return cashFeeType;
}
public void setCashFeeType(String cashFeeType) {
this.cashFeeType = cashFeeType;
}
public Integer getCouponFee() {
return couponFee;
}
public void setCouponFee(Integer couponFee) {
this.couponFee = couponFee;
}
public String getTransactionId() {
return transactionId;
}
public void setTransactionId(String transactionId) {
this.transactionId = transactionId;
}
public String getOutTradeNo() {
return outTradeNo;
}
public void setOutTradeNo(String outTradeNo) {
this.outTradeNo = outTradeNo;
}
public String getAttach() {
return attach;
}
public void setAttach(String attach) {
this.attach = attach;
}
public String getTimeEnd() {
return timeEnd;
}
public void setTimeEnd(String timeEnd) {
this.timeEnd = timeEnd;
}
@Override
public Map<String,String> toMap(){
Map<String,String> resultMap = BeanUtils.xmlBean2Map(this);
if(this.getCouponCount() != null && this.getCouponCount() > 0){
for (int i = 0; i < this.getCouponCount(); i++) {
WxPayOrderNotifyCoupon coupon = couponList.get(i);
resultMap.putAll(coupon.toMap(i));
}
}
return resultMap;
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this,ToStringStyle.MULTI_LINE_STYLE);
}
}
package me.chanjar.weixin.mp.bean.pay.result;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import me.chanjar.weixin.common.util.BeanUtils;
import me.chanjar.weixin.common.util.ToStringUtils;
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
import me.chanjar.weixin.mp.bean.pay.WxPayOrderNotifyCoupon;
import me.chanjar.weixin.mp.bean.pay.WxPayOrderNotifyResultConverter;

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

/**
* 支付结果通用通知 ,文档见:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7
* @author aimilin6688
* @since 2.5.0
*/
@XStreamAlias("xml")
public class WxPayOrderNotifyResult extends WxPayBaseResult implements Serializable {

private static final long serialVersionUID = 5389718115223345496L;


/**
* <pre>
* 设备号
* device_info
* 否
* String(32)
* 013467007045764
* 微信支付分配的终端设备号,
* </pre>
*/
@XStreamAlias("device_info")
private String deviceInfo;

/**
* <pre>
* 用户标识
* openid
* 是
* String(128)
* wxd930ea5d5a258f4f
* 用户在商户appid下的唯一标识
* </pre>
*/
@XStreamAlias("openid")
private String openid;

/**
* <pre>
* 是否关注公众账号
* is_subscribe
* 否
* String(1)
* Y
* 用户是否关注公众账号,Y-关注,N-未关注,仅在公众账号类型支付有效
* </pre>
*/
@XStreamAlias("is_subscribe")
private String isSubscribe;


/**
* <pre>
* 交易类型
* trade_type
* 是
* String(16)
* JSAPI JSAPI、NATIVE、APP
* </pre>
*/
@XStreamAlias("trade_type")
private String tradeType;


/**
* <pre>
* 付款银行
* bank_type
* 是
* String(16)
* CMC
* 银行类型,采用字符串类型的银行标识,银行类型见银行列表
* </pre>
*/
@XStreamAlias("bank_type")
private String bankType;


/**
* <pre>
* 订单金额
* total_fee
* 是
* Int
* 100
* 订单总金额,单位为分
* </pre>
*/
@XStreamAlias("total_fee")
private Integer totalFee;
/**
* <pre>
* 应结订单金额
* settlement_total_fee
* 否
* Int
* 100
* 应结订单金额=订单金额-非充值代金券金额,应结订单金额<=订单金额。
* </pre>
*/
@XStreamAlias("settlement_total_fee")
private Integer settlementTotalFee;
/**
* <pre>
* 货币种类
* fee_type
* 否
* String(8)
* CNY
* 货币类型,符合ISO4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型
* </pre>
*/
@XStreamAlias("fee_type")
private String feeType;
/**
* <pre>
* 现金支付金额
* cash_fee
* 是
* Int
* 100
* 现金支付金额订单现金支付金额,详见支付金额
* </pre>
*/
@XStreamAlias("cash_fee")
private Integer cashFee;
/**
* <pre>
* 现金支付货币类型
* cash_fee_type
* 否
* String(16)
* CNY
* 货币类型,符合ISO4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型
* </pre>
*/
@XStreamAlias("cash_fee_type")
private String cashFeeType;
/**
* <pre>
* 总代金券金额
* coupon_fee
* 否
* Int
* 10
* 代金券金额<=订单金额,订单金额-代金券金额=现金支付金额,详见支付金额
* </pre>
*/
@XStreamAlias("coupon_fee")
private Integer couponFee;

/**
* <pre>
* 代金券使用数量
* coupon_count
* 否
* Int
* 1
* 代金券使用数量
* </pre>
*/
@XStreamAlias("coupon_count")
private Integer couponCount;

private List<WxPayOrderNotifyCoupon> couponList;

/**
* <pre>
* 微信支付订单号
* transaction_id
* 是
* String(32)
* 1217752501201407033233368018
* 微信支付订单号
* </pre>
*/
@XStreamAlias("transaction_id")
private String transactionId;

/**
* <pre>
* 商户订单号
* out_trade_no
* 是
* String(32)
* 1212321211201407033568112322
* 商户系统的订单号,与请求一致。
* </pre>
*/
@XStreamAlias("out_trade_no")
private String outTradeNo;
/**
* <pre>
* 商家数据包
* attach
* 否
* String(128)
* 123456
* 商家数据包,原样返回
* </pre>
*/
@XStreamAlias("attach")
private String attach;
/**
* <pre>
* 支付完成时间
* time_end
* 是
* String(14)
* 20141030133525
* 支付完成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则
* </pre>
*/
@XStreamAlias("time_end")
private String timeEnd;

public Integer getCouponCount() {
return couponCount;
}

public void setCouponCount(Integer couponCount) {
this.couponCount = couponCount;
}

public List<WxPayOrderNotifyCoupon> getCouponList() {
return couponList;
}

public void setCouponList(List<WxPayOrderNotifyCoupon> couponList) {
this.couponList = couponList;
}

public String getDeviceInfo() {
return deviceInfo;
}

public void setDeviceInfo(String deviceInfo) {
this.deviceInfo = deviceInfo;
}

public String getOpenid() {
return openid;
}

public void setOpenid(String openid) {
this.openid = openid;
}

public String getIsSubscribe() {
return isSubscribe;
}

public void setIsSubscribe(String isSubscribe) {
this.isSubscribe = isSubscribe;
}

public String getTradeType() {
return tradeType;
}

public void setTradeType(String tradeType) {
this.tradeType = tradeType;
}

public String getBankType() {
return bankType;
}

public void setBankType(String bankType) {
this.bankType = bankType;
}

public Integer getTotalFee() {
return totalFee;
}

public void setTotalFee(Integer totalFee) {
this.totalFee = totalFee;
}

public Integer getSettlementTotalFee() {
return settlementTotalFee;
}

public void setSettlementTotalFee(Integer settlementTotalFee) {
this.settlementTotalFee = settlementTotalFee;
}

public String getFeeType() {
return feeType;
}

public void setFeeType(String feeType) {
this.feeType = feeType;
}

public Integer getCashFee() {
return cashFee;
}

public void setCashFee(Integer cashFee) {
this.cashFee = cashFee;
}

public String getCashFeeType() {
return cashFeeType;
}

public void setCashFeeType(String cashFeeType) {
this.cashFeeType = cashFeeType;
}

public Integer getCouponFee() {
return couponFee;
}

public void setCouponFee(Integer couponFee) {
this.couponFee = couponFee;
}

public String getTransactionId() {
return transactionId;
}

public void setTransactionId(String transactionId) {
this.transactionId = transactionId;
}

public String getOutTradeNo() {
return outTradeNo;
}

public void setOutTradeNo(String outTradeNo) {
this.outTradeNo = outTradeNo;
}

public String getAttach() {
return attach;
}

public void setAttach(String attach) {
this.attach = attach;
}

public String getTimeEnd() {
return timeEnd;
}

public void setTimeEnd(String timeEnd) {
this.timeEnd = timeEnd;
}

@Override
public Map<String,String> toMap(){
Map<String,String> resultMap = BeanUtils.xmlBean2Map(this);
if(this.getCouponCount() != null && this.getCouponCount() > 0){
for (int i = 0; i < this.getCouponCount(); i++) {
WxPayOrderNotifyCoupon coupon = couponList.get(i);
resultMap.putAll(coupon.toMap(i));
}
}
return resultMap;
}

@Override
public String toString() {
return ToStringUtils.toSimpleString(this);
}

public static WxPayOrderNotifyResult fromXML(String xmlString) {
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxPayOrderNotifyResult.class);
xstream.registerConverter(new WxPayOrderNotifyResultConverter(xstream.getMapper(), xstream.getReflectionProvider()));
WxPayOrderNotifyResult result = (WxPayOrderNotifyResult) xstream.fromXML(xmlString);
result.setXmlString(xmlString);
return result;
}
}

+ 81
- 76
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayOrderQueryResult.java View File

@@ -2,6 +2,7 @@ package me.chanjar.weixin.mp.bean.pay.result;


import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAlias;
import io.restassured.path.xml.XmlPath;


import java.util.List; import java.util.List;


@@ -17,6 +18,7 @@ import java.util.List;
* <li>示例值 * <li>示例值
* <li>描述 * <li>描述
* </pre> * </pre>
*
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a> * @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
*/ */
@XStreamAlias("xml") @XStreamAlias("xml")
@@ -179,75 +181,6 @@ public class WxPayOrderQueryResult extends WxPayBaseResult {
private Integer couponCount; private Integer couponCount;


private List<Coupon> coupons; private List<Coupon> coupons;

public static class Coupon {
/**
* <pre>代金券类型
* coupon_type_$n
* 否
* String
* CASH
* <li>CASH--充值代金券
* <li>NO_CASH---非充值代金券
* 订单使用代金券时有返回(取值:CASH、NO_CASH)。$n为下标,从0开始编号,举例:coupon_type_$0
* </pre>
*/
private String couponType;

/**
* <pre>代金券ID
* coupon_id_$n
* 否
* String(20)
* 10000
* 代金券ID, $n为下标,从0开始编号
* </pre>
*/
private String couponId;

/**
* <pre>单个代金券支付金额
* coupon_fee_$n
* 否
* Int
* 100
* 单个代金券支付金额, $n为下标,从0开始编号
* </pre>
*/
private Integer couponFee;

public Coupon(String couponType, String couponId, Integer couponFee) {
this.couponType = couponType;
this.couponId = couponId;
this.couponFee = couponFee;
}

public String getCouponType() {
return this.couponType;
}

public void setCouponType(String couponType) {
this.couponType = couponType;
}

public String getCouponId() {
return this.couponId;
}

public void setCouponId(String couponId) {
this.couponId = couponId;
}

public Integer getCouponFee() {
return this.couponFee;
}

public void setCouponFee(Integer couponFee) {
this.couponFee = couponFee;
}

}

/** /**
* <pre>微信支付订单号 * <pre>微信支付订单号
* transaction_id * transaction_id
@@ -259,7 +192,6 @@ public class WxPayOrderQueryResult extends WxPayBaseResult {
*/ */
@XStreamAlias("transaction_id") @XStreamAlias("transaction_id")
private String transactionId; private String transactionId;

/** /**
* <pre>商户订单号 * <pre>商户订单号
* out_trade_no * out_trade_no
@@ -271,7 +203,6 @@ public class WxPayOrderQueryResult extends WxPayBaseResult {
*/ */
@XStreamAlias("out_trade_no") @XStreamAlias("out_trade_no")
private String outTradeNo; private String outTradeNo;

/** /**
* <pre>附加数据 * <pre>附加数据
* attach * attach
@@ -283,7 +214,6 @@ public class WxPayOrderQueryResult extends WxPayBaseResult {
*/ */
@XStreamAlias("attach") @XStreamAlias("attach")
private String attach; private String attach;

/** /**
* <pre>支付完成时间 * <pre>支付完成时间
* time_end * time_end
@@ -295,7 +225,6 @@ public class WxPayOrderQueryResult extends WxPayBaseResult {
*/ */
@XStreamAlias("time_end") @XStreamAlias("time_end")
private String timeEnd; private String timeEnd;

/** /**
* <pre>交易状态描述 * <pre>交易状态描述
* trade_state_desc * trade_state_desc
@@ -460,10 +389,86 @@ public class WxPayOrderQueryResult extends WxPayBaseResult {
this.tradeStateDesc = tradeStateDesc; this.tradeStateDesc = tradeStateDesc;
} }


public void composeCoupons(String xmlString){
if(this.couponCount != null && this.couponCount > 0 ){
/**
* 通过xml组装coupons属性内容
*/
public void composeCoupons() {
if (this.couponCount != null && this.couponCount > 0) {
this.coupons = Lists.newArrayList(); this.coupons = Lists.newArrayList();
//TODO 暂时待实现
XmlPath xmlPath = new XmlPath(this.getXmlString());
for (int i = 0; i < this.couponCount; i++){
this.coupons.add(new Coupon(this.getXmlValue(xmlPath, "xml.coupon_type_" + i, String.class),
this.getXmlValue(xmlPath, "xml.coupon_id_" + i, String.class),
this.getXmlValue(xmlPath, "xml.coupon_fee_" + i, Integer.class)));
}
}
}

public static class Coupon {
/**
* <pre>代金券类型
* coupon_type_$n
* 否
* String
* CASH
* <li>CASH--充值代金券
* <li>NO_CASH---非充值代金券
* 订单使用代金券时有返回(取值:CASH、NO_CASH)。$n为下标,从0开始编号,举例:coupon_type_$0
* </pre>
*/
private String couponType;

/**
* <pre>代金券ID
* coupon_id_$n
* 否
* String(20)
* 10000
* 代金券ID, $n为下标,从0开始编号
* </pre>
*/
private String couponId;

/**
* <pre>单个代金券支付金额
* coupon_fee_$n
* 否
* Int
* 100
* 单个代金券支付金额, $n为下标,从0开始编号
* </pre>
*/
private Integer couponFee;

public Coupon(String couponType, String couponId, Integer couponFee) {
this.couponType = couponType;
this.couponId = couponId;
this.couponFee = couponFee;
}

public String getCouponType() {
return this.couponType;
}

public void setCouponType(String couponType) {
this.couponType = couponType;
} }

public String getCouponId() {
return this.couponId;
}

public void setCouponId(String couponId) {
this.couponId = couponId;
}

public Integer getCouponFee() {
return this.couponFee;
}

public void setCouponFee(Integer couponFee) {
this.couponFee = couponFee;
}

} }
} }

+ 6
- 5
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayRedpackQueryResult.java View File

@@ -15,6 +15,7 @@ import com.thoughtworks.xstream.annotations.XStreamAlias;
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a> * @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
* </pre> * </pre>
*/ */
@XStreamAlias("xml")
public class WxPayRedpackQueryResult extends WxPayBaseResult { public class WxPayRedpackQueryResult extends WxPayBaseResult {


/** /**
@@ -51,11 +52,11 @@ public class WxPayRedpackQueryResult extends WxPayBaseResult {
* RECEIVED * RECEIVED
* string(16) * string(16)
* SENDING:发放中, * SENDING:发放中,
* SENT:已发放待领取,
* FAILED:发放失败,
* RECEIVED:已领取,
* RFUND_ING:退款中,
* REFUND:已退款
* SENT:已发放待领取,
* FAILED:发放失败,
* RECEIVED:已领取,
* RFUND_ING:退款中,
* REFUND:已退款
* </pre> * </pre>
*/ */
@XStreamAlias("status") @XStreamAlias("status")


+ 60
- 16
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayRefundQueryResult.java View File

@@ -2,6 +2,7 @@ package me.chanjar.weixin.mp.bean.pay.result;


import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAlias;
import io.restassured.path.xml.XmlPath;


import java.util.List; import java.util.List;


@@ -183,10 +184,44 @@ public class WxPayRefundQueryResult extends WxPayBaseResult {
this.refundRecords = refundRecords; this.refundRecords = refundRecords;
} }


public void composeRefundRecords(String xmlString) {
/**
* 组装生成退款记录属性的内容
*/
public void composeRefundRecords() {
if (this.refundCount != null && this.refundCount > 0) { if (this.refundCount != null && this.refundCount > 0) {
this.refundRecords = Lists.newArrayList(); this.refundRecords = Lists.newArrayList();
//TODO 暂时待实现
XmlPath xmlPath = new XmlPath(this.getXmlString());

for (int i = 0; i < this.refundCount; i++) {
RefundRecord refundRecord = new RefundRecord();
this.refundRecords.add(refundRecord);

refundRecord.setOutRefundNo(this.getXmlValue(xmlPath, "xml.out_refund_no_" + i, String.class));
refundRecord.setRefundId(this.getXmlValue(xmlPath, "xml.refund_id_" + i, String.class));
refundRecord.setRefundChannel(this.getXmlValue(xmlPath, "xml.refund_channel_" + i, String.class));
refundRecord.setRefundFee(this.getXmlValue(xmlPath, "xml.refund_fee_" + i, Integer.class));
refundRecord.setSettlementRefundFee(this.getXmlValue(xmlPath, "xml.settlement_refund_fee_" + i, Integer.class));
refundRecord.setCouponType(this.getXmlValue(xmlPath, "xml.coupon_type_" + i, String.class));
refundRecord.setCouponRefundFee(this.getXmlValue(xmlPath, "xml.coupon_refund_fee_" + i, Integer.class));
refundRecord.setCouponRefundCount(this.getXmlValue(xmlPath, "xml.coupon_refund_count_" + i, Integer.class));
refundRecord.setRefundStatus(this.getXmlValue(xmlPath, "xml.refund_status_" + i, String.class));
refundRecord.setRefundRecvAccout(this.getXmlValue(xmlPath, "xml.refund_recv_accout_" + i, String.class));

if (refundRecord.getCouponRefundCount() == null || refundRecord.getCouponRefundCount() == 0) {
continue;
}

List<RefundRecord.RefundCoupon> coupons = Lists.newArrayList();
for (int j = 0; j < refundRecord.getCouponRefundCount(); j++) {
coupons.add(
new RefundRecord.RefundCoupon(
this.getXmlValue(xmlPath, "xml.coupon_refund_id_" + i + "_" + j, String.class),
this.getXmlValue(xmlPath, "xml.coupon_refund_fee_" + i + "_" + j, Integer.class)
)
);
}
}

} }
} }


@@ -241,7 +276,7 @@ public class WxPayRefundQueryResult extends WxPayBaseResult {
* </pre> * </pre>
*/ */
@XStreamAlias("refund_fee") @XStreamAlias("refund_fee")
private String refundFee;
private Integer refundFee;


/** /**
* <pre> * <pre>
@@ -254,7 +289,7 @@ public class WxPayRefundQueryResult extends WxPayBaseResult {
* </pre> * </pre>
*/ */
@XStreamAlias("settlement_refund_fee") @XStreamAlias("settlement_refund_fee")
private String settlementRefundFee;
private Integer settlementRefundFee;


/** /**
* <pre> * <pre>
@@ -293,7 +328,7 @@ public class WxPayRefundQueryResult extends WxPayBaseResult {
* </pre> * </pre>
*/ */
@XStreamAlias("coupon_refund_fee") @XStreamAlias("coupon_refund_fee")
private String couponRefundFee;
private Integer couponRefundFee;


/** /**
* <pre> * <pre>
@@ -306,7 +341,7 @@ public class WxPayRefundQueryResult extends WxPayBaseResult {
* </pre> * </pre>
*/ */
@XStreamAlias("coupon_refund_count") @XStreamAlias("coupon_refund_count")
private String couponRefundCount;
private Integer couponRefundCount;


private List<RefundCoupon> refundCoupons; private List<RefundCoupon> refundCoupons;


@@ -364,19 +399,19 @@ public class WxPayRefundQueryResult extends WxPayBaseResult {
this.refundChannel = refundChannel; this.refundChannel = refundChannel;
} }


public String getRefundFee() {
public Integer getRefundFee() {
return refundFee; return refundFee;
} }


public void setRefundFee(String refundFee) {
public void setRefundFee(Integer refundFee) {
this.refundFee = refundFee; this.refundFee = refundFee;
} }


public String getSettlementRefundFee() {
public Integer getSettlementRefundFee() {
return settlementRefundFee; return settlementRefundFee;
} }


public void setSettlementRefundFee(String settlementRefundFee) {
public void setSettlementRefundFee(Integer settlementRefundFee) {
this.settlementRefundFee = settlementRefundFee; this.settlementRefundFee = settlementRefundFee;
} }


@@ -396,19 +431,19 @@ public class WxPayRefundQueryResult extends WxPayBaseResult {
this.couponType = couponType; this.couponType = couponType;
} }


public String getCouponRefundFee() {
public Integer getCouponRefundFee() {
return couponRefundFee; return couponRefundFee;
} }


public void setCouponRefundFee(String couponRefundFee) {
public void setCouponRefundFee(Integer couponRefundFee) {
this.couponRefundFee = couponRefundFee; this.couponRefundFee = couponRefundFee;
} }


public String getCouponRefundCount() {
public Integer getCouponRefundCount() {
return couponRefundCount; return couponRefundCount;
} }


public void setCouponRefundCount(String couponRefundCount) {
public void setCouponRefundCount(Integer couponRefundCount) {
this.couponRefundCount = couponRefundCount; this.couponRefundCount = couponRefundCount;
} }


@@ -446,6 +481,8 @@ public class WxPayRefundQueryResult extends WxPayBaseResult {
* 100 * 100
* 退款代金券批次ID ,$n为下标,$m为下标,从0开始编号 * 退款代金券批次ID ,$n为下标,$m为下标,从0开始编号
* </pre> * </pre>
*
* @deprecated 貌似是被去掉了,但不知是何时!
*/ */
@XStreamAlias("coupon_refund_batch_id") @XStreamAlias("coupon_refund_batch_id")
private String couponRefundBatchId; private String couponRefundBatchId;
@@ -474,9 +511,15 @@ public class WxPayRefundQueryResult extends WxPayBaseResult {
* </pre> * </pre>
*/ */
@XStreamAlias("coupon_refund_fee") @XStreamAlias("coupon_refund_fee")
private String couponRefundFee;
private Integer couponRefundFee;

public RefundCoupon(String couponRefundId, Integer couponRefundFee) {
this.couponRefundId = couponRefundId;
this.couponRefundFee = couponRefundFee;
}


public RefundCoupon(String couponRefundBatchId, String couponRefundId, String couponRefundFee) {
@Deprecated
public RefundCoupon(String couponRefundBatchId, String couponRefundId, Integer couponRefundFee) {
this.couponRefundBatchId = couponRefundBatchId; this.couponRefundBatchId = couponRefundBatchId;
this.couponRefundId = couponRefundId; this.couponRefundId = couponRefundId;
this.couponRefundFee = couponRefundFee; this.couponRefundFee = couponRefundFee;
@@ -484,5 +527,6 @@ public class WxPayRefundQueryResult extends WxPayBaseResult {
} }


} }

} }



+ 9
- 0
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayUnifiedOrderResult.java View File

@@ -13,12 +13,21 @@ import com.thoughtworks.xstream.annotations.XStreamAlias;
@XStreamAlias("xml") @XStreamAlias("xml")
public class WxPayUnifiedOrderResult extends WxPayBaseResult { public class WxPayUnifiedOrderResult extends WxPayBaseResult {


/**
* 微信生成的预支付回话标识,用于后续接口调用中使用,该值有效期为2小时
*/
@XStreamAlias("prepay_id") @XStreamAlias("prepay_id")
private String prepayId; private String prepayId;


/**
* 交易类型,取值为:JSAPI,NATIVE,APP等
*/
@XStreamAlias("trade_type") @XStreamAlias("trade_type")
private String tradeType; private String tradeType;


/**
* trade_type为NATIVE时有返回,用于生成二维码,展示给用户进行扫码支付
*/
@XStreamAlias("code_url") @XStreamAlias("code_url")
private String codeURL; private String codeURL;




+ 1
- 1
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMassTagMessageGsonAdapter.java View File

@@ -24,7 +24,7 @@ public class WxMpMassTagMessageGsonAdapter implements JsonSerializer<WxMpMassTag
JsonObject messageJson = new JsonObject(); JsonObject messageJson = new JsonObject();


JsonObject filter = new JsonObject(); JsonObject filter = new JsonObject();
if (null == message.getTagId()) {
if (message.isSendAll() || null == message.getTagId()) {
filter.addProperty("is_to_all", true); filter.addProperty("is_to_all", true);
} else { } else {
filter.addProperty("is_to_all", false); filter.addProperty("is_to_all", false);


+ 4
- 4
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpBaseAPITest.java View File

@@ -2,15 +2,15 @@ package me.chanjar.weixin.mp.api;


import com.google.inject.Inject; import com.google.inject.Inject;
import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.test.ApiTestModule;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.testng.Assert;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
import org.testng.*;
import org.testng.annotations.*;


/** /**
* 基础API测试 * 基础API测试
* @author chanjarster
* *
* @author chanjarster
*/ */
@Test(groups = "baseAPI") @Test(groups = "baseAPI")
@Guice(modules = ApiTestModule.class) @Guice(modules = ApiTestModule.class)


+ 5
- 6
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpBusyRetryTest.java View File

@@ -4,8 +4,7 @@ import me.chanjar.weixin.common.bean.result.WxError;
import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.util.http.RequestExecutor; import me.chanjar.weixin.common.util.http.RequestExecutor;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.testng.annotations.*;


import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
@@ -15,14 +14,14 @@ import java.util.concurrent.Future;
@Test @Test
public class WxMpBusyRetryTest { public class WxMpBusyRetryTest {


@DataProvider(name="getService")
@DataProvider(name = "getService")
public Object[][] getService() { public Object[][] getService() {
WxMpService service = new WxMpServiceImpl() { WxMpService service = new WxMpServiceImpl() {


@Override @Override
protected synchronized <T, E> T executeInternal( protected synchronized <T, E> T executeInternal(
RequestExecutor<T, E> executor, String uri, E data)
throws WxErrorException {
RequestExecutor<T, E> executor, String uri, E data)
throws WxErrorException {
this.log.info("Executed"); this.log.info("Executed");
WxError error = new WxError(); WxError error = new WxError();
error.setErrorCode(-1); error.setErrorCode(-1);
@@ -32,7 +31,7 @@ public class WxMpBusyRetryTest {


service.setMaxRetryTimes(3); service.setMaxRetryTimes(3);
service.setRetrySleepMillis(500); service.setRetrySleepMillis(500);
return new Object[][] { { service } };
return new Object[][]{{service}};
} }


@Test(dataProvider = "getService", expectedExceptions = RuntimeException.class) @Test(dataProvider = "getService", expectedExceptions = RuntimeException.class)


+ 7
- 9
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpJsAPITest.java View File

@@ -1,13 +1,11 @@
package me.chanjar.weixin.mp.api; package me.chanjar.weixin.mp.api;


import org.testng.Assert;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;

import com.google.inject.Inject; import com.google.inject.Inject;

import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.util.crypto.SHA1; import me.chanjar.weixin.common.util.crypto.SHA1;
import me.chanjar.weixin.mp.api.test.ApiTestModule;
import org.testng.*;
import org.testng.annotations.*;


/** /**
* 测试jsapi ticket接口 * 测试jsapi ticket接口
@@ -34,10 +32,10 @@ public class WxMpJsAPITest {
String noncestr = "82693e11-b9bc-448e-892f-f5289f46cd0f"; String noncestr = "82693e11-b9bc-448e-892f-f5289f46cd0f";
String jsapiTicket = "bxLdikRXVbTPdHSM05e5u4RbEYQn7pNQMPrfzl8lJNb1foLDa3HIwI3BRMkQmSO_5F64VFa75uURcq6Uz7QHgA"; String jsapiTicket = "bxLdikRXVbTPdHSM05e5u4RbEYQn7pNQMPrfzl8lJNb1foLDa3HIwI3BRMkQmSO_5F64VFa75uURcq6Uz7QHgA";
String result = SHA1.genWithAmple( String result = SHA1.genWithAmple(
"jsapi_ticket=" + jsapiTicket,
"noncestr=" + noncestr,
"timestamp=" + timestamp,
"url=" + url
"jsapi_ticket=" + jsapiTicket,
"noncestr=" + noncestr,
"timestamp=" + timestamp,
"url=" + url
); );


Assert.assertEquals(result, "c6f04b64d6351d197b71bd23fb7dd2d44c0db486"); Assert.assertEquals(result, "c6f04b64d6351d197b71bd23fb7dd2d44c0db486");


+ 11
- 13
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMassMessageAPITest.java View File

@@ -4,16 +4,16 @@ import com.google.inject.Inject;
import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.test.ApiTestModule;
import me.chanjar.weixin.mp.api.test.TestConfigStorage;
import me.chanjar.weixin.mp.bean.WxMpMassNews; import me.chanjar.weixin.mp.bean.WxMpMassNews;
import me.chanjar.weixin.mp.bean.WxMpMassOpenIdsMessage; import me.chanjar.weixin.mp.bean.WxMpMassOpenIdsMessage;
import me.chanjar.weixin.mp.bean.WxMpMassTagMessage; import me.chanjar.weixin.mp.bean.WxMpMassTagMessage;
import me.chanjar.weixin.mp.bean.WxMpMassVideo; import me.chanjar.weixin.mp.bean.WxMpMassVideo;
import me.chanjar.weixin.mp.bean.result.WxMpMassSendResult; import me.chanjar.weixin.mp.bean.result.WxMpMassSendResult;
import me.chanjar.weixin.mp.bean.result.WxMpMassUploadResult; import me.chanjar.weixin.mp.bean.result.WxMpMassUploadResult;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
import org.testng.*;
import org.testng.annotations.*;


import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@@ -33,7 +33,7 @@ public class WxMpMassMessageAPITest {
@Test @Test
public void testTextMassOpenIdsMessageSend() throws WxErrorException { public void testTextMassOpenIdsMessageSend() throws WxErrorException {
// 发送群发消息 // 发送群发消息
WxXmlMpInMemoryConfigStorage configProvider = (WxXmlMpInMemoryConfigStorage) this.wxService
TestConfigStorage configProvider = (TestConfigStorage) this.wxService
.getWxMpConfigStorage(); .getWxMpConfigStorage();
WxMpMassOpenIdsMessage massMessage = new WxMpMassOpenIdsMessage(); WxMpMassOpenIdsMessage massMessage = new WxMpMassOpenIdsMessage();
massMessage.setMsgType(WxConsts.MASS_MSG_TEXT); massMessage.setMsgType(WxConsts.MASS_MSG_TEXT);
@@ -47,10 +47,9 @@ public class WxMpMassMessageAPITest {
} }


@Test(dataProvider = "massMessages") @Test(dataProvider = "massMessages")
public void testMediaMassOpenIdsMessageSend(String massMsgType,
String mediaId) throws WxErrorException {
public void testMediaMassOpenIdsMessageSend(String massMsgType, String mediaId) throws WxErrorException {
// 发送群发消息 // 发送群发消息
WxXmlMpInMemoryConfigStorage configProvider = (WxXmlMpInMemoryConfigStorage) this.wxService
TestConfigStorage configProvider = (TestConfigStorage) this.wxService
.getWxMpConfigStorage(); .getWxMpConfigStorage();
WxMpMassOpenIdsMessage massMessage = new WxMpMassOpenIdsMessage(); WxMpMassOpenIdsMessage massMessage = new WxMpMassOpenIdsMessage();
massMessage.setMsgType(massMsgType); massMessage.setMsgType(massMsgType);
@@ -83,8 +82,7 @@ public class WxMpMassMessageAPITest {
WxMpMassTagMessage massMessage = new WxMpMassTagMessage(); WxMpMassTagMessage massMessage = new WxMpMassTagMessage();
massMessage.setMsgType(massMsgType); massMessage.setMsgType(massMsgType);
massMessage.setMediaId(mediaId); massMessage.setMediaId(mediaId);
massMessage
.setTagId(this.wxService.getUserTagService().tagGet().get(0).getId());
massMessage.setTagId(this.wxService.getUserTagService().tagGet().get(0).getId());


WxMpMassSendResult massResult = this.wxService WxMpMassSendResult massResult = this.wxService
.massGroupMessageSend(massMessage); .massGroupMessageSend(massMessage);
@@ -118,7 +116,7 @@ public class WxMpMassMessageAPITest {
messages[0] = new Object[]{WxConsts.MASS_MSG_VIDEO, uploadResult.getMediaId()}; messages[0] = new Object[]{WxConsts.MASS_MSG_VIDEO, uploadResult.getMediaId()};
} }


/**
/*
* 图片素材 * 图片素材
*/ */
try (InputStream inputStream = ClassLoader try (InputStream inputStream = ClassLoader
@@ -130,7 +128,7 @@ public class WxMpMassMessageAPITest {
messages[1] = new Object[]{WxConsts.MASS_MSG_IMAGE, uploadMediaRes.getMediaId()}; messages[1] = new Object[]{WxConsts.MASS_MSG_IMAGE, uploadMediaRes.getMediaId()};
} }


/**
/*
* 语音素材 * 语音素材
*/ */
try (InputStream inputStream = ClassLoader try (InputStream inputStream = ClassLoader
@@ -142,7 +140,7 @@ public class WxMpMassMessageAPITest {
messages[2] = new Object[]{WxConsts.MASS_MSG_VOICE, uploadMediaRes.getMediaId()}; messages[2] = new Object[]{WxConsts.MASS_MSG_VOICE, uploadMediaRes.getMediaId()};
} }


/**
/*
* 图文素材 * 图文素材
*/ */
try (InputStream inputStream = ClassLoader try (InputStream inputStream = ClassLoader


+ 67
- 67
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMessageRouterTest.java View File

@@ -5,16 +5,15 @@ import me.chanjar.weixin.common.session.StandardSessionManager;
import me.chanjar.weixin.common.session.WxSessionManager; import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.testng.*;
import org.testng.annotations.*;


import java.util.Map; import java.util.Map;


/** /**
* 测试消息路由器 * 测试消息路由器
* @author chanjarster
* *
* @author chanjarster
*/ */
@Test @Test
public class WxMpMessageRouterTest { public class WxMpMessageRouterTest {
@@ -23,19 +22,19 @@ public class WxMpMessageRouterTest {
public void prepare(boolean async, StringBuffer sb, WxMpMessageRouter router) { public void prepare(boolean async, StringBuffer sb, WxMpMessageRouter router) {
router router
.rule() .rule()
.async(async)
.msgType(WxConsts.XML_MSG_TEXT).event(WxConsts.EVT_CLICK).eventKey("KEY_1").content("CONTENT_1")
.handler(new WxEchoMpMessageHandler(sb, "COMBINE_4"))
.async(async)
.msgType(WxConsts.XML_MSG_TEXT).event(WxConsts.EVT_CLICK).eventKey("KEY_1").content("CONTENT_1")
.handler(new WxEchoMpMessageHandler(sb, "COMBINE_4"))
.end() .end()
.rule() .rule()
.async(async)
.msgType(WxConsts.XML_MSG_TEXT).event(WxConsts.EVT_CLICK).eventKey("KEY_1")
.handler(new WxEchoMpMessageHandler(sb, "COMBINE_3"))
.async(async)
.msgType(WxConsts.XML_MSG_TEXT).event(WxConsts.EVT_CLICK).eventKey("KEY_1")
.handler(new WxEchoMpMessageHandler(sb, "COMBINE_3"))
.end() .end()
.rule() .rule()
.async(async)
.msgType(WxConsts.XML_MSG_TEXT).event(WxConsts.EVT_CLICK)
.handler(new WxEchoMpMessageHandler(sb, "COMBINE_2"))
.async(async)
.msgType(WxConsts.XML_MSG_TEXT).event(WxConsts.EVT_CLICK)
.handler(new WxEchoMpMessageHandler(sb, "COMBINE_2"))
.end() .end()
.rule().async(async).msgType(WxConsts.XML_MSG_TEXT).handler(new WxEchoMpMessageHandler(sb, WxConsts.XML_MSG_TEXT)).end() .rule().async(async).msgType(WxConsts.XML_MSG_TEXT).handler(new WxEchoMpMessageHandler(sb, WxConsts.XML_MSG_TEXT)).end()
.rule().async(async).event(WxConsts.EVT_CLICK).handler(new WxEchoMpMessageHandler(sb, WxConsts.EVT_CLICK)).end() .rule().async(async).event(WxConsts.EVT_CLICK).handler(new WxEchoMpMessageHandler(sb, WxConsts.EVT_CLICK)).end()
@@ -43,15 +42,15 @@ public class WxMpMessageRouterTest {
.rule().async(async).content("CONTENT_1").handler(new WxEchoMpMessageHandler(sb, "CONTENT_1")).end() .rule().async(async).content("CONTENT_1").handler(new WxEchoMpMessageHandler(sb, "CONTENT_1")).end()
.rule().async(async).rContent(".*bc.*").handler(new WxEchoMpMessageHandler(sb, "abcd")).end() .rule().async(async).rContent(".*bc.*").handler(new WxEchoMpMessageHandler(sb, "abcd")).end()
.rule().async(async).matcher(new WxMpMessageMatcher() { .rule().async(async).matcher(new WxMpMessageMatcher() {
@Override
public boolean match(WxMpXmlMessage message) {
return "strangeformat".equals(message.getFormat());
}
}).handler(new WxEchoMpMessageHandler(sb, "matcher")).end()
@Override
public boolean match(WxMpXmlMessage message) {
return "strangeformat".equals(message.getFormat());
}
}).handler(new WxEchoMpMessageHandler(sb, "matcher")).end()
.rule().async(async).handler(new WxEchoMpMessageHandler(sb, "ALL")).end(); .rule().async(async).handler(new WxEchoMpMessageHandler(sb, "ALL")).end();
} }


@Test(dataProvider="messages-1")
@Test(dataProvider = "messages-1")
public void testSync(WxMpXmlMessage message, String expected) { public void testSync(WxMpXmlMessage message, String expected) {
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
WxMpMessageRouter router = new WxMpMessageRouter(null); WxMpMessageRouter router = new WxMpMessageRouter(null);
@@ -60,11 +59,11 @@ public class WxMpMessageRouterTest {
Assert.assertEquals(sb.toString(), expected); Assert.assertEquals(sb.toString(), expected);
} }


@Test(dataProvider="messages-1")
@Test(dataProvider = "messages-1")
public void testAsync(WxMpXmlMessage message, String expected) throws InterruptedException { public void testAsync(WxMpXmlMessage message, String expected) throws InterruptedException {
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
WxMpMessageRouter router = new WxMpMessageRouter(null); WxMpMessageRouter router = new WxMpMessageRouter(null);
prepare(true, sb, router);
prepare(true, sb, router);
router.route(message); router.route(message);
Thread.sleep(500l); Thread.sleep(500l);
Assert.assertEquals(sb.toString(), expected); Assert.assertEquals(sb.toString(), expected);
@@ -75,7 +74,7 @@ public class WxMpMessageRouterTest {
router.rule().handler(new WxMpMessageHandler() { router.rule().handler(new WxMpMessageHandler() {
@Override @Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService,
WxSessionManager sessionManager) {
WxSessionManager sessionManager) {
return null; return null;
} }
}).end(); }).end();
@@ -97,7 +96,8 @@ public class WxMpMessageRouterTest {


Thread.sleep(1000l * 2); Thread.sleep(1000l * 2);
} }
@DataProvider(name="messages-1")

@DataProvider(name = "messages-1")
public Object[][] messages2() { public Object[][] messages2() {
WxMpXmlMessage message1 = new WxMpXmlMessage(); WxMpXmlMessage message1 = new WxMpXmlMessage();
message1.setMsgType(WxConsts.XML_MSG_TEXT); message1.setMsgType(WxConsts.XML_MSG_TEXT);
@@ -135,40 +135,21 @@ public class WxMpMessageRouterTest {
c4.setEventKey("KEY_1"); c4.setEventKey("KEY_1");
c4.setContent("CONTENT_1"); c4.setContent("CONTENT_1");


return new Object[][] {
new Object[] { message1, WxConsts.XML_MSG_TEXT + "," },
new Object[] { message2, WxConsts.EVT_CLICK + "," },
new Object[] { message3, "KEY_1," },
new Object[] { message4, "CONTENT_1," },
new Object[] { message5, "ALL," },
new Object[] { message6, "abcd," },
new Object[] { message7, "matcher," },
new Object[] { c2, "COMBINE_2," },
new Object[] { c3, "COMBINE_3," },
new Object[] { c4, "COMBINE_4," }
return new Object[][]{
new Object[]{message1, WxConsts.XML_MSG_TEXT + ","},
new Object[]{message2, WxConsts.EVT_CLICK + ","},
new Object[]{message3, "KEY_1,"},
new Object[]{message4, "CONTENT_1,"},
new Object[]{message5, "ALL,"},
new Object[]{message6, "abcd,"},
new Object[]{message7, "matcher,"},
new Object[]{c2, "COMBINE_2,"},
new Object[]{c3, "COMBINE_3,"},
new Object[]{c4, "COMBINE_4,"}
}; };


} }


public static class WxEchoMpMessageHandler implements WxMpMessageHandler {

private StringBuffer sb;
private String echoStr;

public WxEchoMpMessageHandler(StringBuffer sb, String echoStr) {
this.sb = sb;
this.echoStr = echoStr;
}

@Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService,
WxSessionManager sessionManager) {
this.sb.append(this.echoStr).append(',');
return null;
}

}

@DataProvider @DataProvider
public Object[][] standardSessionManager() { public Object[][] standardSessionManager() {


@@ -178,8 +159,8 @@ public class WxMpMessageRouterTest {
ism.setProcessExpiresFrequency(1); ism.setProcessExpiresFrequency(1);
ism.setBackgroundProcessorDelay(1); ism.setBackgroundProcessorDelay(1);


return new Object[][] {
new Object[] { ism }
return new Object[][]{
new Object[]{ism}
}; };


} }
@@ -191,8 +172,8 @@ public class WxMpMessageRouterTest {
final WxMpMessageRouter router = new WxMpMessageRouter(null); final WxMpMessageRouter router = new WxMpMessageRouter(null);
router.setSessionManager(ism); router.setSessionManager(ism);
router router
.rule().async(false).handler(new WxSessionMessageHandler()).next()
.rule().async(false).handler(new WxSessionMessageHandler()).end();
.rule().async(false).handler(new WxSessionMessageHandler()).next()
.rule().async(false).handler(new WxSessionMessageHandler()).end();


WxMpXmlMessage msg = new WxMpXmlMessage(); WxMpXmlMessage msg = new WxMpXmlMessage();
msg.setFromUser("abc"); msg.setFromUser("abc");
@@ -211,8 +192,8 @@ public class WxMpMessageRouterTest {
final WxMpMessageRouter router = new WxMpMessageRouter(null); final WxMpMessageRouter router = new WxMpMessageRouter(null);
router.setSessionManager(ism); router.setSessionManager(ism);
router router
.rule().async(false).handler(new WxSessionMessageHandler()).next()
.rule().async(true).handler(new WxSessionMessageHandler()).end();
.rule().async(false).handler(new WxSessionMessageHandler()).next()
.rule().async(true).handler(new WxSessionMessageHandler()).end();


WxMpXmlMessage msg = new WxMpXmlMessage(); WxMpXmlMessage msg = new WxMpXmlMessage();
msg.setFromUser("abc"); msg.setFromUser("abc");
@@ -225,8 +206,8 @@ public class WxMpMessageRouterTest {
final WxMpMessageRouter router = new WxMpMessageRouter(null); final WxMpMessageRouter router = new WxMpMessageRouter(null);
router.setSessionManager(ism); router.setSessionManager(ism);
router router
.rule().async(true).handler(new WxSessionMessageHandler()).next()
.rule().async(false).handler(new WxSessionMessageHandler()).end();
.rule().async(true).handler(new WxSessionMessageHandler()).next()
.rule().async(false).handler(new WxSessionMessageHandler()).end();


WxMpXmlMessage msg = new WxMpXmlMessage(); WxMpXmlMessage msg = new WxMpXmlMessage();
msg.setFromUser("abc"); msg.setFromUser("abc");
@@ -245,8 +226,8 @@ public class WxMpMessageRouterTest {
final WxMpMessageRouter router = new WxMpMessageRouter(null); final WxMpMessageRouter router = new WxMpMessageRouter(null);
router.setSessionManager(ism); router.setSessionManager(ism);
router router
.rule().async(true).handler(new WxSessionMessageHandler()).next()
.rule().async(true).handler(new WxSessionMessageHandler()).end();
.rule().async(true).handler(new WxSessionMessageHandler()).next()
.rule().async(true).handler(new WxSessionMessageHandler()).end();


WxMpXmlMessage msg = new WxMpXmlMessage(); WxMpXmlMessage msg = new WxMpXmlMessage();
msg.setFromUser("abc"); msg.setFromUser("abc");
@@ -265,7 +246,7 @@ public class WxMpMessageRouterTest {
final WxMpMessageRouter router = new WxMpMessageRouter(null); final WxMpMessageRouter router = new WxMpMessageRouter(null);
router.setSessionManager(ism); router.setSessionManager(ism);
router router
.rule().async(false).handler(new WxSessionMessageHandler()).end();
.rule().async(false).handler(new WxSessionMessageHandler()).end();


WxMpXmlMessage msg = new WxMpXmlMessage(); WxMpXmlMessage msg = new WxMpXmlMessage();
msg.setFromUser("abc"); msg.setFromUser("abc");
@@ -279,7 +260,7 @@ public class WxMpMessageRouterTest {
final WxMpMessageRouter router = new WxMpMessageRouter(null); final WxMpMessageRouter router = new WxMpMessageRouter(null);
router.setSessionManager(ism); router.setSessionManager(ism);
router router
.rule().async(true).handler(new WxSessionMessageHandler()).end();
.rule().async(true).handler(new WxSessionMessageHandler()).end();


WxMpXmlMessage msg = new WxMpXmlMessage(); WxMpXmlMessage msg = new WxMpXmlMessage();
msg.setFromUser("abc"); msg.setFromUser("abc");
@@ -290,11 +271,30 @@ public class WxMpMessageRouterTest {
} }
} }


public static class WxSessionMessageHandler implements WxMpMessageHandler {
public static class WxEchoMpMessageHandler implements WxMpMessageHandler {

private StringBuffer sb;
private String echoStr;

public WxEchoMpMessageHandler(StringBuffer sb, String echoStr) {
this.sb = sb;
this.echoStr = echoStr;
}

@Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService,
WxSessionManager sessionManager) {
this.sb.append(this.echoStr).append(',');
return null;
}

}

public static class WxSessionMessageHandler implements WxMpMessageHandler {


@Override @Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService,
WxSessionManager sessionManager) {
WxSessionManager sessionManager) {
sessionManager.getSession(wxMessage.getFromUser()); sessionManager.getSession(wxMessage.getFromUser());
return null; return null;
} }


+ 3
- 5
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMiscAPITest.java View File

@@ -2,16 +2,14 @@ package me.chanjar.weixin.mp.api;


import com.google.inject.Inject; import com.google.inject.Inject;
import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.exception.WxErrorException;
import org.testng.Assert;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
import me.chanjar.weixin.mp.api.test.ApiTestModule;
import org.testng.*;
import org.testng.annotations.*;


import java.util.Arrays; import java.util.Arrays;


/** /**
*
* @author chanjarster * @author chanjarster
*
*/ */
@Test(groups = "miscAPI") @Test(groups = "miscAPI")
@Guice(modules = ApiTestModule.class) @Guice(modules = ApiTestModule.class)


+ 3
- 3
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpShortUrlAPITest.java View File

@@ -2,9 +2,9 @@ package me.chanjar.weixin.mp.api;


import com.google.inject.Inject; import com.google.inject.Inject;
import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.exception.WxErrorException;
import org.testng.Assert;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
import me.chanjar.weixin.mp.api.test.ApiTestModule;
import org.testng.*;
import org.testng.annotations.*;


/** /**
* 测试短连接 * 测试短连接


+ 4
- 4
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpCardServiceImplTest.java View File

@@ -2,17 +2,17 @@ package me.chanjar.weixin.mp.api.impl;


import com.google.inject.Inject; import com.google.inject.Inject;
import me.chanjar.weixin.common.bean.WxCardApiSignature; import me.chanjar.weixin.common.bean.WxCardApiSignature;
import me.chanjar.weixin.mp.api.ApiTestModule;
import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.test.ApiTestModule;
import me.chanjar.weixin.mp.bean.result.WxMpCardResult; import me.chanjar.weixin.mp.bean.result.WxMpCardResult;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
import org.testng.annotations.*;


import static org.testng.AssertJUnit.assertNotNull;
import static org.testng.AssertJUnit.*;


/** /**
* 测试代码仅供参考,未做严格测试,因原接口作者并未提供单元测试代码 * 测试代码仅供参考,未做严格测试,因原接口作者并未提供单元测试代码
* Created by Binary Wang on 2016/7/27. * Created by Binary Wang on 2016/7/27.
*
* @author binarywang (https://github.com/binarywang) * @author binarywang (https://github.com/binarywang)
*/ */
@Test @Test


+ 43
- 52
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpDataCubeServiceImplTest.java View File

@@ -1,83 +1,74 @@
package me.chanjar.weixin.mp.api.impl; package me.chanjar.weixin.mp.api.impl;


import java.text.ParseException;
import java.util.Date;
import java.util.List;

import com.google.inject.Inject;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.test.ApiTestModule;
import me.chanjar.weixin.mp.bean.datacube.*;
import org.apache.commons.lang3.time.FastDateFormat; import org.apache.commons.lang3.time.FastDateFormat;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;

import com.google.inject.Inject;
import org.testng.*;
import org.testng.annotations.*;


import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.ApiTestModule;
import me.chanjar.weixin.mp.bean.datacube.WxDataCubeArticleResult;
import me.chanjar.weixin.mp.bean.datacube.WxDataCubeArticleTotal;
import me.chanjar.weixin.mp.bean.datacube.WxDataCubeInterfaceResult;
import me.chanjar.weixin.mp.bean.datacube.WxDataCubeMsgResult;
import me.chanjar.weixin.mp.bean.datacube.WxDataCubeUserCumulate;
import me.chanjar.weixin.mp.bean.datacube.WxDataCubeUserSummary;
import java.text.ParseException;
import java.util.Date;
import java.util.List;


/** /**
* 测试统计分析相关的接口 * 测试统计分析相关的接口
* Created by Binary Wang on 2016/8/23.
* Created by Binary Wang on 2016/8/23.
*
* @author binarywang (https://github.com/binarywang) * @author binarywang (https://github.com/binarywang)
*/ */
@Guice(modules = ApiTestModule.class) @Guice(modules = ApiTestModule.class)
public class WxMpDataCubeServiceImplTest { public class WxMpDataCubeServiceImplTest {
private FastDateFormat simpleDateFormat = FastDateFormat
.getInstance("yyyy-MM-dd");

@Inject @Inject
protected WxMpService wxService; protected WxMpService wxService;
private FastDateFormat simpleDateFormat = FastDateFormat
.getInstance("yyyy-MM-dd");


@DataProvider @DataProvider
public Object[][] oneDay() throws ParseException { public Object[][] oneDay() throws ParseException {
return new Object[][] { { this.simpleDateFormat.parse("2016-08-22") } };
return new Object[][]{{this.simpleDateFormat.parse("2016-08-22")}};
} }


@DataProvider @DataProvider
public Object[][] threeDays() throws ParseException { public Object[][] threeDays() throws ParseException {
return new Object[][] { { this.simpleDateFormat.parse("2016-08-20"),
this.simpleDateFormat.parse("2016-08-22") } };
return new Object[][]{{this.simpleDateFormat.parse("2016-08-20"),
this.simpleDateFormat.parse("2016-08-22")}};
} }


@DataProvider @DataProvider
public Object[][] sevenDays() throws ParseException { public Object[][] sevenDays() throws ParseException {
return new Object[][] { { this.simpleDateFormat.parse("2016-08-16"),
this.simpleDateFormat.parse("2016-08-22") } };
return new Object[][]{{this.simpleDateFormat.parse("2016-08-16"),
this.simpleDateFormat.parse("2016-08-22")}};
} }


@DataProvider @DataProvider
public Object[][] fifteenDays() throws ParseException { public Object[][] fifteenDays() throws ParseException {
return new Object[][] { { this.simpleDateFormat.parse("2016-08-14"),
this.simpleDateFormat.parse("2016-08-27") } };
return new Object[][]{{this.simpleDateFormat.parse("2016-08-14"),
this.simpleDateFormat.parse("2016-08-27")}};
} }


@DataProvider @DataProvider
public Object[][] thirtyDays() throws ParseException { public Object[][] thirtyDays() throws ParseException {
return new Object[][] { { this.simpleDateFormat.parse("2016-07-30"),
this.simpleDateFormat.parse("2016-08-27") } };
return new Object[][]{{this.simpleDateFormat.parse("2016-07-30"),
this.simpleDateFormat.parse("2016-08-27")}};
} }


@Test(dataProvider = "sevenDays") @Test(dataProvider = "sevenDays")
public void testGetUserSummary(Date beginDate, Date endDate) public void testGetUserSummary(Date beginDate, Date endDate)
throws WxErrorException {
throws WxErrorException {
List<WxDataCubeUserSummary> summaries = this.wxService.getDataCubeService() List<WxDataCubeUserSummary> summaries = this.wxService.getDataCubeService()
.getUserSummary(beginDate, endDate);
.getUserSummary(beginDate, endDate);
Assert.assertNotNull(summaries); Assert.assertNotNull(summaries);
System.out.println(summaries); System.out.println(summaries);
} }


@Test(dataProvider = "sevenDays") @Test(dataProvider = "sevenDays")
public void testGetUserCumulate(Date beginDate, Date endDate) public void testGetUserCumulate(Date beginDate, Date endDate)
throws WxErrorException {
throws WxErrorException {
List<WxDataCubeUserCumulate> result = this.wxService.getDataCubeService() List<WxDataCubeUserCumulate> result = this.wxService.getDataCubeService()
.getUserCumulate(beginDate, endDate);
.getUserCumulate(beginDate, endDate);
Assert.assertNotNull(result); Assert.assertNotNull(result);
System.out.println(result); System.out.println(result);
} }
@@ -85,7 +76,7 @@ public class WxMpDataCubeServiceImplTest {
@Test(dataProvider = "oneDay") @Test(dataProvider = "oneDay")
public void testGetArticleSummary(Date date) throws WxErrorException { public void testGetArticleSummary(Date date) throws WxErrorException {
List<WxDataCubeArticleResult> results = this.wxService.getDataCubeService() List<WxDataCubeArticleResult> results = this.wxService.getDataCubeService()
.getArticleSummary(date, date);
.getArticleSummary(date, date);
Assert.assertNotNull(results); Assert.assertNotNull(results);
System.out.println(results); System.out.println(results);
} }
@@ -96,16 +87,16 @@ public class WxMpDataCubeServiceImplTest {
@Test(dataProvider = "oneDay") @Test(dataProvider = "oneDay")
public void testGetArticleTotal(Date date) throws WxErrorException { public void testGetArticleTotal(Date date) throws WxErrorException {
List<WxDataCubeArticleTotal> results = this.wxService.getDataCubeService() List<WxDataCubeArticleTotal> results = this.wxService.getDataCubeService()
.getArticleTotal(date, date);
.getArticleTotal(date, date);
Assert.assertNotNull(results); Assert.assertNotNull(results);
System.out.println(results); System.out.println(results);
} }


@Test(dataProvider = "threeDays") @Test(dataProvider = "threeDays")
public void testGetUserRead(Date beginDate, Date endDate) public void testGetUserRead(Date beginDate, Date endDate)
throws WxErrorException {
throws WxErrorException {
List<WxDataCubeArticleResult> results = this.wxService.getDataCubeService() List<WxDataCubeArticleResult> results = this.wxService.getDataCubeService()
.getUserRead(beginDate, endDate);
.getUserRead(beginDate, endDate);
Assert.assertNotNull(results); Assert.assertNotNull(results);
System.out.println(results); System.out.println(results);
} }
@@ -113,16 +104,16 @@ public class WxMpDataCubeServiceImplTest {
@Test(dataProvider = "oneDay") @Test(dataProvider = "oneDay")
public void testGetUserReadHour(Date date) throws WxErrorException { public void testGetUserReadHour(Date date) throws WxErrorException {
List<WxDataCubeArticleResult> results = this.wxService.getDataCubeService() List<WxDataCubeArticleResult> results = this.wxService.getDataCubeService()
.getUserReadHour(date, date);
.getUserReadHour(date, date);
Assert.assertNotNull(results); Assert.assertNotNull(results);
System.out.println(results); System.out.println(results);
} }


@Test(dataProvider = "sevenDays") @Test(dataProvider = "sevenDays")
public void testGetUserShare(Date beginDate, Date endDate) public void testGetUserShare(Date beginDate, Date endDate)
throws WxErrorException {
throws WxErrorException {
List<WxDataCubeArticleResult> results = this.wxService.getDataCubeService() List<WxDataCubeArticleResult> results = this.wxService.getDataCubeService()
.getUserShare(beginDate, endDate);
.getUserShare(beginDate, endDate);
Assert.assertNotNull(results); Assert.assertNotNull(results);
System.out.println(results); System.out.println(results);
} }
@@ -130,7 +121,7 @@ public class WxMpDataCubeServiceImplTest {
@Test(dataProvider = "oneDay") @Test(dataProvider = "oneDay")
public void testGetUserShareHour(Date date) throws WxErrorException { public void testGetUserShareHour(Date date) throws WxErrorException {
List<WxDataCubeArticleResult> results = this.wxService.getDataCubeService() List<WxDataCubeArticleResult> results = this.wxService.getDataCubeService()
.getUserShareHour(date, date);
.getUserShareHour(date, date);
Assert.assertNotNull(results); Assert.assertNotNull(results);
System.out.println(results); System.out.println(results);
} }
@@ -138,7 +129,7 @@ public class WxMpDataCubeServiceImplTest {
@Test(dataProvider = "sevenDays") @Test(dataProvider = "sevenDays")
public void testGetUpstreamMsg(Date beginDate, Date endDate) throws WxErrorException { public void testGetUpstreamMsg(Date beginDate, Date endDate) throws WxErrorException {
List<WxDataCubeMsgResult> results = this.wxService.getDataCubeService() List<WxDataCubeMsgResult> results = this.wxService.getDataCubeService()
.getUpstreamMsg(beginDate, endDate);
.getUpstreamMsg(beginDate, endDate);
Assert.assertNotNull(results); Assert.assertNotNull(results);
System.out.println(results); System.out.println(results);
} }
@@ -146,7 +137,7 @@ public class WxMpDataCubeServiceImplTest {
@Test(dataProvider = "oneDay") @Test(dataProvider = "oneDay")
public void testGetUpstreamMsgHour(Date date) throws WxErrorException { public void testGetUpstreamMsgHour(Date date) throws WxErrorException {
List<WxDataCubeMsgResult> results = this.wxService.getDataCubeService() List<WxDataCubeMsgResult> results = this.wxService.getDataCubeService()
.getUpstreamMsgHour(date, date);
.getUpstreamMsgHour(date, date);
Assert.assertNotNull(results); Assert.assertNotNull(results);
System.out.println(results); System.out.println(results);
} }
@@ -154,7 +145,7 @@ public class WxMpDataCubeServiceImplTest {
@Test(dataProvider = "thirtyDays") @Test(dataProvider = "thirtyDays")
public void testGetUpstreamMsgWeek(Date beginDate, Date endDate) throws WxErrorException { public void testGetUpstreamMsgWeek(Date beginDate, Date endDate) throws WxErrorException {
List<WxDataCubeMsgResult> results = this.wxService.getDataCubeService() List<WxDataCubeMsgResult> results = this.wxService.getDataCubeService()
.getUpstreamMsgWeek(beginDate, endDate);
.getUpstreamMsgWeek(beginDate, endDate);
Assert.assertNotNull(results); Assert.assertNotNull(results);
System.out.println(results); System.out.println(results);
} }
@@ -165,7 +156,7 @@ public class WxMpDataCubeServiceImplTest {
@Test(dataProvider = "thirtyDays") @Test(dataProvider = "thirtyDays")
public void testGetUpstreamMsgMonth(Date beginDate, Date endDate) throws WxErrorException { public void testGetUpstreamMsgMonth(Date beginDate, Date endDate) throws WxErrorException {
List<WxDataCubeMsgResult> results = this.wxService.getDataCubeService() List<WxDataCubeMsgResult> results = this.wxService.getDataCubeService()
.getUpstreamMsgMonth(beginDate, endDate);
.getUpstreamMsgMonth(beginDate, endDate);
Assert.assertNotNull(results); Assert.assertNotNull(results);
System.out.println(results); System.out.println(results);
} }
@@ -173,7 +164,7 @@ public class WxMpDataCubeServiceImplTest {
@Test(dataProvider = "fifteenDays") @Test(dataProvider = "fifteenDays")
public void testGetUpstreamMsgDist(Date beginDate, Date endDate) throws WxErrorException { public void testGetUpstreamMsgDist(Date beginDate, Date endDate) throws WxErrorException {
List<WxDataCubeMsgResult> results = this.wxService.getDataCubeService() List<WxDataCubeMsgResult> results = this.wxService.getDataCubeService()
.getUpstreamMsgDist(beginDate, endDate);
.getUpstreamMsgDist(beginDate, endDate);
Assert.assertNotNull(results); Assert.assertNotNull(results);
System.out.println(results); System.out.println(results);
} }
@@ -181,7 +172,7 @@ public class WxMpDataCubeServiceImplTest {
@Test(dataProvider = "thirtyDays") @Test(dataProvider = "thirtyDays")
public void testGetUpstreamMsgDistWeek(Date beginDate, Date endDate) throws WxErrorException { public void testGetUpstreamMsgDistWeek(Date beginDate, Date endDate) throws WxErrorException {
List<WxDataCubeMsgResult> results = this.wxService.getDataCubeService() List<WxDataCubeMsgResult> results = this.wxService.getDataCubeService()
.getUpstreamMsgDistWeek(beginDate, endDate);
.getUpstreamMsgDistWeek(beginDate, endDate);
Assert.assertNotNull(results); Assert.assertNotNull(results);
System.out.println(results); System.out.println(results);
} }
@@ -192,7 +183,7 @@ public class WxMpDataCubeServiceImplTest {
@Test(dataProvider = "thirtyDays") @Test(dataProvider = "thirtyDays")
public void testGetUpstreamMsgDistMonth(Date beginDate, Date endDate) throws WxErrorException { public void testGetUpstreamMsgDistMonth(Date beginDate, Date endDate) throws WxErrorException {
List<WxDataCubeMsgResult> results = this.wxService.getDataCubeService() List<WxDataCubeMsgResult> results = this.wxService.getDataCubeService()
.getUpstreamMsgDistMonth(beginDate, endDate);
.getUpstreamMsgDistMonth(beginDate, endDate);
Assert.assertNotNull(results); Assert.assertNotNull(results);
System.out.println(results); System.out.println(results);
} }
@@ -200,7 +191,7 @@ public class WxMpDataCubeServiceImplTest {
@Test(dataProvider = "thirtyDays") @Test(dataProvider = "thirtyDays")
public void testGetInterfaceSummary(Date beginDate, Date endDate) throws WxErrorException { public void testGetInterfaceSummary(Date beginDate, Date endDate) throws WxErrorException {
List<WxDataCubeInterfaceResult> results = this.wxService.getDataCubeService() List<WxDataCubeInterfaceResult> results = this.wxService.getDataCubeService()
.getInterfaceSummary(beginDate, endDate);
.getInterfaceSummary(beginDate, endDate);
Assert.assertNotNull(results); Assert.assertNotNull(results);
System.out.println(results); System.out.println(results);
} }
@@ -208,7 +199,7 @@ public class WxMpDataCubeServiceImplTest {
@Test(dataProvider = "oneDay") @Test(dataProvider = "oneDay")
public void testGetInterfaceSummaryHour(Date date) throws WxErrorException { public void testGetInterfaceSummaryHour(Date date) throws WxErrorException {
List<WxDataCubeInterfaceResult> results = this.wxService.getDataCubeService() List<WxDataCubeInterfaceResult> results = this.wxService.getDataCubeService()
.getInterfaceSummaryHour(date, date);
.getInterfaceSummaryHour(date, date);
Assert.assertNotNull(results); Assert.assertNotNull(results);
System.out.println(results); System.out.println(results);
} }


+ 2
- 4
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpDeviceServiceImplTest.java View File

@@ -3,12 +3,10 @@ package me.chanjar.weixin.mp.api.impl;


import com.google.inject.Inject; import com.google.inject.Inject;
import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.ApiTestModule;
import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.test.ApiTestModule;
import me.chanjar.weixin.mp.bean.device.WxDeviceQrCodeResult; import me.chanjar.weixin.mp.bean.device.WxDeviceQrCodeResult;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
import org.testng.annotations.*;


/** /**
* Created by keungtung on 14/12/2016. * Created by keungtung on 14/12/2016.


+ 38
- 40
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java View File

@@ -3,25 +3,23 @@ package me.chanjar.weixin.mp.api.impl;
import com.google.inject.Inject; import com.google.inject.Inject;
import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.ApiTestModule;
import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.WxXmlMpInMemoryConfigStorage;
import me.chanjar.weixin.mp.api.test.ApiTestModule;
import me.chanjar.weixin.mp.api.test.TestConfigStorage;
import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage; import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage;
import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfAccountRequest; import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfAccountRequest;
import me.chanjar.weixin.mp.bean.kefu.result.*; import me.chanjar.weixin.mp.bean.kefu.result.*;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
import org.testng.*;
import org.testng.annotations.*;


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


/** /**
* 测试客服相关接口 * 测试客服相关接口
* @author Binary Wang
* *
* @author Binary Wang
*/ */
@Test @Test
@Guice(modules = ApiTestModule.class) @Guice(modules = ApiTestModule.class)
@@ -31,7 +29,7 @@ public class WxMpKefuServiceImplTest {
protected WxMpService wxService; protected WxMpService wxService;


public void testSendKefuMpNewsMessage() throws WxErrorException { public void testSendKefuMpNewsMessage() throws WxErrorException {
WxXmlMpInMemoryConfigStorage configStorage = (WxXmlMpInMemoryConfigStorage) this.wxService
TestConfigStorage configStorage = (TestConfigStorage) this.wxService
.getWxMpConfigStorage(); .getWxMpConfigStorage();
WxMpKefuMessage message = new WxMpKefuMessage(); WxMpKefuMessage message = new WxMpKefuMessage();
message.setMsgType(WxConsts.CUSTOM_MSG_MPNEWS); message.setMsgType(WxConsts.CUSTOM_MSG_MPNEWS);
@@ -42,26 +40,26 @@ public class WxMpKefuServiceImplTest {
} }


public void testSendKefuMessage() throws WxErrorException { public void testSendKefuMessage() throws WxErrorException {
WxXmlMpInMemoryConfigStorage configStorage = (WxXmlMpInMemoryConfigStorage) this.wxService
.getWxMpConfigStorage();
TestConfigStorage configStorage = (TestConfigStorage) this.wxService
.getWxMpConfigStorage();
WxMpKefuMessage message = new WxMpKefuMessage(); WxMpKefuMessage message = new WxMpKefuMessage();
message.setMsgType(WxConsts.CUSTOM_MSG_TEXT); message.setMsgType(WxConsts.CUSTOM_MSG_TEXT);
message.setToUser(configStorage.getOpenid()); message.setToUser(configStorage.getOpenid());
message.setContent( message.setContent(
"欢迎欢迎,热烈欢迎\n换行测试\n超链接:<a href=\"http://www.baidu.com\">Hello World</a>");
"欢迎欢迎,热烈欢迎\n换行测试\n超链接:<a href=\"http://www.baidu.com\">Hello World</a>");


this.wxService.getKefuService().sendKefuMessage(message); this.wxService.getKefuService().sendKefuMessage(message);
} }


public void testSendKefuMessageWithKfAccount() throws WxErrorException { public void testSendKefuMessageWithKfAccount() throws WxErrorException {
WxXmlMpInMemoryConfigStorage configStorage = (WxXmlMpInMemoryConfigStorage) this.wxService
.getWxMpConfigStorage();
TestConfigStorage configStorage = (TestConfigStorage) this.wxService
.getWxMpConfigStorage();
WxMpKefuMessage message = new WxMpKefuMessage(); WxMpKefuMessage message = new WxMpKefuMessage();
message.setMsgType(WxConsts.CUSTOM_MSG_TEXT); message.setMsgType(WxConsts.CUSTOM_MSG_TEXT);
message.setToUser(configStorage.getOpenid()); message.setToUser(configStorage.getOpenid());
message.setKfAccount(configStorage.getKfAccount()); message.setKfAccount(configStorage.getKfAccount());
message.setContent( message.setContent(
"欢迎欢迎,热烈欢迎\n换行测试\n超链接:<a href=\"http://www.baidu.com\">Hello World</a>");
"欢迎欢迎,热烈欢迎\n换行测试\n超链接:<a href=\"http://www.baidu.com\">Hello World</a>");


this.wxService.getKefuService().sendKefuMessage(message); this.wxService.getKefuService().sendKefuMessage(message);
} }
@@ -76,7 +74,7 @@ public class WxMpKefuServiceImplTest {


public void testKfOnlineList() throws WxErrorException { public void testKfOnlineList() throws WxErrorException {
WxMpKfOnlineList kfOnlineList = this.wxService.getKefuService() WxMpKfOnlineList kfOnlineList = this.wxService.getKefuService()
.kfOnlineList();
.kfOnlineList();
Assert.assertNotNull(kfOnlineList); Assert.assertNotNull(kfOnlineList);
for (WxMpKfInfo k : kfOnlineList.getKfOnlineList()) { for (WxMpKfInfo k : kfOnlineList.getKfOnlineList()) {
System.err.println(k); System.err.println(k);
@@ -85,41 +83,41 @@ public class WxMpKefuServiceImplTest {


@DataProvider @DataProvider
public Object[][] getKfAccount() { public Object[][] getKfAccount() {
WxXmlMpInMemoryConfigStorage configStorage = (WxXmlMpInMemoryConfigStorage) this.wxService
.getWxMpConfigStorage();
return new Object[][] { { configStorage.getKfAccount() } };
TestConfigStorage configStorage = (TestConfigStorage) this.wxService
.getWxMpConfigStorage();
return new Object[][]{{configStorage.getKfAccount()}};
} }


@Test(dataProvider = "getKfAccount") @Test(dataProvider = "getKfAccount")
public void testKfAccountAdd(String kfAccount) throws WxErrorException { public void testKfAccountAdd(String kfAccount) throws WxErrorException {
WxMpKfAccountRequest request = WxMpKfAccountRequest.builder() WxMpKfAccountRequest request = WxMpKfAccountRequest.builder()
.kfAccount(kfAccount).nickName("我晕").build();
.kfAccount(kfAccount).nickName("我晕").build();
Assert.assertTrue(this.wxService.getKefuService().kfAccountAdd(request)); Assert.assertTrue(this.wxService.getKefuService().kfAccountAdd(request));
} }


@Test(dependsOnMethods = { @Test(dependsOnMethods = {
"testKfAccountAdd" }, dataProvider = "getKfAccount")
"testKfAccountAdd"}, dataProvider = "getKfAccount")
public void testKfAccountUpdate(String kfAccount) throws WxErrorException { public void testKfAccountUpdate(String kfAccount) throws WxErrorException {
WxMpKfAccountRequest request = WxMpKfAccountRequest.builder() WxMpKfAccountRequest request = WxMpKfAccountRequest.builder()
.kfAccount(kfAccount).nickName("我晕").build();
.kfAccount(kfAccount).nickName("我晕").build();
Assert.assertTrue(this.wxService.getKefuService().kfAccountUpdate(request)); Assert.assertTrue(this.wxService.getKefuService().kfAccountUpdate(request));
} }


@Test(dependsOnMethods = { @Test(dependsOnMethods = {
"testKfAccountAdd" }, dataProvider = "getKfAccount")
"testKfAccountAdd"}, dataProvider = "getKfAccount")
public void testKfAccountInviteWorker(String kfAccount) throws WxErrorException { public void testKfAccountInviteWorker(String kfAccount) throws WxErrorException {
WxMpKfAccountRequest request = WxMpKfAccountRequest.builder() WxMpKfAccountRequest request = WxMpKfAccountRequest.builder()
.kfAccount(kfAccount).inviteWx(" ").build();
.kfAccount(kfAccount).inviteWx(" ").build();
Assert.assertTrue(this.wxService.getKefuService().kfAccountInviteWorker(request)); Assert.assertTrue(this.wxService.getKefuService().kfAccountInviteWorker(request));
} }


@Test(dependsOnMethods = { @Test(dependsOnMethods = {
"testKfAccountUpdate" }, dataProvider = "getKfAccount")
"testKfAccountUpdate"}, dataProvider = "getKfAccount")
public void testKfAccountUploadHeadImg(String kfAccount) public void testKfAccountUploadHeadImg(String kfAccount)
throws WxErrorException {
throws WxErrorException {
File imgFile = new File("src\\test\\resources\\mm.jpeg"); File imgFile = new File("src\\test\\resources\\mm.jpeg");
boolean result = this.wxService.getKefuService() boolean result = this.wxService.getKefuService()
.kfAccountUploadHeadImg(kfAccount, imgFile);
.kfAccountUploadHeadImg(kfAccount, imgFile);
Assert.assertTrue(result); Assert.assertTrue(result);
} }


@@ -131,33 +129,33 @@ public class WxMpKefuServiceImplTest {


@DataProvider @DataProvider
public Object[][] getKfAccountAndOpenid() { public Object[][] getKfAccountAndOpenid() {
WxXmlMpInMemoryConfigStorage configStorage = (WxXmlMpInMemoryConfigStorage) this.wxService
.getWxMpConfigStorage();
return new Object[][] {
{ configStorage.getKfAccount(), configStorage.getOpenid() } };
TestConfigStorage configStorage = (TestConfigStorage) this.wxService
.getWxMpConfigStorage();
return new Object[][]{
{configStorage.getKfAccount(), configStorage.getOpenid()}};
} }


@Test(dataProvider = "getKfAccountAndOpenid") @Test(dataProvider = "getKfAccountAndOpenid")
public void testKfSessionCreate(String kfAccount, String openid) public void testKfSessionCreate(String kfAccount, String openid)
throws WxErrorException {
throws WxErrorException {
boolean result = this.wxService.getKefuService().kfSessionCreate(openid, boolean result = this.wxService.getKefuService().kfSessionCreate(openid,
kfAccount);
kfAccount);
Assert.assertTrue(result); Assert.assertTrue(result);
} }


@Test(dataProvider = "getKfAccountAndOpenid") @Test(dataProvider = "getKfAccountAndOpenid")
public void testKfSessionClose(String kfAccount, String openid) public void testKfSessionClose(String kfAccount, String openid)
throws WxErrorException {
throws WxErrorException {
boolean result = this.wxService.getKefuService().kfSessionClose(openid, boolean result = this.wxService.getKefuService().kfSessionClose(openid,
kfAccount);
kfAccount);
Assert.assertTrue(result); Assert.assertTrue(result);
} }


@Test(dataProvider = "getKfAccountAndOpenid") @Test(dataProvider = "getKfAccountAndOpenid")
public void testKfSessionGet(@SuppressWarnings("unused") String kfAccount, public void testKfSessionGet(@SuppressWarnings("unused") String kfAccount,
String openid) throws WxErrorException {
String openid) throws WxErrorException {
WxMpKfSessionGetResult result = this.wxService.getKefuService() WxMpKfSessionGetResult result = this.wxService.getKefuService()
.kfSessionGet(openid);
.kfSessionGet(openid);
Assert.assertNotNull(result); Assert.assertNotNull(result);
System.err.println(result); System.err.println(result);
} }
@@ -165,7 +163,7 @@ public class WxMpKefuServiceImplTest {
@Test(dataProvider = "getKfAccount") @Test(dataProvider = "getKfAccount")
public void testKfSessionList(String kfAccount) throws WxErrorException { public void testKfSessionList(String kfAccount) throws WxErrorException {
WxMpKfSessionList result = this.wxService.getKefuService() WxMpKfSessionList result = this.wxService.getKefuService()
.kfSessionList(kfAccount);
.kfSessionList(kfAccount);
Assert.assertNotNull(result); Assert.assertNotNull(result);
System.err.println(result); System.err.println(result);
} }
@@ -173,7 +171,7 @@ public class WxMpKefuServiceImplTest {
@Test @Test
public void testKfSessionGetWaitCase() throws WxErrorException { public void testKfSessionGetWaitCase() throws WxErrorException {
WxMpKfSessionWaitCaseList result = this.wxService.getKefuService() WxMpKfSessionWaitCaseList result = this.wxService.getKefuService()
.kfSessionGetWaitCase();
.kfSessionGetWaitCase();
Assert.assertNotNull(result); Assert.assertNotNull(result);
System.err.println(result); System.err.println(result);
} }
@@ -182,7 +180,7 @@ public class WxMpKefuServiceImplTest {
public void testKfMsgList() throws WxErrorException { public void testKfMsgList() throws WxErrorException {
Date startTime = DateTime.now().minusDays(1).toDate(); Date startTime = DateTime.now().minusDays(1).toDate();
Date endTime = DateTime.now().minusDays(0).toDate(); Date endTime = DateTime.now().minusDays(0).toDate();
WxMpKfMsgList result = this.wxService.getKefuService().kfMsgList(startTime,endTime, 1L, 50);
WxMpKfMsgList result = this.wxService.getKefuService().kfMsgList(startTime, endTime, 1L, 50);
Assert.assertNotNull(result); Assert.assertNotNull(result);
System.err.println(result); System.err.println(result);
} }
@@ -191,7 +189,7 @@ public class WxMpKefuServiceImplTest {
public void testKfMsgListAll() throws WxErrorException { public void testKfMsgListAll() throws WxErrorException {
Date startTime = DateTime.now().minusDays(1).toDate(); Date startTime = DateTime.now().minusDays(1).toDate();
Date endTime = DateTime.now().minusDays(0).toDate(); Date endTime = DateTime.now().minusDays(0).toDate();
WxMpKfMsgList result = this.wxService.getKefuService().kfMsgList(startTime,endTime);
WxMpKfMsgList result = this.wxService.getKefuService().kfMsgList(startTime, endTime);
Assert.assertNotNull(result); Assert.assertNotNull(result);
System.err.println(result); System.err.println(result);
} }


+ 34
- 40
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpMaterialServiceImplTest.java View File

@@ -5,15 +5,10 @@ import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.util.fs.FileUtils; import me.chanjar.weixin.common.util.fs.FileUtils;
import me.chanjar.weixin.mp.api.ApiTestModule;
import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.material.WxMpMaterial;
import me.chanjar.weixin.mp.bean.material.WxMpMaterialArticleUpdate;
import me.chanjar.weixin.mp.bean.material.WxMpMaterialNews;
import me.chanjar.weixin.mp.api.test.ApiTestModule;
import me.chanjar.weixin.mp.bean.material.*; import me.chanjar.weixin.mp.bean.material.*;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
import org.testng.annotations.*;


import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@@ -44,14 +39,16 @@ public class WxMpMaterialServiceImplTest {
private String multiNewsMediaId = ""; private String multiNewsMediaId = "";
// 先查询保存测试开始前永久素材数据 // 先查询保存测试开始前永久素材数据
private WxMpMaterialCountResult wxMaterialCountResultBeforeTest; private WxMpMaterialCountResult wxMaterialCountResultBeforeTest;
// 以下为media接口的测试
private List<String> mediaIdsToDownload = new ArrayList<>();


@DataProvider @DataProvider
public Object[][] mediaFiles() { public Object[][] mediaFiles() {
return new Object[][] {
new Object[] { WxConsts.MEDIA_IMAGE, WxConsts.FILE_JPG, "mm.jpeg" },
new Object[] { WxConsts.MEDIA_VOICE, WxConsts.FILE_MP3, "mm.mp3" },
new Object[] { WxConsts.MEDIA_VIDEO, WxConsts.FILE_MP4, "mm.mp4" },
new Object[] { WxConsts.MEDIA_THUMB, WxConsts.FILE_JPG, "mm.jpeg" }
return new Object[][]{
new Object[]{WxConsts.MEDIA_IMAGE, WxConsts.FILE_JPG, "mm.jpeg"},
new Object[]{WxConsts.MEDIA_VOICE, WxConsts.FILE_MP3, "mm.mp3"},
new Object[]{WxConsts.MEDIA_VIDEO, WxConsts.FILE_MP4, "mm.mp4"},
new Object[]{WxConsts.MEDIA_THUMB, WxConsts.FILE_JPG, "mm.jpeg"}
}; };
} }


@@ -59,13 +56,13 @@ public class WxMpMaterialServiceImplTest {
public void testUploadMaterial(String mediaType, String fileType, String fileName) throws WxErrorException, IOException { public void testUploadMaterial(String mediaType, String fileType, String fileName) throws WxErrorException, IOException {
if (this.wxMaterialCountResultBeforeTest == null) { if (this.wxMaterialCountResultBeforeTest == null) {
this.wxMaterialCountResultBeforeTest = this.wxService.getMaterialService() this.wxMaterialCountResultBeforeTest = this.wxService.getMaterialService()
.materialCount();
.materialCount();
} }


try (InputStream inputStream = ClassLoader try (InputStream inputStream = ClassLoader
.getSystemResourceAsStream(fileName)) {
.getSystemResourceAsStream(fileName)) {
File tempFile = FileUtils.createTmpFile(inputStream, File tempFile = FileUtils.createTmpFile(inputStream,
UUID.randomUUID().toString(), fileType);
UUID.randomUUID().toString(), fileType);
WxMpMaterial wxMaterial = new WxMpMaterial(); WxMpMaterial wxMaterial = new WxMpMaterial();
wxMaterial.setFile(tempFile); wxMaterial.setFile(tempFile);
wxMaterial.setName(fileName); wxMaterial.setName(fileName);
@@ -75,11 +72,11 @@ public class WxMpMaterialServiceImplTest {
} }


WxMpMaterialUploadResult res = this.wxService.getMaterialService() WxMpMaterialUploadResult res = this.wxService.getMaterialService()
.materialFileUpload(mediaType, wxMaterial);
.materialFileUpload(mediaType, wxMaterial);
assertNotNull(res.getMediaId()); assertNotNull(res.getMediaId());


if (WxConsts.MEDIA_IMAGE.equals(mediaType) if (WxConsts.MEDIA_IMAGE.equals(mediaType)
|| WxConsts.MEDIA_THUMB.equals(mediaType)) {
|| WxConsts.MEDIA_THUMB.equals(mediaType)) {
assertNotNull(res.getUrl()); assertNotNull(res.getUrl());
} }


@@ -145,16 +142,16 @@ public class WxMpMaterialServiceImplTest {
WxMpMaterialCountResult wxMaterialCountResult = this.wxService.getMaterialService().materialCount(); WxMpMaterialCountResult wxMaterialCountResult = this.wxService.getMaterialService().materialCount();
// 测试上传过程中添加了一个音频,一个视频,两个图片,两个图文消息 // 测试上传过程中添加了一个音频,一个视频,两个图片,两个图文消息
assertEquals( assertEquals(
this.wxMaterialCountResultBeforeTest.getVoiceCount() + 1,
wxMaterialCountResult.getVoiceCount());
this.wxMaterialCountResultBeforeTest.getVoiceCount() + 1,
wxMaterialCountResult.getVoiceCount());
assertEquals( assertEquals(
this.wxMaterialCountResultBeforeTest.getVideoCount() + 1,
wxMaterialCountResult.getVideoCount());
this.wxMaterialCountResultBeforeTest.getVideoCount() + 1,
wxMaterialCountResult.getVideoCount());
assertEquals( assertEquals(
this.wxMaterialCountResultBeforeTest.getImageCount() + 2,
wxMaterialCountResult.getImageCount());
this.wxMaterialCountResultBeforeTest.getImageCount() + 2,
wxMaterialCountResult.getImageCount());
assertEquals(this.wxMaterialCountResultBeforeTest.getNewsCount() + 2, assertEquals(this.wxMaterialCountResultBeforeTest.getNewsCount() + 2,
wxMaterialCountResult.getNewsCount());
wxMaterialCountResult.getNewsCount());
} }


@Test(dependsOnMethods = {"testMaterialCount"}, dataProvider = "downloadMaterial") @Test(dependsOnMethods = {"testMaterialCount"}, dataProvider = "downloadMaterial")
@@ -164,7 +161,7 @@ public class WxMpMaterialServiceImplTest {
String filename = materialInfo.get("filename").toString(); String filename = materialInfo.get("filename").toString();
if (filename.endsWith(".mp3") || filename.endsWith(".jpeg")) { if (filename.endsWith(".mp3") || filename.endsWith(".jpeg")) {
try (InputStream inputStream = this.wxService.getMaterialService() try (InputStream inputStream = this.wxService.getMaterialService()
.materialImageOrVoiceDownload(mediaId)) {
.materialImageOrVoiceDownload(mediaId)) {
assertNotNull(inputStream); assertNotNull(inputStream);
} }
} }
@@ -178,9 +175,9 @@ public class WxMpMaterialServiceImplTest {
@Test(dependsOnMethods = {"testAddNews"}) @Test(dependsOnMethods = {"testAddNews"})
public void testGetNewsInfo() throws WxErrorException { public void testGetNewsInfo() throws WxErrorException {
WxMpMaterialNews wxMpMaterialNewsSingle = this.wxService WxMpMaterialNews wxMpMaterialNewsSingle = this.wxService
.getMaterialService().materialNewsInfo(this.singleNewsMediaId);
.getMaterialService().materialNewsInfo(this.singleNewsMediaId);
WxMpMaterialNews wxMpMaterialNewsMultiple = this.wxService WxMpMaterialNews wxMpMaterialNewsMultiple = this.wxService
.getMaterialService().materialNewsInfo(this.multiNewsMediaId);
.getMaterialService().materialNewsInfo(this.multiNewsMediaId);
assertNotNull(wxMpMaterialNewsSingle); assertNotNull(wxMpMaterialNewsSingle);
assertNotNull(wxMpMaterialNewsMultiple); assertNotNull(wxMpMaterialNewsMultiple);
} }
@@ -188,7 +185,7 @@ public class WxMpMaterialServiceImplTest {
@Test(dependsOnMethods = {"testGetNewsInfo"}) @Test(dependsOnMethods = {"testGetNewsInfo"})
public void testUpdateNewsInfo() throws WxErrorException { public void testUpdateNewsInfo() throws WxErrorException {
WxMpMaterialNews wxMpMaterialNewsSingle = this.wxService WxMpMaterialNews wxMpMaterialNewsSingle = this.wxService
.getMaterialService().materialNewsInfo(this.singleNewsMediaId);
.getMaterialService().materialNewsInfo(this.singleNewsMediaId);
assertNotNull(wxMpMaterialNewsSingle); assertNotNull(wxMpMaterialNewsSingle);
WxMpMaterialArticleUpdate wxMpMaterialArticleUpdateSingle = new WxMpMaterialArticleUpdate(); WxMpMaterialArticleUpdate wxMpMaterialArticleUpdateSingle = new WxMpMaterialArticleUpdate();
WxMpMaterialNews.WxMpMaterialNewsArticle articleSingle = wxMpMaterialNewsSingle.getArticles().get(0); WxMpMaterialNews.WxMpMaterialNewsArticle articleSingle = wxMpMaterialNewsSingle.getArticles().get(0);
@@ -199,13 +196,13 @@ public class WxMpMaterialServiceImplTest {
boolean resultSingle = this.wxService.getMaterialService().materialNewsUpdate(wxMpMaterialArticleUpdateSingle); boolean resultSingle = this.wxService.getMaterialService().materialNewsUpdate(wxMpMaterialArticleUpdateSingle);
assertTrue(resultSingle); assertTrue(resultSingle);
wxMpMaterialNewsSingle = this.wxService.getMaterialService() wxMpMaterialNewsSingle = this.wxService.getMaterialService()
.materialNewsInfo(this.singleNewsMediaId);
.materialNewsInfo(this.singleNewsMediaId);
assertNotNull(wxMpMaterialNewsSingle); assertNotNull(wxMpMaterialNewsSingle);
assertEquals("content single update", assertEquals("content single update",
wxMpMaterialNewsSingle.getArticles().get(0).getContent());
wxMpMaterialNewsSingle.getArticles().get(0).getContent());


WxMpMaterialNews wxMpMaterialNewsMultiple = this.wxService WxMpMaterialNews wxMpMaterialNewsMultiple = this.wxService
.getMaterialService().materialNewsInfo(this.multiNewsMediaId);
.getMaterialService().materialNewsInfo(this.multiNewsMediaId);
assertNotNull(wxMpMaterialNewsMultiple); assertNotNull(wxMpMaterialNewsMultiple);
WxMpMaterialArticleUpdate wxMpMaterialArticleUpdateMulti = new WxMpMaterialArticleUpdate(); WxMpMaterialArticleUpdate wxMpMaterialArticleUpdateMulti = new WxMpMaterialArticleUpdate();
WxMpMaterialNews.WxMpMaterialNewsArticle articleMulti = wxMpMaterialNewsMultiple.getArticles().get(1); WxMpMaterialNews.WxMpMaterialNewsArticle articleMulti = wxMpMaterialNewsMultiple.getArticles().get(1);
@@ -216,10 +213,10 @@ public class WxMpMaterialServiceImplTest {
boolean resultMulti = this.wxService.getMaterialService().materialNewsUpdate(wxMpMaterialArticleUpdateMulti); boolean resultMulti = this.wxService.getMaterialService().materialNewsUpdate(wxMpMaterialArticleUpdateMulti);
assertTrue(resultMulti); assertTrue(resultMulti);
wxMpMaterialNewsMultiple = this.wxService.getMaterialService() wxMpMaterialNewsMultiple = this.wxService.getMaterialService()
.materialNewsInfo(this.multiNewsMediaId);
.materialNewsInfo(this.multiNewsMediaId);
assertNotNull(wxMpMaterialNewsMultiple); assertNotNull(wxMpMaterialNewsMultiple);
assertEquals("content 2 update", assertEquals("content 2 update",
wxMpMaterialNewsMultiple.getArticles().get(1).getContent());
wxMpMaterialNewsMultiple.getArticles().get(1).getContent());
} }


@Test(dependsOnMethods = {"testUpdateNewsInfo"}) @Test(dependsOnMethods = {"testUpdateNewsInfo"})
@@ -266,12 +263,9 @@ public class WxMpMaterialServiceImplTest {
return params.iterator(); return params.iterator();
} }


// 以下为media接口的测试
private List<String> mediaIdsToDownload = new ArrayList<>();

@Test(dataProvider="mediaFiles")
@Test(dataProvider = "mediaFiles")
public void testUploadMedia(String mediaType, String fileType, String fileName) throws WxErrorException, IOException { public void testUploadMedia(String mediaType, String fileType, String fileName) throws WxErrorException, IOException {
try(InputStream inputStream = ClassLoader.getSystemResourceAsStream(fileName)){
try (InputStream inputStream = ClassLoader.getSystemResourceAsStream(fileName)) {
WxMediaUploadResult res = this.wxService.getMaterialService().mediaUpload(mediaType, fileType, inputStream); WxMediaUploadResult res = this.wxService.getMaterialService().mediaUpload(mediaType, fileType, inputStream);
assertNotNull(res.getType()); assertNotNull(res.getType());
assertNotNull(res.getCreatedAt()); assertNotNull(res.getCreatedAt());
@@ -294,12 +288,12 @@ public class WxMpMaterialServiceImplTest {
public Object[][] downloadMedia() { public Object[][] downloadMedia() {
Object[][] params = new Object[this.mediaIdsToDownload.size()][]; Object[][] params = new Object[this.mediaIdsToDownload.size()][];
for (int i = 0; i < this.mediaIdsToDownload.size(); i++) { for (int i = 0; i < this.mediaIdsToDownload.size(); i++) {
params[i] = new Object[] { this.mediaIdsToDownload.get(i) };
params[i] = new Object[]{this.mediaIdsToDownload.get(i)};
} }
return params; return params;
} }


@Test(dependsOnMethods = { "testUploadMedia" }, dataProvider="downloadMedia")
@Test(dependsOnMethods = {"testUploadMedia"}, dataProvider = "downloadMedia")
public void testDownloadMedia(String mediaId) throws WxErrorException { public void testDownloadMedia(String mediaId) throws WxErrorException {
File file = this.wxService.getMaterialService().mediaDownload(mediaId); File file = this.wxService.getMaterialService().mediaDownload(mediaId);
assertNotNull(file); assertNotNull(file);


+ 101
- 52
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpMenuServiceImplTest.java View File

@@ -5,26 +5,26 @@ import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.menu.WxMenu; import me.chanjar.weixin.common.bean.menu.WxMenu;
import me.chanjar.weixin.common.bean.menu.WxMenuButton; import me.chanjar.weixin.common.bean.menu.WxMenuButton;
import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.ApiTestModule;
import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.test.ApiTestModule;
import me.chanjar.weixin.mp.bean.menu.WxMpGetSelfMenuInfoResult; import me.chanjar.weixin.mp.bean.menu.WxMpGetSelfMenuInfoResult;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
import me.chanjar.weixin.mp.bean.menu.WxMpMenu;
import org.testng.*;
import org.testng.annotations.*;


/** /**
* 测试菜单 * 测试菜单
*
* @author chanjarster * @author chanjarster
* @author Binary Wang * @author Binary Wang
*
*/ */
@Test(groups="menuAPI")
@Test(groups = "menuAPI")
@Guice(modules = ApiTestModule.class) @Guice(modules = ApiTestModule.class)
public class WxMpMenuServiceImplTest { public class WxMpMenuServiceImplTest {


@Inject @Inject
protected WxMpService wxService; protected WxMpService wxService;
private String menuId = null;


@Test(dataProvider = "menu") @Test(dataProvider = "menu")
public void testMenuCreate(WxMenu wxMenu) throws WxErrorException { public void testMenuCreate(WxMenu wxMenu) throws WxErrorException {
@@ -34,7 +34,8 @@ public class WxMpMenuServiceImplTest {


@Test @Test
public void testMenuTryMatch() throws Exception { public void testMenuTryMatch() throws Exception {
//TODO
WxMenu menu = this.wxService.getMenuService().menuTryMatch("...");
System.out.println(menu);
} }


@Test @Test
@@ -44,62 +45,110 @@ public class WxMpMenuServiceImplTest {
} }


@Test @Test
public void testCreateMenu2() throws WxErrorException {
public void testCreateConditionalMenu() throws WxErrorException {
String json = "{\n" +
" \"button\":[\n" +
" { \n" +
" \"type\":\"click\",\n" +
" \"name\":\"今日歌曲\",\n" +
" \"key\":\"V1001_TODAY_MUSIC\" \n" +
" },\n" +
" { \n" +
" \"name\":\"菜单\",\n" +
" \"sub_button\":[\n" +
" { \n" +
" \"type\":\"view\",\n" +
" \"name\":\"搜索\",\n" +
" \"url\":\"http://www.soso.com/\"\n" +
" },\n" +
" {\n" +
" \"type\":\"view\",\n" +
" \"name\":\"视频\",\n" +
" \"url\":\"http://v.qq.com/\"\n" +
" },\n" +
" {\n" +
" \"type\":\"click\",\n" +
" \"name\":\"赞一下我们\",\n" +
" \"key\":\"V1001_GOOD\"\n" +
" }]\n" +
" }],\n" +
"\"matchrule\":{\n" +
" \"tag_id\":\"2\",\n" +
" \"sex\":\"1\",\n" +
" \"country\":\"中国\",\n" +
" \"province\":\"广东\",\n" +
" \"city\":\"广州\",\n" +
" \"client_platform_type\":\"2\",\n" +
" \"language\":\"zh_CN\"\n" +
" }\n" +
"}";

this.menuId = this.wxService.getMenuService().menuCreate(json);
System.out.println(this.menuId);
}

@Test(dependsOnMethods = {"testCreateConditionalMenu"})
public void testDeleteConditionalMenu() throws WxErrorException {
this.wxService.getMenuService().menuDelete(menuId);
}

@Test
public void testCreateMenu_by_json() throws WxErrorException {
String a = "{\n" String a = "{\n"
+ " \"menu\": {\n"
+ " \"button\": [\n"
+ " {\n"
+ " \"type\": \"click\",\n"
+ " \"name\": \"今日歌曲\",\n"
+ " \"key\": \"V1001_TODAY_MUSIC\"\n"
+ " },\n"
+ " {\n"
+ " \"type\": \"click\",\n"
+ " \"name\": \"歌手简介\",\n"
+ " \"key\": \"V1001_TODAY_SINGER\"\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"菜单\",\n"
+ " \"sub_button\": [\n"
+ " {\n"
+ " \"type\": \"view\",\n"
+ " \"name\": \"搜索\",\n"
+ " \"url\": \"http://www.soso.com/\"\n"
+ " },\n"
+ " {\n"
+ " \"type\": \"view\",\n"
+ " \"name\": \"视频\",\n"
+ " \"url\": \"http://v.qq.com/\"\n"
+ " },\n"
+ " {\n"
+ " \"type\": \"click\",\n"
+ " \"name\": \"赞一下我们\",\n"
+ " \"key\": \"V1001_GOOD\"\n"
+ " }\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ " }\n"
+ "}";
+ " \"menu\": {\n"
+ " \"button\": [\n"
+ " {\n"
+ " \"type\": \"click\",\n"
+ " \"name\": \"今日歌曲\",\n"
+ " \"key\": \"V1001_TODAY_MUSIC\"\n"
+ " },\n"
+ " {\n"
+ " \"type\": \"click\",\n"
+ " \"name\": \"歌手简介\",\n"
+ " \"key\": \"V1001_TODAY_SINGER\"\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"菜单\",\n"
+ " \"sub_button\": [\n"
+ " {\n"
+ " \"type\": \"view\",\n"
+ " \"name\": \"搜索\",\n"
+ " \"url\": \"http://www.soso.com/\"\n"
+ " },\n"
+ " {\n"
+ " \"type\": \"view\",\n"
+ " \"name\": \"视频\",\n"
+ " \"url\": \"http://v.qq.com/\"\n"
+ " },\n"
+ " {\n"
+ " \"type\": \"click\",\n"
+ " \"name\": \"赞一下我们\",\n"
+ " \"key\": \"V1001_GOOD\"\n"
+ " }\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ " }\n"
+ "}";


WxMenu menu = WxMenu.fromJson(a); WxMenu menu = WxMenu.fromJson(a);
System.out.println(menu.toJson()); System.out.println(menu.toJson());
this.wxService.getMenuService().menuCreate(menu); this.wxService.getMenuService().menuCreate(menu);
} }


@Test(dependsOnMethods = { "testMenuCreate"})
@Test(dependsOnMethods = {"testMenuCreate"})
public void testMenuGet() throws WxErrorException { public void testMenuGet() throws WxErrorException {
WxMenu wxMenu = this.wxService.getMenuService().menuGet();
WxMpMenu wxMenu = this.wxService.getMenuService().menuGet();
Assert.assertNotNull(wxMenu); Assert.assertNotNull(wxMenu);
System.out.println(wxMenu.toJson()); System.out.println(wxMenu.toJson());
} }


@Test(dependsOnMethods = { "testMenuGet"})
@Test(dependsOnMethods = {"testMenuGet"})
public void testMenuDelete() throws WxErrorException { public void testMenuDelete() throws WxErrorException {
this.wxService.getMenuService().menuDelete(); this.wxService.getMenuService().menuDelete();
} }


@DataProvider(name="menu")
@DataProvider(name = "menu")
public Object[][] getMenu() { public Object[][] getMenu() {
WxMenu menu = new WxMenu(); WxMenu menu = new WxMenu();
WxMenuButton button1 = new WxMenuButton(); WxMenuButton button1 = new WxMenuButton();
@@ -138,10 +187,10 @@ public class WxMpMenuServiceImplTest {
button3.getSubButtons().add(button32); button3.getSubButtons().add(button32);
button3.getSubButtons().add(button33); button3.getSubButtons().add(button33);


return new Object[][] {
new Object[] {
menu
}
return new Object[][]{
new Object[]{
menu
}
}; };


} }


+ 82
- 35
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImplTest.java View File

@@ -1,19 +1,20 @@
package me.chanjar.weixin.mp.api.impl; package me.chanjar.weixin.mp.api.impl;


import com.github.binarywang.utils.qrcode.QrcodeUtils;
import com.google.inject.Inject; import com.google.inject.Inject;
import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.ApiTestModule;
import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.WxXmlMpInMemoryConfigStorage;
import me.chanjar.weixin.mp.bean.pay.request.WxEntPayRequest;
import me.chanjar.weixin.mp.bean.pay.request.WxPayRefundRequest;
import me.chanjar.weixin.mp.bean.pay.request.WxPaySendRedpackRequest;
import me.chanjar.weixin.mp.bean.pay.request.WxPayUnifiedOrderRequest;
import me.chanjar.weixin.mp.api.test.ApiTestModule;
import me.chanjar.weixin.mp.api.test.TestConfigStorage;
import me.chanjar.weixin.mp.bean.pay.request.*;
import me.chanjar.weixin.mp.bean.pay.result.*; import me.chanjar.weixin.mp.bean.pay.result.*;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
import org.testng.annotations.*;


import java.io.File; import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;

import static org.testng.Assert.*;


/** /**
* 测试支付相关接口 * 测试支付相关接口
@@ -33,28 +34,58 @@ public class WxMpPayServiceImplTest {


} }


@Test
public void testDownloadBill() throws Exception {
File file = this.wxService.getPayService().downloadBill("20170101", "ALL", "GZIP", "1111111");
assertNotNull(file);
//必填字段为空时,抛出异常
this.wxService.getPayService().downloadBill("", "", "", null);
}

@Test
public void testReport() throws Exception {
WxPayReportRequest request = new WxPayReportRequest();
request.setInterfaceUrl("hahahah");
request.setSignType("HMAC-SHA256");//貌似接口未校验此字段
request.setExecuteTime(1000);
request.setReturnCode("aaa");
request.setResultCode("aaa");
request.setUserIp("8.8.8");
this.wxService.getPayService().report(request);
}

/** /**
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#refund(WxPayRefundRequest, File)} .
* 需要证书的接口需要先执行该方法
*/ */
@Test @Test
public void setSSLKey() {
TestConfigStorage config = (TestConfigStorage) this.wxService.getWxMpConfigStorage();
config.setSslContextFilePath(config.getKeyPath());
}

/**
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#refund(WxPayRefundRequest)} .
*/
@Test(dependsOnMethods = {"setSSLKey"})
public void testRefund() throws Exception { public void testRefund() throws Exception {
WxPayRefundRequest request = new WxPayRefundRequest(); WxPayRefundRequest request = new WxPayRefundRequest();
request.setOutRefundNo("aaa"); request.setOutRefundNo("aaa");
request.setOutTradeNo("1111"); request.setOutTradeNo("1111");
request.setTotalFee(1222); request.setTotalFee(1222);
request.setRefundFee(111); request.setRefundFee(111);
File keyFile = new File("E:\\dlt.p12");
WxPayRefundResult result = this.wxService.getPayService().refund(request, keyFile);
WxPayRefundResult result = this.wxService.getPayService().refund(request);
System.err.println(result); System.err.println(result);
} }



/** /**
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#refundQuery(String, String, String, String)} . * Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#refundQuery(String, String, String, String)} .
*/ */
@Test @Test
public void testRefundQuery() throws Exception { public void testRefundQuery() throws Exception {
WxPayRefundQueryResult result = this.wxService.getPayService().refundQuery("1", "", "", "");
WxPayRefundQueryResult result;

result = this.wxService.getPayService().refundQuery("1", "", "", "");
System.err.println(result);
result = this.wxService.getPayService().refundQuery("", "2", "", ""); result = this.wxService.getPayService().refundQuery("", "2", "", "");
System.err.println(result); System.err.println(result);
result = this.wxService.getPayService().refundQuery("", "", "3", ""); result = this.wxService.getPayService().refundQuery("", "", "3", "");
@@ -66,34 +97,27 @@ public class WxMpPayServiceImplTest {
System.err.println(result); System.err.println(result);
} }


@Test
public void testCheckJSSDKCallbackDataSignature() throws Exception {

}

/** /**
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#sendRedpack(WxPaySendRedpackRequest, File)} .
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#sendRedpack(WxPaySendRedpackRequest)} .
*/ */
@Test
@Test(dependsOnMethods = {"setSSLKey"})
public void testSendRedpack() throws Exception { public void testSendRedpack() throws Exception {
WxPaySendRedpackRequest request = new WxPaySendRedpackRequest(); WxPaySendRedpackRequest request = new WxPaySendRedpackRequest();
request.setActName("abc"); request.setActName("abc");
request.setClientIp("aaa"); request.setClientIp("aaa");
request.setMchBillNo("aaaa"); request.setMchBillNo("aaaa");
request request
.setReOpenid(((WxXmlMpInMemoryConfigStorage) this.wxService.getWxMpConfigStorage()).getOpenid());
File keyFile = new File("E:\\dlt.p12");
WxPaySendRedpackResult redpackResult = this.wxService.getPayService().sendRedpack(request, keyFile);
.setReOpenid(((TestConfigStorage) this.wxService.getWxMpConfigStorage()).getOpenid());
WxPaySendRedpackResult redpackResult = this.wxService.getPayService().sendRedpack(request);
System.err.println(redpackResult); System.err.println(redpackResult);
} }


/** /**
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#queryRedpack(String, File)}.
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#queryRedpack(String)}.
*/ */
@Test
@Test(dependsOnMethods = {"setSSLKey"})
public void testQueryRedpack() throws Exception { public void testQueryRedpack() throws Exception {
File keyFile = new File("E:\\dlt.p12");
WxPayRedpackQueryResult redpackResult = this.wxService.getPayService().queryRedpack("aaaa", keyFile);
WxPayRedpackQueryResult redpackResult = this.wxService.getPayService().queryRedpack("aaaa");
System.err.println(redpackResult); System.err.println(redpackResult);
} }


@@ -128,21 +152,44 @@ public class WxMpPayServiceImplTest {
} }


/** /**
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#entPay(WxEntPayRequest, File)}.
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#entPay(WxEntPayRequest)}.
*/ */
@Test
@Test(dependsOnMethods = {"setSSLKey"})
public final void testEntPay() throws WxErrorException { public final void testEntPay() throws WxErrorException {
File keyFile = new File("E:\\dlt.p12");
WxEntPayRequest request = new WxEntPayRequest(); WxEntPayRequest request = new WxEntPayRequest();
System.err.println(this.wxService.getPayService().entPay(request, keyFile));
System.err.println(this.wxService.getPayService().entPay(request));
} }


/** /**
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#queryEntPay(String, File)}.
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#queryEntPay(String)}.
*/ */
@Test
@Test(dependsOnMethods = {"setSSLKey"})
public final void testQueryEntPay() throws WxErrorException { public final void testQueryEntPay() throws WxErrorException {
File keyFile = new File("E:\\dlt.p12");
System.err.println(this.wxService.getPayService().queryEntPay("11212121", keyFile));
System.err.println(this.wxService.getPayService().queryEntPay("11212121"));
} }

@Test
public void testCreateScanPayQrcodeMode1() throws Exception {
String productId = "abc";
byte[] bytes = this.wxService.getPayService().createScanPayQrcodeMode1(productId, null, null);
Path qrcodeFilePath = Files.createTempFile("qrcode_", ".jpg");
Files.write(qrcodeFilePath, bytes);
String qrcodeContent = QrcodeUtils.decodeQrcode(qrcodeFilePath.toFile());
System.out.println(qrcodeContent);

assertTrue(qrcodeContent.startsWith("weixin://wxpay/bizpayurl?"));
assertTrue(qrcodeContent.contains("product_id=" + productId));
}

@Test
public void testCreateScanPayQrcodeMode2() throws Exception {
String qrcodeContent = "abc";
byte[] bytes = this.wxService.getPayService().createScanPayQrcodeMode2(qrcodeContent, null, null);
Path qrcodeFilePath = Files.createTempFile("qrcode_", ".jpg");
Files.write(qrcodeFilePath, bytes);

assertEquals(QrcodeUtils.decodeQrcode(qrcodeFilePath.toFile()), qrcodeContent);
}


} }

weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpQrCodeServiceImplTest.java → weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpQrcodeServiceImplTest.java View File

@@ -2,12 +2,11 @@ package me.chanjar.weixin.mp.api.impl;


import com.google.inject.Inject; import com.google.inject.Inject;
import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.ApiTestModule;
import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.test.ApiTestModule;
import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
import org.testng.Assert;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
import org.testng.*;
import org.testng.annotations.*;


import java.io.File; import java.io.File;


@@ -18,21 +17,27 @@ import java.io.File;
*/ */
@Test(groups = "qrCodeAPI") @Test(groups = "qrCodeAPI")
@Guice(modules = ApiTestModule.class) @Guice(modules = ApiTestModule.class)
public class WxMpQrCodeServiceImplTest {

public class WxMpQrcodeServiceImplTest {
@Inject @Inject
protected WxMpService wxService; protected WxMpService wxService;


public void testQrCodeCreateTmpTicket() throws WxErrorException {
WxMpQrCodeTicket ticket = this.wxService.getQrcodeService().qrCodeCreateTmpTicket(1, null);
@DataProvider
public Object[][] sceneIds() {
return new Object[][]{{-1}, {0}, {1}, {200000}};
}

@Test(dataProvider = "sceneIds")
public void testQrCodeCreateTmpTicket(int sceneId) throws WxErrorException {
WxMpQrCodeTicket ticket = this.wxService.getQrcodeService().qrCodeCreateTmpTicket(sceneId, null);
Assert.assertNotNull(ticket.getUrl()); Assert.assertNotNull(ticket.getUrl());
Assert.assertNotNull(ticket.getTicket()); Assert.assertNotNull(ticket.getTicket());
Assert.assertTrue(ticket.getExpire_seconds() != -1); Assert.assertTrue(ticket.getExpire_seconds() != -1);
System.out.println(ticket); System.out.println(ticket);
} }


public void testQrCodeCreateLastTicket() throws WxErrorException {
WxMpQrCodeTicket ticket = this.wxService.getQrcodeService().qrCodeCreateLastTicket(1);
@Test(dataProvider = "sceneIds")
public void testQrCodeCreateLastTicket(int sceneId) throws WxErrorException {
WxMpQrCodeTicket ticket = this.wxService.getQrcodeService().qrCodeCreateLastTicket(sceneId);
Assert.assertNotNull(ticket.getUrl()); Assert.assertNotNull(ticket.getUrl());
Assert.assertNotNull(ticket.getTicket()); Assert.assertNotNull(ticket.getTicket());
Assert.assertTrue(ticket.getExpire_seconds() == -1); Assert.assertTrue(ticket.getExpire_seconds() == -1);

+ 6
- 7
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImplTest.java View File

@@ -2,12 +2,11 @@ package me.chanjar.weixin.mp.api.impl;


import com.google.inject.Inject; import com.google.inject.Inject;
import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.mp.api.ApiTestModule;
import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.WxXmlMpInMemoryConfigStorage;
import org.testng.Assert;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
import me.chanjar.weixin.mp.api.test.ApiTestModule;
import me.chanjar.weixin.mp.api.test.TestConfigStorage;
import org.testng.*;
import org.testng.annotations.*;


@Test @Test
@Guice(modules = ApiTestModule.class) @Guice(modules = ApiTestModule.class)
@@ -103,9 +102,9 @@ public class WxMpServiceImplTest {


@Test @Test
public void testBuildQrConnectUrl() { public void testBuildQrConnectUrl() {
String qrconnectRedirectUrl = ((WxXmlMpInMemoryConfigStorage) this.wxService.getWxMpConfigStorage()).getQrconnectRedirectUrl();
String qrconnectRedirectUrl = ((TestConfigStorage) this.wxService.getWxMpConfigStorage()).getQrconnectRedirectUrl();
String qrConnectUrl = this.wxService.buildQrConnectUrl(qrconnectRedirectUrl, String qrConnectUrl = this.wxService.buildQrConnectUrl(qrconnectRedirectUrl,
WxConsts.QRCONNECT_SCOPE_SNSAPI_LOGIN, null);
WxConsts.QRCONNECT_SCOPE_SNSAPI_LOGIN, null);
Assert.assertNotNull(qrConnectUrl); Assert.assertNotNull(qrConnectUrl);
System.out.println(qrConnectUrl); System.out.println(qrConnectUrl);
} }


+ 8
- 9
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpStoreServiceImplTest.java View File

@@ -2,13 +2,12 @@ package me.chanjar.weixin.mp.api.impl;


import com.google.inject.Inject; import com.google.inject.Inject;
import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.ApiTestModule;
import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.test.ApiTestModule;
import me.chanjar.weixin.mp.bean.store.WxMpStoreBaseInfo; import me.chanjar.weixin.mp.bean.store.WxMpStoreBaseInfo;
import me.chanjar.weixin.mp.bean.store.WxMpStoreInfo; import me.chanjar.weixin.mp.bean.store.WxMpStoreInfo;
import me.chanjar.weixin.mp.bean.store.WxMpStoreListResult; import me.chanjar.weixin.mp.bean.store.WxMpStoreListResult;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
import org.testng.annotations.*;


import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.List; import java.util.List;
@@ -18,7 +17,6 @@ import static org.junit.Assert.assertNotNull;
/** /**
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a> * @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
* Created by Binary Wang on 2016-09-23. * Created by Binary Wang on 2016-09-23.
*
*/ */
@Test @Test
@Guice(modules = ApiTestModule.class) @Guice(modules = ApiTestModule.class)
@@ -28,16 +26,17 @@ public class WxMpStoreServiceImplTest {


/** /**
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpStoreServiceImpl#add(me.chanjar.weixin.mp.bean.store.WxMpStoreBaseInfo)}. * Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpStoreServiceImpl#add(me.chanjar.weixin.mp.bean.store.WxMpStoreBaseInfo)}.
*
* @throws WxErrorException * @throws WxErrorException
*/ */
public void testAdd() throws WxErrorException { public void testAdd() throws WxErrorException {
this.wxMpService.getStoreService().add(WxMpStoreBaseInfo.builder().build()); this.wxMpService.getStoreService().add(WxMpStoreBaseInfo.builder().build());
this.wxMpService.getStoreService() this.wxMpService.getStoreService()
.add(WxMpStoreBaseInfo.builder().businessName("haha").branchName("abc")
.province("aaa").district("aaa").telephone("122").address("abc").categories(new String[] { "美食,江浙菜" })
.longitude(new BigDecimal("115.32375"))
.latitude(new BigDecimal("25.097486")).city("aaa").offsetType(1)
.build());
.add(WxMpStoreBaseInfo.builder().businessName("haha").branchName("abc")
.province("aaa").district("aaa").telephone("122").address("abc").categories(new String[]{"美食,江浙菜"})
.longitude(new BigDecimal("115.32375"))
.latitude(new BigDecimal("25.097486")).city("aaa").offsetType(1)
.build());
} }


public void testUpdate() throws WxErrorException { public void testUpdate() throws WxErrorException {


+ 7
- 8
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpTemplateMsgServiceImplTest.java View File

@@ -2,17 +2,16 @@ package me.chanjar.weixin.mp.api.impl;


import com.google.inject.Inject; import com.google.inject.Inject;
import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.ApiTestModule;
import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.WxXmlMpInMemoryConfigStorage;
import me.chanjar.weixin.mp.api.test.ApiTestModule;
import me.chanjar.weixin.mp.api.test.TestConfigStorage;
import me.chanjar.weixin.mp.bean.template.WxMpTemplate; import me.chanjar.weixin.mp.bean.template.WxMpTemplate;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData; import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateIndustry; import me.chanjar.weixin.mp.bean.template.WxMpTemplateIndustry;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage; import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.RandomStringUtils;
import org.testng.Assert;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
import org.testng.*;
import org.testng.annotations.*;


import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
@@ -33,13 +32,13 @@ public class WxMpTemplateMsgServiceImplTest {
public void testSendTemplateMsg() throws WxErrorException { public void testSendTemplateMsg() throws WxErrorException {
SimpleDateFormat dateFormat = new SimpleDateFormat( SimpleDateFormat dateFormat = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss.SSS"); "yyyy-MM-dd HH:mm:ss.SSS");
WxXmlMpInMemoryConfigStorage configStorage = (WxXmlMpInMemoryConfigStorage) this.wxService
TestConfigStorage configStorage = (TestConfigStorage) this.wxService
.getWxMpConfigStorage(); .getWxMpConfigStorage();
WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder() WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()
.toUser(configStorage.getOpenid()) .toUser(configStorage.getOpenid())
.templateId(configStorage.getTemplateId()).build(); .templateId(configStorage.getTemplateId()).build();
templateMessage.addWxMpTemplateData( templateMessage.addWxMpTemplateData(
new WxMpTemplateData("first", dateFormat.format(new Date()),"#FF00FF"));
new WxMpTemplateData("first", dateFormat.format(new Date()), "#FF00FF"));
templateMessage.addWxMpTemplateData( templateMessage.addWxMpTemplateData(
new WxMpTemplateData("remark", RandomStringUtils.randomAlphanumeric(100), "#FF00FF")); new WxMpTemplateData("remark", RandomStringUtils.randomAlphanumeric(100), "#FF00FF"));
templateMessage.setUrl(" "); templateMessage.setUrl(" ");
@@ -58,7 +57,7 @@ public class WxMpTemplateMsgServiceImplTest {
@Test @Test
public void testSetIndustry() throws Exception { public void testSetIndustry() throws Exception {
WxMpTemplateIndustry industry = new WxMpTemplateIndustry(new WxMpTemplateIndustry.Industry("1"), WxMpTemplateIndustry industry = new WxMpTemplateIndustry(new WxMpTemplateIndustry.Industry("1"),
new WxMpTemplateIndustry.Industry("04"));
new WxMpTemplateIndustry.Industry("04"));
boolean result = this.wxService.getTemplateMsgService().setIndustry(industry); boolean result = this.wxService.getTemplateMsgService().setIndustry(industry);
Assert.assertTrue(result); Assert.assertTrue(result);
} }


+ 7
- 8
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpUserBlacklistServiceImplTest.java View File

@@ -1,12 +1,11 @@
package me.chanjar.weixin.mp.api.impl; package me.chanjar.weixin.mp.api.impl;


import me.chanjar.weixin.mp.api.ApiTestModule;
import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.WxXmlMpInMemoryConfigStorage;
import me.chanjar.weixin.mp.api.test.ApiTestModule;
import me.chanjar.weixin.mp.api.test.TestConfigStorage;
import me.chanjar.weixin.mp.bean.result.WxMpUserBlacklistGetResult; import me.chanjar.weixin.mp.bean.result.WxMpUserBlacklistGetResult;
import org.testng.Assert;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
import org.testng.*;
import org.testng.annotations.*;


import javax.inject.Inject; import javax.inject.Inject;
import java.util.ArrayList; import java.util.ArrayList;
@@ -23,7 +22,7 @@ public class WxMpUserBlacklistServiceImplTest {


@Test @Test
public void testGetBlacklist() throws Exception { public void testGetBlacklist() throws Exception {
WxXmlMpInMemoryConfigStorage configStorage = (WxXmlMpInMemoryConfigStorage) this.wxService
TestConfigStorage configStorage = (TestConfigStorage) this.wxService
.getWxMpConfigStorage(); .getWxMpConfigStorage();
WxMpUserBlacklistGetResult wxMpUserBlacklistGetResult = this.wxService.getBlackListService().getBlacklist(configStorage.getOpenid()); WxMpUserBlacklistGetResult wxMpUserBlacklistGetResult = this.wxService.getBlackListService().getBlacklist(configStorage.getOpenid());
Assert.assertNotNull(wxMpUserBlacklistGetResult); Assert.assertNotNull(wxMpUserBlacklistGetResult);
@@ -35,7 +34,7 @@ public class WxMpUserBlacklistServiceImplTest {


@Test @Test
public void testPushToBlacklist() throws Exception { public void testPushToBlacklist() throws Exception {
WxXmlMpInMemoryConfigStorage configStorage = (WxXmlMpInMemoryConfigStorage) this.wxService
TestConfigStorage configStorage = (TestConfigStorage) this.wxService
.getWxMpConfigStorage(); .getWxMpConfigStorage();
List<String> openidList = new ArrayList<>(); List<String> openidList = new ArrayList<>();
openidList.add(configStorage.getOpenid()); openidList.add(configStorage.getOpenid());
@@ -44,7 +43,7 @@ public class WxMpUserBlacklistServiceImplTest {


@Test @Test
public void testPullFromBlacklist() throws Exception { public void testPullFromBlacklist() throws Exception {
WxXmlMpInMemoryConfigStorage configStorage = (WxXmlMpInMemoryConfigStorage) this.wxService
TestConfigStorage configStorage = (TestConfigStorage) this.wxService
.getWxMpConfigStorage(); .getWxMpConfigStorage();
List<String> openidList = new ArrayList<>(); List<String> openidList = new ArrayList<>();
openidList.add(configStorage.getOpenid()); openidList.add(configStorage.getOpenid());


+ 15
- 20
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpUserServiceImplTest.java View File

@@ -1,23 +1,18 @@

package me.chanjar.weixin.mp.api.impl; package me.chanjar.weixin.mp.api.impl;


import java.util.ArrayList;
import java.util.List;

import me.chanjar.weixin.mp.api.WxMpService;
import org.testng.Assert;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;

import com.google.inject.Inject; import com.google.inject.Inject;

import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.ApiTestModule;
import me.chanjar.weixin.mp.api.WxXmlMpInMemoryConfigStorage;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.test.ApiTestModule;
import me.chanjar.weixin.mp.api.test.TestConfigStorage;
import me.chanjar.weixin.mp.bean.WxMpUserQuery; import me.chanjar.weixin.mp.bean.WxMpUserQuery;
import me.chanjar.weixin.mp.bean.result.WxMpUser; import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.mp.bean.result.WxMpUserList; import me.chanjar.weixin.mp.bean.result.WxMpUserList;
import org.testng.*;
import org.testng.annotations.*;

import java.util.ArrayList;
import java.util.List;


/** /**
* 测试用户相关的接口 * 测试用户相关的接口
@@ -32,22 +27,22 @@ public class WxMpUserServiceImplTest {
@Inject @Inject
private WxMpService wxService; private WxMpService wxService;


private WxXmlMpInMemoryConfigStorage configProvider;
private TestConfigStorage configProvider;


@BeforeTest @BeforeTest
public void setup() { public void setup() {
this.configProvider = (WxXmlMpInMemoryConfigStorage) this.wxService
.getWxMpConfigStorage();
this.configProvider = (TestConfigStorage) this.wxService
.getWxMpConfigStorage();
} }


public void testUserUpdateRemark() throws WxErrorException { public void testUserUpdateRemark() throws WxErrorException {
this.wxService.getUserService() this.wxService.getUserService()
.userUpdateRemark(this.configProvider.getOpenid(), "测试备注名");
.userUpdateRemark(this.configProvider.getOpenid(), "测试备注名");
} }


public void testUserInfo() throws WxErrorException { public void testUserInfo() throws WxErrorException {
WxMpUser user = this.wxService.getUserService() WxMpUser user = this.wxService.getUserService()
.userInfo(this.configProvider.getOpenid(), null);
.userInfo(this.configProvider.getOpenid(), null);
Assert.assertNotNull(user); Assert.assertNotNull(user);
System.out.println(user); System.out.println(user);
} }
@@ -56,7 +51,7 @@ public class WxMpUserServiceImplTest {
List<String> openids = new ArrayList<>(); List<String> openids = new ArrayList<>();
openids.add(this.configProvider.getOpenid()); openids.add(this.configProvider.getOpenid());
List<WxMpUser> userList = this.wxService.getUserService() List<WxMpUser> userList = this.wxService.getUserService()
.userInfoList(openids);
.userInfoList(openids);
Assert.assertEquals(userList.size(), 1); Assert.assertEquals(userList.size(), 1);
System.out.println(userList); System.out.println(userList);
} }
@@ -65,7 +60,7 @@ public class WxMpUserServiceImplTest {
WxMpUserQuery query = new WxMpUserQuery(); WxMpUserQuery query = new WxMpUserQuery();
query.add(this.configProvider.getOpenid(), "zh_CN"); query.add(this.configProvider.getOpenid(), "zh_CN");
List<WxMpUser> userList = this.wxService.getUserService() List<WxMpUser> userList = this.wxService.getUserService()
.userInfoList(query);
.userInfoList(query);
Assert.assertEquals(userList.size(), 1); Assert.assertEquals(userList.size(), 1);
System.out.println(userList); System.out.println(userList);
} }


+ 12
- 16
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpUserTagServiceImplTest.java View File

@@ -1,21 +1,17 @@
package me.chanjar.weixin.mp.api.impl; package me.chanjar.weixin.mp.api.impl;


import java.util.List;

import me.chanjar.weixin.mp.api.WxMpService;
import org.testng.Assert;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;

import com.google.inject.Inject; import com.google.inject.Inject;
import me.chanjar.weixin.mp.api.ApiTestModule;
import me.chanjar.weixin.mp.api.WxXmlMpInMemoryConfigStorage;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.test.ApiTestModule;
import me.chanjar.weixin.mp.api.test.TestConfigStorage;
import me.chanjar.weixin.mp.bean.tag.WxTagListUser; import me.chanjar.weixin.mp.bean.tag.WxTagListUser;
import me.chanjar.weixin.mp.bean.tag.WxUserTag; import me.chanjar.weixin.mp.bean.tag.WxUserTag;
import org.testng.*;
import org.testng.annotations.*;

import java.util.List;


/** /**
*
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a> * @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
* Created by Binary Wang on 2016/9/2. * Created by Binary Wang on 2016/9/2.
*/ */
@@ -43,7 +39,7 @@ public class WxMpUserTagServiceImplTest {
Assert.assertNotNull(res); Assert.assertNotNull(res);
} }


@Test(dependsOnMethods = { "testTagCreate" })
@Test(dependsOnMethods = {"testTagCreate"})
public void testTagUpdate() throws Exception { public void testTagUpdate() throws Exception {
String tagName = "修改标签" + System.currentTimeMillis(); String tagName = "修改标签" + System.currentTimeMillis();
Boolean res = this.wxService.getUserTagService().tagUpdate(this.tagId, tagName); Boolean res = this.wxService.getUserTagService().tagUpdate(this.tagId, tagName);
@@ -51,7 +47,7 @@ public class WxMpUserTagServiceImplTest {
Assert.assertTrue(res); Assert.assertTrue(res);
} }


@Test(dependsOnMethods = { "testTagCreate" })
@Test(dependsOnMethods = {"testTagCreate"})
public void testTagDelete() throws Exception { public void testTagDelete() throws Exception {
Boolean res = this.wxService.getUserTagService().tagDelete(this.tagId); Boolean res = this.wxService.getUserTagService().tagDelete(this.tagId);
System.out.println(res); System.out.println(res);
@@ -67,7 +63,7 @@ public class WxMpUserTagServiceImplTest {


@Test @Test
public void testBatchTagging() throws Exception { public void testBatchTagging() throws Exception {
String[] openids = new String[]{((WxXmlMpInMemoryConfigStorage) this.wxService.getWxMpConfigStorage()).getOpenid()};
String[] openids = new String[]{((TestConfigStorage) this.wxService.getWxMpConfigStorage()).getOpenid()};
boolean res = this.wxService.getUserTagService().batchTagging(this.tagId, openids); boolean res = this.wxService.getUserTagService().batchTagging(this.tagId, openids);
System.out.println(res); System.out.println(res);
Assert.assertTrue(res); Assert.assertTrue(res);
@@ -75,7 +71,7 @@ public class WxMpUserTagServiceImplTest {


@Test @Test
public void testBatchUntagging() throws Exception { public void testBatchUntagging() throws Exception {
String[] openids = new String[]{((WxXmlMpInMemoryConfigStorage) this.wxService.getWxMpConfigStorage()).getOpenid()};
String[] openids = new String[]{((TestConfigStorage) this.wxService.getWxMpConfigStorage()).getOpenid()};
boolean res = this.wxService.getUserTagService().batchUntagging(this.tagId, openids); boolean res = this.wxService.getUserTagService().batchUntagging(this.tagId, openids);
System.out.println(res); System.out.println(res);
Assert.assertTrue(res); Assert.assertTrue(res);
@@ -84,7 +80,7 @@ public class WxMpUserTagServiceImplTest {
@Test @Test
public void testUserTagList() throws Exception { public void testUserTagList() throws Exception {
List<Long> res = this.wxService.getUserTagService().userTagList( List<Long> res = this.wxService.getUserTagService().userTagList(
((WxXmlMpInMemoryConfigStorage) this.wxService.getWxMpConfigStorage()).getOpenid());
((TestConfigStorage) this.wxService.getWxMpConfigStorage()).getOpenid());
System.out.println(res); System.out.println(res);
Assert.assertNotNull(res); Assert.assertNotNull(res);
} }


weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/ApiTestModule.java → weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/test/ApiTestModule.java View File

@@ -1,9 +1,11 @@
package me.chanjar.weixin.mp.api;
package me.chanjar.weixin.mp.api.test;


import com.google.inject.Binder; import com.google.inject.Binder;
import com.google.inject.Module; import com.google.inject.Module;
import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.XStream;
import me.chanjar.weixin.common.util.xml.XStreamInitializer; import me.chanjar.weixin.common.util.xml.XStreamInitializer;
import me.chanjar.weixin.mp.api.WxMpConfigStorage;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;


import java.io.IOException; import java.io.IOException;
@@ -14,10 +16,9 @@ public class ApiTestModule implements Module {


@Override @Override
public void configure(Binder binder) { public void configure(Binder binder) {
try (InputStream is1 = ClassLoader
.getSystemResourceAsStream("test-config.xml")) {
WxXmlMpInMemoryConfigStorage config = this
.fromXml(WxXmlMpInMemoryConfigStorage.class, is1);
try (InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml")) {
TestConfigStorage config = this
.fromXml(TestConfigStorage.class, is1);
config.setAccessTokenLock(new ReentrantLock()); config.setAccessTokenLock(new ReentrantLock());
WxMpService wxService = new WxMpServiceImpl(); WxMpService wxService = new WxMpServiceImpl();
wxService.setWxMpConfigStorage(config); wxService.setWxMpConfigStorage(config);

weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxXmlMpInMemoryConfigStorage.java → weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/test/TestConfigStorage.java View File

@@ -1,18 +1,27 @@
package me.chanjar.weixin.mp.api;
package me.chanjar.weixin.mp.api.test;


import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAlias;
import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;


import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;


@XStreamAlias("xml") @XStreamAlias("xml")
public class WxXmlMpInMemoryConfigStorage
extends WxMpInMemoryConfigStorage {
public class TestConfigStorage extends WxMpInMemoryConfigStorage {


private String openid; private String openid;
private String kfAccount; private String kfAccount;
private String qrconnectRedirectUrl; private String qrconnectRedirectUrl;
private String templateId; private String templateId;
private String keyPath;

public String getKeyPath() {
return keyPath;
}

public void setKeyPath(String keyPath) {
this.keyPath = keyPath;
}


public String getOpenid() { public String getOpenid() {
return this.openid; return this.openid;
@@ -51,7 +60,14 @@ public class WxXmlMpInMemoryConfigStorage
this.templateId = templateId; this.templateId = templateId;
} }


public void setAccessTokenLock(Lock lock){
public void setAccessTokenLock(Lock lock) {
super.accessTokenLock = lock; super.accessTokenLock = lock;
} }

@Override
public boolean useSandboxForWxPay() {
return false;
//沙箱环境不成熟,有问题无法使用,暂时屏蔽掉
// return true;
}
} }

+ 9
- 9
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/kefu/WxMpKefuMessageTest.java View File

@@ -2,8 +2,8 @@ package me.chanjar.weixin.mp.bean.kefu;


import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage.WxArticle; import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage.WxArticle;
import org.testng.Assert;
import org.testng.annotations.Test;
import org.testng.*;
import org.testng.annotations.*;


@Test @Test
public class WxMpKefuMessageTest { public class WxMpKefuMessageTest {
@@ -77,13 +77,13 @@ public class WxMpKefuMessageTest {


public void testMusicBuild() { public void testMusicBuild() {
WxMpKefuMessage reply = WxMpKefuMessage.MUSIC() WxMpKefuMessage reply = WxMpKefuMessage.MUSIC()
.toUser("OPENID")
.title("TITLE")
.thumbMediaId("MEDIA_ID")
.description("DESCRIPTION")
.musicUrl("MUSIC_URL")
.hqMusicUrl("HQ_MUSIC_URL")
.build();
.toUser("OPENID")
.title("TITLE")
.thumbMediaId("MEDIA_ID")
.description("DESCRIPTION")
.musicUrl("MUSIC_URL")
.hqMusicUrl("HQ_MUSIC_URL")
.build();
Assert.assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"music\",\"music\":{\"title\":\"TITLE\",\"description\":\"DESCRIPTION\",\"thumb_media_id\":\"MEDIA_ID\",\"musicurl\":\"MUSIC_URL\",\"hqmusicurl\":\"HQ_MUSIC_URL\"}}"); Assert.assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"music\",\"music\":{\"title\":\"TITLE\",\"description\":\"DESCRIPTION\",\"thumb_media_id\":\"MEDIA_ID\",\"musicurl\":\"MUSIC_URL\",\"hqmusicurl\":\"HQ_MUSIC_URL\"}}");
} }




+ 25
- 25
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfListTest.java View File

@@ -1,36 +1,36 @@
package me.chanjar.weixin.mp.bean.kefu.result; package me.chanjar.weixin.mp.bean.kefu.result;


import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
import org.testng.Assert;
import org.testng.annotations.Test;
import org.testng.*;
import org.testng.annotations.*;


@Test @Test
public class WxMpKfListTest { public class WxMpKfListTest {


public void testFromJson() { public void testFromJson() {
String json=" {\r\n" +
" \"kf_list\" : [\r\n" +
" {\r\n" +
" \"kf_account\" : \"test1@test\",\r\n" +
" \"kf_headimgurl\" : \"http://mmbiz.qpic.cn/mmbiz/4whpV1VZl2iccsvYbHvnphkyGtnvjfUS8Ym0GSaLic0FD3vN0V8PILcibEGb2fPfEOmw/0\",\r\n" +
" \"kf_id\" : \"1001\",\r\n" +
" \"kf_nick\" : \"ntest1\"\r\n" +
" },\r\n" +
" {\r\n" +
" \"kf_account\" : \"test2@test\",\r\n" +
" \"kf_headimgurl\" : \"http://mmbiz.qpic.cn/mmbiz/4whpV1VZl2iccsvYbHvnphkyGtnvjfUS8Ym0GSaLic0FD3vN0V8PILcibEGb2fPfEOmw/0\",\r\n" +
" \"kf_id\" : \"1002\",\r\n" +
" \"kf_nick\" : \"ntest2\"\r\n" +
" },\r\n" +
" {\r\n" +
" \"kf_account\" : \"test3@test\",\r\n" +
" \"kf_headimgurl\" : \"http://mmbiz.qpic.cn/mmbiz/4whpV1VZl2iccsvYbHvnphkyGtnvjfUS8Ym0GSaLic0FD3vN0V8PILcibEGb2fPfEOmw/0\",\r\n" +
" \"kf_id\" : \"1003\",\r\n" +
" \"kf_nick\" : \"ntest3\"\r\n" +
" }\r\n" +
" ]\r\n" +
" }";
String json = " {\r\n" +
" \"kf_list\" : [\r\n" +
" {\r\n" +
" \"kf_account\" : \"test1@test\",\r\n" +
" \"kf_headimgurl\" : \"http://mmbiz.qpic.cn/mmbiz/4whpV1VZl2iccsvYbHvnphkyGtnvjfUS8Ym0GSaLic0FD3vN0V8PILcibEGb2fPfEOmw/0\",\r\n" +
" \"kf_id\" : \"1001\",\r\n" +
" \"kf_nick\" : \"ntest1\"\r\n" +
" },\r\n" +
" {\r\n" +
" \"kf_account\" : \"test2@test\",\r\n" +
" \"kf_headimgurl\" : \"http://mmbiz.qpic.cn/mmbiz/4whpV1VZl2iccsvYbHvnphkyGtnvjfUS8Ym0GSaLic0FD3vN0V8PILcibEGb2fPfEOmw/0\",\r\n" +
" \"kf_id\" : \"1002\",\r\n" +
" \"kf_nick\" : \"ntest2\"\r\n" +
" },\r\n" +
" {\r\n" +
" \"kf_account\" : \"test3@test\",\r\n" +
" \"kf_headimgurl\" : \"http://mmbiz.qpic.cn/mmbiz/4whpV1VZl2iccsvYbHvnphkyGtnvjfUS8Ym0GSaLic0FD3vN0V8PILcibEGb2fPfEOmw/0\",\r\n" +
" \"kf_id\" : \"1003\",\r\n" +
" \"kf_nick\" : \"ntest3\"\r\n" +
" }\r\n" +
" ]\r\n" +
" }";
WxMpKfList wxMpKfList = WxMpKfList.fromJson(json); WxMpKfList wxMpKfList = WxMpKfList.fromJson(json);
Assert.assertNotNull(wxMpKfList); Assert.assertNotNull(wxMpKfList);
System.err.println(ToStringBuilder.reflectionToString(wxMpKfList)); System.err.println(ToStringBuilder.reflectionToString(wxMpKfList));


+ 20
- 22
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfOnlineListTest.java View File

@@ -1,34 +1,32 @@
package me.chanjar.weixin.mp.bean.kefu.result; package me.chanjar.weixin.mp.bean.kefu.result;


import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
import org.testng.Assert;
import org.testng.annotations.Test;

import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfOnlineList;
import org.testng.*;
import org.testng.annotations.*;


@Test @Test
public class WxMpKfOnlineListTest { public class WxMpKfOnlineListTest {


@Test @Test
public void testFromJson() { public void testFromJson() {
String json = "{\r\n" +
" \"kf_online_list\": [\r\n" +
" {\r\n" +
" \"kf_account\": \"test1@test\", \r\n" +
" \"status\": 1, \r\n" +
" \"kf_id\": \"1001\", \r\n" +
" \"auto_accept\": 0, \r\n" +
" \"accepted_case\": 1\r\n" +
" },\r\n" +
" {\r\n" +
" \"kf_account\": \"test2@test\", \r\n" +
" \"status\": 1, \r\n" +
" \"kf_id\": \"1002\", \r\n" +
" \"auto_accept\": 0, \r\n" +
" \"accepted_case\": 2\r\n" +
" }\r\n" +
" ]\r\n" +
"}";
String json = "{\r\n" +
" \"kf_online_list\": [\r\n" +
" {\r\n" +
" \"kf_account\": \"test1@test\", \r\n" +
" \"status\": 1, \r\n" +
" \"kf_id\": \"1001\", \r\n" +
" \"auto_accept\": 0, \r\n" +
" \"accepted_case\": 1\r\n" +
" },\r\n" +
" {\r\n" +
" \"kf_account\": \"test2@test\", \r\n" +
" \"status\": 1, \r\n" +
" \"kf_id\": \"1002\", \r\n" +
" \"auto_accept\": 0, \r\n" +
" \"accepted_case\": 2\r\n" +
" }\r\n" +
" ]\r\n" +
"}";


WxMpKfOnlineList wxMpKfOnlineList = WxMpKfOnlineList.fromJson(json); WxMpKfOnlineList wxMpKfOnlineList = WxMpKfOnlineList.fromJson(json);
Assert.assertNotNull(wxMpKfOnlineList); Assert.assertNotNull(wxMpKfOnlineList);


+ 2
- 2
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlMessageTest.java View File

@@ -1,8 +1,8 @@
package me.chanjar.weixin.mp.bean.message; package me.chanjar.weixin.mp.bean.message;


import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.api.WxConsts;
import org.testng.Assert;
import org.testng.annotations.Test;
import org.testng.*;
import org.testng.annotations.*;


@Test @Test
public class WxMpXmlMessageTest { public class WxMpXmlMessageTest {


+ 22
- 22
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutImageMessageTest.java View File

@@ -1,7 +1,7 @@
package me.chanjar.weixin.mp.bean.message; package me.chanjar.weixin.mp.bean.message;


import org.testng.Assert;
import org.testng.annotations.Test;
import org.testng.*;
import org.testng.annotations.*;


@Test @Test
public class WxMpXmlOutImageMessageTest { public class WxMpXmlOutImageMessageTest {
@@ -14,12 +14,12 @@ public class WxMpXmlOutImageMessageTest {
m.setToUserName("to"); m.setToUserName("to");


String expected = "<xml>" String expected = "<xml>"
+ "<ToUserName><![CDATA[to]]></ToUserName>"
+ "<FromUserName><![CDATA[from]]></FromUserName>"
+ "<CreateTime>1122</CreateTime>"
+ "<MsgType><![CDATA[image]]></MsgType>"
+ "<Image><MediaId><![CDATA[ddfefesfsdfef]]></MediaId></Image>"
+ "</xml>";
+ "<ToUserName><![CDATA[to]]></ToUserName>"
+ "<FromUserName><![CDATA[from]]></FromUserName>"
+ "<CreateTime>1122</CreateTime>"
+ "<MsgType><![CDATA[image]]></MsgType>"
+ "<Image><MediaId><![CDATA[ddfefesfsdfef]]></MediaId></Image>"
+ "</xml>";
System.out.println(m.toXml()); System.out.println(m.toXml());
Assert.assertEquals(m.toXml().replaceAll("\\s", ""), expected.replaceAll("\\s", "")); Assert.assertEquals(m.toXml().replaceAll("\\s", ""), expected.replaceAll("\\s", ""));
} }
@@ -27,22 +27,22 @@ public class WxMpXmlOutImageMessageTest {
public void testBuild() { public void testBuild() {
WxMpXmlOutImageMessage m = WxMpXmlOutMessage.IMAGE().mediaId("ddfefesfsdfef").fromUser("from").toUser("to").build(); WxMpXmlOutImageMessage m = WxMpXmlOutMessage.IMAGE().mediaId("ddfefesfsdfef").fromUser("from").toUser("to").build();
String expected = "<xml>" String expected = "<xml>"
+ "<ToUserName><![CDATA[to]]></ToUserName>"
+ "<FromUserName><![CDATA[from]]></FromUserName>"
+ "<CreateTime>1122</CreateTime>"
+ "<MsgType><![CDATA[image]]></MsgType>"
+ "<Image><MediaId><![CDATA[ddfefesfsdfef]]></MediaId></Image>"
+ "</xml>";
+ "<ToUserName><![CDATA[to]]></ToUserName>"
+ "<FromUserName><![CDATA[from]]></FromUserName>"
+ "<CreateTime>1122</CreateTime>"
+ "<MsgType><![CDATA[image]]></MsgType>"
+ "<Image><MediaId><![CDATA[ddfefesfsdfef]]></MediaId></Image>"
+ "</xml>";
System.out.println(m.toXml()); System.out.println(m.toXml());
Assert.assertEquals( Assert.assertEquals(
m
.toXml()
.replaceAll("\\s", "")
.replaceAll("<CreateTime>.*?</CreateTime>", ""),
expected
.replaceAll("\\s", "")
.replaceAll("<CreateTime>.*?</CreateTime>", "")
);
m
.toXml()
.replaceAll("\\s", "")
.replaceAll("<CreateTime>.*?</CreateTime>", ""),
expected
.replaceAll("\\s", "")
.replaceAll("<CreateTime>.*?</CreateTime>", "")
);


} }
} }

+ 37
- 37
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutMusicMessageTest.java View File

@@ -1,7 +1,7 @@
package me.chanjar.weixin.mp.bean.message; package me.chanjar.weixin.mp.bean.message;


import org.testng.Assert;
import org.testng.annotations.Test;
import org.testng.*;
import org.testng.annotations.*;


@Test @Test
public class WxMpXmlOutMusicMessageTest { public class WxMpXmlOutMusicMessageTest {
@@ -18,55 +18,55 @@ public class WxMpXmlOutMusicMessageTest {
m.setToUserName("toUser"); m.setToUserName("toUser");


String expected = "<xml>" String expected = "<xml>"
+ "<ToUserName><![CDATA[toUser]]></ToUserName>"
+ "<FromUserName><![CDATA[fromUser]]></FromUserName>"
+ "<CreateTime>1122</CreateTime>"
+ "<MsgType><![CDATA[music]]></MsgType>"
+ "<Music>"
+ " <Title><![CDATA[title]]></Title>"
+ " <Description><![CDATA[ddfff]]></Description>"
+ " <ThumbMediaId><![CDATA[thumbMediaId]]></ThumbMediaId>"
+ " <MusicUrl><![CDATA[musicUrl]]></MusicUrl>"
+ " <HQMusicUrl><![CDATA[hQMusicUrl]]></HQMusicUrl>"
+ " </Music>"
+ "</xml>";
+ "<ToUserName><![CDATA[toUser]]></ToUserName>"
+ "<FromUserName><![CDATA[fromUser]]></FromUserName>"
+ "<CreateTime>1122</CreateTime>"
+ "<MsgType><![CDATA[music]]></MsgType>"
+ "<Music>"
+ " <Title><![CDATA[title]]></Title>"
+ " <Description><![CDATA[ddfff]]></Description>"
+ " <ThumbMediaId><![CDATA[thumbMediaId]]></ThumbMediaId>"
+ " <MusicUrl><![CDATA[musicUrl]]></MusicUrl>"
+ " <HQMusicUrl><![CDATA[hQMusicUrl]]></HQMusicUrl>"
+ " </Music>"
+ "</xml>";
System.out.println(m.toXml()); System.out.println(m.toXml());
Assert.assertEquals(m.toXml().replaceAll("\\s", ""), expected.replaceAll("\\s", "")); Assert.assertEquals(m.toXml().replaceAll("\\s", ""), expected.replaceAll("\\s", ""));
} }


public void testBuild() { public void testBuild() {
WxMpXmlOutMusicMessage m = WxMpXmlOutMessage.MUSIC() WxMpXmlOutMusicMessage m = WxMpXmlOutMessage.MUSIC()
.fromUser("fromUser")
.toUser("toUser")
.title("title")
.description("ddfff")
.hqMusicUrl("hQMusicUrl")
.musicUrl("musicUrl")
.thumbMediaId("thumbMediaId")
.build();
.fromUser("fromUser")
.toUser("toUser")
.title("title")
.description("ddfff")
.hqMusicUrl("hQMusicUrl")
.musicUrl("musicUrl")
.thumbMediaId("thumbMediaId")
.build();
String expected = "<xml>" String expected = "<xml>"
+ "<ToUserName><![CDATA[toUser]]></ToUserName>"
+ "<FromUserName><![CDATA[fromUser]]></FromUserName>"
+ "<CreateTime>1122</CreateTime>"
+ "<MsgType><![CDATA[music]]></MsgType>"
+ "<Music>"
+ " <Title><![CDATA[title]]></Title>"
+ " <Description><![CDATA[ddfff]]></Description>"
+ " <ThumbMediaId><![CDATA[thumbMediaId]]></ThumbMediaId>"
+ " <MusicUrl><![CDATA[musicUrl]]></MusicUrl>"
+ " <HQMusicUrl><![CDATA[hQMusicUrl]]></HQMusicUrl>"
+ " </Music>"
+ "</xml>";
+ "<ToUserName><![CDATA[toUser]]></ToUserName>"
+ "<FromUserName><![CDATA[fromUser]]></FromUserName>"
+ "<CreateTime>1122</CreateTime>"
+ "<MsgType><![CDATA[music]]></MsgType>"
+ "<Music>"
+ " <Title><![CDATA[title]]></Title>"
+ " <Description><![CDATA[ddfff]]></Description>"
+ " <ThumbMediaId><![CDATA[thumbMediaId]]></ThumbMediaId>"
+ " <MusicUrl><![CDATA[musicUrl]]></MusicUrl>"
+ " <HQMusicUrl><![CDATA[hQMusicUrl]]></HQMusicUrl>"
+ " </Music>"
+ "</xml>";
System.out.println(m.toXml()); System.out.println(m.toXml());
Assert.assertEquals( Assert.assertEquals(
m
m
.toXml() .toXml()
.replaceAll("\\s", "") .replaceAll("\\s", "")
.replaceAll("<CreateTime>.*?</CreateTime>", ""), .replaceAll("<CreateTime>.*?</CreateTime>", ""),
expected
expected
.replaceAll("\\s", "") .replaceAll("\\s", "")
.replaceAll("<CreateTime>.*?</CreateTime>", "") .replaceAll("<CreateTime>.*?</CreateTime>", "")
);
);
} }


} }

+ 50
- 50
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutNewsMessageTest.java View File

@@ -1,7 +1,7 @@
package me.chanjar.weixin.mp.bean.message; package me.chanjar.weixin.mp.bean.message;


import org.testng.Assert;
import org.testng.annotations.Test;
import org.testng.*;
import org.testng.annotations.*;


@Test @Test
public class WxMpXmlOutNewsMessageTest { public class WxMpXmlOutNewsMessageTest {
@@ -20,26 +20,26 @@ public class WxMpXmlOutNewsMessageTest {
m.addArticle(item); m.addArticle(item);
m.addArticle(item); m.addArticle(item);
String expected = "<xml>" String expected = "<xml>"
+ "<ToUserName><![CDATA[toUser]]></ToUserName>"
+ "<FromUserName><![CDATA[fromUser]]></FromUserName>"
+ "<CreateTime>1122</CreateTime>"
+ "<MsgType><![CDATA[news]]></MsgType>"
+ " <ArticleCount>2</ArticleCount>"
+ " <Articles>"
+ " <item>"
+ " <Title><![CDATA[title]]></Title>"
+ " <Description><![CDATA[description]]></Description>"
+ " <PicUrl><![CDATA[picUrl]]></PicUrl>"
+ " <Url><![CDATA[url]]></Url>"
+ " </item>"
+ " <item>"
+ " <Title><![CDATA[title]]></Title>"
+ " <Description><![CDATA[description]]></Description>"
+ " <PicUrl><![CDATA[picUrl]]></PicUrl>"
+ " <Url><![CDATA[url]]></Url>"
+ " </item>"
+ " </Articles>"
+ "</xml>";
+ "<ToUserName><![CDATA[toUser]]></ToUserName>"
+ "<FromUserName><![CDATA[fromUser]]></FromUserName>"
+ "<CreateTime>1122</CreateTime>"
+ "<MsgType><![CDATA[news]]></MsgType>"
+ " <ArticleCount>2</ArticleCount>"
+ " <Articles>"
+ " <item>"
+ " <Title><![CDATA[title]]></Title>"
+ " <Description><![CDATA[description]]></Description>"
+ " <PicUrl><![CDATA[picUrl]]></PicUrl>"
+ " <Url><![CDATA[url]]></Url>"
+ " </item>"
+ " <item>"
+ " <Title><![CDATA[title]]></Title>"
+ " <Description><![CDATA[description]]></Description>"
+ " <PicUrl><![CDATA[picUrl]]></PicUrl>"
+ " <Url><![CDATA[url]]></Url>"
+ " </item>"
+ " </Articles>"
+ "</xml>";
System.out.println(m.toXml()); System.out.println(m.toXml());
Assert.assertEquals(m.toXml().replaceAll("\\s", ""), expected.replaceAll("\\s", "")); Assert.assertEquals(m.toXml().replaceAll("\\s", ""), expected.replaceAll("\\s", ""));
} }
@@ -52,42 +52,42 @@ public class WxMpXmlOutNewsMessageTest {
item.setUrl("url"); item.setUrl("url");


WxMpXmlOutNewsMessage m = WxMpXmlOutMessage.NEWS() WxMpXmlOutNewsMessage m = WxMpXmlOutMessage.NEWS()
.fromUser("fromUser")
.toUser("toUser")
.addArticle(item)
.addArticle(item)
.build();
.fromUser("fromUser")
.toUser("toUser")
.addArticle(item)
.addArticle(item)
.build();
String expected = "<xml>" String expected = "<xml>"
+ "<ToUserName><![CDATA[toUser]]></ToUserName>"
+ "<FromUserName><![CDATA[fromUser]]></FromUserName>"
+ "<CreateTime>1122</CreateTime>"
+ "<MsgType><![CDATA[news]]></MsgType>"
+ " <ArticleCount>2</ArticleCount>"
+ " <Articles>"
+ " <item>"
+ " <Title><![CDATA[title]]></Title>"
+ " <Description><![CDATA[description]]></Description>"
+ " <PicUrl><![CDATA[picUrl]]></PicUrl>"
+ " <Url><![CDATA[url]]></Url>"
+ " </item>"
+ " <item>"
+ " <Title><![CDATA[title]]></Title>"
+ " <Description><![CDATA[description]]></Description>"
+ " <PicUrl><![CDATA[picUrl]]></PicUrl>"
+ " <Url><![CDATA[url]]></Url>"
+ " </item>"
+ " </Articles>"
+ "</xml>";
+ "<ToUserName><![CDATA[toUser]]></ToUserName>"
+ "<FromUserName><![CDATA[fromUser]]></FromUserName>"
+ "<CreateTime>1122</CreateTime>"
+ "<MsgType><![CDATA[news]]></MsgType>"
+ " <ArticleCount>2</ArticleCount>"
+ " <Articles>"
+ " <item>"
+ " <Title><![CDATA[title]]></Title>"
+ " <Description><![CDATA[description]]></Description>"
+ " <PicUrl><![CDATA[picUrl]]></PicUrl>"
+ " <Url><![CDATA[url]]></Url>"
+ " </item>"
+ " <item>"
+ " <Title><![CDATA[title]]></Title>"
+ " <Description><![CDATA[description]]></Description>"
+ " <PicUrl><![CDATA[picUrl]]></PicUrl>"
+ " <Url><![CDATA[url]]></Url>"
+ " </item>"
+ " </Articles>"
+ "</xml>";
System.out.println(m.toXml()); System.out.println(m.toXml());
Assert.assertEquals( Assert.assertEquals(
m
m
.toXml() .toXml()
.replaceAll("\\s", "") .replaceAll("\\s", "")
.replaceAll("<CreateTime>.*?</CreateTime>", ""), .replaceAll("<CreateTime>.*?</CreateTime>", ""),
expected
expected
.replaceAll("\\s", "") .replaceAll("\\s", "")
.replaceAll("<CreateTime>.*?</CreateTime>", "") .replaceAll("<CreateTime>.*?</CreateTime>", "")
);
);
} }


} }

+ 17
- 17
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutTextMessageTest.java View File

@@ -1,7 +1,7 @@
package me.chanjar.weixin.mp.bean.message; package me.chanjar.weixin.mp.bean.message;


import org.testng.Assert;
import org.testng.annotations.Test;
import org.testng.*;
import org.testng.annotations.*;


@Test @Test
public class WxMpXmlOutTextMessageTest { public class WxMpXmlOutTextMessageTest {
@@ -14,12 +14,12 @@ public class WxMpXmlOutTextMessageTest {
m.setToUserName("to"); m.setToUserName("to");


String expected = "<xml>" String expected = "<xml>"
+ "<ToUserName><![CDATA[to]]></ToUserName>"
+ "<FromUserName><![CDATA[from]]></FromUserName>"
+ "<CreateTime>1122</CreateTime>"
+ "<MsgType><![CDATA[text]]></MsgType>"
+ "<Content><![CDATA[content]]></Content>"
+ "</xml>";
+ "<ToUserName><![CDATA[to]]></ToUserName>"
+ "<FromUserName><![CDATA[from]]></FromUserName>"
+ "<CreateTime>1122</CreateTime>"
+ "<MsgType><![CDATA[text]]></MsgType>"
+ "<Content><![CDATA[content]]></Content>"
+ "</xml>";
System.out.println(m.toXml()); System.out.println(m.toXml());
Assert.assertEquals(m.toXml().replaceAll("\\s", ""), expected.replaceAll("\\s", "")); Assert.assertEquals(m.toXml().replaceAll("\\s", ""), expected.replaceAll("\\s", ""));
} }
@@ -27,22 +27,22 @@ public class WxMpXmlOutTextMessageTest {
public void testBuild() { public void testBuild() {
WxMpXmlOutTextMessage m = WxMpXmlOutMessage.TEXT().content("content").fromUser("from").toUser("to").build(); WxMpXmlOutTextMessage m = WxMpXmlOutMessage.TEXT().content("content").fromUser("from").toUser("to").build();
String expected = "<xml>" String expected = "<xml>"
+ "<ToUserName><![CDATA[to]]></ToUserName>"
+ "<FromUserName><![CDATA[from]]></FromUserName>"
+ "<CreateTime>1122</CreateTime>"
+ "<MsgType><![CDATA[text]]></MsgType>"
+ "<Content><![CDATA[content]]></Content>"
+ "</xml>";
+ "<ToUserName><![CDATA[to]]></ToUserName>"
+ "<FromUserName><![CDATA[from]]></FromUserName>"
+ "<CreateTime>1122</CreateTime>"
+ "<MsgType><![CDATA[text]]></MsgType>"
+ "<Content><![CDATA[content]]></Content>"
+ "</xml>";
System.out.println(m.toXml()); System.out.println(m.toXml());
Assert.assertEquals( Assert.assertEquals(
m
m
.toXml() .toXml()
.replaceAll("\\s", "") .replaceAll("\\s", "")
.replaceAll("<CreateTime>.*?</CreateTime>", ""), .replaceAll("<CreateTime>.*?</CreateTime>", ""),
expected
expected
.replaceAll("\\s", "") .replaceAll("\\s", "")
.replaceAll("<CreateTime>.*?</CreateTime>", "") .replaceAll("<CreateTime>.*?</CreateTime>", "")
);
);


} }




+ 2
- 2
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutTransferKefuMessageTest.java View File

@@ -1,7 +1,7 @@
package me.chanjar.weixin.mp.bean.message; package me.chanjar.weixin.mp.bean.message;


import org.testng.Assert;
import org.testng.annotations.Test;
import org.testng.*;
import org.testng.annotations.*;


/** /**
* Created by ben on 2015/12/29. * Created by ben on 2015/12/29.


+ 31
- 31
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutVideoMessageTest.java View File

@@ -1,7 +1,7 @@
package me.chanjar.weixin.mp.bean.message; package me.chanjar.weixin.mp.bean.message;


import org.testng.Assert;
import org.testng.annotations.Test;
import org.testng.*;
import org.testng.annotations.*;


@Test @Test
public class WxMpXmlOutVideoMessageTest { public class WxMpXmlOutVideoMessageTest {
@@ -16,49 +16,49 @@ public class WxMpXmlOutVideoMessageTest {
m.setToUserName("toUser"); m.setToUserName("toUser");


String expected = "<xml>" String expected = "<xml>"
+ "<ToUserName><![CDATA[toUser]]></ToUserName>"
+ "<FromUserName><![CDATA[fromUser]]></FromUserName>"
+ "<CreateTime>1122</CreateTime>"
+ "<MsgType><![CDATA[video]]></MsgType>"
+ "<Video>"
+ "<MediaId><![CDATA[media_id]]></MediaId>"
+ "<Title><![CDATA[title]]></Title>"
+ "<Description><![CDATA[ddfff]]></Description>"
+ "</Video> "
+ "</xml>";
+ "<ToUserName><![CDATA[toUser]]></ToUserName>"
+ "<FromUserName><![CDATA[fromUser]]></FromUserName>"
+ "<CreateTime>1122</CreateTime>"
+ "<MsgType><![CDATA[video]]></MsgType>"
+ "<Video>"
+ "<MediaId><![CDATA[media_id]]></MediaId>"
+ "<Title><![CDATA[title]]></Title>"
+ "<Description><![CDATA[ddfff]]></Description>"
+ "</Video> "
+ "</xml>";
System.out.println(m.toXml()); System.out.println(m.toXml());
Assert.assertEquals(m.toXml().replaceAll("\\s", ""), expected.replaceAll("\\s", "")); Assert.assertEquals(m.toXml().replaceAll("\\s", ""), expected.replaceAll("\\s", ""));
} }


public void testBuild() { public void testBuild() {
WxMpXmlOutVideoMessage m = WxMpXmlOutMessage.VIDEO() WxMpXmlOutVideoMessage m = WxMpXmlOutMessage.VIDEO()
.mediaId("media_id")
.fromUser("fromUser")
.toUser("toUser")
.title("title")
.description("ddfff")
.build();
.mediaId("media_id")
.fromUser("fromUser")
.toUser("toUser")
.title("title")
.description("ddfff")
.build();
String expected = "<xml>" String expected = "<xml>"
+ "<ToUserName><![CDATA[toUser]]></ToUserName>"
+ "<FromUserName><![CDATA[fromUser]]></FromUserName>"
+ "<CreateTime>1122</CreateTime>"
+ "<MsgType><![CDATA[video]]></MsgType>"
+ "<Video>"
+ "<MediaId><![CDATA[media_id]]></MediaId>"
+ "<Title><![CDATA[title]]></Title>"
+ "<Description><![CDATA[ddfff]]></Description>"
+ "</Video> "
+ "</xml>";
+ "<ToUserName><![CDATA[toUser]]></ToUserName>"
+ "<FromUserName><![CDATA[fromUser]]></FromUserName>"
+ "<CreateTime>1122</CreateTime>"
+ "<MsgType><![CDATA[video]]></MsgType>"
+ "<Video>"
+ "<MediaId><![CDATA[media_id]]></MediaId>"
+ "<Title><![CDATA[title]]></Title>"
+ "<Description><![CDATA[ddfff]]></Description>"
+ "</Video> "
+ "</xml>";
System.out.println(m.toXml()); System.out.println(m.toXml());
Assert.assertEquals( Assert.assertEquals(
m
m
.toXml() .toXml()
.replaceAll("\\s", "") .replaceAll("\\s", "")
.replaceAll("<CreateTime>.*?</CreateTime>", ""), .replaceAll("<CreateTime>.*?</CreateTime>", ""),
expected
expected
.replaceAll("\\s", "") .replaceAll("\\s", "")
.replaceAll("<CreateTime>.*?</CreateTime>", "") .replaceAll("<CreateTime>.*?</CreateTime>", "")
);
);
} }


} }

+ 17
- 17
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutVoiceMessageTest.java View File

@@ -1,7 +1,7 @@
package me.chanjar.weixin.mp.bean.message; package me.chanjar.weixin.mp.bean.message;


import org.testng.Assert;
import org.testng.annotations.Test;
import org.testng.*;
import org.testng.annotations.*;


@Test @Test
public class WxMpXmlOutVoiceMessageTest { public class WxMpXmlOutVoiceMessageTest {
@@ -14,12 +14,12 @@ public class WxMpXmlOutVoiceMessageTest {
m.setToUserName("to"); m.setToUserName("to");


String expected = "<xml>" String expected = "<xml>"
+ "<ToUserName><![CDATA[to]]></ToUserName>"
+ "<FromUserName><![CDATA[from]]></FromUserName>"
+ "<CreateTime>1122</CreateTime>"
+ "<MsgType><![CDATA[voice]]></MsgType>"
+ "<Voice><MediaId><![CDATA[ddfefesfsdfef]]></MediaId></Voice>"
+ "</xml>";
+ "<ToUserName><![CDATA[to]]></ToUserName>"
+ "<FromUserName><![CDATA[from]]></FromUserName>"
+ "<CreateTime>1122</CreateTime>"
+ "<MsgType><![CDATA[voice]]></MsgType>"
+ "<Voice><MediaId><![CDATA[ddfefesfsdfef]]></MediaId></Voice>"
+ "</xml>";
System.out.println(m.toXml()); System.out.println(m.toXml());
Assert.assertEquals(m.toXml().replaceAll("\\s", ""), expected.replaceAll("\\s", "")); Assert.assertEquals(m.toXml().replaceAll("\\s", ""), expected.replaceAll("\\s", ""));
} }
@@ -27,22 +27,22 @@ public class WxMpXmlOutVoiceMessageTest {
public void testBuild() { public void testBuild() {
WxMpXmlOutVoiceMessage m = WxMpXmlOutMessage.VOICE().mediaId("ddfefesfsdfef").fromUser("from").toUser("to").build(); WxMpXmlOutVoiceMessage m = WxMpXmlOutMessage.VOICE().mediaId("ddfefesfsdfef").fromUser("from").toUser("to").build();
String expected = "<xml>" String expected = "<xml>"
+ "<ToUserName><![CDATA[to]]></ToUserName>"
+ "<FromUserName><![CDATA[from]]></FromUserName>"
+ "<CreateTime>1122</CreateTime>"
+ "<MsgType><![CDATA[voice]]></MsgType>"
+ "<Voice><MediaId><![CDATA[ddfefesfsdfef]]></MediaId></Voice>"
+ "</xml>";
+ "<ToUserName><![CDATA[to]]></ToUserName>"
+ "<FromUserName><![CDATA[from]]></FromUserName>"
+ "<CreateTime>1122</CreateTime>"
+ "<MsgType><![CDATA[voice]]></MsgType>"
+ "<Voice><MediaId><![CDATA[ddfefesfsdfef]]></MediaId></Voice>"
+ "</xml>";
System.out.println(m.toXml()); System.out.println(m.toXml());
Assert.assertEquals( Assert.assertEquals(
m
m
.toXml() .toXml()
.replaceAll("\\s", "") .replaceAll("\\s", "")
.replaceAll("<CreateTime>.*?</CreateTime>", ""), .replaceAll("<CreateTime>.*?</CreateTime>", ""),
expected
expected
.replaceAll("\\s", "") .replaceAll("\\s", "")
.replaceAll("<CreateTime>.*?</CreateTime>", "") .replaceAll("<CreateTime>.*?</CreateTime>", "")
);
);
} }


} }

+ 49
- 0
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/pay/result/WxPayBaseResultTest.java View File

@@ -0,0 +1,49 @@
package me.chanjar.weixin.mp.bean.pay.result;

import org.testng.*;
import org.testng.annotations.*;

import java.util.Map;

/**
* <pre>
* Created by Binary Wang on 2017-01-04.
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
* </pre>
*/
public class WxPayBaseResultTest {
@Test
public void testToMap() throws Exception {
WxPayOrderQueryResult result = new WxPayOrderQueryResult();
result.setXmlString("<xml>\n" +
" <return_code><![CDATA[SUCCESS]]></return_code>\n" +
" <return_msg><![CDATA[OK]]></return_msg>\n" +
" <appid><![CDATA[wx2421b1c4370ec43b]]></appid>\n" +
" <mch_id><![CDATA[10000100]]></mch_id>\n" +
" <device_info><![CDATA[1000]]></device_info>\n" +
" <nonce_str><![CDATA[TN55wO9Pba5yENl8]]></nonce_str>\n" +
" <sign><![CDATA[BDF0099C15FF7BC6B1585FBB110AB635]]></sign>\n" +
" <result_code><![CDATA[SUCCESS]]></result_code>\n" +
" <openid><![CDATA[oUpF8uN95-Ptaags6E_roPHg7AG0]]></openid>\n" +
" <is_subscribe><![CDATA[Y]]></is_subscribe>\n" +
" <trade_type><![CDATA[MICROPAY]]></trade_type>\n" +
" <bank_type><![CDATA[CCB_DEBIT]]></bank_type>\n" +
" <total_fee>1</total_fee>\n" +
" <fee_type><![CDATA[CNY]]></fee_type>\n" +
" <transaction_id><![CDATA[1008450740201411110005820873]]></transaction_id>\n" +
" <out_trade_no><![CDATA[1415757673]]></out_trade_no>\n" +
" <attach><![CDATA[订单额外描述]]></attach>\n" +
" <time_end><![CDATA[20141111170043]]></time_end>\n" +
" <trade_state><![CDATA[SUCCESS]]></trade_state>\n" +
"</xml>");
Map<String, String> map = result.toMap();
System.out.println(map);

Assert.assertEquals("SUCCESS", map.get("return_code"));
Assert.assertEquals("订单额外描述", map.get("attach"));

result.setXmlString("");
System.out.println(result.toMap());
}

}

+ 65
- 0
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/pay/result/WxPayOrderQueryResultTest.java View File

@@ -0,0 +1,65 @@
package me.chanjar.weixin.mp.bean.pay.result;

import org.testng.*;
import org.testng.annotations.*;

/**
* <pre>
* Created by Binary Wang on 2017-01-04.
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
* </pre>
*/
public class WxPayOrderQueryResultTest {
@Test
public void testComposeCoupons() throws Exception {
/**
* xml样例字符串来自于官方文档,并稍加改造加入了coupon相关的数据便于测试
*/
String xmlString = "<xml>\n" +
" <return_code><![CDATA[SUCCESS]]></return_code>\n" +
" <return_msg><![CDATA[OK]]></return_msg>\n" +
" <appid><![CDATA[wx2421b1c4370ec43b]]></appid>\n" +
" <mch_id><![CDATA[10000100]]></mch_id>\n" +
" <device_info><![CDATA[1000]]></device_info>\n" +
" <nonce_str><![CDATA[TN55wO9Pba5yENl8]]></nonce_str>\n" +
" <sign><![CDATA[BDF0099C15FF7BC6B1585FBB110AB635]]></sign>\n" +
" <result_code><![CDATA[SUCCESS]]></result_code>\n" +
" <openid><![CDATA[oUpF8uN95-Ptaags6E_roPHg7AG0]]></openid>\n" +
" <is_subscribe><![CDATA[Y]]></is_subscribe>\n" +
" <trade_type><![CDATA[MICROPAY]]></trade_type>\n" +
" <bank_type><![CDATA[CCB_DEBIT]]></bank_type>\n" +
" <total_fee>1</total_fee>\n" +
" <fee_type><![CDATA[CNY]]></fee_type>\n" +
" <transaction_id><![CDATA[1008450740201411110005820873]]></transaction_id>\n" +
" <out_trade_no><![CDATA[1415757673]]></out_trade_no>\n" +
" <attach><![CDATA[订单额外描述]]></attach>\n" +
" <time_end><![CDATA[20141111170043]]></time_end>\n" +
" <trade_state><![CDATA[SUCCESS]]></trade_state>\n" +
" <coupon_count>2</coupon_count>\n" +
" <coupon_type_0><![CDATA[CASH]]></coupon_type_0>\n" +
" <coupon_id_0>10000</coupon_id_0>\n" +
" <coupon_fee_0>100</coupon_fee_0>\n" +
" <coupon_type_1><![CDATA[NO_CASH]]></coupon_type_1>\n" +
" <coupon_id_1>10001</coupon_id_1>\n" +
" <coupon_fee_1>200</coupon_fee_1>\n" +
"</xml>";

WxPayOrderQueryResult orderQueryResult = WxPayOrderQueryResult.fromXML(xmlString, WxPayOrderQueryResult.class);
orderQueryResult.composeCoupons();

Assert.assertEquals(orderQueryResult.getCouponCount().intValue(), 2);
Assert.assertNotNull(orderQueryResult.getCoupons());
Assert.assertEquals(orderQueryResult.getCoupons().size(), 2);

Assert.assertEquals(orderQueryResult.getCoupons().get(0).getCouponFee().intValue(), 100);
Assert.assertEquals(orderQueryResult.getCoupons().get(1).getCouponFee().intValue(), 200);

Assert.assertEquals(orderQueryResult.getCoupons().get(0).getCouponType(), "CASH");
Assert.assertEquals(orderQueryResult.getCoupons().get(1).getCouponType(), "NO_CASH");

Assert.assertEquals(orderQueryResult.getCoupons().get(0).getCouponId(), "10000");
Assert.assertEquals(orderQueryResult.getCoupons().get(1).getCouponId(), "10001");

}

}

+ 48
- 0
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/pay/result/WxPayRefundQueryResultTest.java View File

@@ -0,0 +1,48 @@
package me.chanjar.weixin.mp.bean.pay.result;


import org.testng.*;
import org.testng.annotations.*;

/**
* <pre>
* Created by Binary Wang on 2016-12-29.
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
* </pre>
*/
public class WxPayRefundQueryResultTest {
@Test
public void composeRefundRecords() throws Exception {
/*
该xml字符串来自于官方文档示例
*/
String xmlString = "<xml>\n" +
" <appid><![CDATA[wx2421b1c4370ec43b]]></appid>\n" +
" <mch_id><![CDATA[10000100]]></mch_id>\n" +
" <nonce_str><![CDATA[TeqClE3i0mvn3DrK]]></nonce_str>\n" +
" <out_refund_no_0><![CDATA[1415701182]]></out_refund_no_0>\n" +
" <out_trade_no><![CDATA[1415757673]]></out_trade_no>\n" +
" <refund_count>1</refund_count>\n" +
" <refund_fee_0>1</refund_fee_0>\n" +
" <refund_id_0><![CDATA[2008450740201411110000174436]]></refund_id_0>\n" +
" <refund_status_0><![CDATA[PROCESSING]]></refund_status_0>\n" +
" <result_code><![CDATA[SUCCESS]]></result_code>\n" +
" <return_code><![CDATA[SUCCESS]]></return_code>\n" +
" <return_msg><![CDATA[OK]]></return_msg>\n" +
" <sign><![CDATA[1F2841558E233C33ABA71A961D27561C]]></sign>\n" +
" <transaction_id><![CDATA[1008450740201411110005820873]]></transaction_id>\n" +
"</xml>";

WxPayRefundQueryResult result = WxPayRefundQueryResult.fromXML(xmlString, WxPayRefundQueryResult.class);
result.composeRefundRecords();

Assert.assertNotNull(result.getRefundRecords());
Assert.assertEquals(result.getRefundRecords().size(), 1);
Assert.assertEquals(result.getRefundRecords().get(0).getRefundId(), "2008450740201411110000174436");
Assert.assertEquals(result.getRefundRecords().get(0).getRefundFee().intValue(), 1);
Assert.assertEquals(result.getRefundRecords().get(0).getOutRefundNo(), "1415701182");
Assert.assertEquals(result.getRefundRecords().get(0).getRefundStatus(), "PROCESSING");

}

}

+ 28
- 29
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/pay/result/WxPaySendRedpackResultTest.java View File

@@ -2,9 +2,8 @@ package me.chanjar.weixin.mp.bean.pay.result;


import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.XStream;
import me.chanjar.weixin.common.util.xml.XStreamInitializer; import me.chanjar.weixin.common.util.xml.XStreamInitializer;
import org.testng.Assert;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import org.testng.*;
import org.testng.annotations.*;


public class WxPaySendRedpackResultTest { public class WxPaySendRedpackResultTest {


@@ -12,26 +11,26 @@ public class WxPaySendRedpackResultTest {


@BeforeTest @BeforeTest
public void setup() { public void setup() {
this.xstream = XStreamInitializer.getInstance();
this.xstream.processAnnotations(WxPaySendRedpackResult.class);
this.xstream = XStreamInitializer.getInstance();
this.xstream.processAnnotations(WxPaySendRedpackResult.class);
} }


@Test @Test
public void loadSuccessResult() { public void loadSuccessResult() {
final String successSample = "<xml>\n" + final String successSample = "<xml>\n" +
"<return_code><![CDATA[SUCCESS]]></return_code>\n" +
"<return_msg><![CDATA[发放成功.]]></return_msg>\n" +
"<result_code><![CDATA[SUCCESS]]></result_code>\n" +
"<err_code><![CDATA[0]]></err_code>\n" +
"<err_code_des><![CDATA[发放成功.]]></err_code_des>\n" +
"<mch_billno><![CDATA[0010010404201411170000046545]]></mch_billno>\n" +
"<mch_id>10010404</mch_id>\n" +
"<wxappid><![CDATA[wx6fa7e3bab7e15415]]></wxappid>\n" +
"<re_openid><![CDATA[onqOjjmM1tad-3ROpncN-yUfa6uI]]></re_openid>\n" +
"<total_amount>1</total_amount>\n" +
"<send_listid>100000000020150520314766074200</send_listid>\n" +
"<send_time>20150520102602</send_time>\n" +
"</xml>";
"<return_code><![CDATA[SUCCESS]]></return_code>\n" +
"<return_msg><![CDATA[发放成功.]]></return_msg>\n" +
"<result_code><![CDATA[SUCCESS]]></result_code>\n" +
"<err_code><![CDATA[0]]></err_code>\n" +
"<err_code_des><![CDATA[发放成功.]]></err_code_des>\n" +
"<mch_billno><![CDATA[0010010404201411170000046545]]></mch_billno>\n" +
"<mch_id>10010404</mch_id>\n" +
"<wxappid><![CDATA[wx6fa7e3bab7e15415]]></wxappid>\n" +
"<re_openid><![CDATA[onqOjjmM1tad-3ROpncN-yUfa6uI]]></re_openid>\n" +
"<total_amount>1</total_amount>\n" +
"<send_listid>100000000020150520314766074200</send_listid>\n" +
"<send_time>20150520102602</send_time>\n" +
"</xml>";
WxPaySendRedpackResult wxMpRedpackResult = (WxPaySendRedpackResult) this.xstream.fromXML(successSample); WxPaySendRedpackResult wxMpRedpackResult = (WxPaySendRedpackResult) this.xstream.fromXML(successSample);
Assert.assertEquals("SUCCESS", wxMpRedpackResult.getReturnCode()); Assert.assertEquals("SUCCESS", wxMpRedpackResult.getReturnCode());
Assert.assertEquals("SUCCESS", wxMpRedpackResult.getResultCode()); Assert.assertEquals("SUCCESS", wxMpRedpackResult.getResultCode());
@@ -41,17 +40,17 @@ public class WxPaySendRedpackResultTest {
@Test @Test
public void loadFailureResult() { public void loadFailureResult() {
final String failureSample = "<xml>\n" + final String failureSample = "<xml>\n" +
"<return_code><![CDATA[FAIL]]></return_code>\n" +
"<return_msg><![CDATA[系统繁忙,请稍后再试.]]></return_msg>\n" +
"<result_code><![CDATA[FAIL]]></result_code>\n" +
"<err_code><![CDATA[268458547]]></err_code>\n" +
"<err_code_des><![CDATA[系统繁忙,请稍后再试.]]></err_code_des>\n" +
"<mch_billno><![CDATA[0010010404201411170000046542]]></mch_billno>\n" +
"<mch_id>10010404</mch_id>\n" +
"<wxappid><![CDATA[wx6fa7e3bab7e15415]]></wxappid>\n" +
"<re_openid><![CDATA[onqOjjmM1tad-3ROpncN-yUfa6uI]]></re_openid>\n" +
"<total_amount>1</total_amount>\n" +
"</xml>";
"<return_code><![CDATA[FAIL]]></return_code>\n" +
"<return_msg><![CDATA[系统繁忙,请稍后再试.]]></return_msg>\n" +
"<result_code><![CDATA[FAIL]]></result_code>\n" +
"<err_code><![CDATA[268458547]]></err_code>\n" +
"<err_code_des><![CDATA[系统繁忙,请稍后再试.]]></err_code_des>\n" +
"<mch_billno><![CDATA[0010010404201411170000046542]]></mch_billno>\n" +
"<mch_id>10010404</mch_id>\n" +
"<wxappid><![CDATA[wx6fa7e3bab7e15415]]></wxappid>\n" +
"<re_openid><![CDATA[onqOjjmM1tad-3ROpncN-yUfa6uI]]></re_openid>\n" +
"<total_amount>1</total_amount>\n" +
"</xml>";
WxPaySendRedpackResult wxMpRedpackResult = (WxPaySendRedpackResult) this.xstream.fromXML(failureSample); WxPaySendRedpackResult wxMpRedpackResult = (WxPaySendRedpackResult) this.xstream.fromXML(failureSample);
Assert.assertEquals("FAIL", wxMpRedpackResult.getReturnCode()); Assert.assertEquals("FAIL", wxMpRedpackResult.getReturnCode());
Assert.assertEquals("FAIL", wxMpRedpackResult.getResultCode()); Assert.assertEquals("FAIL", wxMpRedpackResult.getResultCode());


+ 25
- 25
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoGuessNumberHandler.java View File

@@ -1,9 +1,5 @@
package me.chanjar.weixin.mp.demo; package me.chanjar.weixin.mp.demo;


import java.util.Map;
import java.util.Random;
import java.util.regex.Pattern;

import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.session.WxSession; import me.chanjar.weixin.common.session.WxSession;
import me.chanjar.weixin.common.session.WxSessionManager; import me.chanjar.weixin.common.session.WxSessionManager;
@@ -14,6 +10,10 @@ import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;


import java.util.Map;
import java.util.Random;
import java.util.regex.Pattern;

public class DemoGuessNumberHandler implements WxMpMessageHandler, WxMpMessageMatcher { public class DemoGuessNumberHandler implements WxMpMessageHandler, WxMpMessageMatcher {


private Random random = new Random(); private Random random = new Random();
@@ -35,7 +35,7 @@ public class DemoGuessNumberHandler implements WxMpMessageHandler, WxMpMessageMa


@Override @Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService,
WxSessionManager sessionManager) throws WxErrorException {
WxSessionManager sessionManager) throws WxErrorException {


if (isUserWantGuess(wxMessage)) { if (isUserWantGuess(wxMessage)) {
letsGo(wxMessage, wxMpService, sessionManager); letsGo(wxMessage, wxMpService, sessionManager);
@@ -53,17 +53,17 @@ public class DemoGuessNumberHandler implements WxMpMessageHandler, WxMpMessageMa
WxSession session = sessionManager.getSession(wxMessage.getFromUser()); WxSession session = sessionManager.getSession(wxMessage.getFromUser());
if (session.getAttribute("guessing") == null) { if (session.getAttribute("guessing") == null) {
WxMpKefuMessage m = WxMpKefuMessage WxMpKefuMessage m = WxMpKefuMessage
.TEXT()
.toUser(wxMessage.getFromUser())
.content("请猜一个100以内的数字")
.build();
.TEXT()
.toUser(wxMessage.getFromUser())
.content("请猜一个100以内的数字")
.build();
wxMpService.getKefuService().sendKefuMessage(m); wxMpService.getKefuService().sendKefuMessage(m);
} else { } else {
WxMpKefuMessage m = WxMpKefuMessage WxMpKefuMessage m = WxMpKefuMessage
.TEXT()
.toUser(wxMessage.getFromUser())
.content("放弃了吗?那请重新猜一个100以内的数字")
.build();
.TEXT()
.toUser(wxMessage.getFromUser())
.content("放弃了吗?那请重新猜一个100以内的数字")
.build();
wxMpService.getKefuService().sendKefuMessage(m); wxMpService.getKefuService().sendKefuMessage(m);
} }


@@ -88,25 +88,25 @@ public class DemoGuessNumberHandler implements WxMpMessageHandler, WxMpMessageMa
int guessNumber = Integer.valueOf(wxMessage.getContent()); int guessNumber = Integer.valueOf(wxMessage.getContent());
if (guessNumber < answer) { if (guessNumber < answer) {
WxMpKefuMessage m = WxMpKefuMessage WxMpKefuMessage m = WxMpKefuMessage
.TEXT()
.toUser(wxMessage.getFromUser())
.content("小了")
.build();
.TEXT()
.toUser(wxMessage.getFromUser())
.content("小了")
.build();
wxMpService.getKefuService().sendKefuMessage(m); wxMpService.getKefuService().sendKefuMessage(m);


} else if (guessNumber > answer) { } else if (guessNumber > answer) {
WxMpKefuMessage m = WxMpKefuMessage WxMpKefuMessage m = WxMpKefuMessage
.TEXT()
.toUser(wxMessage.getFromUser())
.content("大了")
.build();
.TEXT()
.toUser(wxMessage.getFromUser())
.content("大了")
.build();
wxMpService.getKefuService().sendKefuMessage(m); wxMpService.getKefuService().sendKefuMessage(m);
} else { } else {
WxMpKefuMessage m = WxMpKefuMessage WxMpKefuMessage m = WxMpKefuMessage
.TEXT()
.toUser(wxMessage.getFromUser())
.content("Bingo!")
.build();
.TEXT()
.toUser(wxMessage.getFromUser())
.content("Bingo!")
.build();
session.removeAttribute("guessing"); session.removeAttribute("guessing");
wxMpService.getKefuService().sendKefuMessage(m); wxMpService.getKefuService().sendKefuMessage(m);
} }


+ 8
- 8
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoImageHandler.java View File

@@ -15,17 +15,17 @@ import java.util.Map;
public class DemoImageHandler implements WxMpMessageHandler { public class DemoImageHandler implements WxMpMessageHandler {
@Override @Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context,
WxMpService wxMpService, WxSessionManager sessionManager) {
WxMpService wxMpService, WxSessionManager sessionManager) {
try { try {
WxMediaUploadResult wxMediaUploadResult = wxMpService.getMaterialService() WxMediaUploadResult wxMediaUploadResult = wxMpService.getMaterialService()
.mediaUpload(WxConsts.MEDIA_IMAGE, WxConsts.FILE_JPG, ClassLoader.getSystemResourceAsStream("mm.jpeg"));
.mediaUpload(WxConsts.MEDIA_IMAGE, WxConsts.FILE_JPG, ClassLoader.getSystemResourceAsStream("mm.jpeg"));
WxMpXmlOutImageMessage m WxMpXmlOutImageMessage m
= WxMpXmlOutMessage
.IMAGE()
.mediaId(wxMediaUploadResult.getMediaId())
.fromUser(wxMessage.getToUser())
.toUser(wxMessage.getFromUser())
.build();
= WxMpXmlOutMessage
.IMAGE()
.mediaId(wxMediaUploadResult.getMediaId())
.fromUser(wxMessage.getToUser())
.toUser(wxMessage.getFromUser())
.build();
return m; return m;
} catch (WxErrorException e) { } catch (WxErrorException e) {
e.printStackTrace(); e.printStackTrace();


+ 1
- 1
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoLogHandler.java View File

@@ -14,7 +14,7 @@ import java.util.Map;
public class DemoLogHandler implements WxMpMessageHandler { public class DemoLogHandler implements WxMpMessageHandler {
@Override @Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService,
WxSessionManager sessionManager) {
WxSessionManager sessionManager) {
System.out.println(wxMessage.toString()); System.out.println(wxMessage.toString());
return null; return null;
} }


+ 6
- 6
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoOAuth2Handler.java View File

@@ -15,13 +15,13 @@ import java.util.Map;
public class DemoOAuth2Handler implements WxMpMessageHandler { public class DemoOAuth2Handler implements WxMpMessageHandler {
@Override @Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
Map<String, Object> context, WxMpService wxMpService,
WxSessionManager sessionManager) {
Map<String, Object> context, WxMpService wxMpService,
WxSessionManager sessionManager) {
String href = "<a href=\"" + wxMpService.oauth2buildAuthorizationUrl( String href = "<a href=\"" + wxMpService.oauth2buildAuthorizationUrl(
wxMpService.getWxMpConfigStorage().getOauth2redirectUri(),
WxConsts.OAUTH2_SCOPE_USER_INFO, null) + "\">测试oauth2</a>";
wxMpService.getWxMpConfigStorage().getOauth2redirectUri(),
WxConsts.OAUTH2_SCOPE_USER_INFO, null) + "\">测试oauth2</a>";
return WxMpXmlOutMessage.TEXT().content(href) return WxMpXmlOutMessage.TEXT().content(href)
.fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser())
.build();
.fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser())
.build();
} }
} }

+ 3
- 3
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoTextHandler.java View File

@@ -15,10 +15,10 @@ import java.util.Map;
public class DemoTextHandler implements WxMpMessageHandler { public class DemoTextHandler implements WxMpMessageHandler {
@Override @Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context,
WxMpService wxMpService, WxSessionManager sessionManager) {
WxMpService wxMpService, WxSessionManager sessionManager) {
WxMpXmlOutTextMessage m WxMpXmlOutTextMessage m
= WxMpXmlOutMessage.TEXT().content("测试加密消息").fromUser(wxMessage.getToUser())
.toUser(wxMessage.getFromUser()).build();
= WxMpXmlOutMessage.TEXT().content("测试加密消息").fromUser(wxMessage.getToUser())
.toUser(wxMessage.getFromUser()).build();
return m; return m;
} }




+ 6
- 7
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpDemoInMemoryConfigStorage.java View File

@@ -13,17 +13,16 @@ import java.io.InputStream;
@XStreamAlias("xml") @XStreamAlias("xml")
class WxMpDemoInMemoryConfigStorage extends WxMpInMemoryConfigStorage { class WxMpDemoInMemoryConfigStorage extends WxMpInMemoryConfigStorage {


@Override
public String toString() {
return "SimpleWxConfigProvider [appId=" + this.appId + ", secret=" + this.secret + ", accessToken=" + this.accessToken
+ ", expiresTime=" + this.expiresTime + ", token=" + this.token + ", aesKey=" + this.aesKey + "]";
}


public static WxMpDemoInMemoryConfigStorage fromXml(InputStream is) { public static WxMpDemoInMemoryConfigStorage fromXml(InputStream is) {
XStream xstream = XStreamInitializer.getInstance(); XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxMpDemoInMemoryConfigStorage.class); xstream.processAnnotations(WxMpDemoInMemoryConfigStorage.class);
return (WxMpDemoInMemoryConfigStorage) xstream.fromXML(is); return (WxMpDemoInMemoryConfigStorage) xstream.fromXML(is);
} }


@Override
public String toString() {
return "SimpleWxConfigProvider [appId=" + this.appId + ", secret=" + this.secret + ", accessToken=" + this.accessToken
+ ", expiresTime=" + this.expiresTime + ", token=" + this.token + ", aesKey=" + this.aesKey + "]";
}

} }

+ 16
- 17
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpDemoServer.java View File

@@ -1,18 +1,17 @@
package me.chanjar.weixin.mp.demo; package me.chanjar.weixin.mp.demo;


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

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;

import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.mp.api.WxMpConfigStorage; import me.chanjar.weixin.mp.api.WxMpConfigStorage;
import me.chanjar.weixin.mp.api.WxMpMessageHandler; import me.chanjar.weixin.mp.api.WxMpMessageHandler;
import me.chanjar.weixin.mp.api.WxMpMessageRouter; import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;

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


public class WxMpDemoServer { public class WxMpDemoServer {


@@ -29,12 +28,12 @@ public class WxMpDemoServer {
server.setHandler(servletHandler); server.setHandler(servletHandler);


ServletHolder endpointServletHolder = new ServletHolder( ServletHolder endpointServletHolder = new ServletHolder(
new WxMpEndpointServlet(wxMpConfigStorage, wxMpService,
wxMpMessageRouter));
new WxMpEndpointServlet(wxMpConfigStorage, wxMpService,
wxMpMessageRouter));
servletHandler.addServletWithMapping(endpointServletHolder, "/*"); servletHandler.addServletWithMapping(endpointServletHolder, "/*");


ServletHolder oauthServletHolder = new ServletHolder( ServletHolder oauthServletHolder = new ServletHolder(
new WxMpOAuth2Servlet(wxMpService));
new WxMpOAuth2Servlet(wxMpService));
servletHandler.addServletWithMapping(oauthServletHolder, "/oauth2/*"); servletHandler.addServletWithMapping(oauthServletHolder, "/oauth2/*");


server.start(); server.start();
@@ -43,9 +42,9 @@ public class WxMpDemoServer {


private static void initWeixin() { private static void initWeixin() {
try (InputStream is1 = ClassLoader try (InputStream is1 = ClassLoader
.getSystemResourceAsStream("test-config.xml")) {
.getSystemResourceAsStream("test-config.xml")) {
WxMpDemoInMemoryConfigStorage config = WxMpDemoInMemoryConfigStorage WxMpDemoInMemoryConfigStorage config = WxMpDemoInMemoryConfigStorage
.fromXml(is1);
.fromXml(is1);


wxMpConfigStorage = config; wxMpConfigStorage = config;
wxMpService = new WxMpServiceImpl(); wxMpService = new WxMpServiceImpl();
@@ -59,11 +58,11 @@ public class WxMpDemoServer {


wxMpMessageRouter = new WxMpMessageRouter(wxMpService); wxMpMessageRouter = new WxMpMessageRouter(wxMpService);
wxMpMessageRouter.rule().handler(logHandler).next().rule() wxMpMessageRouter.rule().handler(logHandler).next().rule()
.msgType(WxConsts.XML_MSG_TEXT).matcher(guessNumberHandler)
.handler(guessNumberHandler).end().rule().async(false).content("哈哈")
.handler(textHandler).end().rule().async(false).content("图片")
.handler(imageHandler).end().rule().async(false).content("oauth")
.handler(oauth2handler).end();
.msgType(WxConsts.XML_MSG_TEXT).matcher(guessNumberHandler)
.handler(guessNumberHandler).end().rule().async(false).content("哈哈")
.handler(textHandler).end().rule().async(false).content("图片")
.handler(imageHandler).end().rule().async(false).content("oauth")
.handler(oauth2handler).end();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }


+ 4
- 4
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpEndpointServlet.java View File

@@ -23,7 +23,7 @@ public class WxMpEndpointServlet extends HttpServlet {
protected WxMpMessageRouter wxMpMessageRouter; protected WxMpMessageRouter wxMpMessageRouter;


public WxMpEndpointServlet(WxMpConfigStorage wxMpConfigStorage, WxMpService wxMpService, public WxMpEndpointServlet(WxMpConfigStorage wxMpConfigStorage, WxMpService wxMpService,
WxMpMessageRouter wxMpMessageRouter) {
WxMpMessageRouter wxMpMessageRouter) {
this.wxMpConfigStorage = wxMpConfigStorage; this.wxMpConfigStorage = wxMpConfigStorage;
this.wxMpService = wxMpService; this.wxMpService = wxMpService;
this.wxMpMessageRouter = wxMpMessageRouter; this.wxMpMessageRouter = wxMpMessageRouter;
@@ -31,7 +31,7 @@ public class WxMpEndpointServlet extends HttpServlet {


@Override @Override
protected void service(HttpServletRequest request, HttpServletResponse response) protected void service(HttpServletRequest request, HttpServletResponse response)
throws IOException {
throws IOException {


response.setContentType("text/html;charset=utf-8"); response.setContentType("text/html;charset=utf-8");
response.setStatus(HttpServletResponse.SC_OK); response.setStatus(HttpServletResponse.SC_OK);
@@ -54,8 +54,8 @@ public class WxMpEndpointServlet extends HttpServlet {
} }


String encryptType = StringUtils.isBlank(request.getParameter("encrypt_type")) ? String encryptType = StringUtils.isBlank(request.getParameter("encrypt_type")) ?
"raw" :
request.getParameter("encrypt_type");
"raw" :
request.getParameter("encrypt_type");


if ("raw".equals(encryptType)) { if ("raw".equals(encryptType)) {
// 明文传输的消息 // 明文传输的消息


+ 6
- 7
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpOAuth2Servlet.java View File

@@ -1,16 +1,15 @@
package me.chanjar.weixin.mp.demo; package me.chanjar.weixin.mp.demo;


import java.io.IOException;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken; import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser; import me.chanjar.weixin.mp.bean.result.WxMpUser;


import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class WxMpOAuth2Servlet extends HttpServlet { public class WxMpOAuth2Servlet extends HttpServlet {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;


@@ -22,7 +21,7 @@ public class WxMpOAuth2Servlet extends HttpServlet {


@Override @Override
protected void service(HttpServletRequest request, HttpServletResponse response) protected void service(HttpServletRequest request, HttpServletResponse response)
throws IOException {
throws IOException {


response.setContentType("text/html;charset=utf-8"); response.setContentType("text/html;charset=utf-8");
response.setStatus(HttpServletResponse.SC_OK); response.setStatus(HttpServletResponse.SC_OK);


+ 14
- 13
weixin-java-mp/src/test/resources/test-config.sample.xml View File

@@ -1,15 +1,16 @@
<xml> <xml>
<appId>公众号appID</appId>
<secret>公众号appsecret</secret>
<token>公众号Token</token>
<aesKey>公众号EncodingAESKey</aesKey>
<accessToken>可以不填写</accessToken>
<expiresTime>可以不填写</expiresTime>
<openid>某个加你公众号的用户的openId</openid>
<partnerId>微信商户平台ID</partnerId>
<partnerKey>商户平台设置的API密钥</partnerKey>
<templateId>模版消息的模版ID</templateId>
<oauth2redirectUri>网页授权获取用户信息回调地址</oauth2redirectUri>
<qrconnectRedirectUrl>网页应用授权登陆回调地址</qrconnectRedirectUrl>
<kfAccount>完整客服账号,格式为:账号前缀@公众号微信号</kfAccount>
<appId>公众号appID</appId>
<secret>公众号appsecret</secret>
<token>公众号Token</token>
<aesKey>公众号EncodingAESKey</aesKey>
<accessToken>可以不填写</accessToken>
<expiresTime>可以不填写</expiresTime>
<openid>某个加你公众号的用户的openId</openid>
<partnerId>微信商户平台ID</partnerId>
<partnerKey>商户平台设置的API密钥</partnerKey>
<keyPath>商户平台的证书文件地址</keyPath>
<templateId>模版消息的模版ID</templateId>
<oauth2redirectUri>网页授权获取用户信息回调地址</oauth2redirectUri>
<qrconnectRedirectUrl>网页应用授权登陆回调地址</qrconnectRedirectUrl>
<kfAccount>完整客服账号,格式为:账号前缀@公众号微信号</kfAccount>
</xml> </xml>

+ 1
- 1
weixin-java-mp/src/test/resources/testng.xml View File

@@ -7,7 +7,7 @@
<class name="me.chanjar.weixin.mp.api.WxMpBaseAPITest" /> <class name="me.chanjar.weixin.mp.api.WxMpBaseAPITest" />
<class name="me.chanjar.weixin.mp.api.WxMpMassMessageAPITest" /> <class name="me.chanjar.weixin.mp.api.WxMpMassMessageAPITest" />
<class name="me.chanjar.weixin.mp.api.impl.WxMpUserServiceImplTest" /> <class name="me.chanjar.weixin.mp.api.impl.WxMpUserServiceImplTest" />
<class name="me.chanjar.weixin.mp.api.impl.WxMpQrCodeServiceImplTest" />
<class name="me.chanjar.weixin.mp.api.impl.WxMpQrcodeServiceImplTest" />
<class name="me.chanjar.weixin.mp.api.WxMpShortUrlAPITest" /> <class name="me.chanjar.weixin.mp.api.WxMpShortUrlAPITest" />
<class name="me.chanjar.weixin.mp.api.WxMpMessageRouterTest" /> <class name="me.chanjar.weixin.mp.api.WxMpMessageRouterTest" />
<class name="me.chanjar.weixin.mp.api.WxMpJsAPITest" /> <class name="me.chanjar.weixin.mp.api.WxMpJsAPITest" />


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

@@ -6,7 +6,7 @@
<parent> <parent>
<groupId>com.github.binarywang</groupId> <groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-parent</artifactId> <artifactId>weixin-java-parent</artifactId>
<version>2.4.4-beta</version>
<version>2.6.0-SNAPSHOT</version>
</parent> </parent>


<artifactId>weixin-java-osgi</artifactId> <artifactId>weixin-java-osgi</artifactId>


Loading…
Cancel
Save