diff --git a/.circleci/config.yml b/.circleci/config.yml
new file mode 100644
index 0000000000..435b7250ba
--- /dev/null
+++ b/.circleci/config.yml
@@ -0,0 +1,11 @@
+version: 2.1
+jobs:
+ build:
+ docker:
+ - image: cimg/openjdk:11.0
+ steps:
+ - checkout
+ - run:
+ name: Build
+ command: mvn -B -DskipTests clean package -Dcheckstyle.skip=true
+
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index d87b6c73fa..ced7d6de0c 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -8,10 +8,11 @@ assignees: ''
---
# 提问前,请确保阅读过项目首页说明以及wiki开发文档相关内容,尤其是常见问题部分。完成内容后,请务必移除包括本句在内的无用内容,以免影响阅读,否则直接关闭,谢谢合作~
-# 另外如果确认属于bug,而且已明确如何修复,请参考贡献指南直接提交PR,省的浪费时间在这里描述问题,非常感谢配合
+
+## 另外如果确认属于bug,而且已明确如何修复,请参考贡献指南直接提交PR,省的浪费时间在这里描述问题,非常感谢配合
### 简要描述
-__简单概括描述下你所遇到的问题。__
+__请简单概括描述下你所遇到的问题。__
### 模块版本情况
* WxJava 模块名:
@@ -21,4 +22,7 @@ __简单概括描述下你所遇到的问题。__
__尽量详细描述。请不要使用截图,尽量使用文字描述,代码直接贴上来,日志则请附在后面所示区域。__
### 日志
-__将日志放在 [pastebin](https://paste.ubuntu.com/) 或者其他地方,并将其url地址贴在这里__
+__如果日志不多,直接使用md代码引用格式贴在此处,否则如果太长,请将日志放在 [pastebin](https://paste.ubuntu.com/) 或者其他地方,然后将其url地址贴在这里__
+```
+日志请写于此处
+```
diff --git a/.github/workflows b/.github/workflows
new file mode 100644
index 0000000000..e420c7d44d
--- /dev/null
+++ b/.github/workflows
@@ -0,0 +1,4 @@
+- name: Upload coverage reports to Codecov
+ uses: codecov/codecov-action@v3
+ env:
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
diff --git a/.travis.yml b/.travis.yml
index 2b128c8a08..99850df729 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,5 @@
language: java
-
jdk:
- openjdk8
script: "mvn clean package -DskipTests=true -Dcheckstyle.skip=true"
@@ -15,4 +14,4 @@ cache:
notifications:
email:
- - binarywang@vip.qq.com
+ - a@binarywang.com
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index ba8e495afb..c703964824 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,5 +1,5 @@
# 代码贡献指南
-1. 首先非常欢迎和感谢对本项目发起`Pull Request`的同学。
+1. 首先非常欢迎和感谢对本项目发起 `Pull Request` 的热心小伙伴们。
1. **特别提示:请务必在 `develop` 分支提交 `PR`,`release` 分支目前仅是正式版的代码,即发布正式版本后才会从 `develop` 分支进行合并。**
1. 本项目代码风格为使用2个空格代表一个Tab,因此在提交代码时请注意一下,否则很容易在IDE格式化代码后与原代码产生大量diff,这样会给其他人阅读代码带来极大的困扰。
1. 为了便于设置,本项目引入`editorconfig`支持,请使用Eclipse的同学在贡献代码前安装相关插件,而`IntelliJ IDEA`新版本自带支持,如果没有可自行安装插件。
@@ -24,7 +24,7 @@ $ #do some change on the content
$ git commit -am "Fix issue #1: change something"
$ git push
```
-* 在 GitHub 网站上提交 Pull Request。
+* 在 `GitHub` 或 `Gitee` 网站上提交 `Pull Request`。
* 定期使用项目仓库内容更新自己仓库内容。
```bash
diff --git a/LICENSE b/LICENSE
index 0c8a80022e..7783de532a 100644
--- a/LICENSE
+++ b/LICENSE
@@ -37,7 +37,7 @@ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
You must give any other recipients of the Work or Derivative Works a copy of this License; and
You must cause any modified files to carry prominent notices stating that You changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
-If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
+If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
diff --git a/README.md b/README.md
index 8f0a4f95b6..8232e535c0 100644
--- a/README.md
+++ b/README.md
@@ -1,61 +1,74 @@
-## WxJava - 微信开发 Java SDK(开发工具包) [](https://github.com/996icu/996.ICU/blob/master/LICENSE) [](https://996.icu/#/zh_CN)
+## WxJava - 微信开发 Java SDK
[](https://gitee.com/binary/weixin-java-tools)
[](https://github.com/Wechat-Group/WxJava)
[](https://github.com/Wechat-Group/WxJava/releases)
[](http://mvnrepository.com/artifact/com.github.binarywang/wx-java)
-[](https://travis-ci.com/Wechat-Group/WxJava)
-[](https://www.jetbrains.com/?from=WxJava-weixin-java-tools)
+[](https://circleci.com/gh/Wechat-Group/WxJava/tree/develop)
+[](https://www.jetbrains.com/?from=WxJava-weixin-java-tools)
[](https://opensource.org/licenses/Apache-2.0)
-#### 支持包括微信支付、开放平台、公众号、企业微信/企业号、小程序等微信功能的后端开发。
+#### 微信`Java`开发工具包,支持包括微信支付、开放平台、公众号、企业微信/企业号、小程序等微信功能模块的后端开发。
-
+
特别赞助
-
-
-
-
-
-
-
-
-
-
-
-
- |
-
-
-
- 1. 驰骋快速开发平台、工作流引擎、表单引擎采用GPL协议.
-2. 驰骋.net版称为ccflow, java版称为jflow,代码100%开源.
-3. 支持10多个国内外数据库. 单机版\集团版\SAAS版本.
-
- |
-
-
+
+
### 重要信息
-1. **2021-06-02 发布 [【4.1.0正式版】](https://mp.weixin.qq.com/s/nIk_xOf6dxkhKfqq830Cuw)**!
-1. 新手重要提示:本项目仅是一个SDK开发工具包,未提供Web实现,建议使用 `maven` 或 `gradle` 引用本项目即可使用本SDK提供的各种功能,详情可参考 **[【Demo项目】](demo.md)** 或本项目中的部分单元测试代码;另外微信开发新手请务必阅读[【开发文档 Wiki 首页】](https://github.com/Wechat-Group/WxJava/wiki)的常见问题部分,可以少走很多弯路,节省不少时间。
-1. 技术交流群:想获得QQ群/微信群/钉钉企业群等信息的同学,请使用微信扫描上面的微信公众号二维码关注 `WxJava` 后点击相关菜单即可获取加入方式,同时也可以在微信中搜索 `weixin-java-tools` 或 `WxJava` 后选择正确的公众号进行关注,该公众号会及时通知SDK相关更新信息,并不定期分享微信Java开发相关技术知识;
-1. 钉钉技术交流群:`32206329`(技术交流2群), `30294972`(技术交流1群,目前已满),`35724728`(通知群,实时通知Github项目变更记录)。
-1. 微信开发新手或者Java开发新手在群内提问或新开Issue提问前,请先阅读[【提问的智慧】](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/master/README-zh_CN.md),并确保已查阅过 [【开发文档Wiki】](https://github.com/wechat-group/WxJava/wiki) ,避免浪费大家的宝贵时间;
-1. 寻求帮助时需贴代码或大长串异常信息的,请利用 http://paste.ubuntu.com
+1. 项目合作洽谈请联系微信`binary0000`(在微信里自行搜索并添加好友,请注明来意,如有关于SDK问题需讨论请参考下文入群讨论,不要加此微信)。
+2. **2023-4-23 发布 [【4.5.0正式版】](https://mp.weixin.qq.com/s/4ZYKJnIwP9YNDvbyOhW_3A)**!
+3. 贡献源码可以参考视频:[【贡献源码全过程(上集)】](https://mp.weixin.qq.com/s/3xUZSATWwHR_gZZm207h7Q)、[【贡献源码全过程(下集)】](https://mp.weixin.qq.com/s/nyzJwVVoYSJ4hSbwyvTx9A) ,友情提供:[程序员小山与Bug](https://space.bilibili.com/473631007)
+4. 新手重要提示:本项目仅是一个SDK开发工具包,未提供Web实现,建议使用 `maven` 或 `gradle` 引用本项目即可使用本SDK提供的各种功能,详情可参考 **[【Demo项目】](demo.md)** 或本项目中的部分单元测试代码;
+5. 微信开发新手请务必阅读【开发文档】([Gitee Wiki](https://gitee.com/binary/weixin-java-tools/wikis/Home) 或者 [Github Wiki](https://github.com/Wechat-Group/WxJava/wiki))的常见问题部分,可以少走很多弯路,节省不少时间。
+6. 技术交流群:想获得QQ群/微信群/钉钉企业群等信息的同学,请使用微信扫描上面的微信公众号二维码关注 `WxJava` 后点击相关菜单即可获取加入方式,同时也可以在微信中搜索 `weixin-java-tools` 或 `WxJava` 后选择正确的公众号进行关注,该公众号会及时通知SDK相关更新信息,并不定期分享微信Java开发相关技术知识;
+7. 钉钉技术交流群:`32206329`(技术交流2群), `30294972`(技术交流1群,目前已满),`35724728`(通知群,实时通知Github项目变更记录)。
+8. 微信开发新手或者Java开发新手在群内提问或新开Issue提问前,请先阅读[【提问的智慧】](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/master/README-zh_CN.md),并确保已查阅过 [【开发文档Wiki】](https://github.com/wechat-group/WxJava/wiki) ,避免浪费大家的宝贵时间;
+9. 寻求帮助时需贴代码或大长串异常信息的,请利用 http://paste.ubuntu.com
--------------------------------
### 其他说明
1. **阅读源码的同学请注意,本SDK为简化代码编译时加入了`lombok`支持,如果不了解`lombok`的话,请先学习下相关知识,比如可以阅读[此文章](https://mp.weixin.qq.com/s/cUc-bUcprycADfNepnSwZQ);**
-1. 如有新功能需求,发现BUG,或者由于微信官方接口调整导致的代码问题,可以直接在[【Issues】](https://github.com/Wechat-Group/WxJava/issues)页提出issue,便于讨论追踪问题;
-1. 如果需要贡献代码,请务必在提交PR之前先仔细阅读[【代码贡献指南】](CONTRIBUTING.md),谢谢理解配合;
-1. 目前本`SDK`最新版本要求的`JDK`最低版本是`8`,使用`7`的同学可以使用`WxJava` `3.8.0`及以前版本,而还在使用`JDK`6的用户请参考[【此项目】]( https://github.com/binarywang/weixin-java-tools-for-jdk6) ,而其他更早的JDK版本则需要自己改造实现。
-1. [本项目在开源中国的页面](https://www.oschina.net/p/weixin-java-tools-new),欢迎大家积极留言评分 🙂
-1. SDK开发文档请查阅 [【开发文档Wiki】](https://github.com/wechat-group/WxJava/wiki),部分文档可能未能及时更新,如有发现,可以及时上报或者自行修改。
-1. **如果本开发工具包对您有所帮助,欢迎对我们的努力进行肯定,可以直接前往[【托管于码云的项目首页】](http://gitee.com/binary/weixin-java-tools),在页尾部分找到“捐助”按钮进行打赏,多多益善 😄。非常感谢各位打赏和捐助的同学!**
-1. 各个模块的Javadoc可以在线查看:[weixin-java-miniapp](http://binary.ac.cn/weixin-java-miniapp-javadoc/)、[weixin-java-pay](http://binary.ac.cn/weixin-java-pay-javadoc/)、[weixin-java-mp](http://binary.ac.cn/weixin-java-mp-javadoc/)、[weixin-java-common](http://binary.ac.cn/weixin-java-common-javadoc/)、[weixin-java-cp](http://binary.ac.cn/weixin-java-cp-javadoc/)、[weixin-java-open](http://binary.ac.cn/weixin-java-open-javadoc/)
-1. 本SDK项目在以下代码托管网站同步更新:
+2. 如有新功能需求,发现BUG,或者由于微信官方接口调整导致的代码问题,可以直接在[【Issues】](https://github.com/Wechat-Group/WxJava/issues)页提出issue,便于讨论追踪问题;
+3. 如果需要贡献代码,请务必在提交PR之前先仔细阅读[【代码贡献指南】](CONTRIBUTING.md),谢谢理解配合;
+4. 目前本`SDK`最新版本要求的`JDK`最低版本是`8`,使用`7`的同学可以使用`WxJava` `3.8.0`及以前版本,而还在使用`JDK`6的用户请参考[【此项目】]( https://github.com/binarywang/weixin-java-tools-for-jdk6) ,而其他更早的JDK版本则需要自己改造实现。
+5. [本项目在开源中国的页面](https://www.oschina.net/p/weixin-java-tools-new),欢迎大家积极留言评分 🙂
+6. SDK开发文档请查阅 [【开发文档Wiki】](https://github.com/wechat-group/WxJava/wiki),部分文档可能未能及时更新,如有发现,可以及时上报或者自行修改。
+7. **如果本开发工具包对您有所帮助,欢迎对我们的努力进行肯定,可以直接前往[【托管于码云的项目首页】](http://gitee.com/binary/weixin-java-tools),在页尾部分找到“捐助”按钮进行打赏,多多益善 😄。非常感谢各位打赏和捐助的同学!**
+8. 各个模块的Javadoc可以在线查看:[weixin-java-miniapp](http://binary.ac.cn/weixin-java-miniapp-javadoc/)、[weixin-java-pay](http://binary.ac.cn/weixin-java-pay-javadoc/)、[weixin-java-mp](http://binary.ac.cn/weixin-java-mp-javadoc/)、[weixin-java-common](http://binary.ac.cn/weixin-java-common-javadoc/)、[weixin-java-cp](http://binary.ac.cn/weixin-java-cp-javadoc/)、[weixin-java-open](http://binary.ac.cn/weixin-java-open-javadoc/)
+9. 本SDK项目在以下代码托管网站同步更新:
* 码云:https://gitee.com/binary/weixin-java-tools
* GitHub:https://github.com/wechat-group/WxJava
@@ -67,7 +80,7 @@
com.github.binarywang
(不同模块参考下文)
- 4.1.0
+ 4.5.0
```
@@ -85,8 +98,8 @@
点此展开查看
1. 本项目定为大约每两个月发布一次正式版(同时 `develop` 分支代码合并进入 `master` 分支),版本号格式为 `X.X.0`(如`2.1.0`,`2.2.0`等),遇到重大问题需修复会及时提交新版本,欢迎大家随时提交Pull Request;
-1. BUG修复和新特性一般会先发布成小版本作为临时测试版本(如`3.6.8.B`,即尾号不为0,并添加B,以区别于正式版),代码仅存在于 `develop` 分支中;
-1. 目前最新版本号为 [](http://mvnrepository.com/artifact/com.github.binarywang/wx-java) ,也可以通过访问链接 [【微信支付】](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.github.binarywang%22%20AND%20a%3A%22weixin-java-pay%22) 、[【微信小程序】](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.github.binarywang%22%20AND%20a%3A%22weixin-java-miniapp%22) 、[【公众号】](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://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.github.binarywang%22%20AND%20a%3A%22weixin-java-open%22)
+2. BUG修复和新特性一般会先发布成小版本作为临时测试版本(如`3.6.8.B`,即尾号不为0,并添加B,以区别于正式版),代码仅存在于 `develop` 分支中;
+3. 目前最新版本号为 [](http://mvnrepository.com/artifact/com.github.binarywang/wx-java) ,也可以通过访问链接 [【微信支付】](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.github.binarywang%22%20AND%20a%3A%22weixin-java-pay%22) 、[【微信小程序】](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.github.binarywang%22%20AND%20a%3A%22weixin-java-miniapp%22) 、[【公众号】](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://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.github.binarywang%22%20AND%20a%3A%22weixin-java-open%22)
分别查看所有最新的版本。
@@ -165,16 +178,17 @@
点击此处展开查看贡献次数最多的几位小伙伴
1. [chanjarster (Daniel Qian)](https://github.com/chanjarster)
-1. [binarywang (Binary Wang)](https://github.com/binarywang)
-1. [007gzs](https://github.com/007gzs)
-1. [Silloy](https://github.com/silloy)
-1. [mgcnrx11](https://github.com/mgcnrx11)
-1. [yuanqixun](https://github.com/yuanqixun)
-1. [kakotor](https://github.com/kakotor)
-1. [aimilin6688 (Jonk)](https://github.com/aimilin6688)
-1. [lkqm (Mario Luo)](https://github.com/lkqm)
-1. [kareanyi (MillerLin)](https://github.com/kareanyi)
-
+2. [binarywang (Binary Wang)](https://github.com/binarywang)
+3. [007gzs](https://github.com/007gzs)
+4. [Silloy](https://github.com/silloy)
+5. [mgcnrx11](https://github.com/mgcnrx11)
+6. [0katekate0 (Wang_Wong)](https://github.com/0katekate0)
+7. [yuanqixun](https://github.com/yuanqixun)
+8. [kakotor](https://github.com/kakotor)
+9. [aimilin6688 (Jonk)](https://github.com/aimilin6688)
+10. [lkqm (Mario Luo)](https://github.com/lkqm)
+11. [kareanyi (MillerLin)](https://github.com/kareanyi)
+12. [Bincent (Hongbin.hsu)](https://gitee.com/bincent)
### GitHub Stargazers over time
diff --git a/demo.md b/demo.md
index de5e462099..d6b55b89e2 100644
--- a/demo.md
+++ b/demo.md
@@ -14,12 +14,12 @@
- [使用该 `starter` 实现的小程序 `Demo`](https://github.com/binarywang/wx-java-miniapp-demo)
### Demo 列表
-1. 微信支付 Demo:[GitHub](http://github.com/binarywang/weixin-java-pay-demo)、[码云](http://gitee.com/binary/weixin-java-pay-demo) [](https://travis-ci.org/binarywang/weixin-java-pay-demo)
-1. 企业号/企业微信 Demo:[GitHub](http://github.com/binarywang/weixin-java-cp-demo)、[码云](http://gitee.com/binary/weixin-java-cp-demo) [](https://travis-ci.org/binarywang/weixin-java-cp-demo)
-1. 微信小程序 Demo:[GitHub](http://github.com/binarywang/weixin-java-miniapp-demo)、[码云](http://gitee.com/binary/weixin-java-miniapp-demo) [](https://travis-ci.org/binarywang/weixin-java-miniapp-demo)
-1. 开放平台 Demo:[GitHub](http://github.com/Wechat-Group/weixin-java-open-demo)、[码云](http://gitee.com/binary/weixin-java-open-demo) [](https://travis-ci.org/Wechat-Group/weixin-java-open-demo)
-1. 公众号 Demo:
- - 使用 `Spring MVC` 实现的公众号 Demo:[GitHub](http://github.com/binarywang/weixin-java-mp-demo-springmvc)、[码云](https://gitee.com/binary/weixin-java-mp-demo) [](https://travis-ci.org/binarywang/weixin-java-mp-demo-springmvc)
- - 使用 `Spring Boot` 实现的公众号 Demo(支持多公众号):[GitHub](http://github.com/binarywang/weixin-java-mp-demo)、[码云](http://gitee.com/binary/weixin-java-mp-demo-springboot) [](https://travis-ci.org/binarywang/weixin-java-mp-demo)
- - 含公众号和部分微信支付代码的 Demo:[GitHub](http://github.com/Wechat-Group/weixin-java-demo-springmvc)、[码云](http://gitee.com/binary/weixin-java-tools-springmvc) [](https://travis-ci.org/Wechat-Group/weixin-java-demo-springmvc)
+1. 微信支付 Demo:[GitHub](http://github.com/binarywang/weixin-java-pay-demo)、[码云](http://gitee.com/binary/weixin-java-pay-demo) [](https://app.travis-ci.com/binarywang/weixin-java-pay-demo)
+1. 企业号/企业微信 Demo:[GitHub](http://github.com/binarywang/weixin-java-cp-demo)、[码云](http://gitee.com/binary/weixin-java-cp-demo) [](https://app.travis-ci.com/binarywang/weixin-java-cp-demo)
+1. 微信小程序 Demo:[GitHub](http://github.com/binarywang/weixin-java-miniapp-demo)、[码云](http://gitee.com/binary/weixin-java-miniapp-demo) [](https://app.travis-ci.com/binarywang/weixin-java-miniapp-demo)
+1. 开放平台 Demo:[GitHub](http://github.com/Wechat-Group/weixin-java-open-demo)、[码云](http://gitee.com/binary/weixin-java-open-demo) [](https://app.travis-ci.com/Wechat-Group/weixin-java-open-demo)
+1. 微信公众号 Demo:
+ - 使用 `Spring MVC` 实现的公众号 Demo:[GitHub](http://github.com/binarywang/weixin-java-mp-demo-springmvc)、[码云](https://gitee.com/binary/weixin-java-mp-demo) [](https://app.travis-ci.com/binarywang/weixin-java-mp-demo-springmvc)
+ - 使用 `Spring Boot` 实现的公众号 Demo(支持多公众号):[GitHub](http://github.com/binarywang/weixin-java-mp-demo)、[码云](http://gitee.com/binary/weixin-java-mp-demo-springboot) [](https://app.travis-ci.com/binarywang/weixin-java-mp-demo)
+ - 含公众号和部分微信支付代码的 Demo:[GitHub](http://github.com/Wechat-Group/weixin-java-demo-springmvc)、[码云](http://gitee.com/binary/weixin-java-tools-springmvc) [](https://app.travis-ci.com/Wechat-Group/weixin-java-demo-springmvc)
diff --git a/images/banners/ccflow.png b/images/banners/ccflow.png
new file mode 100644
index 0000000000..1209739f6a
Binary files /dev/null and b/images/banners/ccflow.png differ
diff --git a/images/banners/diboot.png b/images/banners/diboot.png
new file mode 100644
index 0000000000..c22d0b8ed8
Binary files /dev/null and b/images/banners/diboot.png differ
diff --git a/images/banners/vultr.jpg b/images/banners/vultr.jpg
deleted file mode 100644
index 80cf3c2b5e..0000000000
Binary files a/images/banners/vultr.jpg and /dev/null differ
diff --git a/others/weixin-java-config/README.md b/others/weixin-java-config/README.md
new file mode 100644
index 0000000000..aa70de9579
--- /dev/null
+++ b/others/weixin-java-config/README.md
@@ -0,0 +1,424 @@
+# weixin-java-config
+1.目录说明:多配置文件目录
+
+2.项目多配置集锦
+```yml
+wechat:
+ pay: #微信服务商支付
+ configs:
+ - appId: wxe97b2x9c2b3d #spAppId
+ mchId: 16486610 #服务商商户
+ subAppId: wx118cexxe3c07679 #子appId
+ subMchId: 16496705 #子商户
+ apiV3Key: Dc1DBwSc094jAKDGR5aqqb7PTHr #apiV3密钥
+ privateKeyPath: classpath:cert/apiclient_key.pem #服务商证书文件,apiclient_key.pem证书文件的绝对路径或者以classpath:开头的类路径(可以配置绝对路径)
+ privateCertPath: classpath:cert/apiclient_cert.pem #apiclient_cert.pem证书文件的绝对路径或者以classpath:开头的类路径
+ miniapp: #小程序
+ configs:
+ - appid: wx118ce3xxc76ccg
+ secret: 8a132a276ee2f8fb58b1ed8f2
+ token: #微信小程序消息服务器配置的token
+ aesKey: #微信小程序消息服务器配置的EncodingAESKey
+ msgDataFormat: JSON
+ cp: #企业微信
+ corpId: wwa3be8efd2addfgj
+ appConfigs:
+ - agentId: 10001 #客户联系
+ secret: T5fTj1n-sBAT4rKNW5c9IYNfPdXZ8-oGol5tX
+ token: 2bSNqTcLtFYBUa1u2
+ aesKey: AXazu2Xyw44SNY1x8go2phn9p9B2O9oiEfqPN
+ - agentId: 10003 #会话内容存档
+ secret: xIpum7Yt4NMXcyxdzcQ2l_46BG4QIQDR57MhA
+ token:
+ aesKey:
+ - agentId: 3010011 #打卡
+ secret: 3i2Mhfusifaw_-04bMYI8OoKGxPe9mDALbUxV
+ token:
+ aesKey:
+ - agentId: 19998 #通讯录同步
+ secret: rNyDae0Pg-3d-wqTd_ozMSJfF0DEjTCz3b_pr
+ token: xUke8yZciAZqImGZ
+ aesKey: EUTVyArqJcfnpFiudxjRpuOexNqBoPbwrNG3R
+ - agentId: 20000 #微盘
+ secret: D-TVMvUji7PZZdjhZOSgiy2MTuBd0OCdvI_zi
+ token:
+ aesKey:
+```
+
+3.主要代码
+###### 1)微信服务商支付
+```java
+@Data
+@ConfigurationProperties(prefix = "wechat.pay")
+public class WxPayProperties {
+
+ private List configs;
+
+ @Getter
+ @Setter
+ public static class Config {
+
+ private String appId;
+ private String mchId;
+ private String subAppId;
+ private String subMchId;
+ private String apiV3Key;
+ private String privateKeyPath;
+ private String privateCertPath;
+
+ }
+
+}
+```
+```java
+@Configuration
+@EnableConfigurationProperties(WxPayProperties.class)
+@AllArgsConstructor
+public class WxPayConfiguration {
+
+ private WxPayProperties properties;
+
+ @Bean
+ public WxPayService wxPayService() {
+
+ // 多配置
+ WxPayService wxPayService = new WxPayServiceImpl();
+ Map payConfigs = this.properties.getConfigs().stream().map(config -> {
+ WxPayConfig payConfig = new WxPayConfig();
+ payConfig.setAppId(StringUtils.trimToNull(config.getAppId()));
+ payConfig.setMchId(StringUtils.trimToNull(config.getMchId()));
+ payConfig.setSubAppId(StringUtils.trimToNull(config.getSubAppId()));
+ payConfig.setSubMchId(StringUtils.trimToNull(config.getSubMchId()));
+ payConfig.setApiV3Key(StringUtils.trimToNull(config.getApiV3Key()));
+ payConfig.setPrivateKeyPath(StringUtils.trimToNull(config.getPrivateKeyPath()));
+ payConfig.setPrivateCertPath(StringUtils.trimToNull(config.getPrivateCertPath()));
+
+ // 可以指定是否使用沙箱环境
+ payConfig.setUseSandboxEnv(false);
+ return payConfig;
+ }).collect(Collectors.toMap(config -> config.getSubMchId(), a -> a));
+
+ wxPayService.setMultiConfig(payConfigs);
+ return wxPayService;
+ }
+
+}
+```
+###### 2)微信小程序
+```java
+@Setter
+@Getter
+@ConfigurationProperties(prefix = "wechat.miniapp")
+public class WxMaProperties {
+
+ private List configs;
+
+ @Data
+ public static class Config {
+
+ /**
+ * 设置微信小程序的appid
+ */
+ private String appid;
+
+ /**
+ * 设置微信小程序的Secret
+ */
+ private String secret;
+
+ /**
+ * 设置微信小程序消息服务器配置的token
+ */
+ private String token;
+
+ /**
+ * 设置微信小程序消息服务器配置的EncodingAESKey
+ */
+ private String aesKey;
+
+ /**
+ * 消息格式,XML或者JSON
+ */
+ private String msgDataFormat;
+
+ }
+
+}
+```
+```java
+@Configuration
+@EnableConfigurationProperties(WxMaProperties.class)
+public class WxMaConfiguration {
+
+ private WxMaProperties properties;
+ private static Map maServices;
+ private static final Map routers = Maps.newHashMap();
+
+ @Autowired
+ public WxMaConfiguration(WxMaProperties properties) {
+ this.properties = properties;
+ }
+
+ public static WxMaService getMaService(String appId) {
+ WxMaService wxService = maServices.get(appId);
+ Optional.ofNullable(wxService).orElseThrow(() -> new RuntimeException("没有配置appId"));
+ return wxService;
+ }
+
+ public static WxMaMessageRouter getRouter(String appId) {
+ return routers.get(appId);
+ }
+
+ @PostConstruct
+ public void init() {
+ List configs = this.properties.getConfigs();
+ if (configs == null) {
+ return;
+ }
+
+ maServices = configs.stream().map(a -> {
+ // 多配置
+ WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();
+ config.setAppid(a.getAppid());
+ config.setSecret(a.getSecret());
+ config.setToken(a.getToken());
+ config.setAesKey(a.getAesKey());
+ config.setMsgDataFormat(a.getMsgDataFormat());
+
+ WxMaService service = new WxMaServiceImpl();
+ service.setWxMaConfig(config);
+
+ routers.put(a.getAppid(), this.newRouter(service));
+ return service;
+ }).collect(Collectors.toMap(s -> s.getWxMaConfig().getAppid(), a -> a));
+ }
+
+ private WxMaMessageRouter newRouter(WxMaService service) {
+ final WxMaMessageRouter router = new WxMaMessageRouter(service);
+ router
+ .rule().handler(logHandler).next()
+ .rule().async(false).content("订阅消息").handler(subscribeMsgHandler).end()
+ .rule().async(false).content("文本").handler(textHandler).end()
+ .rule().async(false).content("图片").handler(picHandler).end()
+ .rule().async(false).content("二维码").handler(qrcodeHandler).end();
+ return router;
+ }
+
+ private final WxMaMessageHandler subscribeMsgHandler = (wxMessage, context, service, sessionManager) -> {
+ service.getMsgService().sendSubscribeMsg(WxMaSubscribeMessage.builder()
+ .templateId("此处更换为自己的模板id")
+ .data(Lists.newArrayList(
+ new WxMaSubscribeMessage.MsgData("keyword1", "339208499")))
+ .toUser(wxMessage.getFromUser())
+ .build());
+ return null;
+ };
+
+ private final WxMaMessageHandler logHandler = (wxMessage, context, service, sessionManager) -> {
+ log.info("收到logHandler消息:" + wxMessage.toString());
+ service.getMsgService().sendKefuMsg(WxMaKefuMessage.newTextBuilder().content("收到信息为:" + wxMessage.toJson())
+ .toUser(wxMessage.getFromUser()).build());
+ return null;
+ };
+
+ private final WxMaMessageHandler textHandler = (wxMessage, context, service, sessionManager) -> {
+ log.info("收到textHandler消息:" + wxMessage.toString());
+ service.getMsgService().sendKefuMsg(WxMaKefuMessage.newTextBuilder().content("回复文本消息")
+ .toUser(wxMessage.getFromUser()).build());
+ return null;
+ };
+
+ private final WxMaMessageHandler picHandler = (wxMessage, context, service, sessionManager) -> {
+ log.info("收到picHandler消息:" + wxMessage.toString());
+ try {
+ WxMediaUploadResult uploadResult = service.getMediaService()
+ .uploadMedia("image", "png",
+ ClassLoader.getSystemResourceAsStream("tmp.png"));
+ service.getMsgService().sendKefuMsg(
+ WxMaKefuMessage
+ .newImageBuilder()
+ .mediaId(uploadResult.getMediaId())
+ .toUser(wxMessage.getFromUser())
+ .build());
+ } catch (WxErrorException e) {
+ e.printStackTrace();
+ }
+
+ return null;
+ };
+
+ private final WxMaMessageHandler qrcodeHandler = (wxMessage, context, service, sessionManager) -> {
+ log.info("收到qrcodeHandler消息:" + wxMessage.toString());
+ try {
+ final File file = service.getQrcodeService().createQrcode("123", 430);
+ WxMediaUploadResult uploadResult = service.getMediaService().uploadMedia("image", file);
+ service.getMsgService().sendKefuMsg(
+ WxMaKefuMessage
+ .newImageBuilder()
+ .mediaId(uploadResult.getMediaId())
+ .toUser(wxMessage.getFromUser())
+ .build());
+ } catch (WxErrorException e) {
+ e.printStackTrace();
+ }
+
+ return null;
+ };
+
+}
+```
+###### 3)企业微信
+```java
+@Getter
+@Setter
+@ConfigurationProperties(prefix = "wechat.cp")
+public class WxCpProperties {
+
+ /**
+ * 设置企业微信的corpId
+ */
+ private String corpId;
+
+ private List appConfigs;
+
+ @Getter
+ @Setter
+ public static class AppConfig {
+ /**
+ * 设置企业微信应用的AgentId
+ */
+ private Integer agentId;
+
+ /**
+ * 设置企业微信应用的Secret
+ */
+ private String secret;
+
+ /**
+ * 设置企业微信应用的token
+ */
+ private String token;
+
+ /**
+ * 设置企业微信应用的EncodingAESKey
+ */
+ private String aesKey;
+
+ }
+
+}
+```
+```java
+@Configuration
+@EnableConfigurationProperties(WxCpProperties.class)
+public class WxCpConfiguration {
+
+ private LogHandler logHandler;
+ private NullHandler nullHandler;
+ private LocationHandler locationHandler;
+ private MenuHandler menuHandler;
+ private MsgHandler msgHandler;
+ private UnsubscribeHandler unsubscribeHandler;
+ private SubscribeHandler subscribeHandler;
+
+ private WxCpProperties properties;
+
+ private static Map routers = Maps.newHashMap();
+ private static Map cpServices = Maps.newHashMap();
+
+ @Autowired
+ public WxCpConfiguration(LogHandler logHandler, NullHandler nullHandler, LocationHandler locationHandler,
+ MenuHandler menuHandler, MsgHandler msgHandler, UnsubscribeHandler unsubscribeHandler,
+ SubscribeHandler subscribeHandler, WxCpProperties properties) {
+ this.logHandler = logHandler;
+ this.nullHandler = nullHandler;
+ this.locationHandler = locationHandler;
+ this.menuHandler = menuHandler;
+ this.msgHandler = msgHandler;
+ this.unsubscribeHandler = unsubscribeHandler;
+ this.subscribeHandler = subscribeHandler;
+ this.properties = properties;
+ }
+
+
+ public static Map getRouters() {
+ return routers;
+ }
+
+
+ public static WxCpService getCpService(Integer agentId) {
+ WxCpService cpService = cpServices.get(agentId);
+ Optional.ofNullable(cpService).orElseThrow(() -> new RuntimeException("cpService不能为空"));
+ return cpService;
+ }
+
+ @PostConstruct
+ public void initServices() {
+ cpServices = this.properties.getAppConfigs().stream().map(a -> {
+ val configStorage = new WxCpDefaultConfigImpl();
+ configStorage.setCorpId(this.properties.getCorpId());
+ configStorage.setAgentId(a.getAgentId());
+ configStorage.setCorpSecret(a.getSecret());
+ configStorage.setToken(a.getToken());
+ configStorage.setAesKey(a.getAesKey());
+
+ val service = new WxCpServiceImpl();
+ service.setWxCpConfigStorage(configStorage);
+
+ routers.put(a.getAgentId(), this.newRouter(service));
+ return service;
+ }).collect(Collectors.toMap(service -> service.getWxCpConfigStorage().getAgentId(), a -> a));
+ }
+
+ private WxCpMessageRouter newRouter(WxCpService wxCpService) {
+ final val newRouter = new WxCpMessageRouter(wxCpService);
+
+ // 记录所有事件的日志 (异步执行)
+ newRouter.rule().handler(this.logHandler).next();
+
+ // 自定义菜单事件
+ newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
+ .event(WxConsts.MenuButtonType.CLICK).handler(this.menuHandler).end();
+
+ // 点击菜单链接事件(这里使用了一个空的处理器,可以根据自己需要进行扩展)
+ newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
+ .event(WxConsts.MenuButtonType.VIEW).handler(this.nullHandler).end();
+
+ // 关注事件
+ newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
+ .event(WxConsts.EventType.SUBSCRIBE).handler(this.subscribeHandler)
+ .end();
+
+ // 取消关注事件
+ newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
+ .event(WxConsts.EventType.UNSUBSCRIBE)
+ .handler(this.unsubscribeHandler).end();
+
+ // 上报地理位置事件
+ newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
+ .event(WxConsts.EventType.LOCATION).handler(this.locationHandler)
+ .end();
+
+ // 接收地理位置消息
+ newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.LOCATION)
+ .handler(this.locationHandler).end();
+
+ // 扫码事件(这里使用了一个空的处理器,可以根据自己需要进行扩展)
+ newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
+ .event(WxConsts.EventType.SCAN).handler(this.nullHandler).end();
+
+ newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
+ .event(WxCpConsts.EventType.CHANGE_CONTACT).handler(new ContactChangeHandler()).end();
+
+ newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
+ .event(WxCpConsts.EventType.ENTER_AGENT).handler(new EnterAgentHandler()).end();
+
+ // 默认
+ newRouter.rule().async(false).handler(this.msgHandler).end();
+
+ return newRouter;
+ }
+
+}
+```
+4.其他请移步wiki:[GitHub wiki](https://github.com/Wechat-Group/WxJava/wiki)
diff --git a/others/weixin-java-osgi/pom.xml b/others/weixin-java-osgi/pom.xml
index 7207e9b99d..0018b73e5e 100644
--- a/others/weixin-java-osgi/pom.xml
+++ b/others/weixin-java-osgi/pom.xml
@@ -28,7 +28,7 @@
com.thoughtworks.xstream
xstream
- 1.4.18
+ 1.4.19
provided
diff --git a/pom.xml b/pom.xml
index 842aae46f1..dd4d91bb9b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
4.0.0
com.github.binarywang
wx-java
- 4.1.9.B
+ 4.5.7.B
pom
WxJava - Weixin/Wechat Java SDK
微信开发Java SDK
@@ -12,7 +12,7 @@
The Apache License, Version 2.0
- http://www.apache.org/licenses/LICENSE-2.0.txt
+ https://www.apache.org/licenses/LICENSE-2.0.txt
@@ -92,6 +92,21 @@
huangxm129@163.com
https://github.com/huangxm129
+
+ xiaohe
+ xiaohe@53jy.net
+ https://github.com/xiaohe-53
+
+
+ Wang_Wong
+ wangkaikate@163.com
+ https://github.com/0katekate0
+
+
+ Bincent
+ hongbin.hsu@qq.com
+ https://gitee.com/bincent
+
@@ -109,6 +124,7 @@
weixin-java-miniapp
weixin-java-open
weixin-java-qidian
+ weixin-java-channel
spring-boot-starters
@@ -119,7 +135,8 @@
UTF-8
4.5.13
- 9.4.41.v20210516
+ 9.4.51.v20230217
+
@@ -127,12 +144,12 @@
com.github.binarywang
qrcode-utils
- 1.1
+ 1.3
org.jodd
jodd-http
- 5.2.0
+ 6.3.0
provided
@@ -155,7 +172,7 @@
commons-codec
commons-codec
- 1.10
+ 1.13
commons-io
@@ -175,17 +192,22 @@
com.thoughtworks.xstream
xstream
- 1.4.18
+ 1.4.20
com.google.guava
guava
- 30.0-jre
+ 32.1.2-jre
com.google.code.gson
gson
- 2.8.0
+ 2.10.1
+
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-xml
+ 2.15.2
@@ -198,7 +220,7 @@
ch.qos.logback
logback-classic
- 1.2.3
+ 1.3.12
test
@@ -210,8 +232,19 @@
org.testng
testng
- 7.1.0
+ 7.5.1
+
test
+
+
+ guice
+ com.google.inject
+
+
+ org.yaml
+ snakeyaml
+
+
org.mockito
@@ -247,7 +280,7 @@
redis.clients
jedis
- 3.3.0
+ 4.3.2
provided
@@ -259,9 +292,23 @@
org.redisson
redisson
- 3.12.0
+ 3.23.3
true
provided
+
+
+ com.fasterxml.jackson.core
+ jackson-core
+
+
+ org.jodd
+ jodd-core
+
+
+ org.reactivestreams
+ reactive-streams
+
+
org.springframework.data
@@ -273,13 +320,13 @@
org.projectlombok
lombok
- 1.18.8
+ 1.18.24
provided
org.bouncycastle
bcpkix-jdk15on
- 1.68
+ 1.70
@@ -313,7 +360,7 @@
org.apache.maven.plugins
maven-source-plugin
- 2.2.1
+ 3.1.0
attach-sources
@@ -344,7 +391,7 @@
org.apache.maven.plugins
maven-gpg-plugin
- 1.6
+ 3.1.0
sign-artifacts
diff --git a/spring-boot-starters/pom.xml b/spring-boot-starters/pom.xml
index 85fe5094b0..2a0abc777b 100644
--- a/spring-boot-starters/pom.xml
+++ b/spring-boot-starters/pom.xml
@@ -1,10 +1,12 @@
-
+
4.0.0
com.github.binarywang
wx-java
- 4.1.9.B
+ 4.5.7.B
pom
wx-java-spring-boot-starters
@@ -12,7 +14,7 @@
WxJava 各个模块的 Spring Boot Starter
- 2.5.3
+ 2.5.15
@@ -21,6 +23,9 @@
wx-java-pay-spring-boot-starter
wx-java-open-spring-boot-starter
wx-java-qidian-spring-boot-starter
+ wx-java-cp-multi-spring-boot-starter
+ wx-java-cp-spring-boot-starter
+ wx-java-channel-spring-boot-starter
diff --git a/spring-boot-starters/wx-java-channel-spring-boot-starter/pom.xml b/spring-boot-starters/wx-java-channel-spring-boot-starter/pom.xml
new file mode 100644
index 0000000000..4477d79e09
--- /dev/null
+++ b/spring-boot-starters/wx-java-channel-spring-boot-starter/pom.xml
@@ -0,0 +1,59 @@
+
+
+ wx-java-spring-boot-starters
+ com.github.binarywang
+ 4.5.7.B
+
+ 4.0.0
+
+ wx-java-channel-spring-boot-starter
+ WxJava - Spring Boot Starter for Channel
+ 微信视频号开发的 Spring Boot Starter
+
+
+
+ com.github.binarywang
+ weixin-java-channel
+ ${project.version}
+
+
+ redis.clients
+ jedis
+ provided
+
+
+ org.redisson
+ redisson
+ provided
+
+
+ org.springframework.data
+ spring-data-redis
+ provided
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ ${spring.boot.version}
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 2.2.1
+
+
+ attach-sources
+
+ jar-no-fork
+
+
+
+
+
+
+
diff --git a/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/config/WxChannelAutoConfiguration.java b/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/config/WxChannelAutoConfiguration.java
new file mode 100644
index 0000000000..ad9d90b28d
--- /dev/null
+++ b/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/config/WxChannelAutoConfiguration.java
@@ -0,0 +1,20 @@
+package com.binarywang.spring.starter.wxjava.channel.config;
+
+import com.binarywang.spring.starter.wxjava.channel.properties.WxChannelProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+
+/**
+ * 自动配置
+ *
+ * @author Zeyes
+ */
+@Configuration
+@EnableConfigurationProperties(WxChannelProperties.class)
+@Import({
+ WxChannelStorageAutoConfiguration.class,
+ WxChannelServiceAutoConfiguration.class
+})
+public class WxChannelAutoConfiguration {
+}
diff --git a/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/config/WxChannelServiceAutoConfiguration.java b/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/config/WxChannelServiceAutoConfiguration.java
new file mode 100644
index 0000000000..5276a803e7
--- /dev/null
+++ b/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/config/WxChannelServiceAutoConfiguration.java
@@ -0,0 +1,37 @@
+package com.binarywang.spring.starter.wxjava.channel.config;
+
+
+import com.binarywang.spring.starter.wxjava.channel.properties.WxChannelProperties;
+import lombok.AllArgsConstructor;
+import me.chanjar.weixin.channel.api.WxChannelService;
+import me.chanjar.weixin.channel.api.impl.WxChannelServiceImpl;
+import me.chanjar.weixin.channel.config.WxChannelConfig;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 微信小程序平台相关服务自动注册
+ *
+ * @author Zeyes
+ */
+@Configuration
+@AllArgsConstructor
+public class WxChannelServiceAutoConfiguration {
+ private final WxChannelProperties properties;
+
+ /**
+ * Channel Service
+ *
+ * @return Channel Service
+ */
+ @Bean
+ @ConditionalOnMissingBean(WxChannelService.class)
+ @ConditionalOnBean(WxChannelConfig.class)
+ public WxChannelService wxChannelService(WxChannelConfig wxChannelConfig) {
+ WxChannelService wxChannelService = new WxChannelServiceImpl();
+ wxChannelService.setConfig(wxChannelConfig);
+ return wxChannelService;
+ }
+}
diff --git a/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/config/WxChannelStorageAutoConfiguration.java b/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/config/WxChannelStorageAutoConfiguration.java
new file mode 100644
index 0000000000..66f2276a35
--- /dev/null
+++ b/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/config/WxChannelStorageAutoConfiguration.java
@@ -0,0 +1,23 @@
+package com.binarywang.spring.starter.wxjava.channel.config;
+
+import com.binarywang.spring.starter.wxjava.channel.config.storage.WxChannelInJedisConfigStorageConfiguration;
+import com.binarywang.spring.starter.wxjava.channel.config.storage.WxChannelInMemoryConfigStorageConfiguration;
+import com.binarywang.spring.starter.wxjava.channel.config.storage.WxChannelInRedisTemplateConfigStorageConfiguration;
+import com.binarywang.spring.starter.wxjava.channel.config.storage.WxChannelInRedissonConfigStorageConfiguration;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+
+/**
+ * 微信小程序存储策略自动配置
+ *
+ * @author Zeyes
+ */
+@Configuration
+@Import({
+ WxChannelInMemoryConfigStorageConfiguration.class,
+ WxChannelInJedisConfigStorageConfiguration.class,
+ WxChannelInRedisTemplateConfigStorageConfiguration.class,
+ WxChannelInRedissonConfigStorageConfiguration.class
+})
+public class WxChannelStorageAutoConfiguration {
+}
diff --git a/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/config/storage/AbstractWxChannelConfigStorageConfiguration.java b/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/config/storage/AbstractWxChannelConfigStorageConfiguration.java
new file mode 100644
index 0000000000..a87028a1cd
--- /dev/null
+++ b/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/config/storage/AbstractWxChannelConfigStorageConfiguration.java
@@ -0,0 +1,39 @@
+package com.binarywang.spring.starter.wxjava.channel.config.storage;
+
+import com.binarywang.spring.starter.wxjava.channel.properties.WxChannelProperties;
+import me.chanjar.weixin.channel.config.impl.WxChannelDefaultConfigImpl;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * @author Zeyes
+ */
+public abstract class AbstractWxChannelConfigStorageConfiguration {
+
+ protected WxChannelDefaultConfigImpl config(WxChannelDefaultConfigImpl config, WxChannelProperties properties) {
+ config.setAppid(StringUtils.trimToNull(properties.getAppid()));
+ config.setSecret(StringUtils.trimToNull(properties.getSecret()));
+ config.setToken(StringUtils.trimToNull(properties.getToken()));
+ config.setAesKey(StringUtils.trimToNull(properties.getAesKey()));
+ config.setMsgDataFormat(StringUtils.trimToNull(properties.getMsgDataFormat()));
+
+ WxChannelProperties.ConfigStorage configStorageProperties = properties.getConfigStorage();
+ config.setHttpProxyHost(configStorageProperties.getHttpProxyHost());
+ config.setHttpProxyUsername(configStorageProperties.getHttpProxyUsername());
+ config.setHttpProxyPassword(configStorageProperties.getHttpProxyPassword());
+ if (configStorageProperties.getHttpProxyPort() != null) {
+ config.setHttpProxyPort(configStorageProperties.getHttpProxyPort());
+ }
+
+ int maxRetryTimes = configStorageProperties.getMaxRetryTimes();
+ if (configStorageProperties.getMaxRetryTimes() < 0) {
+ maxRetryTimes = 0;
+ }
+ int retrySleepMillis = configStorageProperties.getRetrySleepMillis();
+ if (retrySleepMillis < 0) {
+ retrySleepMillis = 1000;
+ }
+ config.setRetrySleepMillis(retrySleepMillis);
+ config.setMaxRetryTimes(maxRetryTimes);
+ return config;
+ }
+}
diff --git a/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/config/storage/WxChannelInJedisConfigStorageConfiguration.java b/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/config/storage/WxChannelInJedisConfigStorageConfiguration.java
new file mode 100644
index 0000000000..f88548c3e9
--- /dev/null
+++ b/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/config/storage/WxChannelInJedisConfigStorageConfiguration.java
@@ -0,0 +1,73 @@
+package com.binarywang.spring.starter.wxjava.channel.config.storage;
+
+
+import com.binarywang.spring.starter.wxjava.channel.properties.RedisProperties;
+import com.binarywang.spring.starter.wxjava.channel.properties.WxChannelProperties;
+import lombok.RequiredArgsConstructor;
+import me.chanjar.weixin.channel.config.WxChannelConfig;
+import me.chanjar.weixin.channel.config.impl.WxChannelRedisConfigImpl;
+import me.chanjar.weixin.common.redis.JedisWxRedisOps;
+import me.chanjar.weixin.common.redis.WxRedisOps;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import redis.clients.jedis.JedisPool;
+import redis.clients.jedis.JedisPoolConfig;
+
+/**
+ * @author Zeyes
+ */
+@Configuration
+@ConditionalOnProperty(prefix = WxChannelProperties.PREFIX + ".config-storage", name = "type", havingValue = "jedis")
+@ConditionalOnClass({JedisPool.class, JedisPoolConfig.class})
+@RequiredArgsConstructor
+public class WxChannelInJedisConfigStorageConfiguration extends AbstractWxChannelConfigStorageConfiguration {
+ private final WxChannelProperties properties;
+ private final ApplicationContext applicationContext;
+
+ @Bean
+ @ConditionalOnMissingBean(WxChannelConfig.class)
+ public WxChannelConfig wxChannelConfig() {
+ WxChannelRedisConfigImpl config = getWxChannelRedisConfig();
+ return this.config(config, properties);
+ }
+
+ private WxChannelRedisConfigImpl getWxChannelRedisConfig() {
+ RedisProperties redisProperties = properties.getConfigStorage().getRedis();
+ JedisPool jedisPool;
+ if (redisProperties != null && StringUtils.isNotEmpty(redisProperties.getHost())) {
+ jedisPool = getJedisPool();
+ } else {
+ jedisPool = applicationContext.getBean(JedisPool.class);
+ }
+ WxRedisOps redisOps = new JedisWxRedisOps(jedisPool);
+ return new WxChannelRedisConfigImpl(redisOps, properties.getConfigStorage().getKeyPrefix());
+ }
+
+ private JedisPool getJedisPool() {
+ WxChannelProperties.ConfigStorage storage = properties.getConfigStorage();
+ RedisProperties redis = storage.getRedis();
+
+ JedisPoolConfig config = new JedisPoolConfig();
+ if (redis.getMaxActive() != null) {
+ config.setMaxTotal(redis.getMaxActive());
+ }
+ if (redis.getMaxIdle() != null) {
+ config.setMaxIdle(redis.getMaxIdle());
+ }
+ if (redis.getMaxWaitMillis() != null) {
+ config.setMaxWaitMillis(redis.getMaxWaitMillis());
+ }
+ if (redis.getMinIdle() != null) {
+ config.setMinIdle(redis.getMinIdle());
+ }
+ config.setTestOnBorrow(true);
+ config.setTestWhileIdle(true);
+
+ return new JedisPool(config, redis.getHost(), redis.getPort(), redis.getTimeout(), redis.getPassword(), redis.getDatabase());
+ }
+}
diff --git a/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/config/storage/WxChannelInMemoryConfigStorageConfiguration.java b/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/config/storage/WxChannelInMemoryConfigStorageConfiguration.java
new file mode 100644
index 0000000000..deb586ae7b
--- /dev/null
+++ b/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/config/storage/WxChannelInMemoryConfigStorageConfiguration.java
@@ -0,0 +1,29 @@
+package com.binarywang.spring.starter.wxjava.channel.config.storage;
+
+
+import com.binarywang.spring.starter.wxjava.channel.properties.WxChannelProperties;
+import lombok.RequiredArgsConstructor;
+import me.chanjar.weixin.channel.config.WxChannelConfig;
+import me.chanjar.weixin.channel.config.impl.WxChannelDefaultConfigImpl;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author Zeyes
+ */
+@Configuration
+@ConditionalOnProperty(prefix = WxChannelProperties.PREFIX + ".config-storage", name = "type",
+ matchIfMissing = true, havingValue = "memory")
+@RequiredArgsConstructor
+public class WxChannelInMemoryConfigStorageConfiguration extends AbstractWxChannelConfigStorageConfiguration {
+ private final WxChannelProperties properties;
+
+ @Bean
+ @ConditionalOnMissingBean(WxChannelProperties.class)
+ public WxChannelConfig wxChannelConfig() {
+ WxChannelDefaultConfigImpl config = new WxChannelDefaultConfigImpl();
+ return this.config(config, properties);
+ }
+}
diff --git a/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/config/storage/WxChannelInRedisTemplateConfigStorageConfiguration.java b/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/config/storage/WxChannelInRedisTemplateConfigStorageConfiguration.java
new file mode 100644
index 0000000000..e190fbd755
--- /dev/null
+++ b/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/config/storage/WxChannelInRedisTemplateConfigStorageConfiguration.java
@@ -0,0 +1,40 @@
+package com.binarywang.spring.starter.wxjava.channel.config.storage;
+
+import com.binarywang.spring.starter.wxjava.channel.properties.WxChannelProperties;
+import lombok.RequiredArgsConstructor;
+import me.chanjar.weixin.channel.config.WxChannelConfig;
+import me.chanjar.weixin.channel.config.impl.WxChannelRedisConfigImpl;
+import me.chanjar.weixin.common.redis.RedisTemplateWxRedisOps;
+import me.chanjar.weixin.common.redis.WxRedisOps;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.core.StringRedisTemplate;
+
+/**
+ * @author Zeyes
+ */
+@Configuration
+@ConditionalOnProperty(prefix = WxChannelProperties.PREFIX + ".config-storage", name = "type", havingValue = "redistemplate")
+@ConditionalOnClass(StringRedisTemplate.class)
+@RequiredArgsConstructor
+public class WxChannelInRedisTemplateConfigStorageConfiguration extends AbstractWxChannelConfigStorageConfiguration {
+ private final WxChannelProperties properties;
+ private final ApplicationContext applicationContext;
+
+ @Bean
+ @ConditionalOnMissingBean(WxChannelConfig.class)
+ public WxChannelConfig wxChannelConfig() {
+ WxChannelRedisConfigImpl config = getWxChannelInRedisTemplateConfig();
+ return this.config(config, properties);
+ }
+
+ private WxChannelRedisConfigImpl getWxChannelInRedisTemplateConfig() {
+ StringRedisTemplate redisTemplate = applicationContext.getBean(StringRedisTemplate.class);
+ WxRedisOps redisOps = new RedisTemplateWxRedisOps(redisTemplate);
+ return new WxChannelRedisConfigImpl(redisOps, properties.getConfigStorage().getKeyPrefix());
+ }
+}
diff --git a/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/config/storage/WxChannelInRedissonConfigStorageConfiguration.java b/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/config/storage/WxChannelInRedissonConfigStorageConfiguration.java
new file mode 100644
index 0000000000..16db4395a7
--- /dev/null
+++ b/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/config/storage/WxChannelInRedissonConfigStorageConfiguration.java
@@ -0,0 +1,62 @@
+package com.binarywang.spring.starter.wxjava.channel.config.storage;
+
+
+import com.binarywang.spring.starter.wxjava.channel.properties.RedisProperties;
+import com.binarywang.spring.starter.wxjava.channel.properties.WxChannelProperties;
+import lombok.RequiredArgsConstructor;
+import me.chanjar.weixin.channel.config.WxChannelConfig;
+import me.chanjar.weixin.channel.config.impl.WxChannelRedissonConfigImpl;
+import org.apache.commons.lang3.StringUtils;
+import org.redisson.Redisson;
+import org.redisson.api.RedissonClient;
+import org.redisson.config.Config;
+import org.redisson.config.TransportMode;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author Zeyes
+ */
+@Configuration
+@ConditionalOnProperty(prefix = WxChannelProperties.PREFIX + ".config-storage", name = "type", havingValue = "redisson")
+@ConditionalOnClass({Redisson.class, RedissonClient.class})
+@RequiredArgsConstructor
+public class WxChannelInRedissonConfigStorageConfiguration extends AbstractWxChannelConfigStorageConfiguration {
+ private final WxChannelProperties properties;
+ private final ApplicationContext applicationContext;
+
+ @Bean
+ @ConditionalOnMissingBean(WxChannelConfig.class)
+ public WxChannelConfig wxChannelConfig() {
+ WxChannelRedissonConfigImpl config = getWxChannelRedissonConfig();
+ return this.config(config, properties);
+ }
+
+ private WxChannelRedissonConfigImpl getWxChannelRedissonConfig() {
+ RedisProperties redisProperties = properties.getConfigStorage().getRedis();
+ RedissonClient redissonClient;
+ if (redisProperties != null && StringUtils.isNotEmpty(redisProperties.getHost())) {
+ redissonClient = getRedissonClient();
+ } else {
+ redissonClient = applicationContext.getBean(RedissonClient.class);
+ }
+ return new WxChannelRedissonConfigImpl(redissonClient, properties.getConfigStorage().getKeyPrefix());
+ }
+
+ private RedissonClient getRedissonClient() {
+ WxChannelProperties.ConfigStorage storage = properties.getConfigStorage();
+ RedisProperties redis = storage.getRedis();
+
+ Config config = new Config();
+ config.useSingleServer()
+ .setAddress("redis://" + redis.getHost() + ":" + redis.getPort())
+ .setDatabase(redis.getDatabase())
+ .setPassword(redis.getPassword());
+ config.setTransportMode(TransportMode.NIO);
+ return Redisson.create(config);
+ }
+}
diff --git a/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/enums/HttpClientType.java b/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/enums/HttpClientType.java
new file mode 100644
index 0000000000..63a7bf0c24
--- /dev/null
+++ b/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/enums/HttpClientType.java
@@ -0,0 +1,13 @@
+package com.binarywang.spring.starter.wxjava.channel.enums;
+
+/**
+ * httpclient类型
+ *
+ * @author Zeyes
+ */
+public enum HttpClientType {
+ /**
+ * HttpClient
+ */
+ HttpClient
+}
diff --git a/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/enums/StorageType.java b/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/enums/StorageType.java
new file mode 100644
index 0000000000..59b27fc022
--- /dev/null
+++ b/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/enums/StorageType.java
@@ -0,0 +1,25 @@
+package com.binarywang.spring.starter.wxjava.channel.enums;
+
+/**
+ * storage类型
+ *
+ * @author Zeyes
+ */
+public enum StorageType {
+ /**
+ * 内存
+ */
+ Memory,
+ /**
+ * redis(JedisClient)
+ */
+ Jedis,
+ /**
+ * redis(Redisson)
+ */
+ Redisson,
+ /**
+ * redis(RedisTemplate)
+ */
+ RedisTemplate
+}
diff --git a/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/properties/RedisProperties.java b/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/properties/RedisProperties.java
new file mode 100644
index 0000000000..19f27d0682
--- /dev/null
+++ b/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/properties/RedisProperties.java
@@ -0,0 +1,42 @@
+package com.binarywang.spring.starter.wxjava.channel.properties;
+
+import lombok.Data;
+
+/**
+ * redis 配置
+ *
+ * @author Zeyes
+ */
+@Data
+public class RedisProperties {
+
+ /**
+ * 主机地址,不填则从spring容器内获取JedisPool
+ */
+ private String host;
+
+ /**
+ * 端口号
+ */
+ private int port = 6379;
+
+ /**
+ * 密码
+ */
+ private String password;
+
+ /**
+ * 超时
+ */
+ private int timeout = 2000;
+
+ /**
+ * 数据库
+ */
+ private int database = 0;
+
+ private Integer maxActive;
+ private Integer maxIdle;
+ private Integer maxWaitMillis;
+ private Integer minIdle;
+}
diff --git a/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/properties/WxChannelProperties.java b/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/properties/WxChannelProperties.java
new file mode 100644
index 0000000000..98f1f3b723
--- /dev/null
+++ b/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/channel/properties/WxChannelProperties.java
@@ -0,0 +1,109 @@
+package com.binarywang.spring.starter.wxjava.channel.properties;
+
+import com.binarywang.spring.starter.wxjava.channel.enums.HttpClientType;
+import com.binarywang.spring.starter.wxjava.channel.enums.StorageType;
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.properties.NestedConfigurationProperty;
+
+/**
+ * 属性配置类
+ *
+ * @author Zeyes
+ */
+@Data
+@ConfigurationProperties(prefix = WxChannelProperties.PREFIX)
+public class WxChannelProperties {
+ public static final String PREFIX = "wx.channel";
+
+ /**
+ * 设置视频号小店的appid
+ */
+ private String appid;
+
+ /**
+ * 设置视频号小店的Secret
+ */
+ private String secret;
+
+ /**
+ * 设置视频号小店消息服务器配置的token.
+ */
+ private String token;
+
+ /**
+ * 设置视频号小店消息服务器配置的EncodingAESKey
+ */
+ private String aesKey;
+
+ /**
+ * 消息格式,XML或者JSON
+ */
+ private String msgDataFormat = "JSON";
+
+ /**
+ * 存储策略
+ */
+ private final ConfigStorage configStorage = new ConfigStorage();
+
+ @Data
+ public static class ConfigStorage {
+
+ /**
+ * 存储类型
+ */
+ private StorageType type = StorageType.Memory;
+
+ /**
+ * 指定key前缀
+ */
+ private String keyPrefix = "wh";
+
+ /**
+ * redis连接配置
+ */
+ @NestedConfigurationProperty
+ private final RedisProperties redis = new RedisProperties();
+
+ /**
+ * http客户端类型
+ */
+ private HttpClientType httpClientType = HttpClientType.HttpClient;
+
+ /**
+ * http代理主机
+ */
+ private String httpProxyHost;
+
+ /**
+ * http代理端口
+ */
+ private Integer httpProxyPort;
+
+ /**
+ * http代理用户名
+ */
+ private String httpProxyUsername;
+
+ /**
+ * http代理密码
+ */
+ private String httpProxyPassword;
+
+ /**
+ * http 请求重试间隔
+ *
+ * {@link me.chanjar.weixin.channel.api.BaseWxChannelService#setRetrySleepMillis(int)}
+ *
+ */
+ private int retrySleepMillis = 1000;
+ /**
+ * http 请求最大重试次数
+ *
+ * {@link me.chanjar.weixin.channel.api.BaseWxChannelService#setMaxRetryTimes(int)}
+ *
+ */
+ private int maxRetryTimes = 5;
+ }
+
+}
diff --git a/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/resources/META-INF/spring.factories b/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/resources/META-INF/spring.factories
new file mode 100644
index 0000000000..a9401752a0
--- /dev/null
+++ b/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,2 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+ com.binarywang.spring.starter.wxjava.channel.config.WxChannelAutoConfiguration
diff --git a/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000000..99ccbadbbc
--- /dev/null
+++ b/spring-boot-starters/wx-java-channel-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+com.binarywang.spring.starter.wxjava.channel.config.WxChannelAutoConfiguration
diff --git a/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/README.md b/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/README.md
new file mode 100644
index 0000000000..6b1ddaeb3b
--- /dev/null
+++ b/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/README.md
@@ -0,0 +1,96 @@
+# wx-java-cp-multi-spring-boot-starter
+
+企业微信多账号配置
+
+- 实现多 WxCpService 初始化。
+- 未实现 WxCpTpService 初始化,需要的小伙伴可以参考多 WxCpService 配置的实现。
+- 未实现 WxCpCgService 初始化,需要的小伙伴可以参考多 WxCpService 配置的实现。
+
+## 快速开始
+
+1. 引入依赖
+ ```xml
+
+ com.github.binarywang
+ wx-java-cp-multi-spring-boot-starter
+ ${version}
+
+ ```
+2. 添加配置(application.properties)
+ ```properties
+ # 应用 1 配置
+ wx.cp.corps.tenantId1.corp-id = @corp-id
+ wx.cp.corps.tenantId1.corp-secret = @corp-secret
+ ## 选填
+ wx.cp.corps.tenantId1.agent-id = @agent-id
+ wx.cp.corps.tenantId1.token = @token
+ wx.cp.corps.tenantId1.aes-key = @aes-key
+ wx.cp.corps.tenantId1.msg-audit-priKey = @msg-audit-priKey
+ wx.cp.corps.tenantId1.msg-audit-lib-path = @msg-audit-lib-path
+
+ # 应用 2 配置
+ wx.cp.corps.tenantId2.corp-id = @corp-id
+ wx.cp.corps.tenantId2.corp-secret = @corp-secret
+ ## 选填
+ wx.cp.corps.tenantId2.agent-id = @agent-id
+ wx.cp.corps.tenantId2.token = @token
+ wx.cp.corps.tenantId2.aes-key = @aes-key
+ wx.cp.corps.tenantId2.msg-audit-priKey = @msg-audit-priKey
+ wx.cp.corps.tenantId2.msg-audit-lib-path = @msg-audit-lib-path
+
+ # 公共配置
+ ## ConfigStorage 配置(选填)
+ wx.cp.config-storage.type=memory # 配置类型: memory(默认), jedis, redisson, redistemplate
+ ## http 客户端配置(选填)
+ wx.cp.config-storage.http-proxy-host=
+ wx.cp.config-storage.http-proxy-port=
+ wx.cp.config-storage.http-proxy-username=
+ wx.cp.config-storage.http-proxy-password=
+ ## 最大重试次数,默认:5 次,如果小于 0,则为 0
+ wx.cp.config-storage.max-retry-times=5
+ ## 重试时间间隔步进,默认:1000 毫秒,如果小于 0,则为 1000
+ wx.cp.config-storage.retry-sleep-millis=1000
+ ```
+3. 支持自动注入的类型: `WxCpMultiServices`
+
+4. 使用样例
+
+```java
+import com.binarywang.spring.starter.wxjava.cp.service.WxCpMultiServices;
+import com.binarywang.spring.starter.wxjava.cp.service.WxCpServices;
+import me.chanjar.weixin.cp.api.WxCpService;
+import me.chanjar.weixin.cp.api.WxCpUserService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class DemoService {
+ @Autowired
+ private WxCpMultiServices wxCpMultiServices;
+
+ public void test() {
+ // 应用 1 的 WxCpService
+ WxCpService wxCpService1 = wxCpMultiServices.getWxCpService("tenantId1");
+ WxCpUserService userService1 = wxCpService1.getUserService();
+ userService1.getUserId("xxx");
+ // todo ...
+
+ // 应用 2 的 WxCpService
+ WxCpService wxCpService2 = wxCpMultiServices.getWxCpService("tenantId2");
+ WxCpUserService userService2 = wxCpService2.getUserService();
+ userService2.getUserId("xxx");
+ // todo ...
+
+ // 应用 3 的 WxCpService
+ WxCpService wxCpService3 = wxCpMultiServices.getWxCpService("tenantId3");
+ // 判断是否为空
+ if (wxCpService3 == null) {
+ // todo wxCpService3 为空,请先配置 tenantId3 企业微信应用参数
+ return;
+ }
+ WxCpUserService userService3 = wxCpService3.getUserService();
+ userService3.getUserId("xxx");
+ // todo ...
+ }
+}
+```
diff --git a/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/pom.xml b/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/pom.xml
new file mode 100644
index 0000000000..693dd1624c
--- /dev/null
+++ b/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/pom.xml
@@ -0,0 +1,60 @@
+
+
+
+ wx-java-spring-boot-starters
+ com.github.binarywang
+ 4.5.7.B
+
+ 4.0.0
+
+ wx-java-cp-multi-spring-boot-starter
+ WxJava - Spring Boot Starter for WxCp::支持多账号配置
+ 微信企业号开发的 Spring Boot Starter::支持多账号配置
+
+
+
+ com.github.binarywang
+ weixin-java-cp
+ ${project.version}
+
+
+ redis.clients
+ jedis
+ provided
+
+
+ org.redisson
+ redisson
+ provided
+
+
+ org.springframework.data
+ spring-data-redis
+ provided
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ ${spring.boot.version}
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 2.2.1
+
+
+ attach-sources
+
+ jar-no-fork
+
+
+
+
+
+
+
diff --git a/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/autoconfigure/WxCpMultiAutoConfiguration.java b/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/autoconfigure/WxCpMultiAutoConfiguration.java
new file mode 100644
index 0000000000..8977b214ba
--- /dev/null
+++ b/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/autoconfigure/WxCpMultiAutoConfiguration.java
@@ -0,0 +1,20 @@
+package com.binarywang.spring.starter.wxjava.cp.autoconfigure;
+
+import com.binarywang.spring.starter.wxjava.cp.properties.WxCpMultiProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+
+/**
+ * 企业微信自动注册
+ *
+ * @author yl
+ * created on 2023/10/16
+ */
+@Configuration
+@EnableConfigurationProperties(WxCpMultiProperties.class)
+@Import({
+ WxCpMultiServicesAutoConfiguration.class
+})
+public class WxCpMultiAutoConfiguration {
+}
diff --git a/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/autoconfigure/WxCpMultiServicesAutoConfiguration.java b/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/autoconfigure/WxCpMultiServicesAutoConfiguration.java
new file mode 100644
index 0000000000..743888cad5
--- /dev/null
+++ b/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/autoconfigure/WxCpMultiServicesAutoConfiguration.java
@@ -0,0 +1,26 @@
+package com.binarywang.spring.starter.wxjava.cp.autoconfigure;
+
+import com.binarywang.spring.starter.wxjava.cp.autoconfigure.services.WxCpInJedisConfiguration;
+import com.binarywang.spring.starter.wxjava.cp.autoconfigure.services.WxCpInMemoryConfiguration;
+import com.binarywang.spring.starter.wxjava.cp.autoconfigure.services.WxCpInRedisTemplateConfiguration;
+import com.binarywang.spring.starter.wxjava.cp.autoconfigure.services.WxCpInRedissonConfiguration;
+import lombok.RequiredArgsConstructor;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+
+/**
+ * 企业微信平台相关服务自动注册
+ *
+ * @author yl
+ * created on 2023/10/16
+ */
+@Configuration
+@RequiredArgsConstructor
+@Import({
+ WxCpInJedisConfiguration.class,
+ WxCpInMemoryConfiguration.class,
+ WxCpInRedissonConfiguration.class,
+ WxCpInRedisTemplateConfiguration.class
+})
+public class WxCpMultiServicesAutoConfiguration {
+}
diff --git a/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/autoconfigure/services/AbstractWxCpConfiguration.java b/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/autoconfigure/services/AbstractWxCpConfiguration.java
new file mode 100644
index 0000000000..ec45ceaa2f
--- /dev/null
+++ b/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/autoconfigure/services/AbstractWxCpConfiguration.java
@@ -0,0 +1,145 @@
+package com.binarywang.spring.starter.wxjava.cp.autoconfigure.services;
+
+import com.binarywang.spring.starter.wxjava.cp.properties.CorpProperties;
+import com.binarywang.spring.starter.wxjava.cp.properties.WxCpMultiProperties;
+import com.binarywang.spring.starter.wxjava.cp.service.WxCpMultiServices;
+import com.binarywang.spring.starter.wxjava.cp.service.WxCpMultiServicesImpl;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.cp.api.WxCpService;
+import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl;
+import me.chanjar.weixin.cp.config.WxCpConfigStorage;
+import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * WxCpConfigStorage 抽象配置类
+ *
+ * @author yl
+ * created on 2023/10/16
+ */
+@RequiredArgsConstructor
+@Slf4j
+public abstract class AbstractWxCpConfiguration {
+
+ protected WxCpMultiServices configWxCpServices(WxCpMultiProperties wxCpMultiProperties) {
+ Map corps = wxCpMultiProperties.getCorps();
+ if (corps == null || corps.isEmpty()) {
+ log.warn("企业微信应用参数未配置,通过 WxCpMultiServices#getWxCpService(\"tenantId\")获取实例将返回空");
+ return new WxCpMultiServicesImpl();
+ }
+ /**
+ * 校验同一个企业下,agentId 是否唯一,避免使用 redis 缓存 token、ticket 时错乱。
+ *
+ * 查看 {@link me.chanjar.weixin.cp.config.impl.AbstractWxCpInRedisConfigImpl#setAgentId(Integer)}
+ */
+ Collection corpList = corps.values();
+ if (corpList.size() > 1) {
+ // 先按 corpId 分组统计
+ Map> corpsMap = corpList.stream()
+ .collect(Collectors.groupingBy(CorpProperties::getCorpId));
+ Set>> entries = corpsMap.entrySet();
+ for (Map.Entry> entry : entries) {
+ String corpId = entry.getKey();
+ // 校验每个企业下,agentId 是否唯一
+ boolean multi = entry.getValue().stream()
+ // 通讯录没有 agentId,如果不判断是否为空,这里会报 NPE 异常
+ .collect(Collectors.groupingBy(c -> c.getAgentId() == null ? 0 : c.getAgentId(), Collectors.counting()))
+ .entrySet().stream().anyMatch(e -> e.getValue() > 1);
+ if (multi) {
+ throw new RuntimeException("请确保企业微信配置唯一性[" + corpId + "]");
+ }
+ }
+ }
+ WxCpMultiServicesImpl services = new WxCpMultiServicesImpl();
+
+ Set> entries = corps.entrySet();
+ for (Map.Entry entry : entries) {
+ String tenantId = entry.getKey();
+ CorpProperties corpProperties = entry.getValue();
+ WxCpDefaultConfigImpl storage = this.configWxCpDefaultConfigImpl(wxCpMultiProperties);
+ this.configCorp(storage, corpProperties);
+ this.configHttp(storage, wxCpMultiProperties.getConfigStorage());
+ WxCpService wxCpService = this.configWxCpService(storage, wxCpMultiProperties.getConfigStorage());
+ services.addWxCpService(tenantId, wxCpService);
+ }
+ return services;
+ }
+
+ /**
+ * 配置 WxCpDefaultConfigImpl
+ *
+ * @param wxCpMultiProperties 参数
+ * @return WxCpDefaultConfigImpl
+ */
+ protected abstract WxCpDefaultConfigImpl configWxCpDefaultConfigImpl(WxCpMultiProperties wxCpMultiProperties);
+
+ private WxCpService configWxCpService(WxCpConfigStorage wxCpConfigStorage, WxCpMultiProperties.ConfigStorage storage) {
+ WxCpService wxCpService = new WxCpServiceImpl();
+ wxCpService.setWxCpConfigStorage(wxCpConfigStorage);
+
+ int maxRetryTimes = storage.getMaxRetryTimes();
+ if (maxRetryTimes < 0) {
+ maxRetryTimes = 0;
+ }
+ int retrySleepMillis = storage.getRetrySleepMillis();
+ if (retrySleepMillis < 0) {
+ retrySleepMillis = 1000;
+ }
+ wxCpService.setRetrySleepMillis(retrySleepMillis);
+ wxCpService.setMaxRetryTimes(maxRetryTimes);
+ return wxCpService;
+ }
+
+ private void configCorp(WxCpDefaultConfigImpl config, CorpProperties corpProperties) {
+ String corpId = corpProperties.getCorpId();
+ String corpSecret = corpProperties.getCorpSecret();
+ Integer agentId = corpProperties.getAgentId();
+ String token = corpProperties.getToken();
+ String aesKey = corpProperties.getAesKey();
+ // 企业微信,私钥,会话存档路径
+ String msgAuditPriKey = corpProperties.getMsgAuditPriKey();
+ String msgAuditLibPath = corpProperties.getMsgAuditLibPath();
+
+ config.setCorpId(corpId);
+ config.setCorpSecret(corpSecret);
+ config.setAgentId(agentId);
+ if (StringUtils.isNotBlank(token)) {
+ config.setToken(token);
+ }
+ if (StringUtils.isNotBlank(aesKey)) {
+ config.setAesKey(aesKey);
+ }
+ if (StringUtils.isNotBlank(msgAuditPriKey)) {
+ config.setMsgAuditPriKey(msgAuditPriKey);
+ }
+ if (StringUtils.isNotBlank(msgAuditLibPath)) {
+ config.setMsgAuditLibPath(msgAuditLibPath);
+ }
+ }
+
+ private void configHttp(WxCpDefaultConfigImpl config, WxCpMultiProperties.ConfigStorage storage) {
+ String httpProxyHost = storage.getHttpProxyHost();
+ Integer httpProxyPort = storage.getHttpProxyPort();
+ String httpProxyUsername = storage.getHttpProxyUsername();
+ String httpProxyPassword = storage.getHttpProxyPassword();
+ if (StringUtils.isNotBlank(httpProxyHost)) {
+ config.setHttpProxyHost(httpProxyHost);
+ if (httpProxyPort != null) {
+ config.setHttpProxyPort(httpProxyPort);
+ }
+ if (StringUtils.isNotBlank(httpProxyUsername)) {
+ config.setHttpProxyUsername(httpProxyUsername);
+ }
+ if (StringUtils.isNotBlank(httpProxyPassword)) {
+ config.setHttpProxyPassword(httpProxyPassword);
+ }
+ }
+ }
+}
diff --git a/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/autoconfigure/services/WxCpInJedisConfiguration.java b/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/autoconfigure/services/WxCpInJedisConfiguration.java
new file mode 100644
index 0000000000..3e49a5024a
--- /dev/null
+++ b/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/autoconfigure/services/WxCpInJedisConfiguration.java
@@ -0,0 +1,76 @@
+package com.binarywang.spring.starter.wxjava.cp.autoconfigure.services;
+
+import com.binarywang.spring.starter.wxjava.cp.properties.WxCpMultiProperties;
+import com.binarywang.spring.starter.wxjava.cp.properties.WxCpMultiRedisProperties;
+import com.binarywang.spring.starter.wxjava.cp.service.WxCpMultiServices;
+import lombok.RequiredArgsConstructor;
+import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl;
+import me.chanjar.weixin.cp.config.impl.WxCpJedisConfigImpl;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import redis.clients.jedis.JedisPool;
+import redis.clients.jedis.JedisPoolConfig;
+
+/**
+ * 自动装配基于 jedis 策略配置
+ *
+ * @author yl
+ * created on 2023/10/16
+ */
+@Configuration
+@ConditionalOnProperty(
+ prefix = WxCpMultiProperties.PREFIX + ".config-storage", name = "type", havingValue = "jedis"
+)
+@RequiredArgsConstructor
+public class WxCpInJedisConfiguration extends AbstractWxCpConfiguration {
+ private final WxCpMultiProperties wxCpMultiProperties;
+ private final ApplicationContext applicationContext;
+
+ @Bean
+ public WxCpMultiServices wxCpMultiServices() {
+ return this.configWxCpServices(wxCpMultiProperties);
+ }
+
+ @Override
+ protected WxCpDefaultConfigImpl configWxCpDefaultConfigImpl(WxCpMultiProperties wxCpMultiProperties) {
+ return this.configRedis(wxCpMultiProperties);
+ }
+
+ private WxCpDefaultConfigImpl configRedis(WxCpMultiProperties wxCpMultiProperties) {
+ WxCpMultiRedisProperties wxCpMultiRedisProperties = wxCpMultiProperties.getConfigStorage().getRedis();
+ JedisPool jedisPool;
+ if (wxCpMultiRedisProperties != null && StringUtils.isNotEmpty(wxCpMultiRedisProperties.getHost())) {
+ jedisPool = getJedisPool(wxCpMultiProperties);
+ } else {
+ jedisPool = applicationContext.getBean(JedisPool.class);
+ }
+ return new WxCpJedisConfigImpl(jedisPool, wxCpMultiProperties.getConfigStorage().getKeyPrefix());
+ }
+
+ private JedisPool getJedisPool(WxCpMultiProperties wxCpMultiProperties) {
+ WxCpMultiProperties.ConfigStorage storage = wxCpMultiProperties.getConfigStorage();
+ WxCpMultiRedisProperties redis = storage.getRedis();
+
+ JedisPoolConfig config = new JedisPoolConfig();
+ if (redis.getMaxActive() != null) {
+ config.setMaxTotal(redis.getMaxActive());
+ }
+ if (redis.getMaxIdle() != null) {
+ config.setMaxIdle(redis.getMaxIdle());
+ }
+ if (redis.getMaxWaitMillis() != null) {
+ config.setMaxWaitMillis(redis.getMaxWaitMillis());
+ }
+ if (redis.getMinIdle() != null) {
+ config.setMinIdle(redis.getMinIdle());
+ }
+ config.setTestOnBorrow(true);
+ config.setTestWhileIdle(true);
+
+ return new JedisPool(config, redis.getHost(), redis.getPort(),
+ redis.getTimeout(), redis.getPassword(), redis.getDatabase());
+ }
+}
diff --git a/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/autoconfigure/services/WxCpInMemoryConfiguration.java b/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/autoconfigure/services/WxCpInMemoryConfiguration.java
new file mode 100644
index 0000000000..dd0946fc53
--- /dev/null
+++ b/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/autoconfigure/services/WxCpInMemoryConfiguration.java
@@ -0,0 +1,38 @@
+package com.binarywang.spring.starter.wxjava.cp.autoconfigure.services;
+
+import com.binarywang.spring.starter.wxjava.cp.properties.WxCpMultiProperties;
+import com.binarywang.spring.starter.wxjava.cp.service.WxCpMultiServices;
+import lombok.RequiredArgsConstructor;
+import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 自动装配基于内存策略配置
+ *
+ * @author yl
+ * created on 2023/10/16
+ */
+@Configuration
+@ConditionalOnProperty(
+ prefix = WxCpMultiProperties.PREFIX + ".config-storage", name = "type", havingValue = "memory", matchIfMissing = true
+)
+@RequiredArgsConstructor
+public class WxCpInMemoryConfiguration extends AbstractWxCpConfiguration {
+ private final WxCpMultiProperties wxCpMultiProperties;
+
+ @Bean
+ public WxCpMultiServices wxCpMultiServices() {
+ return this.configWxCpServices(wxCpMultiProperties);
+ }
+
+ @Override
+ protected WxCpDefaultConfigImpl configWxCpDefaultConfigImpl(WxCpMultiProperties wxCpMultiProperties) {
+ return this.configInMemory();
+ }
+
+ private WxCpDefaultConfigImpl configInMemory() {
+ return new WxCpDefaultConfigImpl();
+ }
+}
diff --git a/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/autoconfigure/services/WxCpInRedisTemplateConfiguration.java b/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/autoconfigure/services/WxCpInRedisTemplateConfiguration.java
new file mode 100644
index 0000000000..103956fed3
--- /dev/null
+++ b/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/autoconfigure/services/WxCpInRedisTemplateConfiguration.java
@@ -0,0 +1,43 @@
+package com.binarywang.spring.starter.wxjava.cp.autoconfigure.services;
+
+import com.binarywang.spring.starter.wxjava.cp.properties.WxCpMultiProperties;
+import com.binarywang.spring.starter.wxjava.cp.service.WxCpMultiServices;
+import lombok.RequiredArgsConstructor;
+import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl;
+import me.chanjar.weixin.cp.config.impl.WxCpRedisTemplateConfigImpl;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.core.StringRedisTemplate;
+
+/**
+ * 自动装配基于 redisTemplate 策略配置
+ *
+ * @author yl
+ * created on 2023/10/16
+ */
+@Configuration
+@ConditionalOnProperty(
+ prefix = WxCpMultiProperties.PREFIX + ".config-storage", name = "type", havingValue = "redistemplate"
+)
+@RequiredArgsConstructor
+public class WxCpInRedisTemplateConfiguration extends AbstractWxCpConfiguration {
+ private final WxCpMultiProperties wxCpMultiProperties;
+ private final ApplicationContext applicationContext;
+
+ @Bean
+ public WxCpMultiServices wxCpMultiServices() {
+ return this.configWxCpServices(wxCpMultiProperties);
+ }
+
+ @Override
+ protected WxCpDefaultConfigImpl configWxCpDefaultConfigImpl(WxCpMultiProperties wxCpMultiProperties) {
+ return this.configRedisTemplate(wxCpMultiProperties);
+ }
+
+ private WxCpDefaultConfigImpl configRedisTemplate(WxCpMultiProperties wxCpMultiProperties) {
+ StringRedisTemplate redisTemplate = applicationContext.getBean(StringRedisTemplate.class);
+ return new WxCpRedisTemplateConfigImpl(redisTemplate, wxCpMultiProperties.getConfigStorage().getKeyPrefix());
+ }
+}
diff --git a/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/autoconfigure/services/WxCpInRedissonConfiguration.java b/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/autoconfigure/services/WxCpInRedissonConfiguration.java
new file mode 100644
index 0000000000..b8fc3a83ac
--- /dev/null
+++ b/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/autoconfigure/services/WxCpInRedissonConfiguration.java
@@ -0,0 +1,67 @@
+package com.binarywang.spring.starter.wxjava.cp.autoconfigure.services;
+
+import com.binarywang.spring.starter.wxjava.cp.properties.WxCpMultiProperties;
+import com.binarywang.spring.starter.wxjava.cp.properties.WxCpMultiRedisProperties;
+import com.binarywang.spring.starter.wxjava.cp.service.WxCpMultiServices;
+import lombok.RequiredArgsConstructor;
+import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl;
+import me.chanjar.weixin.cp.config.impl.WxCpRedissonConfigImpl;
+import org.apache.commons.lang3.StringUtils;
+import org.redisson.Redisson;
+import org.redisson.api.RedissonClient;
+import org.redisson.config.Config;
+import org.redisson.config.TransportMode;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 自动装配基于 redisson 策略配置
+ *
+ * @author yl
+ * created on 2023/10/16
+ */
+@Configuration
+@ConditionalOnProperty(
+ prefix = WxCpMultiProperties.PREFIX + ".config-storage", name = "type", havingValue = "redisson"
+)
+@RequiredArgsConstructor
+public class WxCpInRedissonConfiguration extends AbstractWxCpConfiguration {
+ private final WxCpMultiProperties wxCpMultiProperties;
+ private final ApplicationContext applicationContext;
+
+ @Bean
+ public WxCpMultiServices wxCpMultiServices() {
+ return this.configWxCpServices(wxCpMultiProperties);
+ }
+
+ @Override
+ protected WxCpDefaultConfigImpl configWxCpDefaultConfigImpl(WxCpMultiProperties wxCpMultiProperties) {
+ return this.configRedisson(wxCpMultiProperties);
+ }
+
+ private WxCpDefaultConfigImpl configRedisson(WxCpMultiProperties wxCpMultiProperties) {
+ WxCpMultiRedisProperties redisProperties = wxCpMultiProperties.getConfigStorage().getRedis();
+ RedissonClient redissonClient;
+ if (redisProperties != null && StringUtils.isNotEmpty(redisProperties.getHost())) {
+ redissonClient = getRedissonClient(wxCpMultiProperties);
+ } else {
+ redissonClient = applicationContext.getBean(RedissonClient.class);
+ }
+ return new WxCpRedissonConfigImpl(redissonClient, wxCpMultiProperties.getConfigStorage().getKeyPrefix());
+ }
+
+ private RedissonClient getRedissonClient(WxCpMultiProperties wxCpMultiProperties) {
+ WxCpMultiProperties.ConfigStorage storage = wxCpMultiProperties.getConfigStorage();
+ WxCpMultiRedisProperties redis = storage.getRedis();
+
+ Config config = new Config();
+ config.useSingleServer()
+ .setAddress("redis://" + redis.getHost() + ":" + redis.getPort())
+ .setDatabase(redis.getDatabase())
+ .setPassword(redis.getPassword());
+ config.setTransportMode(TransportMode.NIO);
+ return Redisson.create(config);
+ }
+}
diff --git a/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/properties/CorpProperties.java b/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/properties/CorpProperties.java
new file mode 100644
index 0000000000..354078d053
--- /dev/null
+++ b/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/properties/CorpProperties.java
@@ -0,0 +1,43 @@
+package com.binarywang.spring.starter.wxjava.cp.properties;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 企业微信企业相关配置属性
+ *
+ * @author yl
+ * created on 2023/10/16
+ */
+@Data
+@NoArgsConstructor
+public class CorpProperties {
+ /**
+ * 微信企业号 corpId
+ */
+ private String corpId;
+ /**
+ * 微信企业号 corpSecret
+ */
+ private String corpSecret;
+ /**
+ * 微信企业号应用 token
+ */
+ private String token;
+ /**
+ * 微信企业号应用 ID
+ */
+ private Integer agentId;
+ /**
+ * 微信企业号应用 EncodingAESKey
+ */
+ private String aesKey;
+ /**
+ * 微信企业号应用 会话存档私钥
+ */
+ private String msgAuditPriKey;
+ /**
+ * 微信企业号应用 会话存档类库路径
+ */
+ private String msgAuditLibPath;
+}
diff --git a/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/properties/WxCpMultiProperties.java b/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/properties/WxCpMultiProperties.java
new file mode 100644
index 0000000000..2d2b418ade
--- /dev/null
+++ b/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/properties/WxCpMultiProperties.java
@@ -0,0 +1,108 @@
+package com.binarywang.spring.starter.wxjava.cp.properties;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.properties.NestedConfigurationProperty;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 企业微信多企业接入相关配置属性
+ *
+ * @author yl
+ * created on 2023/10/16
+ */
+@Data
+@NoArgsConstructor
+@ConfigurationProperties(prefix = WxCpMultiProperties.PREFIX)
+public class WxCpMultiProperties {
+ public static final String PREFIX = "wx.cp";
+
+ private Map corps = new HashMap<>();
+
+ /**
+ * 配置存储策略,默认内存
+ */
+ private ConfigStorage configStorage = new ConfigStorage();
+
+ @Data
+ @NoArgsConstructor
+ public static class ConfigStorage implements Serializable {
+ private static final long serialVersionUID = 4815731027000065434L;
+ /**
+ * 存储类型
+ */
+ private StorageType type = StorageType.memory;
+
+ /**
+ * 指定key前缀
+ */
+ private String keyPrefix = "wx:cp";
+
+ /**
+ * redis连接配置
+ */
+ @NestedConfigurationProperty
+ private WxCpMultiRedisProperties redis = new WxCpMultiRedisProperties();
+
+ /**
+ * http代理主机
+ */
+ private String httpProxyHost;
+
+ /**
+ * http代理端口
+ */
+ private Integer httpProxyPort;
+
+ /**
+ * http代理用户名
+ */
+ private String httpProxyUsername;
+
+ /**
+ * http代理密码
+ */
+ private String httpProxyPassword;
+
+ /**
+ * http 请求最大重试次数
+ *
+ * {@link me.chanjar.weixin.cp.api.WxCpService#setMaxRetryTimes(int)}
+ * {@link me.chanjar.weixin.cp.api.impl.BaseWxCpServiceImpl#setMaxRetryTimes(int)}
+ *
+ */
+ private int maxRetryTimes = 5;
+
+ /**
+ * http 请求重试间隔
+ *
+ * {@link me.chanjar.weixin.cp.api.WxCpService#setRetrySleepMillis(int)}
+ * {@link me.chanjar.weixin.cp.api.impl.BaseWxCpServiceImpl#setRetrySleepMillis(int)}
+ *
+ */
+ private int retrySleepMillis = 1000;
+ }
+
+ public enum StorageType {
+ /**
+ * 内存
+ */
+ memory,
+ /**
+ * jedis
+ */
+ jedis,
+ /**
+ * redisson
+ */
+ redisson,
+ /**
+ * redistemplate
+ */
+ redistemplate
+ }
+}
diff --git a/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/properties/WxCpMultiRedisProperties.java b/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/properties/WxCpMultiRedisProperties.java
new file mode 100644
index 0000000000..e684333aea
--- /dev/null
+++ b/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/properties/WxCpMultiRedisProperties.java
@@ -0,0 +1,46 @@
+package com.binarywang.spring.starter.wxjava.cp.properties;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * Redis配置.
+ *
+ * @author yl
+ * created on 2023/10/16
+ */
+@Data
+public class WxCpMultiRedisProperties implements Serializable {
+ private static final long serialVersionUID = -5924815351660074401L;
+
+ /**
+ * 主机地址.
+ */
+ private String host;
+
+ /**
+ * 端口号.
+ */
+ private int port = 6379;
+
+ /**
+ * 密码.
+ */
+ private String password;
+
+ /**
+ * 超时.
+ */
+ private int timeout = 2000;
+
+ /**
+ * 数据库.
+ */
+ private int database = 0;
+
+ private Integer maxActive;
+ private Integer maxIdle;
+ private Integer maxWaitMillis;
+ private Integer minIdle;
+}
diff --git a/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/service/WxCpMultiServices.java b/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/service/WxCpMultiServices.java
new file mode 100644
index 0000000000..dfcb25631d
--- /dev/null
+++ b/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/service/WxCpMultiServices.java
@@ -0,0 +1,26 @@
+package com.binarywang.spring.starter.wxjava.cp.service;
+
+import me.chanjar.weixin.cp.api.WxCpService;
+
+/**
+ * 企业微信 {@link WxCpService} 所有实例存放类.
+ *
+ * @author yl
+ * created on 2023/10/16
+ */
+public interface WxCpMultiServices {
+ /**
+ * 通过租户 Id 获取 WxCpService
+ *
+ * @param tenantId 租户 Id
+ * @return WxCpService
+ */
+ WxCpService getWxCpService(String tenantId);
+
+ /**
+ * 根据租户 Id,从列表中移除一个 WxCpService 实例
+ *
+ * @param tenantId 租户 Id
+ */
+ void removeWxCpService(String tenantId);
+}
diff --git a/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/service/WxCpMultiServicesImpl.java b/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/service/WxCpMultiServicesImpl.java
new file mode 100644
index 0000000000..19eae24159
--- /dev/null
+++ b/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/service/WxCpMultiServicesImpl.java
@@ -0,0 +1,42 @@
+package com.binarywang.spring.starter.wxjava.cp.service;
+
+import me.chanjar.weixin.cp.api.WxCpService;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * 企业微信 {@link WxCpMultiServices} 默认实现
+ *
+ * @author yl
+ * created on 2023/10/16
+ */
+public class WxCpMultiServicesImpl implements WxCpMultiServices {
+ private final Map services = new ConcurrentHashMap<>();
+
+ /**
+ * 通过租户 Id 获取 WxCpService
+ *
+ * @param tenantId 租户 Id
+ * @return WxCpService
+ */
+ @Override
+ public WxCpService getWxCpService(String tenantId) {
+ return this.services.get(tenantId);
+ }
+
+ /**
+ * 根据租户 Id,添加一个 WxCpService 到列表
+ *
+ * @param tenantId 租户 Id
+ * @param wxCpService WxCpService 实例
+ */
+ public void addWxCpService(String tenantId, WxCpService wxCpService) {
+ this.services.put(tenantId, wxCpService);
+ }
+
+ @Override
+ public void removeWxCpService(String tenantId) {
+ this.services.remove(tenantId);
+ }
+}
diff --git a/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/resources/META-INF/spring.factories b/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/resources/META-INF/spring.factories
new file mode 100644
index 0000000000..6010561a96
--- /dev/null
+++ b/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,2 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+com.binarywang.spring.starter.wxjava.cp.autoconfigure.WxCpMultiAutoConfiguration
diff --git a/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000000..3c48ec34e1
--- /dev/null
+++ b/spring-boot-starters/wx-java-cp-multi-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+com.binarywang.spring.starter.wxjava.cp.autoconfigure.WxCpMultiAutoConfiguration
diff --git a/spring-boot-starters/wx-java-cp-spring-boot-starter/README.md b/spring-boot-starters/wx-java-cp-spring-boot-starter/README.md
new file mode 100644
index 0000000000..d6c1abc945
--- /dev/null
+++ b/spring-boot-starters/wx-java-cp-spring-boot-starter/README.md
@@ -0,0 +1,41 @@
+# wx-java-cp-spring-boot-starter
+
+## 快速开始
+
+1. 引入依赖
+ ```xml
+
+ com.github.binarywang
+ wx-java-cp-spring-boot-starter
+ ${version}
+
+ ```
+2. 添加配置(application.properties)
+ ```properties
+ # 企业微信号配置(必填)
+ wx.cp.corp-id = @corp-id
+ wx.cp.corp-secret = @corp-secret
+ # 选填
+ wx.cp.agent-id = @agent-id
+ wx.cp.token = @token
+ wx.cp.aes-key = @aes-key
+ wx.cp.msg-audit-priKey = @msg-audit-priKey
+ wx.cp.msg-audit-lib-path = @msg-audit-lib-path
+ # ConfigStorage 配置(选填)
+ wx.cp.config-storage.type=memory # 配置类型: memory(默认), jedis, redisson, redistemplate
+ # http 客户端配置(选填)
+ wx.cp.config-storage.http-proxy-host=
+ wx.cp.config-storage.http-proxy-port=
+ wx.cp.config-storage.http-proxy-username=
+ wx.cp.config-storage.http-proxy-password=
+ # 最大重试次数,默认:5 次,如果小于 0,则为 0
+ wx.cp.config-storage.max-retry-times=5
+ # 重试时间间隔步进,默认:1000 毫秒,如果小于 0,则为 1000
+ wx.cp.config-storage.retry-sleep-millis=1000
+ ```
+3. 支持自动注入的类型: `WxCpService`, `WxCpConfigStorage`
+
+4. 覆盖自动配置: 自定义注入的bean会覆盖自动注入的
+
+- WxCpService
+- WxCpConfigStorage
diff --git a/spring-boot-starters/wx-java-cp-spring-boot-starter/pom.xml b/spring-boot-starters/wx-java-cp-spring-boot-starter/pom.xml
new file mode 100644
index 0000000000..d64aec432c
--- /dev/null
+++ b/spring-boot-starters/wx-java-cp-spring-boot-starter/pom.xml
@@ -0,0 +1,57 @@
+
+
+
+ wx-java-spring-boot-starters
+ com.github.binarywang
+ 4.5.7.B
+
+ 4.0.0
+
+ wx-java-cp-spring-boot-starter
+ WxJava - Spring Boot Starter for WxCp
+ 微信企业号开发的 Spring Boot Starter
+
+
+
+ com.github.binarywang
+ weixin-java-cp
+ ${project.version}
+
+
+ redis.clients
+ jedis
+
+
+ org.redisson
+ redisson
+
+
+ org.springframework.data
+ spring-data-redis
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ ${spring.boot.version}
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 2.2.1
+
+
+ attach-sources
+
+ jar-no-fork
+
+
+
+
+
+
+
diff --git a/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/config/WxCpAutoConfiguration.java b/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/config/WxCpAutoConfiguration.java
new file mode 100644
index 0000000000..f78c39dd45
--- /dev/null
+++ b/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/config/WxCpAutoConfiguration.java
@@ -0,0 +1,21 @@
+package com.binarywang.spring.starter.wxjava.cp.config;
+
+import com.binarywang.spring.starter.wxjava.cp.properties.WxCpProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+
+/**
+ * 企业微信自动注册
+ *
+ * @author yl
+ * created on 2021/12/6
+ */
+@Configuration
+@EnableConfigurationProperties(WxCpProperties.class)
+@Import({
+ WxCpStorageAutoConfiguration.class,
+ WxCpServiceAutoConfiguration.class
+})
+public class WxCpAutoConfiguration {
+}
diff --git a/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/config/WxCpServiceAutoConfiguration.java b/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/config/WxCpServiceAutoConfiguration.java
new file mode 100644
index 0000000000..70c4045259
--- /dev/null
+++ b/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/config/WxCpServiceAutoConfiguration.java
@@ -0,0 +1,44 @@
+package com.binarywang.spring.starter.wxjava.cp.config;
+
+import com.binarywang.spring.starter.wxjava.cp.properties.WxCpProperties;
+import lombok.RequiredArgsConstructor;
+import me.chanjar.weixin.cp.api.WxCpService;
+import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl;
+import me.chanjar.weixin.cp.config.WxCpConfigStorage;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 企业微信平台相关服务自动注册
+ *
+ * @author yl
+ * created on 2021/12/6
+ */
+@Configuration
+@RequiredArgsConstructor
+public class WxCpServiceAutoConfiguration {
+ private final WxCpProperties wxCpProperties;
+
+ @Bean
+ @ConditionalOnMissingBean
+ @ConditionalOnBean(WxCpConfigStorage.class)
+ public WxCpService wxCpService(WxCpConfigStorage wxCpConfigStorage) {
+ WxCpService wxCpService = new WxCpServiceImpl();
+ wxCpService.setWxCpConfigStorage(wxCpConfigStorage);
+
+ WxCpProperties.ConfigStorage storage = wxCpProperties.getConfigStorage();
+ int maxRetryTimes = storage.getMaxRetryTimes();
+ if (maxRetryTimes < 0) {
+ maxRetryTimes = 0;
+ }
+ int retrySleepMillis = storage.getRetrySleepMillis();
+ if (retrySleepMillis < 0) {
+ retrySleepMillis = 1000;
+ }
+ wxCpService.setRetrySleepMillis(retrySleepMillis);
+ wxCpService.setMaxRetryTimes(maxRetryTimes);
+ return wxCpService;
+ }
+}
diff --git a/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/config/WxCpStorageAutoConfiguration.java b/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/config/WxCpStorageAutoConfiguration.java
new file mode 100644
index 0000000000..1c7d80b84e
--- /dev/null
+++ b/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/config/WxCpStorageAutoConfiguration.java
@@ -0,0 +1,24 @@
+package com.binarywang.spring.starter.wxjava.cp.config;
+
+import com.binarywang.spring.starter.wxjava.cp.storage.WxCpInJedisConfigStorageConfiguration;
+import com.binarywang.spring.starter.wxjava.cp.storage.WxCpInMemoryConfigStorageConfiguration;
+import com.binarywang.spring.starter.wxjava.cp.storage.WxCpInRedisTemplateConfigStorageConfiguration;
+import com.binarywang.spring.starter.wxjava.cp.storage.WxCpInRedissonConfigStorageConfiguration;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+
+/**
+ * 企业微信存储策略自动配置
+ *
+ * @author yl
+ * created on 2021/12/6
+ */
+@Configuration
+@Import({
+ WxCpInMemoryConfigStorageConfiguration.class,
+ WxCpInJedisConfigStorageConfiguration.class,
+ WxCpInRedissonConfigStorageConfiguration.class,
+ WxCpInRedisTemplateConfigStorageConfiguration.class
+})
+public class WxCpStorageAutoConfiguration {
+}
diff --git a/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/properties/WxCpProperties.java b/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/properties/WxCpProperties.java
new file mode 100644
index 0000000000..b87ddc2454
--- /dev/null
+++ b/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/properties/WxCpProperties.java
@@ -0,0 +1,133 @@
+package com.binarywang.spring.starter.wxjava.cp.properties;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.properties.NestedConfigurationProperty;
+
+import java.io.Serializable;
+
+/**
+ * 企业微信接入相关配置属性
+ *
+ * @author yl
+ * created on 2021/12/6
+ */
+@Data
+@NoArgsConstructor
+@ConfigurationProperties(prefix = WxCpProperties.PREFIX)
+public class WxCpProperties {
+ public static final String PREFIX = "wx.cp";
+
+ /**
+ * 微信企业号 corpId
+ */
+ private String corpId;
+ /**
+ * 微信企业号 corpSecret
+ */
+ private String corpSecret;
+ /**
+ * 微信企业号应用 token
+ */
+ private String token;
+ /**
+ * 微信企业号应用 ID
+ */
+ private Integer agentId;
+ /**
+ * 微信企业号应用 EncodingAESKey
+ */
+ private String aesKey;
+ /**
+ * 微信企业号应用 会话存档私钥
+ */
+ private String msgAuditPriKey;
+ /**
+ * 微信企业号应用 会话存档类库路径
+ */
+ private String msgAuditLibPath;
+
+ /**
+ * 配置存储策略,默认内存
+ */
+ private ConfigStorage configStorage = new ConfigStorage();
+
+ @Data
+ @NoArgsConstructor
+ public static class ConfigStorage implements Serializable {
+ private static final long serialVersionUID = 4815731027000065434L;
+ /**
+ * 存储类型
+ */
+ private StorageType type = StorageType.memory;
+
+ /**
+ * 指定key前缀
+ */
+ private String keyPrefix = "wx:cp";
+
+ /**
+ * redis连接配置
+ */
+ @NestedConfigurationProperty
+ private WxCpRedisProperties redis = new WxCpRedisProperties();
+
+ /**
+ * http代理主机
+ */
+ private String httpProxyHost;
+
+ /**
+ * http代理端口
+ */
+ private Integer httpProxyPort;
+
+ /**
+ * http代理用户名
+ */
+ private String httpProxyUsername;
+
+ /**
+ * http代理密码
+ */
+ private String httpProxyPassword;
+
+ /**
+ * http 请求最大重试次数
+ *
+ * {@link me.chanjar.weixin.cp.api.WxCpService#setMaxRetryTimes(int)}
+ * {@link me.chanjar.weixin.cp.api.impl.BaseWxCpServiceImpl#setMaxRetryTimes(int)}
+ *
+ */
+ private int maxRetryTimes = 5;
+
+ /**
+ * http 请求重试间隔
+ *
+ * {@link me.chanjar.weixin.cp.api.WxCpService#setRetrySleepMillis(int)}
+ * {@link me.chanjar.weixin.cp.api.impl.BaseWxCpServiceImpl#setRetrySleepMillis(int)}
+ *
+ */
+ private int retrySleepMillis = 1000;
+ }
+
+ public enum StorageType {
+ /**
+ * 内存
+ */
+ memory,
+ /**
+ * jedis
+ */
+ jedis,
+ /**
+ * redisson
+ */
+ redisson,
+ /**
+ * redistemplate
+ */
+ redistemplate
+ }
+}
diff --git a/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/properties/WxCpRedisProperties.java b/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/properties/WxCpRedisProperties.java
new file mode 100644
index 0000000000..63a7fe01e0
--- /dev/null
+++ b/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/properties/WxCpRedisProperties.java
@@ -0,0 +1,46 @@
+package com.binarywang.spring.starter.wxjava.cp.properties;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * Redis配置.
+ *
+ * @author yl
+ * created on 2023/04/23
+ */
+@Data
+public class WxCpRedisProperties implements Serializable {
+ private static final long serialVersionUID = -5924815351660074401L;
+
+ /**
+ * 主机地址.
+ */
+ private String host;
+
+ /**
+ * 端口号.
+ */
+ private int port = 6379;
+
+ /**
+ * 密码.
+ */
+ private String password;
+
+ /**
+ * 超时.
+ */
+ private int timeout = 2000;
+
+ /**
+ * 数据库.
+ */
+ private int database = 0;
+
+ private Integer maxActive;
+ private Integer maxIdle;
+ private Integer maxWaitMillis;
+ private Integer minIdle;
+}
diff --git a/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/storage/AbstractWxCpConfigStorageConfiguration.java b/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/storage/AbstractWxCpConfigStorageConfiguration.java
new file mode 100644
index 0000000000..0f2995e967
--- /dev/null
+++ b/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/storage/AbstractWxCpConfigStorageConfiguration.java
@@ -0,0 +1,61 @@
+package com.binarywang.spring.starter.wxjava.cp.storage;
+
+import com.binarywang.spring.starter.wxjava.cp.properties.WxCpProperties;
+import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * WxCpConfigStorage 抽象配置类
+ *
+ * @author yl & Wang_Wong
+ * created on 2021/12/6
+ */
+public abstract class AbstractWxCpConfigStorageConfiguration {
+
+ protected WxCpDefaultConfigImpl config(WxCpDefaultConfigImpl config, WxCpProperties properties) {
+ String corpId = properties.getCorpId();
+ String corpSecret = properties.getCorpSecret();
+ Integer agentId = properties.getAgentId();
+ String token = properties.getToken();
+ String aesKey = properties.getAesKey();
+ // 企业微信,私钥,会话存档路径
+ String msgAuditPriKey = properties.getMsgAuditPriKey();
+ String msgAuditLibPath = properties.getMsgAuditLibPath();
+
+ config.setCorpId(corpId);
+ config.setCorpSecret(corpSecret);
+ config.setAgentId(agentId);
+ if (StringUtils.isNotBlank(token)) {
+ config.setToken(token);
+ }
+ if (StringUtils.isNotBlank(aesKey)) {
+ config.setAesKey(aesKey);
+ }
+ if (StringUtils.isNotBlank(msgAuditPriKey)) {
+ config.setMsgAuditPriKey(msgAuditPriKey);
+ }
+ if (StringUtils.isNotBlank(msgAuditLibPath)) {
+ config.setMsgAuditLibPath(msgAuditLibPath);
+ }
+
+ WxCpProperties.ConfigStorage storage = properties.getConfigStorage();
+ String httpProxyHost = storage.getHttpProxyHost();
+ Integer httpProxyPort = storage.getHttpProxyPort();
+ String httpProxyUsername = storage.getHttpProxyUsername();
+ String httpProxyPassword = storage.getHttpProxyPassword();
+ if (StringUtils.isNotBlank(httpProxyHost)) {
+ config.setHttpProxyHost(httpProxyHost);
+ if (httpProxyPort != null) {
+ config.setHttpProxyPort(httpProxyPort);
+ }
+ if (StringUtils.isNotBlank(httpProxyUsername)) {
+ config.setHttpProxyUsername(httpProxyUsername);
+ }
+ if (StringUtils.isNotBlank(httpProxyPassword)) {
+ config.setHttpProxyPassword(httpProxyPassword);
+ }
+ }
+ return config;
+ }
+
+}
diff --git a/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/storage/WxCpInJedisConfigStorageConfiguration.java b/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/storage/WxCpInJedisConfigStorageConfiguration.java
new file mode 100644
index 0000000000..246971baed
--- /dev/null
+++ b/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/storage/WxCpInJedisConfigStorageConfiguration.java
@@ -0,0 +1,74 @@
+package com.binarywang.spring.starter.wxjava.cp.storage;
+
+import com.binarywang.spring.starter.wxjava.cp.properties.WxCpProperties;
+import com.binarywang.spring.starter.wxjava.cp.properties.WxCpRedisProperties;
+import lombok.RequiredArgsConstructor;
+import me.chanjar.weixin.cp.config.WxCpConfigStorage;
+import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl;
+import me.chanjar.weixin.cp.config.impl.WxCpJedisConfigImpl;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import redis.clients.jedis.JedisPool;
+import redis.clients.jedis.JedisPoolConfig;
+
+/**
+ * 自动装配基于 jedis 策略配置
+ *
+ * @author yl
+ * created on 2023/04/23
+ */
+@Configuration
+@ConditionalOnProperty(
+ prefix = WxCpProperties.PREFIX + ".config-storage", name = "type", havingValue = "jedis"
+)
+@RequiredArgsConstructor
+public class WxCpInJedisConfigStorageConfiguration extends AbstractWxCpConfigStorageConfiguration {
+ private final WxCpProperties wxCpProperties;
+ private final ApplicationContext applicationContext;
+
+ @Bean
+ @ConditionalOnMissingBean(WxCpConfigStorage.class)
+ public WxCpConfigStorage wxCpConfigStorage() {
+ WxCpDefaultConfigImpl config = getConfigStorage();
+ return this.config(config, wxCpProperties);
+ }
+
+ private WxCpJedisConfigImpl getConfigStorage() {
+ WxCpRedisProperties wxCpRedisProperties = wxCpProperties.getConfigStorage().getRedis();
+ JedisPool jedisPool;
+ if (wxCpRedisProperties != null && StringUtils.isNotEmpty(wxCpRedisProperties.getHost())) {
+ jedisPool = getJedisPool();
+ } else {
+ jedisPool = applicationContext.getBean(JedisPool.class);
+ }
+ return new WxCpJedisConfigImpl(jedisPool, wxCpProperties.getConfigStorage().getKeyPrefix());
+ }
+
+ private JedisPool getJedisPool() {
+ WxCpProperties.ConfigStorage storage = wxCpProperties.getConfigStorage();
+ WxCpRedisProperties redis = storage.getRedis();
+
+ JedisPoolConfig config = new JedisPoolConfig();
+ if (redis.getMaxActive() != null) {
+ config.setMaxTotal(redis.getMaxActive());
+ }
+ if (redis.getMaxIdle() != null) {
+ config.setMaxIdle(redis.getMaxIdle());
+ }
+ if (redis.getMaxWaitMillis() != null) {
+ config.setMaxWaitMillis(redis.getMaxWaitMillis());
+ }
+ if (redis.getMinIdle() != null) {
+ config.setMinIdle(redis.getMinIdle());
+ }
+ config.setTestOnBorrow(true);
+ config.setTestWhileIdle(true);
+
+ return new JedisPool(config, redis.getHost(), redis.getPort(),
+ redis.getTimeout(), redis.getPassword(), redis.getDatabase());
+ }
+}
diff --git a/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/storage/WxCpInMemoryConfigStorageConfiguration.java b/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/storage/WxCpInMemoryConfigStorageConfiguration.java
new file mode 100644
index 0000000000..3722bd07d1
--- /dev/null
+++ b/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/storage/WxCpInMemoryConfigStorageConfiguration.java
@@ -0,0 +1,33 @@
+package com.binarywang.spring.starter.wxjava.cp.storage;
+
+import com.binarywang.spring.starter.wxjava.cp.properties.WxCpProperties;
+import lombok.RequiredArgsConstructor;
+import me.chanjar.weixin.cp.config.WxCpConfigStorage;
+import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 自动装配基于内存策略配置
+ *
+ * @author yl
+ * created on 2021/12/6
+ */
+@Configuration
+@ConditionalOnProperty(
+ prefix = WxCpProperties.PREFIX + ".config-storage", name = "type",
+ matchIfMissing = true, havingValue = "memory"
+)
+@RequiredArgsConstructor
+public class WxCpInMemoryConfigStorageConfiguration extends AbstractWxCpConfigStorageConfiguration {
+ private final WxCpProperties wxCpProperties;
+
+ @Bean
+ @ConditionalOnMissingBean(WxCpConfigStorage.class)
+ public WxCpConfigStorage wxCpConfigStorage() {
+ WxCpDefaultConfigImpl config = new WxCpDefaultConfigImpl();
+ return this.config(config, wxCpProperties);
+ }
+}
diff --git a/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/storage/WxCpInRedisTemplateConfigStorageConfiguration.java b/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/storage/WxCpInRedisTemplateConfigStorageConfiguration.java
new file mode 100644
index 0000000000..879568b16a
--- /dev/null
+++ b/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/storage/WxCpInRedisTemplateConfigStorageConfiguration.java
@@ -0,0 +1,41 @@
+package com.binarywang.spring.starter.wxjava.cp.storage;
+
+import com.binarywang.spring.starter.wxjava.cp.properties.WxCpProperties;
+import lombok.RequiredArgsConstructor;
+import me.chanjar.weixin.cp.config.WxCpConfigStorage;
+import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl;
+import me.chanjar.weixin.cp.config.impl.WxCpRedisTemplateConfigImpl;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.core.StringRedisTemplate;
+
+/**
+ * 自动装配基于 redisTemplate 策略配置
+ *
+ * @author yl
+ * created on 2023/04/23
+ */
+@Configuration
+@ConditionalOnProperty(
+ prefix = WxCpProperties.PREFIX + ".config-storage", name = "type", havingValue = "redistemplate"
+)
+@RequiredArgsConstructor
+public class WxCpInRedisTemplateConfigStorageConfiguration extends AbstractWxCpConfigStorageConfiguration {
+ private final WxCpProperties wxCpProperties;
+ private final ApplicationContext applicationContext;
+
+ @Bean
+ @ConditionalOnMissingBean(WxCpConfigStorage.class)
+ public WxCpConfigStorage wxCpConfigStorage() {
+ WxCpDefaultConfigImpl config = getConfigStorage();
+ return this.config(config, wxCpProperties);
+ }
+
+ private WxCpRedisTemplateConfigImpl getConfigStorage() {
+ StringRedisTemplate redisTemplate = applicationContext.getBean(StringRedisTemplate.class);
+ return new WxCpRedisTemplateConfigImpl(redisTemplate, wxCpProperties.getConfigStorage().getKeyPrefix());
+ }
+}
diff --git a/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/storage/WxCpInRedissonConfigStorageConfiguration.java b/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/storage/WxCpInRedissonConfigStorageConfiguration.java
new file mode 100644
index 0000000000..060b894fd1
--- /dev/null
+++ b/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/cp/storage/WxCpInRedissonConfigStorageConfiguration.java
@@ -0,0 +1,65 @@
+package com.binarywang.spring.starter.wxjava.cp.storage;
+
+import com.binarywang.spring.starter.wxjava.cp.properties.WxCpProperties;
+import com.binarywang.spring.starter.wxjava.cp.properties.WxCpRedisProperties;
+import lombok.RequiredArgsConstructor;
+import me.chanjar.weixin.cp.config.WxCpConfigStorage;
+import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl;
+import me.chanjar.weixin.cp.config.impl.WxCpRedissonConfigImpl;
+import org.apache.commons.lang3.StringUtils;
+import org.redisson.Redisson;
+import org.redisson.api.RedissonClient;
+import org.redisson.config.Config;
+import org.redisson.config.TransportMode;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 自动装配基于 redisson 策略配置
+ *
+ * @author yl
+ * created on 2023/04/23
+ */
+@Configuration
+@ConditionalOnProperty(
+ prefix = WxCpProperties.PREFIX + ".config-storage", name = "type", havingValue = "redisson"
+)
+@RequiredArgsConstructor
+public class WxCpInRedissonConfigStorageConfiguration extends AbstractWxCpConfigStorageConfiguration {
+ private final WxCpProperties wxCpProperties;
+ private final ApplicationContext applicationContext;
+
+ @Bean
+ @ConditionalOnMissingBean(WxCpConfigStorage.class)
+ public WxCpConfigStorage wxCpConfigStorage() {
+ WxCpDefaultConfigImpl config = getConfigStorage();
+ return this.config(config, wxCpProperties);
+ }
+
+ private WxCpRedissonConfigImpl getConfigStorage() {
+ WxCpRedisProperties redisProperties = wxCpProperties.getConfigStorage().getRedis();
+ RedissonClient redissonClient;
+ if (redisProperties != null && StringUtils.isNotEmpty(redisProperties.getHost())) {
+ redissonClient = getRedissonClient();
+ } else {
+ redissonClient = applicationContext.getBean(RedissonClient.class);
+ }
+ return new WxCpRedissonConfigImpl(redissonClient, wxCpProperties.getConfigStorage().getKeyPrefix());
+ }
+
+ private RedissonClient getRedissonClient() {
+ WxCpProperties.ConfigStorage storage = wxCpProperties.getConfigStorage();
+ WxCpRedisProperties redis = storage.getRedis();
+
+ Config config = new Config();
+ config.useSingleServer()
+ .setAddress("redis://" + redis.getHost() + ":" + redis.getPort())
+ .setDatabase(redis.getDatabase())
+ .setPassword(redis.getPassword());
+ config.setTransportMode(TransportMode.NIO);
+ return Redisson.create(config);
+ }
+}
diff --git a/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/resources/META-INF/spring.factories b/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/resources/META-INF/spring.factories
new file mode 100644
index 0000000000..c2ef7f6354
--- /dev/null
+++ b/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,2 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+com.binarywang.spring.starter.wxjava.cp.config.WxCpAutoConfiguration
diff --git a/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000000..0beff3f862
--- /dev/null
+++ b/spring-boot-starters/wx-java-cp-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+com.binarywang.spring.starter.wxjava.cp.config.WxCpAutoConfiguration
diff --git a/spring-boot-starters/wx-java-miniapp-spring-boot-starter/pom.xml b/spring-boot-starters/wx-java-miniapp-spring-boot-starter/pom.xml
index 743650b256..6149c253e7 100644
--- a/spring-boot-starters/wx-java-miniapp-spring-boot-starter/pom.xml
+++ b/spring-boot-starters/wx-java-miniapp-spring-boot-starter/pom.xml
@@ -1,11 +1,10 @@
-
wx-java-spring-boot-starters
com.github.binarywang
- 4.1.9.B
+ 4.5.7.B
4.0.0
@@ -32,7 +31,16 @@
org.springframework.data
spring-data-redis
- ${spring.boot.version}
+ provided
+
+
+ org.jodd
+ jodd-http
+ provided
+
+
+ com.squareup.okhttp3
+ okhttp
provided
diff --git a/spring-boot-starters/wx-java-miniapp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/miniapp/config/WxMaAutoConfiguration.java b/spring-boot-starters/wx-java-miniapp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/miniapp/config/WxMaAutoConfiguration.java
index fbfae6dfe0..67a7efaecf 100644
--- a/spring-boot-starters/wx-java-miniapp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/miniapp/config/WxMaAutoConfiguration.java
+++ b/spring-boot-starters/wx-java-miniapp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/miniapp/config/WxMaAutoConfiguration.java
@@ -9,7 +9,7 @@
* 自动配置.
*
* @author Binary Wang
- * @date 2019-08-10
+ * created on 2019-08-10
*/
@Configuration
@EnableConfigurationProperties(WxMaProperties.class)
diff --git a/spring-boot-starters/wx-java-miniapp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/miniapp/enums/HttpClientType.java b/spring-boot-starters/wx-java-miniapp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/miniapp/enums/HttpClientType.java
index 52a53debdc..b3e4b464fe 100644
--- a/spring-boot-starters/wx-java-miniapp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/miniapp/enums/HttpClientType.java
+++ b/spring-boot-starters/wx-java-miniapp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/miniapp/enums/HttpClientType.java
@@ -4,7 +4,7 @@
* httpclient类型.
*
* @author Binary Wang
- * @date 2020-05-25
+ * created on 2020-05-25
*/
public enum HttpClientType {
/**
diff --git a/spring-boot-starters/wx-java-miniapp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/miniapp/enums/StorageType.java b/spring-boot-starters/wx-java-miniapp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/miniapp/enums/StorageType.java
index 9328980bb2..31c6e4b602 100644
--- a/spring-boot-starters/wx-java-miniapp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/miniapp/enums/StorageType.java
+++ b/spring-boot-starters/wx-java-miniapp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/miniapp/enums/StorageType.java
@@ -4,7 +4,7 @@
* storage类型.
*
* @author Binary Wang
- * @date 2020-05-25
+ * created on 2020-05-25
*/
public enum StorageType {
/**
@@ -15,6 +15,10 @@ public enum StorageType {
* redis(JedisClient).
*/
Jedis,
+ /**
+ * redis(Redisson).
+ */
+ Redisson,
/**
* redis(RedisTemplate).
*/
diff --git a/spring-boot-starters/wx-java-miniapp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/miniapp/properties/RedisProperties.java b/spring-boot-starters/wx-java-miniapp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/miniapp/properties/RedisProperties.java
index 9cfaf80e8d..75e3740a19 100644
--- a/spring-boot-starters/wx-java-miniapp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/miniapp/properties/RedisProperties.java
+++ b/spring-boot-starters/wx-java-miniapp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/miniapp/properties/RedisProperties.java
@@ -6,7 +6,7 @@
* redis 配置.
*
* @author Binary Wang
- * @date 2020-08-30
+ * created on 2020-08-30
*/
@Data
public class RedisProperties {
diff --git a/spring-boot-starters/wx-java-miniapp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/miniapp/properties/WxMaProperties.java b/spring-boot-starters/wx-java-miniapp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/miniapp/properties/WxMaProperties.java
index 280330e928..b7ccb45374 100644
--- a/spring-boot-starters/wx-java-miniapp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/miniapp/properties/WxMaProperties.java
+++ b/spring-boot-starters/wx-java-miniapp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/miniapp/properties/WxMaProperties.java
@@ -12,7 +12,7 @@
* 属性配置类.
*
* @author Binary Wang
- * @date 2019-08-10
+ * created on 2019-08-10
*/
@Data
@ConfigurationProperties(prefix = PREFIX)
diff --git a/spring-boot-starters/wx-java-miniapp-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-boot-starters/wx-java-miniapp-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000000..6644fa9701
--- /dev/null
+++ b/spring-boot-starters/wx-java-miniapp-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+com.binarywang.spring.starter.wxjava.miniapp.config.WxMaAutoConfiguration
diff --git a/spring-boot-starters/wx-java-mp-spring-boot-starter/pom.xml b/spring-boot-starters/wx-java-mp-spring-boot-starter/pom.xml
index e62e70040c..c24a097c14 100644
--- a/spring-boot-starters/wx-java-mp-spring-boot-starter/pom.xml
+++ b/spring-boot-starters/wx-java-mp-spring-boot-starter/pom.xml
@@ -5,7 +5,7 @@
wx-java-spring-boot-starters
com.github.binarywang
- 4.1.9.B
+ 4.5.7.B
4.0.0
@@ -27,7 +27,6 @@
org.springframework.data
spring-data-redis
- ${spring.boot.version}
provided
diff --git a/spring-boot-starters/wx-java-mp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/config/WxMpStorageAutoConfiguration.java b/spring-boot-starters/wx-java-mp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/config/WxMpStorageAutoConfiguration.java
index 145c663efe..912b902624 100644
--- a/spring-boot-starters/wx-java-mp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/config/WxMpStorageAutoConfiguration.java
+++ b/spring-boot-starters/wx-java-mp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/config/WxMpStorageAutoConfiguration.java
@@ -14,23 +14,23 @@
import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;
import me.chanjar.weixin.mp.config.impl.WxMpRedisConfigImpl;
import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
+import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
-import redis.clients.jedis.JedisPoolAbstract;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;
+import redis.clients.jedis.util.Pool;
import java.util.Set;
/**
* 微信公众号存储策略自动配置.
*
- * @author someone
+ * @author Luo
*/
@Slf4j
@Configuration
@@ -40,12 +40,6 @@ public class WxMpStorageAutoConfiguration {
private final WxMpProperties wxMpProperties;
- @Value("${wx.mp.config-storage.redis.host:")
- private String redisHost;
-
- @Value("${wx.mp.configStorage.redis.host:")
- private String redisHost2;
-
@Bean
@ConditionalOnMissingBean(WxMpConfigStorage.class)
public WxMpConfigStorage wxMpConfigStorage() {
@@ -80,15 +74,16 @@ private WxMpConfigStorage defaultConfigStorage() {
}
private WxMpConfigStorage jedisConfigStorage() {
- JedisPoolAbstract jedisPool;
- if (StringUtils.isNotEmpty(redisHost) || StringUtils.isNotEmpty(redisHost2)) {
+ Pool jedisPool;
+ if (wxMpProperties.getConfigStorage() != null && wxMpProperties.getConfigStorage().getRedis() != null
+ && StringUtils.isNotEmpty(wxMpProperties.getConfigStorage().getRedis().getHost())) {
jedisPool = getJedisPool();
} else {
jedisPool = applicationContext.getBean(JedisPool.class);
}
WxRedisOps redisOps = new JedisWxRedisOps(jedisPool);
WxMpRedisConfigImpl wxMpRedisConfig = new WxMpRedisConfigImpl(redisOps,
- wxMpProperties.getConfigStorage().getKeyPrefix());
+ wxMpProperties.getConfigStorage().getKeyPrefix());
setWxMpInfo(wxMpRedisConfig);
return wxMpRedisConfig;
}
@@ -114,7 +109,7 @@ private WxMpConfigStorage redisTemplateConfigStorage() {
WxRedisOps redisOps = new RedisTemplateWxRedisOps(redisTemplate);
WxMpRedisConfigImpl wxMpRedisConfig = new WxMpRedisConfigImpl(redisOps,
- wxMpProperties.getConfigStorage().getKeyPrefix());
+ wxMpProperties.getConfigStorage().getKeyPrefix());
setWxMpInfo(wxMpRedisConfig);
return wxMpRedisConfig;
@@ -136,7 +131,7 @@ private void setWxMpInfo(WxMpDefaultConfigImpl config) {
}
}
- private JedisPoolAbstract getJedisPool() {
+ private Pool getJedisPool() {
RedisProperties redis = wxMpProperties.getConfigStorage().getRedis();
JedisPoolConfig config = new JedisPoolConfig();
@@ -160,6 +155,6 @@ private JedisPoolAbstract getJedisPool() {
}
return new JedisPool(config, redis.getHost(), redis.getPort(), redis.getTimeout(), redis.getPassword(),
- redis.getDatabase());
+ redis.getDatabase());
}
}
diff --git a/spring-boot-starters/wx-java-mp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/enums/HttpClientType.java b/spring-boot-starters/wx-java-mp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/enums/HttpClientType.java
index 1fa235e4af..f67ef97c2e 100644
--- a/spring-boot-starters/wx-java-mp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/enums/HttpClientType.java
+++ b/spring-boot-starters/wx-java-mp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/enums/HttpClientType.java
@@ -4,7 +4,7 @@
* httpclient类型.
*
* @author Binary Wang
- * @date 2020-08-30
+ * created on 2020-08-30
*/
public enum HttpClientType {
/**
diff --git a/spring-boot-starters/wx-java-mp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/enums/StorageType.java b/spring-boot-starters/wx-java-mp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/enums/StorageType.java
index 7dcb5a1157..05ed6ce393 100644
--- a/spring-boot-starters/wx-java-mp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/enums/StorageType.java
+++ b/spring-boot-starters/wx-java-mp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/enums/StorageType.java
@@ -4,7 +4,7 @@
* storage类型.
*
* @author Binary Wang
- * @date 2020-08-30
+ * created on 2020-08-30
*/
public enum StorageType {
/**
@@ -15,6 +15,10 @@ public enum StorageType {
* redis(JedisClient).
*/
Jedis,
+ /**
+ * redis(Redisson).
+ */
+ Redisson,
/**
* redis(RedisTemplate).
*/
diff --git a/spring-boot-starters/wx-java-mp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/properties/RedisProperties.java b/spring-boot-starters/wx-java-mp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/properties/RedisProperties.java
index 59f82558d7..573c87630f 100644
--- a/spring-boot-starters/wx-java-mp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/properties/RedisProperties.java
+++ b/spring-boot-starters/wx-java-mp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/properties/RedisProperties.java
@@ -8,7 +8,7 @@
* redis 配置属性.
*
* @author Binary Wang
- * @date 2020-08-30
+ * created on 2020-08-30
*/
@Data
public class RedisProperties implements Serializable {
diff --git a/spring-boot-starters/wx-java-mp-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-boot-starters/wx-java-mp-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000000..cdffb05c9e
--- /dev/null
+++ b/spring-boot-starters/wx-java-mp-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+com.binarywang.spring.starter.wxjava.mp.config.WxMpAutoConfiguration
diff --git a/spring-boot-starters/wx-java-open-spring-boot-starter/pom.xml b/spring-boot-starters/wx-java-open-spring-boot-starter/pom.xml
index 9545eb445f..d537af929b 100644
--- a/spring-boot-starters/wx-java-open-spring-boot-starter/pom.xml
+++ b/spring-boot-starters/wx-java-open-spring-boot-starter/pom.xml
@@ -5,7 +5,7 @@
wx-java-spring-boot-starters
com.github.binarywang
- 4.1.9.B
+ 4.5.7.B
4.0.0
@@ -22,18 +22,14 @@
redis.clients
jedis
- provided
org.redisson
redisson
- provided
org.springframework.data
spring-data-redis
- ${spring.boot.version}
- provided
diff --git a/spring-boot-starters/wx-java-open-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/config/storage/AbstractWxOpenConfigStorageConfiguration.java b/spring-boot-starters/wx-java-open-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/config/storage/AbstractWxOpenConfigStorageConfiguration.java
index 0f77633e4d..ee0443c9ae 100644
--- a/spring-boot-starters/wx-java-open-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/config/storage/AbstractWxOpenConfigStorageConfiguration.java
+++ b/spring-boot-starters/wx-java-open-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/config/storage/AbstractWxOpenConfigStorageConfiguration.java
@@ -9,19 +9,20 @@
public abstract class AbstractWxOpenConfigStorageConfiguration {
protected WxOpenInMemoryConfigStorage config(WxOpenInMemoryConfigStorage config, WxOpenProperties properties) {
- WxOpenProperties.ConfigStorage configStorageProperties = properties.getConfigStorage();
+ WxOpenProperties.ConfigStorage storage = properties.getConfigStorage();
config.setWxOpenInfo(properties.getAppId(), properties.getSecret(), properties.getToken(), properties.getAesKey());
- config.setHttpProxyHost(configStorageProperties.getHttpProxyHost());
- config.setHttpProxyUsername(configStorageProperties.getHttpProxyUsername());
- config.setHttpProxyPassword(configStorageProperties.getHttpProxyPassword());
- if (configStorageProperties.getHttpProxyPort() != null) {
- config.setHttpProxyPort(configStorageProperties.getHttpProxyPort());
+ config.setHttpProxyHost(storage.getHttpProxyHost());
+ config.setHttpProxyUsername(storage.getHttpProxyUsername());
+ config.setHttpProxyPassword(storage.getHttpProxyPassword());
+ Integer httpProxyPort = storage.getHttpProxyPort();
+ if (httpProxyPort != null) {
+ config.setHttpProxyPort(httpProxyPort);
}
- int maxRetryTimes = configStorageProperties.getMaxRetryTimes();
- if (configStorageProperties.getMaxRetryTimes() < 0) {
+ int maxRetryTimes = storage.getMaxRetryTimes();
+ if (maxRetryTimes < 0) {
maxRetryTimes = 0;
}
- int retrySleepMillis = configStorageProperties.getRetrySleepMillis();
+ int retrySleepMillis = storage.getRetrySleepMillis();
if (retrySleepMillis < 0) {
retrySleepMillis = 1000;
}
diff --git a/spring-boot-starters/wx-java-open-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/config/storage/WxOpenInJedisConfigStorageConfiguration.java b/spring-boot-starters/wx-java-open-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/config/storage/WxOpenInJedisConfigStorageConfiguration.java
index 353b670e6a..73a0183d72 100644
--- a/spring-boot-starters/wx-java-open-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/config/storage/WxOpenInJedisConfigStorageConfiguration.java
+++ b/spring-boot-starters/wx-java-open-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/config/storage/WxOpenInJedisConfigStorageConfiguration.java
@@ -1,10 +1,8 @@
package com.binarywang.spring.starter.wxjava.open.config.storage;
-import com.binarywang.spring.starter.wxjava.open.properties.RedisProperties;
import com.binarywang.spring.starter.wxjava.open.properties.WxOpenProperties;
+import com.binarywang.spring.starter.wxjava.open.properties.WxOpenRedisProperties;
import lombok.RequiredArgsConstructor;
-import me.chanjar.weixin.common.redis.JedisWxRedisOps;
-import me.chanjar.weixin.common.redis.WxRedisOps;
import me.chanjar.weixin.open.api.WxOpenConfigStorage;
import me.chanjar.weixin.open.api.impl.WxOpenInMemoryConfigStorage;
import me.chanjar.weixin.open.api.impl.WxOpenInRedisConfigStorage;
@@ -39,20 +37,19 @@ public WxOpenConfigStorage wxOpenConfigStorage() {
}
private WxOpenInRedisConfigStorage getWxOpenInRedisConfigStorage() {
- RedisProperties redisProperties = properties.getConfigStorage().getRedis();
+ WxOpenRedisProperties wxOpenRedisProperties = properties.getConfigStorage().getRedis();
JedisPool jedisPool;
- if (redisProperties != null && StringUtils.isNotEmpty(redisProperties.getHost())) {
+ if (wxOpenRedisProperties != null && StringUtils.isNotEmpty(wxOpenRedisProperties.getHost())) {
jedisPool = getJedisPool();
} else {
jedisPool = applicationContext.getBean(JedisPool.class);
}
- WxRedisOps redisOps = new JedisWxRedisOps(jedisPool);
- return new WxOpenInRedisConfigStorage(redisOps, properties.getConfigStorage().getKeyPrefix());
+ return new WxOpenInRedisConfigStorage(jedisPool, properties.getConfigStorage().getKeyPrefix());
}
private JedisPool getJedisPool() {
WxOpenProperties.ConfigStorage storage = properties.getConfigStorage();
- RedisProperties redis = storage.getRedis();
+ WxOpenRedisProperties redis = storage.getRedis();
JedisPoolConfig config = new JedisPoolConfig();
if (redis.getMaxActive() != null) {
diff --git a/spring-boot-starters/wx-java-open-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/config/storage/WxOpenInRedissonConfigStorageConfiguration.java b/spring-boot-starters/wx-java-open-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/config/storage/WxOpenInRedissonConfigStorageConfiguration.java
index 85aa1d20e0..ea1dce3670 100644
--- a/spring-boot-starters/wx-java-open-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/config/storage/WxOpenInRedissonConfigStorageConfiguration.java
+++ b/spring-boot-starters/wx-java-open-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/config/storage/WxOpenInRedissonConfigStorageConfiguration.java
@@ -1,13 +1,11 @@
package com.binarywang.spring.starter.wxjava.open.config.storage;
-import com.binarywang.spring.starter.wxjava.open.properties.RedisProperties;
import com.binarywang.spring.starter.wxjava.open.properties.WxOpenProperties;
+import com.binarywang.spring.starter.wxjava.open.properties.WxOpenRedisProperties;
import lombok.RequiredArgsConstructor;
-import me.chanjar.weixin.common.redis.RedissonWxRedisOps;
-import me.chanjar.weixin.common.redis.WxRedisOps;
import me.chanjar.weixin.open.api.WxOpenConfigStorage;
import me.chanjar.weixin.open.api.impl.WxOpenInMemoryConfigStorage;
-import me.chanjar.weixin.open.api.impl.WxOpenInRedisConfigStorage;
+import me.chanjar.weixin.open.api.impl.WxOpenInRedissonConfigStorage;
import org.apache.commons.lang3.StringUtils;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
@@ -40,21 +38,20 @@ public WxOpenConfigStorage wxOpenConfigStorage() {
return this.config(config, properties);
}
- private WxOpenInRedisConfigStorage getWxOpenInRedissonConfigStorage() {
- RedisProperties redisProperties = properties.getConfigStorage().getRedis();
+ private WxOpenInRedissonConfigStorage getWxOpenInRedissonConfigStorage() {
+ WxOpenRedisProperties wxOpenRedisProperties = properties.getConfigStorage().getRedis();
RedissonClient redissonClient;
- if (redisProperties != null && StringUtils.isNotEmpty(redisProperties.getHost())) {
+ if (wxOpenRedisProperties != null && StringUtils.isNotEmpty(wxOpenRedisProperties.getHost())) {
redissonClient = getRedissonClient();
} else {
redissonClient = applicationContext.getBean(RedissonClient.class);
}
- WxRedisOps redisOps = new RedissonWxRedisOps(redissonClient);
- return new WxOpenInRedisConfigStorage(redisOps, properties.getConfigStorage().getKeyPrefix());
+ return new WxOpenInRedissonConfigStorage(redissonClient, properties.getConfigStorage().getKeyPrefix());
}
private RedissonClient getRedissonClient() {
WxOpenProperties.ConfigStorage storage = properties.getConfigStorage();
- RedisProperties redis = storage.getRedis();
+ WxOpenRedisProperties redis = storage.getRedis();
Config config = new Config();
config.useSingleServer()
diff --git a/spring-boot-starters/wx-java-open-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/properties/WxOpenProperties.java b/spring-boot-starters/wx-java-open-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/properties/WxOpenProperties.java
index adb35c2fa3..641c57b005 100644
--- a/spring-boot-starters/wx-java-open-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/properties/WxOpenProperties.java
+++ b/spring-boot-starters/wx-java-open-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/properties/WxOpenProperties.java
@@ -58,13 +58,13 @@ public static class ConfigStorage implements Serializable {
/**
* 指定key前缀.
*/
- private String keyPrefix = "wx";
+ private String keyPrefix = "wx:open";
/**
* redis连接配置.
*/
@NestedConfigurationProperty
- private RedisProperties redis = new RedisProperties();
+ private WxOpenRedisProperties redis = new WxOpenRedisProperties();
/**
* http客户端类型.
diff --git a/spring-boot-starters/wx-java-open-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/properties/RedisProperties.java b/spring-boot-starters/wx-java-open-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/properties/WxOpenRedisProperties.java
similarity index 91%
rename from spring-boot-starters/wx-java-open-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/properties/RedisProperties.java
rename to spring-boot-starters/wx-java-open-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/properties/WxOpenRedisProperties.java
index a03d3a47f6..0aafc73da6 100644
--- a/spring-boot-starters/wx-java-open-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/properties/RedisProperties.java
+++ b/spring-boot-starters/wx-java-open-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/properties/WxOpenRedisProperties.java
@@ -10,7 +10,7 @@
* @author someone
*/
@Data
-public class RedisProperties implements Serializable {
+public class WxOpenRedisProperties implements Serializable {
private static final long serialVersionUID = -5924815351660074401L;
/**
diff --git a/spring-boot-starters/wx-java-open-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-boot-starters/wx-java-open-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000000..ce327ba462
--- /dev/null
+++ b/spring-boot-starters/wx-java-open-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+com.binarywang.spring.starter.wxjava.open.config.WxOpenAutoConfiguration
diff --git a/spring-boot-starters/wx-java-pay-spring-boot-starter/README.md b/spring-boot-starters/wx-java-pay-spring-boot-starter/README.md
index a4d91fade0..d87a38fb9c 100644
--- a/spring-boot-starters/wx-java-pay-spring-boot-starter/README.md
+++ b/spring-boot-starters/wx-java-pay-spring-boot-starter/README.md
@@ -8,20 +8,36 @@
```
2. 添加配置(application.yml)
+###### 1)V2版本
```yml
wx:
pay:
appId:
mchId:
mchKey:
- subAppId:
- subMchId:
keyPath:
```
-
-
-
-
-
-
-
+###### 2)V3版本
+```yml
+wx:
+ pay:
+ appId: xxxxxxxxxxx
+ mchId: 15xxxxxxxxx #商户id
+ apiV3Key: Dc1DBwSc094jACxxxxxxxxxxxxxxx #V3密钥
+ certSerialNo: 62C6CEAA360BCxxxxxxxxxxxxxxx
+ privateKeyPath: classpath:cert/apiclient_key.pem #apiclient_key.pem证书文件的绝对路径或者以classpath:开头的类路径
+ privateCertPath: classpath:cert/apiclient_cert.pem #apiclient_cert.pem证书文件的绝对路径或者以classpath:开头的类路径
+```
+###### 3)V3服务商版本
+```yml
+wx:
+ pay: #微信服务商支付
+ configs:
+ - appId: wxe97b2x9c2b3d #spAppId
+ mchId: 16486610 #服务商商户
+ subAppId: wx118cexxe3c07679 #子appId
+ subMchId: 16496705 #子商户
+ apiV3Key: Dc1DBwSc094jAKDGR5aqqb7PTHr #apiV3密钥
+ privateKeyPath: classpath:cert/apiclient_key.pem #服务商证书文件,apiclient_key.pem证书文件的绝对路径或者以classpath:开头的类路径(可以配置绝对路径)
+ privateCertPath: classpath:cert/apiclient_cert.pem #apiclient_cert.pem证书文件的绝对路径或者以classpath:开头的类路径
+```
diff --git a/spring-boot-starters/wx-java-pay-spring-boot-starter/pom.xml b/spring-boot-starters/wx-java-pay-spring-boot-starter/pom.xml
index 074e202146..5c3fc0df26 100644
--- a/spring-boot-starters/wx-java-pay-spring-boot-starter/pom.xml
+++ b/spring-boot-starters/wx-java-pay-spring-boot-starter/pom.xml
@@ -5,7 +5,7 @@
wx-java-spring-boot-starters
com.github.binarywang
- 4.1.9.B
+ 4.5.7.B
4.0.0
diff --git a/spring-boot-starters/wx-java-pay-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-boot-starters/wx-java-pay-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000000..28cbbace5f
--- /dev/null
+++ b/spring-boot-starters/wx-java-pay-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+com.binarywang.spring.starter.wxjava.pay.config.WxPayAutoConfiguration
diff --git a/spring-boot-starters/wx-java-qidian-spring-boot-starter/pom.xml b/spring-boot-starters/wx-java-qidian-spring-boot-starter/pom.xml
index fe8b29ecaa..b1da6f2505 100644
--- a/spring-boot-starters/wx-java-qidian-spring-boot-starter/pom.xml
+++ b/spring-boot-starters/wx-java-qidian-spring-boot-starter/pom.xml
@@ -3,7 +3,7 @@
wx-java-spring-boot-starters
com.github.binarywang
- 4.1.9.B
+ 4.5.7.B
4.0.0
@@ -25,7 +25,6 @@
org.springframework.data
spring-data-redis
- ${spring.boot.version}
provided
diff --git a/spring-boot-starters/wx-java-qidian-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/qidian/config/WxQidianStorageAutoConfiguration.java b/spring-boot-starters/wx-java-qidian-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/qidian/config/WxQidianStorageAutoConfiguration.java
index 84163b005a..80809fefce 100644
--- a/spring-boot-starters/wx-java-qidian-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/qidian/config/WxQidianStorageAutoConfiguration.java
+++ b/spring-boot-starters/wx-java-qidian-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/qidian/config/WxQidianStorageAutoConfiguration.java
@@ -21,9 +21,9 @@
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
import redis.clients.jedis.JedisPool;
-import redis.clients.jedis.JedisPoolAbstract;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;
+import redis.clients.jedis.util.Pool;
import java.util.Set;
@@ -80,7 +80,7 @@ private WxQidianConfigStorage defaultConfigStorage() {
}
private WxQidianConfigStorage jedisConfigStorage() {
- JedisPoolAbstract jedisPool;
+ Pool jedisPool;
if (StringUtils.isNotEmpty(redisHost) || StringUtils.isNotEmpty(redisHost2)) {
jedisPool = getJedisPool();
} else {
@@ -136,7 +136,7 @@ private void setWxMpInfo(WxQidianDefaultConfigImpl config) {
}
}
- private JedisPoolAbstract getJedisPool() {
+ private Pool getJedisPool() {
WxQidianProperties.ConfigStorage storage = wxQidianProperties.getConfigStorage();
RedisProperties redis = storage.getRedis();
@@ -156,8 +156,9 @@ private JedisPoolAbstract getJedisPool() {
config.setTestOnBorrow(true);
config.setTestWhileIdle(true);
if (StringUtils.isNotEmpty(redis.getSentinelIps())) {
+
Set sentinels = Sets.newHashSet(redis.getSentinelIps().split(","));
- return new JedisSentinelPool(redis.getSentinelName(), sentinels);
+ return new JedisSentinelPool(redis.getSentinelName(), sentinels,config);
}
return new JedisPool(config, redis.getHost(), redis.getPort(), redis.getTimeout(), redis.getPassword(),
diff --git a/spring-boot-starters/wx-java-qidian-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/qidian/enums/HttpClientType.java b/spring-boot-starters/wx-java-qidian-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/qidian/enums/HttpClientType.java
index 9418a8bec5..1a927211cc 100644
--- a/spring-boot-starters/wx-java-qidian-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/qidian/enums/HttpClientType.java
+++ b/spring-boot-starters/wx-java-qidian-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/qidian/enums/HttpClientType.java
@@ -4,7 +4,7 @@
* httpclient类型.
*
* @author Binary Wang
- * @date 2020-08-30
+ * created on 2020-08-30
*/
public enum HttpClientType {
/**
diff --git a/spring-boot-starters/wx-java-qidian-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/qidian/enums/StorageType.java b/spring-boot-starters/wx-java-qidian-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/qidian/enums/StorageType.java
index 0a7a6b85df..f4e26bc156 100644
--- a/spring-boot-starters/wx-java-qidian-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/qidian/enums/StorageType.java
+++ b/spring-boot-starters/wx-java-qidian-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/qidian/enums/StorageType.java
@@ -4,7 +4,7 @@
* storage类型.
*
* @author Binary Wang
- * @date 2020-08-30
+ * created on 2020-08-30
*/
public enum StorageType {
/**
@@ -15,6 +15,10 @@ public enum StorageType {
* redis(JedisClient).
*/
Jedis,
+ /**
+ * redis(Redisson).
+ */
+ Redisson,
/**
* redis(RedisTemplate).
*/
diff --git a/spring-boot-starters/wx-java-qidian-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/qidian/properties/RedisProperties.java b/spring-boot-starters/wx-java-qidian-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/qidian/properties/RedisProperties.java
index b055b63fe9..abfad572e7 100644
--- a/spring-boot-starters/wx-java-qidian-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/qidian/properties/RedisProperties.java
+++ b/spring-boot-starters/wx-java-qidian-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/qidian/properties/RedisProperties.java
@@ -8,7 +8,7 @@
* redis 配置属性.
*
* @author Binary Wang
- * @date 2020-08-30
+ * created on 2020-08-30
*/
@Data
public class RedisProperties implements Serializable {
diff --git a/spring-boot-starters/wx-java-qidian-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-boot-starters/wx-java-qidian-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000000..6e7e511448
--- /dev/null
+++ b/spring-boot-starters/wx-java-qidian-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+com.binarywang.spring.starter.wxjava.qidian.config.WxQidianAutoConfiguration
diff --git a/weixin-graal/pom.xml b/weixin-graal/pom.xml
index 896a812b5a..66a177f87b 100644
--- a/weixin-graal/pom.xml
+++ b/weixin-graal/pom.xml
@@ -6,7 +6,7 @@
com.github.binarywang
wx-java
- 4.1.9.B
+ 4.5.7.B
weixin-graal
diff --git a/weixin-java-channel/pom.xml b/weixin-java-channel/pom.xml
new file mode 100644
index 0000000000..e797a03da1
--- /dev/null
+++ b/weixin-java-channel/pom.xml
@@ -0,0 +1,163 @@
+
+
+ 4.0.0
+
+ com.github.binarywang
+ wx-java
+ 4.5.7.B
+
+
+ weixin-java-channel
+ WxJava - Channel Java SDK
+ 微信视频号 Java SDK
+
+
+ 2.15.0
+
+
+
+
+ com.github.binarywang
+ weixin-java-common
+ ${project.version}
+
+
+
+ org.jodd
+ jodd-http
+ provided
+
+
+
+ com.fasterxml.jackson.core
+ jackson-core
+ ${jackson.version}
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+ ${jackson.version}
+
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-xml
+ ${jackson.version}
+ true
+
+
+
+ org.bouncycastle
+ bcpkix-jdk15on
+
+
+ org.projectlombok
+ lombok
+
+
+ org.redisson
+ redisson
+
+
+
+ com.squareup.okhttp3
+ okhttp
+ provided
+
+
+
+ org.testng
+ testng
+ test
+
+
+ ch.qos.logback
+ logback-classic
+ test
+
+
+ com.google.inject
+ guice
+ test
+
+
+ org.eclipse.jetty
+ jetty-server
+ test
+
+
+ org.eclipse.jetty
+ jetty-servlet
+ test
+
+
+ org.assertj
+ assertj-guava
+ test
+
+
+ redis.clients
+ jedis
+
+
+
+ com.github.jedis-lock
+ jedis-lock
+ true
+
+
+ org.mockito
+ mockito-core
+ 3.3.3
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ src/test/resources/testng.xml
+
+
+
+
+
+
+
+
+ native-image
+
+ false
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.5.1
+
+
+ com.github.binarywang.wx.graal.GraalProcessor,lombok.launch.AnnotationProcessorHider$AnnotationProcessor,lombok.launch.AnnotationProcessorHider$ClaimingProcessor
+
+
+
+ com.github.binarywang
+ weixin-graal
+ ${project.version}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/BaseWxChannelMessageService.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/BaseWxChannelMessageService.java
new file mode 100644
index 0000000000..211024d33a
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/BaseWxChannelMessageService.java
@@ -0,0 +1,372 @@
+package me.chanjar.weixin.channel.api;
+
+import java.util.Map;
+import me.chanjar.weixin.channel.bean.message.after.AfterSaleMessage;
+import me.chanjar.weixin.channel.bean.message.after.ComplaintMessage;
+import me.chanjar.weixin.channel.bean.message.coupon.CouponActionMessage;
+import me.chanjar.weixin.channel.bean.message.coupon.CouponReceiveMessage;
+import me.chanjar.weixin.channel.bean.message.coupon.UserCouponExpireMessage;
+import me.chanjar.weixin.channel.bean.message.fund.AccountNotifyMessage;
+import me.chanjar.weixin.channel.bean.message.fund.QrNotifyMessage;
+import me.chanjar.weixin.channel.bean.message.fund.WithdrawNotifyMessage;
+import me.chanjar.weixin.channel.bean.message.order.OrderCancelMessage;
+import me.chanjar.weixin.channel.bean.message.order.OrderConfirmMessage;
+import me.chanjar.weixin.channel.bean.message.order.OrderDeliveryMessage;
+import me.chanjar.weixin.channel.bean.message.order.OrderExtMessage;
+import me.chanjar.weixin.channel.bean.message.order.OrderIdMessage;
+import me.chanjar.weixin.channel.bean.message.order.OrderPayMessage;
+import me.chanjar.weixin.channel.bean.message.order.OrderSettleMessage;
+import me.chanjar.weixin.channel.bean.message.order.OrderStatusMessage;
+import me.chanjar.weixin.channel.bean.message.product.BrandMessage;
+import me.chanjar.weixin.channel.bean.message.product.CategoryAuditMessage;
+import me.chanjar.weixin.channel.bean.message.product.SpuAuditMessage;
+import me.chanjar.weixin.channel.bean.message.supplier.SupplierItemMessage;
+import me.chanjar.weixin.channel.message.WxChannelMessage;
+import me.chanjar.weixin.channel.message.WxChannelMessageRouterRule;
+import me.chanjar.weixin.common.session.WxSessionManager;
+
+/**
+ * @author Zeyes
+ */
+public interface BaseWxChannelMessageService {
+
+ /**
+ * 路由微信消息
+ *
+ * @param message 消息
+ * @param content 消息原始内容
+ * @param appId appId
+ * @param service 服务实例
+ * @return Object
+ */
+ Object route(final WxChannelMessage message, final String content, final String appId,
+ final WxChannelService service);
+
+ /**
+ * 添加一条规则进入路由器
+ *
+ * @param rule 规则
+ */
+ void addRule(WxChannelMessageRouterRule extends WxChannelMessage> rule);
+
+ /**
+ * 订单下单
+ *
+ * @param message 消息
+ * @param appId appId
+ * @param context 上下文
+ * @param sessionManager session管理器
+ */
+ void orderNew(final OrderIdMessage message, final String content, final String appId,
+ final Map context, final WxSessionManager sessionManager);
+
+ /**
+ * 订单取消
+ *
+ * @param message 消息
+ * @param appId appId
+ * @param context 上下文
+ * @param sessionManager session管理器
+ */
+ void orderCancel(OrderCancelMessage message, final String content, final String appId,
+ final Map context, final WxSessionManager sessionManager);
+
+ /**
+ * 订单支付成功
+ *
+ * @param message 消息
+ * @param appId appId
+ * @param context 上下文
+ * @param sessionManager session管理器
+ */
+ void orderPay(OrderPayMessage message, final String content, final String appId, final Map context,
+ final WxSessionManager sessionManager);
+
+ /**
+ * 订单发货
+ *
+ * @param message 消息
+ * @param appId appId
+ * @param context 上下文
+ * @param sessionManager session管理器
+ */
+ void orderDelivery(OrderDeliveryMessage message, final String content, final String appId,
+ final Map context, final WxSessionManager sessionManager);
+
+ /**
+ * 订单确认收货
+ *
+ * @param message 消息
+ * @param appId appId
+ * @param context 上下文
+ * @param sessionManager session管理器
+ */
+ void orderConfirm(OrderConfirmMessage message, final String content, final String appId,
+ final Map context, final WxSessionManager sessionManager);
+
+ /**
+ * 订单结算成功
+ *
+ * @param message 消息
+ * @param appId appId
+ * @param context 上下文
+ * @param sessionManager session管理器
+ */
+ void orderSettle(OrderSettleMessage message, final String content, final String appId,
+ final Map context, final WxSessionManager sessionManager);
+
+ /**
+ * 订单其他信息更新
+ *
+ * @param message 消息
+ * @param appId appId
+ * @param context 上下文
+ * @param sessionManager session管理器
+ */
+ void orderExtInfoUpdate(OrderExtMessage message, final String content, final String appId,
+ final Map context, final WxSessionManager sessionManager);
+
+ /**
+ * 订单状态更新
+ *
+ * @param message 消息
+ * @param appId appId
+ * @param context 上下文
+ * @param sessionManager session管理器
+ */
+ void orderStatusUpdate(OrderStatusMessage message, final String content, final String appId,
+ final Map context, final WxSessionManager sessionManager);
+
+ /**
+ * 商品审核结果
+ *
+ * @param message 消息
+ * @param appId appId
+ * @param context 上下文
+ * @param sessionManager session管理器
+ */
+ void spuAudit(SpuAuditMessage message, final String content, final String appId, final Map context,
+ final WxSessionManager sessionManager);
+
+ /**
+ * 商品系统下架通知
+ *
+ * @param message 消息
+ * @param appId appId
+ * @param context 上下文
+ * @param sessionManager session管理器
+ */
+ void spuStatusUpdate(SpuAuditMessage message, final String content, final String appId,
+ final Map context, final WxSessionManager sessionManager);
+
+ /**
+ * 商品更新通知
+ *
+ * @param message 消息
+ * @param appId appId
+ * @param context 上下文
+ * @param sessionManager session管理器
+ */
+ void spuUpdate(SpuAuditMessage message, final String content, final String appId, final Map context,
+ final WxSessionManager sessionManager);
+
+ /**
+ * 类目审核结果
+ *
+ * @param message 消息
+ * @param appId appId
+ * @param context 上下文
+ * @param sessionManager session管理器
+ */
+ void categoryAudit(CategoryAuditMessage message, final String content, final String appId,
+ final Map context, final WxSessionManager sessionManager);
+
+ /**
+ * 品牌更新
+ *
+ * @param message 消息
+ * @param appId appId
+ * @param context 上下文
+ * @param sessionManager session管理器
+ */
+ void brandUpdate(BrandMessage message, final String content, final String appId, final Map context,
+ final WxSessionManager sessionManager);
+
+ /**
+ * 售后单状态更新
+ *
+ * @param message 消息
+ * @param appId appId
+ * @param context 上下文
+ * @param sessionManager session管理器
+ */
+ void afterSaleStatusUpdate(AfterSaleMessage message, final String content, final String appId,
+ final Map context, final WxSessionManager sessionManager);
+
+ /**
+ * 纠纷回调
+ *
+ * @param message 消息
+ * @param appId appId
+ * @param context 上下文
+ * @param sessionManager session管理器
+ */
+ void complaintNotify(ComplaintMessage message, final String content, final String appId,
+ final Map context, final WxSessionManager sessionManager);
+
+ /**
+ * 用户领券通知
+ *
+ * @param message 消息
+ * @param appId appId
+ * @param context 上下文
+ * @param sessionManager session管理器
+ */
+ void couponReceive(CouponReceiveMessage message, final String content, final String appId,
+ final Map context, final WxSessionManager sessionManager);
+
+ /**
+ * 创建优惠券通知
+ *
+ * @param message 消息
+ * @param appId appId
+ * @param context 上下文
+ * @param sessionManager session管理器
+ */
+ void couponCreate(CouponActionMessage message, final String content, final String appId,
+ final Map context, final WxSessionManager sessionManager);
+
+ /**
+ * 优惠券删除通知
+ *
+ * @param message 消息
+ * @param appId appId
+ * @param context 上下文
+ * @param sessionManager session管理器
+ */
+ void couponDelete(CouponActionMessage message, final String content, final String appId,
+ final Map context, final WxSessionManager sessionManager);
+
+ /**
+ * 优惠券过期通知
+ *
+ * @param message 消息
+ * @param appId appId
+ * @param context 上下文
+ * @param sessionManager session管理器
+ */
+ void couponExpire(CouponActionMessage message, final String content, final String appId,
+ final Map context, final WxSessionManager sessionManager);
+
+ /**
+ * 更新优惠券信息通知
+ *
+ * @param message 消息
+ * @param appId appId
+ * @param context 上下文
+ * @param sessionManager session管理器
+ */
+ void couponUpdate(CouponActionMessage message, final String content, final String appId,
+ final Map context, final WxSessionManager sessionManager);
+
+ /**
+ * 优惠券作废通知
+ *
+ * @param message 消息
+ * @param appId appId
+ * @param context 上下文
+ * @param sessionManager session管理器
+ */
+ void couponInvalid(CouponActionMessage message, final String content, final String appId,
+ final Map context, final WxSessionManager sessionManager);
+
+ /**
+ * 用户优惠券过期通知
+ *
+ * @param message 消息
+ * @param appId appId
+ * @param context 上下文
+ * @param sessionManager session管理器
+ */
+ void userCouponExpire(UserCouponExpireMessage message, final String content, final String appId,
+ final Map context, final WxSessionManager sessionManager);
+
+ /**
+ * 用户优惠券使用通知
+ *
+ * @param message 消息
+ * @param appId appId
+ * @param context 上下文
+ * @param sessionManager session管理器
+ */
+ void userCouponUse(UserCouponExpireMessage message, final String content, final String appId,
+ final Map context, final WxSessionManager sessionManager);
+
+ /**
+ * 用户优惠券返还通知
+ *
+ * @param message 消息
+ * @param appId appId
+ * @param context 上下文
+ * @param sessionManager session管理器
+ */
+ void userCouponUnuse(UserCouponExpireMessage message, final String content, final String appId,
+ final Map context, final WxSessionManager sessionManager);
+
+ /**
+ * 结算账户变更回调
+ *
+ * @param message 消息
+ * @param appId appId
+ * @param context 上下文
+ * @param sessionManager session管理器
+ */
+ void accountNotify(AccountNotifyMessage message, final String content, final String appId,
+ final Map context, final WxSessionManager sessionManager);
+
+ /**
+ * 提现回调
+ *
+ * @param message 消息
+ * @param appId appId
+ * @param context 上下文
+ * @param sessionManager session管理器
+ */
+ void withdrawNotify(WithdrawNotifyMessage message, final String content, final String appId,
+ final Map context, final WxSessionManager sessionManager);
+
+ /**
+ * 提现二维码回调
+ *
+ * @param message 消息
+ * @param appId appId
+ * @param context 上下文
+ * @param sessionManager session管理器
+ */
+ void qrNotify(QrNotifyMessage message, final String content, final String appId, final Map context,
+ final WxSessionManager sessionManager);
+
+ /**
+ * 团长商品变更
+ *
+ * @param message 消息
+ * @param appId appId
+ * @param context 上下文
+ * @param sessionManager session管理器
+ */
+ void supplierItemUpdate(SupplierItemMessage message, final String content, final String appId,
+ final Map context, final WxSessionManager sessionManager);
+
+ /**
+ * 默认消息处理
+ *
+ * @param message 消息
+ * @param content 内容
+ * @param appId appId
+ * @param context 上下文
+ * @param sessionManager session管理器
+ * @return Object
+ */
+ Object defaultMessageHandler(WxChannelMessage message, final String content, final String appId,
+ final Map context, final WxSessionManager sessionManager);
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/BaseWxChannelService.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/BaseWxChannelService.java
new file mode 100644
index 0000000000..f745ff3e41
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/BaseWxChannelService.java
@@ -0,0 +1,136 @@
+package me.chanjar.weixin.channel.api;
+
+import me.chanjar.weixin.channel.config.WxChannelConfig;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.service.WxService;
+import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor;
+import me.chanjar.weixin.common.util.http.RequestExecutor;
+import me.chanjar.weixin.common.util.http.RequestHttp;
+
+/**
+ * The interface Wx Channel service
+ *
+ * @author Zeyes
+ */
+public interface BaseWxChannelService extends WxService {
+
+ /**
+ *
+ * 验证消息的确来自微信服务器.
+ * 详情请见: http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421135319&token=&lang=zh_CN
+ *
+ *
+ * @param timestamp the timestamp
+ * @param nonce the nonce
+ * @param signature the signature
+ * @return the boolean
+ */
+ boolean checkSignature(String timestamp, String nonce, String signature);
+
+ /**
+ * 获取access_token, 不强制刷新access_token.
+ *
+ * @return the access token
+ *
+ * @throws WxErrorException the wx error exception
+ * @see #getAccessToken(boolean) #getAccessToken(boolean)
+ */
+ String getAccessToken() throws WxErrorException;
+
+ /**
+ *
+ * 获取access_token,本方法线程安全.
+ * 且在多线程同时刷新时只刷新一次,避免超出2000次/日的调用次数上限
+ *
+ * 另:本service的所有方法都会在access_token过期是调用此方法
+ *
+ * 程序员在非必要情况下尽量不要主动调用此方法
+ *
+ * 详情请见: http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140183&token=&lang=zh_CN
+ *
+ *
+ * @param forceRefresh 强制刷新
+ * @return the access token
+ *
+ * @throws WxErrorException the wx error exception
+ */
+ String getAccessToken(boolean forceRefresh) throws WxErrorException;
+
+ /**
+ *
+ * Service没有实现某个API的时候,可以用这个,
+ * 比{@link #get}和{@link #post}方法更灵活,可以自己构造RequestExecutor用来处理不同的参数和不同的返回类型。
+ * 可以参考,{@link MediaUploadRequestExecutor}的实现方法
+ *
+ *
+ * @param .
+ * @param .
+ * @param executor 执行器
+ * @param uri 接口请求地址
+ * @param data 参数或请求数据
+ * @return . t
+ *
+ * @throws WxErrorException the wx error exception
+ */
+ T execute(RequestExecutor executor, String uri, E data) throws WxErrorException;
+
+ /**
+ * 执行器
+ *
+ * @param .
+ * @param .
+ * @param executor 执行器
+ * @param uri 接口请求地址
+ * @param data 参数或请求数据
+ * @return T
+ *
+ * @throws WxErrorException the wx error exception
+ */
+ T executeWithoutLog(RequestExecutor executor, String uri, E data) throws WxErrorException;
+
+ /**
+ *
+ * 设置当微信系统响应系统繁忙时,要等待多少 retrySleepMillis(ms) * 2^(重试次数 - 1) 再发起重试.
+ * 默认:1000ms
+ *
+ *
+ * @param retrySleepMillis 重试等待毫秒数
+ */
+ void setRetrySleepMillis(int retrySleepMillis);
+
+ /**
+ *
+ * 设置当微信系统响应系统繁忙时,最大重试次数.
+ * 默认:5次
+ *
+ *
+ * @param maxRetryTimes 最大重试次数
+ */
+ void setMaxRetryTimes(int maxRetryTimes);
+
+ /**
+ * WxChannelConfig对象
+ *
+ * @return WxMaConfig wx channel config
+ */
+ WxChannelConfig getConfig();
+
+ /**
+ * 注入 {@link WxChannelConfig} 的实现.
+ *
+ * @param config config
+ */
+ void setConfig(WxChannelConfig config);
+
+ /**
+ * 初始化http请求对象.
+ */
+ void initHttp();
+
+ /**
+ * 请求http请求相关信息.
+ *
+ * @return . request http
+ */
+ RequestHttp getRequestHttp();
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelAddressService.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelAddressService.java
new file mode 100644
index 0000000000..063dd53948
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelAddressService.java
@@ -0,0 +1,68 @@
+package me.chanjar.weixin.channel.api;
+
+
+import me.chanjar.weixin.channel.bean.address.AddressDetail;
+import me.chanjar.weixin.channel.bean.address.AddressIdResponse;
+import me.chanjar.weixin.channel.bean.address.AddressInfoResponse;
+import me.chanjar.weixin.channel.bean.address.AddressListResponse;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+import me.chanjar.weixin.common.error.WxErrorException;
+
+/**
+ * 视频号小店 地址管理服务
+ *
+ * @author Zeyes
+ */
+public interface WxChannelAddressService {
+
+ /**
+ * 获取地址列表
+ *
+ * @param offset 起始位置
+ * @param limit 拉取个数
+ * @return 列表
+ *
+ * @throws WxErrorException 异常
+ */
+ AddressListResponse listAddress(Integer offset, Integer limit) throws WxErrorException;
+
+ /**
+ * 获取地址详情
+ *
+ * @param addressId 地址id
+ * @return 地址详情
+ *
+ * @throws WxErrorException 异常
+ */
+ AddressInfoResponse getAddress(String addressId) throws WxErrorException;
+
+ /**
+ * 添加地址
+ *
+ * @param addressDetail 地址
+ * @return AddressIdResponse
+ *
+ * @throws WxErrorException 异常
+ */
+ AddressIdResponse addAddress(AddressDetail addressDetail) throws WxErrorException;
+
+ /**
+ * 更新地址
+ *
+ * @param addressDetail 地址
+ * @return BaseResponse
+ *
+ * @throws WxErrorException 异常
+ */
+ WxChannelBaseResponse updateAddress(AddressDetail addressDetail) throws WxErrorException;
+
+ /**
+ * 删除地址
+ *
+ * @param addressId 地址id
+ * @return BaseResponse
+ *
+ * @throws WxErrorException 异常
+ */
+ WxChannelBaseResponse deleteAddress(String addressId) throws WxErrorException;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelAfterSaleService.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelAfterSaleService.java
new file mode 100644
index 0000000000..ac1e61729b
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelAfterSaleService.java
@@ -0,0 +1,111 @@
+package me.chanjar.weixin.channel.api;
+
+
+import java.util.List;
+import me.chanjar.weixin.channel.bean.after.AfterSaleInfoResponse;
+import me.chanjar.weixin.channel.bean.after.AfterSaleListResponse;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+import me.chanjar.weixin.channel.bean.complaint.ComplaintOrderResponse;
+import me.chanjar.weixin.common.error.WxErrorException;
+
+/**
+ * 视频号小店 售后服务接口
+ *
+ * @author Zeyes
+ */
+public interface WxChannelAfterSaleService {
+
+ /**
+ * 获取售后单列表
+ *
+ * @param beginCreateTime 订单创建启始时间 unix时间戳
+ * @param endCreateTime 订单创建结束时间,end_create_time减去begin_create_time不得大于24小时
+ * @param nextKey 翻页参数,从第二页开始传,来源于上一页的返回值
+ * @return 售后单列表
+ *
+ * @throws WxErrorException 异常
+ */
+ AfterSaleListResponse listIds(Long beginCreateTime, Long endCreateTime, String nextKey)
+ throws WxErrorException;
+
+ /**
+ * 获取售后单详情
+ *
+ * @param afterSaleOrderId 售后单号
+ * @return 售后单信息
+ *
+ * @throws WxErrorException 异常
+ */
+ AfterSaleInfoResponse get(String afterSaleOrderId) throws WxErrorException;
+
+ /**
+ * 同意退款
+ *
+ * @param afterSaleOrderId 售后单号
+ * @param addressId 同意退货时传入地址id
+ * @return BaseResponse
+ *
+ * @throws WxErrorException 异常
+ */
+ WxChannelBaseResponse accept(String afterSaleOrderId, String addressId) throws WxErrorException;
+
+ /**
+ * 拒绝售后
+ *
+ * @param afterSaleOrderId 售后单号
+ * @param rejectReason 拒绝原因
+ * @return BaseResponse
+ *
+ * @throws WxErrorException 异常
+ */
+ WxChannelBaseResponse reject(String afterSaleOrderId, String rejectReason) throws WxErrorException;
+
+ /**
+ * 上传退款凭证
+ *
+ * @param afterSaleOrderId 售后单号
+ * @param desc 退款凭证描述
+ * @param certificates 退款凭证图片列表
+ * @return BaseResponse
+ *
+ * @throws WxErrorException 异常
+ */
+ WxChannelBaseResponse uploadRefundEvidence(String afterSaleOrderId, String desc, List certificates)
+ throws WxErrorException;
+
+ /**
+ * 商家补充纠纷单留言
+ *
+ * @param complaintId 纠纷单号
+ * @param content 留言内容,最多500字
+ * @param mediaIds 图片media_id列表,所有留言总图片数量最多20张
+ * @return BaseResponse
+ *
+ * @throws WxErrorException 异常
+ */
+ WxChannelBaseResponse addComplaintMaterial(String complaintId, String content, List mediaIds)
+ throws WxErrorException;
+
+ /**
+ * 商家举证
+ *
+ * @param complaintId 纠纷单号
+ * @param content 举证内容,最多500字
+ * @param mediaIds 图片media_id列表,所有留言总图片数量最多20张
+ * @return BaseResponse
+ *
+ * @throws WxErrorException 异常
+ */
+ WxChannelBaseResponse addComplaintEvidence(String complaintId, String content, List mediaIds)
+ throws WxErrorException;
+
+ /**
+ * 获取纠纷单
+ *
+ * @param complaintId 纠纷单号
+ * @return BaseResponse
+ *
+ * @throws WxErrorException 异常
+ */
+ ComplaintOrderResponse getComplaint(String complaintId) throws WxErrorException;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelBasicService.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelBasicService.java
new file mode 100644
index 0000000000..a687aaeb5c
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelBasicService.java
@@ -0,0 +1,73 @@
+package me.chanjar.weixin.channel.api;
+
+import java.io.File;
+import me.chanjar.weixin.channel.bean.address.AddressCodeResponse;
+import me.chanjar.weixin.channel.bean.image.ChannelImageInfo;
+import me.chanjar.weixin.channel.bean.image.ChannelImageResponse;
+import me.chanjar.weixin.channel.bean.image.QualificationFileResponse;
+import me.chanjar.weixin.channel.bean.shop.ShopInfoResponse;
+import me.chanjar.weixin.common.error.WxErrorException;
+
+/**
+ * 基础接口
+ *
+ * @author Zeyes
+ */
+public interface WxChannelBasicService {
+
+ /**
+ * 获取店铺基本信息
+ *
+ * @return 店铺基本信息
+ */
+ ShopInfoResponse getShopInfo() throws WxErrorException;
+
+ /**
+ * 上传图片
+ *
+ * @param respType 0:media_id和pay_media_id;1:图片链接(商品信息相关图片请务必使用此参数得到链接)
+ * @param imgUrl 图片url
+ * @return 图片信息
+ *
+ * @throws WxErrorException 异常
+ */
+ ChannelImageInfo uploadImg(int respType, String imgUrl) throws WxErrorException;
+
+ /**
+ * 上传图片
+ *
+ * @param respType 0:media_id和pay_media_id;1:图片链接(商品信息相关图片请务必使用此参数得到链接)
+ * @param file 图片文件
+ * @param height 图片的高,单位:像素
+ * @param width 图片的宽,单位:像素
+ * @return 图片信息
+ *
+ * @throws WxErrorException 异常
+ */
+ ChannelImageInfo uploadImg(int respType, File file, int height, int width) throws WxErrorException;
+
+ /**
+ * 上传资质图片
+ *
+ * @param file 资质图片
+ * @return 结果
+ *
+ * @throws WxErrorException 异常
+ */
+ QualificationFileResponse uploadQualificationFile(File file) throws WxErrorException;
+
+ /**
+ * 根据media_id获取图片
+ *
+ * @param mediaId media_id
+ */
+ ChannelImageResponse getImg(String mediaId) throws WxErrorException;
+
+ /**
+ * 获取地址编码(最多获取4级)
+ *
+ * @param code 地址行政编码,不填或者填0时,拉取全国的省级行政编码
+ * @return AddressCodeResponse
+ */
+ AddressCodeResponse getAddressCode(Integer code) throws WxErrorException;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelBrandService.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelBrandService.java
new file mode 100644
index 0000000000..905d354955
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelBrandService.java
@@ -0,0 +1,103 @@
+package me.chanjar.weixin.channel.api;
+
+
+import me.chanjar.weixin.channel.bean.audit.AuditApplyResponse;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+import me.chanjar.weixin.channel.bean.brand.Brand;
+import me.chanjar.weixin.channel.bean.brand.BrandApplyListResponse;
+import me.chanjar.weixin.channel.bean.brand.BrandInfoResponse;
+import me.chanjar.weixin.channel.bean.brand.BrandListResponse;
+import me.chanjar.weixin.common.error.WxErrorException;
+
+/**
+ * 视频号小店 品牌服务接口
+ *
+ * @author Zeyes
+ */
+public interface WxChannelBrandService {
+
+ /**
+ * 获取品牌库列表
+ *
+ * @param pageSize 每页数量(默认10, 不超过50)
+ * @param nextKey 由上次请求返回, 记录翻页的上下文, 传入时会从上次返回的结果往后翻一页, 不传默认拉取第一页数据
+ * @return 品牌库列表
+ *
+ * @throws WxErrorException 异常
+ */
+ BrandListResponse listAllBrand(Integer pageSize, String nextKey) throws WxErrorException;
+
+ /**
+ * 新增品牌资质
+ *
+ * @param brand 品牌参数
+ * @return 审核id
+ *
+ * @throws WxErrorException 异常
+ */
+ AuditApplyResponse addBrandApply(Brand brand) throws WxErrorException;
+
+ /**
+ * 修改品牌资质
+ *
+ * @param brand 品牌参数
+ * @return 审核id
+ *
+ * @throws WxErrorException 异常
+ */
+ AuditApplyResponse updateBrandApply(Brand brand) throws WxErrorException;
+
+ /**
+ * 撤回品牌资质审核
+ *
+ * @param brandId 品牌id
+ * @param auditId 审核id
+ * @return 审核id
+ *
+ * @throws WxErrorException 异常
+ */
+ WxChannelBaseResponse cancelBrandApply(String brandId, String auditId) throws WxErrorException;
+
+ /**
+ * 删除品牌资质
+ *
+ * @param brandId 品牌id
+ * @return 结果
+ *
+ * @throws WxErrorException 异常
+ */
+ WxChannelBaseResponse deleteBrandApply(String brandId) throws WxErrorException;
+
+ /**
+ * 获取品牌资质申请详情
+ *
+ * @param brandId 品牌id
+ * @return 品牌信息
+ *
+ * @throws WxErrorException 异常
+ */
+ BrandInfoResponse getBrandApply(String brandId) throws WxErrorException;
+
+ /**
+ * 获取品牌资质申请列表
+ *
+ * @param pageSize 每页数量(默认10, 不超过50)
+ * @param nextKey 由上次请求返回, 记录翻页的上下文, 传入时会从上次返回的结果往后翻一页, 不传默认拉取第一页数据
+ * @param status 审核单状态, 不填默认拉全部商品
+ * @return 品牌列表
+ *
+ * @throws WxErrorException 异常
+ */
+ BrandApplyListResponse listBrandApply(Integer pageSize, String nextKey, Integer status) throws WxErrorException;
+
+ /**
+ * 获取生效中的品牌资质列表
+ *
+ * @param pageSize 每页数量(默认10, 不超过50)
+ * @param nextKey 由上次请求返回, 记录翻页的上下文, 传入时会从上次返回的结果往后翻一页, 不传默认拉取第一页数据
+ * @return 品牌列表
+ *
+ * @throws WxErrorException 异常
+ */
+ BrandApplyListResponse listValidBrandApply(Integer pageSize, String nextKey) throws WxErrorException;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelCategoryService.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelCategoryService.java
new file mode 100644
index 0000000000..ddbc99e5d4
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelCategoryService.java
@@ -0,0 +1,93 @@
+package me.chanjar.weixin.channel.api;
+
+import java.io.File;
+import java.util.List;
+import me.chanjar.weixin.channel.bean.audit.AuditApplyResponse;
+import me.chanjar.weixin.channel.bean.audit.AuditResponse;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+import me.chanjar.weixin.channel.bean.category.CategoryDetailResult;
+import me.chanjar.weixin.channel.bean.category.CategoryQualificationResponse;
+import me.chanjar.weixin.channel.bean.category.PassCategoryResponse;
+import me.chanjar.weixin.channel.bean.category.ShopCategory;
+import me.chanjar.weixin.common.error.WxErrorException;
+
+/**
+ * 视频号小店 商品类目相关接口
+ *
+ * @author Zeyes
+ */
+public interface WxChannelCategoryService {
+
+ /**
+ * 获取所有的类目
+ *
+ * @return 所有类目以及资质信息
+ *
+ * @throws WxErrorException 异常
+ */
+ CategoryQualificationResponse listAllCategory() throws WxErrorException;
+
+ /**
+ * 获取商品类目列表(全量) 有频率限制
+ *
+ * @param parentId 类目父id
+ * @return 类目列表
+ *
+ * @throws WxErrorException 异常
+ */
+ List listAvailableCategory(String parentId) throws WxErrorException;
+
+ /**
+ * 获取类目信息
+ *
+ * @param id 三级类目id
+ * @return 类目信息
+ *
+ * @throws WxErrorException 异常
+ */
+ CategoryDetailResult getCategoryDetail(String id) throws WxErrorException;
+
+ /**
+ * 上传类目资质
+ *
+ * @param level1 一级类目ID
+ * @param level2 二级类目ID
+ * @param level3 三级类目ID
+ * @param certificate 资质材料,图片mediaid,图片类型,最多不超过10张
+ * @return 审核id
+ *
+ * @throws WxErrorException 异常
+ * @see WxChannelBasicService#uploadQualificationFile(File)
+ */
+ AuditApplyResponse addCategory(String level1, String level2, String level3, List certificate)
+ throws WxErrorException;
+
+ /**
+ * 取消类目提审
+ *
+ * @param auditId 提交审核时返回的id
+ * @return BaseResponse
+ *
+ * @throws WxErrorException 异常
+ */
+ WxChannelBaseResponse cancelCategoryAudit(String auditId) throws WxErrorException;
+
+ /**
+ * 查询类目审核结果
+ *
+ * @param auditId 审核id
+ * @return 审核结果
+ *
+ * @throws WxErrorException 异常
+ */
+ AuditResponse getAudit(String auditId) throws WxErrorException;
+
+ /**
+ * 获取账号申请通过的类目和资质信息
+ *
+ * @return 类目和资质信息
+ *
+ * @throws WxErrorException 异常
+ */
+ PassCategoryResponse listPassCategory() throws WxErrorException;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelCouponService.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelCouponService.java
new file mode 100644
index 0000000000..df59fdc8b9
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelCouponService.java
@@ -0,0 +1,92 @@
+package me.chanjar.weixin.channel.api;
+
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+import me.chanjar.weixin.channel.bean.coupon.CouponIdResponse;
+import me.chanjar.weixin.channel.bean.coupon.CouponInfoResponse;
+import me.chanjar.weixin.channel.bean.coupon.CouponListParam;
+import me.chanjar.weixin.channel.bean.coupon.CouponListResponse;
+import me.chanjar.weixin.channel.bean.coupon.CouponParam;
+import me.chanjar.weixin.channel.bean.coupon.UserCouponListParam;
+import me.chanjar.weixin.channel.bean.coupon.UserCouponListResponse;
+import me.chanjar.weixin.channel.bean.coupon.UserCouponResponse;
+import me.chanjar.weixin.common.error.WxErrorException;
+
+/**
+ * 视频号小店 优惠券服务
+ *
+ * @author Zeyes
+ */
+public interface WxChannelCouponService {
+
+ /**
+ * 创建优惠券
+ *
+ * @param coupon 优惠券
+ * @return 优惠券ID
+ *
+ * @throws WxErrorException 异常
+ */
+ CouponIdResponse createCoupon(CouponParam coupon) throws WxErrorException;
+
+ /**
+ * 更新优惠券
+ *
+ * @param coupon 优惠券
+ * @return 优惠券ID
+ *
+ * @throws WxErrorException 异常
+ */
+ CouponIdResponse updateCoupon(CouponParam coupon) throws WxErrorException;
+
+ /**
+ * 更新优惠券状态
+ *
+ * @param couponId 优惠券ID
+ * @param status 状态 2生效 4已作废 5删除 {@link me.chanjar.weixin.channel.enums.WxCouponStatus}
+ * @return BaseResponse
+ *
+ * @throws WxErrorException 异常
+ */
+ WxChannelBaseResponse updateCouponStatus(String couponId, Integer status) throws WxErrorException;
+
+ /**
+ * 获取优惠券详情
+ *
+ * @param couponId 优惠券ID
+ * @return CouponInfoResponse
+ *
+ * @throws WxErrorException 异常
+ */
+ CouponInfoResponse getCoupon(String couponId) throws WxErrorException;
+
+ /**
+ * 获取优惠券ID列表
+ *
+ * @param param 条件参数
+ * @return 优惠券ID列表
+ *
+ * @throws WxErrorException 异常
+ */
+ CouponListResponse getCouponList(CouponListParam param) throws WxErrorException;
+
+ /**
+ * 获取用户优惠券
+ *
+ * @param openId 用户openid
+ * @param userCouponId 用户优惠券ID
+ * @return UserCouponResponse
+ *
+ * @throws WxErrorException 异常
+ */
+ UserCouponResponse getUserCoupon(String openId, String userCouponId) throws WxErrorException;
+
+ /**
+ * 获取用户优惠券ID列表
+ *
+ * @param param 条件参数
+ * @return UserCouponListResponse
+ *
+ * @throws WxErrorException 异常
+ */
+ UserCouponListResponse getUserCouponList(UserCouponListParam param) throws WxErrorException;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelFreightTemplateService.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelFreightTemplateService.java
new file mode 100644
index 0000000000..188b33464b
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelFreightTemplateService.java
@@ -0,0 +1,57 @@
+package me.chanjar.weixin.channel.api;
+
+
+import me.chanjar.weixin.channel.bean.freight.FreightTemplate;
+import me.chanjar.weixin.channel.bean.freight.TemplateIdResponse;
+import me.chanjar.weixin.channel.bean.freight.TemplateInfoResponse;
+import me.chanjar.weixin.channel.bean.freight.TemplateListResponse;
+import me.chanjar.weixin.common.error.WxErrorException;
+
+/**
+ * 视频号小店 运费模板服务接口
+ *
+ * @author Zeyes
+ */
+public interface WxChannelFreightTemplateService {
+
+ /**
+ * 获取运费模板列表
+ *
+ * @param offset 起始位置
+ * @param limit 拉取个数
+ * @return 列表
+ *
+ * @throws WxErrorException 异常
+ */
+ TemplateListResponse listTemplate(Integer offset, Integer limit) throws WxErrorException;
+
+ /**
+ * 获取运费模板
+ *
+ * @param templateId 模板id
+ * @return 运费模板
+ *
+ * @throws WxErrorException 异常
+ */
+ TemplateInfoResponse getTemplate(String templateId) throws WxErrorException;
+
+ /**
+ * 添加运费模板
+ *
+ * @param template 运费模板
+ * @return TemplateIdResponse
+ *
+ * @throws WxErrorException 异常
+ */
+ TemplateIdResponse addTemplate(FreightTemplate template) throws WxErrorException;
+
+ /**
+ * 更新运费模板
+ *
+ * @param template 运费模板
+ * @return TemplateIdResponse
+ *
+ * @throws WxErrorException 异常
+ */
+ TemplateIdResponse updateTemplate(FreightTemplate template) throws WxErrorException;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelFundService.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelFundService.java
new file mode 100644
index 0000000000..cb0f5aab79
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelFundService.java
@@ -0,0 +1,189 @@
+package me.chanjar.weixin.channel.api;
+
+
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+import me.chanjar.weixin.channel.bean.fund.AccountInfo;
+import me.chanjar.weixin.channel.bean.fund.AccountInfoResponse;
+import me.chanjar.weixin.channel.bean.fund.BalanceInfoResponse;
+import me.chanjar.weixin.channel.bean.fund.FlowListResponse;
+import me.chanjar.weixin.channel.bean.fund.FundsFlowResponse;
+import me.chanjar.weixin.channel.bean.fund.FundsListParam;
+import me.chanjar.weixin.channel.bean.fund.WithdrawDetailResponse;
+import me.chanjar.weixin.channel.bean.fund.WithdrawListResponse;
+import me.chanjar.weixin.channel.bean.fund.WithdrawSubmitResponse;
+import me.chanjar.weixin.channel.bean.fund.bank.BankCityResponse;
+import me.chanjar.weixin.channel.bean.fund.bank.BankInfoResponse;
+import me.chanjar.weixin.channel.bean.fund.bank.BankListResponse;
+import me.chanjar.weixin.channel.bean.fund.bank.BankProvinceResponse;
+import me.chanjar.weixin.channel.bean.fund.bank.BranchInfoResponse;
+import me.chanjar.weixin.channel.bean.fund.qrcode.QrCheckResponse;
+import me.chanjar.weixin.channel.bean.fund.qrcode.QrCodeResponse;
+import me.chanjar.weixin.common.error.WxErrorException;
+
+/**
+ * 资金相关服务
+ *
+ * @author Zeyes
+ */
+public interface WxChannelFundService {
+
+ /**
+ * 获取账户余额
+ *
+ * @return 账户余额
+ *
+ * @throws WxErrorException 异常
+ */
+ BalanceInfoResponse getBalance() throws WxErrorException;
+
+ /**
+ * 获取结算账户
+ *
+ * @return 结算账户
+ *
+ * @throws WxErrorException 异常
+ */
+ AccountInfoResponse getBankAccount() throws WxErrorException;
+
+ /**
+ * 获取资金流水详情
+ *
+ * @param flowId 资金流水号
+ * @return 资金流水详情
+ *
+ * @throws WxErrorException 异常
+ */
+ FundsFlowResponse getFundsFlowDetail(String flowId) throws WxErrorException;
+
+ /**
+ * 获取资金流水列表
+ *
+ * @param param 资金流水列表参数
+ * @return 资金流水列表
+ *
+ * @throws WxErrorException 异常
+ */
+ FlowListResponse listFundsFlow(FundsListParam param) throws WxErrorException;
+
+ /**
+ * 获取提现记录
+ *
+ * @param withdrawId 提现单号
+ * @return 提现记录
+ *
+ * @throws WxErrorException 异常
+ */
+ WithdrawDetailResponse getWithdrawDetail(String withdrawId) throws WxErrorException;
+
+ /**
+ * 获取提现记录列表
+ *
+ * @param pageNum 页码
+ * @param pageSize 每页大小
+ * @param startTime 开始时间
+ * @param endTime 结束时间
+ * @return 提现记录列表
+ *
+ * @throws WxErrorException 异常
+ */
+ WithdrawListResponse listWithdraw(Integer pageNum, Integer pageSize, Long startTime, Long endTime)
+ throws WxErrorException;
+
+ /**
+ * 修改结算账户
+ *
+ * @param accountInfo 结算账户信息
+ * @return 修改结果
+ *
+ * @throws WxErrorException 异常
+ */
+ WxChannelBaseResponse setBankAccount(AccountInfo accountInfo) throws WxErrorException;
+
+ /***
+ * 商户提现
+ *
+ * @param amount 提现金额(单位:分)
+ * @param remark 提现备注
+ * @param bankMemo 银行附言
+ * @return 提现结果
+ * @throws WxErrorException 异常
+ */
+ WithdrawSubmitResponse submitWithdraw(Integer amount, String remark, String bankMemo) throws WxErrorException;
+
+ /**
+ * 根据卡号查银行信息
+ *
+ * @param accountNumber 卡号
+ * @return 银行信息
+ *
+ * @throws WxErrorException 异常
+ */
+ BankInfoResponse getBankInfoByCardNo(String accountNumber) throws WxErrorException;
+
+ /**
+ * 搜索银行列表
+ *
+ * @param offset 偏移量
+ * @param limit 每页数据大小
+ * @param keywords 银行关键字
+ * @param bankType 银行类型(1:对私银行,2:对公银行; 默认对公)
+ * @return 银行列表
+ *
+ * @throws WxErrorException 异常
+ */
+ BankListResponse searchBankList(Integer offset, Integer limit, String keywords, Integer bankType)
+ throws WxErrorException;
+
+ /**
+ * 查询城市列表
+ *
+ * @param provinceCode 省份编码
+ * @return 城市列表
+ *
+ * @throws WxErrorException 异常
+ */
+ BankCityResponse searchCityList(String provinceCode) throws WxErrorException;
+
+ /**
+ * 查询大陆银行省份列表
+ *
+ * @return 省份列表
+ *
+ * @throws WxErrorException 异常
+ */
+ BankProvinceResponse getProvinceList() throws WxErrorException;
+
+ /**
+ * 查询支行列表
+ *
+ * @param bankCode 银行编码
+ * @param cityCode 城市编码
+ * @param offset 偏移量
+ * @param limit 每页数据大小
+ * @return 支行列表
+ *
+ * @throws WxErrorException 异常
+ */
+ BranchInfoResponse searchBranchList(String bankCode, String cityCode, Integer offset, Integer limit)
+ throws WxErrorException;
+
+ /**
+ * 获取二维码
+ *
+ * @param qrcodeTicket 二维码ticket
+ * @return 二维码响应
+ *
+ * @throws WxErrorException 异常
+ */
+ QrCodeResponse getQrCode(String qrcodeTicket) throws WxErrorException;
+
+ /**
+ * 查询扫码状态
+ *
+ * @param qrcodeTicket 二维码ticket
+ * @return 扫码状态
+ *
+ * @throws WxErrorException 异常
+ */
+ QrCheckResponse checkQrStatus(String qrcodeTicket) throws WxErrorException;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelOrderService.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelOrderService.java
new file mode 100644
index 0000000000..6179510e78
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelOrderService.java
@@ -0,0 +1,146 @@
+package me.chanjar.weixin.channel.api;
+
+import java.util.List;
+import me.chanjar.weixin.channel.bean.base.AddressInfo;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+import me.chanjar.weixin.channel.bean.delivery.DeliveryCompanyResponse;
+import me.chanjar.weixin.channel.bean.delivery.DeliveryInfo;
+import me.chanjar.weixin.channel.bean.order.ChangeOrderInfo;
+import me.chanjar.weixin.channel.bean.order.DeliveryUpdateParam;
+import me.chanjar.weixin.channel.bean.order.OrderInfoResponse;
+import me.chanjar.weixin.channel.bean.order.OrderListParam;
+import me.chanjar.weixin.channel.bean.order.OrderListResponse;
+import me.chanjar.weixin.channel.bean.order.OrderSearchParam;
+import me.chanjar.weixin.common.error.WxErrorException;
+
+/**
+ * 视频号小店 订单服务接口
+ *
+ * @author Zeyes
+ * @link 订单接口文档
+ */
+public interface WxChannelOrderService {
+
+ /**
+ * 获取订单
+ *
+ * @param orderId 订单id
+ * @return 订单详情
+ *
+ * @throws WxErrorException 异常
+ */
+ OrderInfoResponse getOrder(String orderId) throws WxErrorException;
+
+ /**
+ * 获取订单列表
+ *
+ * @param param 搜索条件
+ * @return 订单列表
+ *
+ * @throws WxErrorException 异常
+ */
+ OrderListResponse getOrders(OrderListParam param) throws WxErrorException;
+
+ /**
+ * 订单搜索
+ *
+ * @param param 搜索条件
+ * @return 订单列表
+ *
+ * @throws WxErrorException 异常
+ */
+ OrderListResponse searchOrder(OrderSearchParam param) throws WxErrorException;
+
+ /**
+ * 更改订单价格
+ *
+ * @param orderId 订单id
+ * @param expressFee 运费价格(以分为单位)(不填不改)
+ * @param changeOrderInfos 改价列表
+ * @return 结果
+ *
+ * @throws WxErrorException 异常
+ */
+ WxChannelBaseResponse updatePrice(String orderId, Integer expressFee, List changeOrderInfos)
+ throws WxErrorException;
+
+ /**
+ * 更改订单备注
+ *
+ * @param orderId 订单id
+ * @param merchantNotes 备注
+ * @return BaseResponse
+ *
+ * @throws WxErrorException 异常
+ */
+ WxChannelBaseResponse updateRemark(String orderId, String merchantNotes) throws WxErrorException;
+
+ /**
+ * 更新订单地址
+ *
+ * @param orderId 订单id
+ * @param userAddress 用户地址
+ * @return BaseResponse
+ *
+ * @throws WxErrorException 异常
+ */
+ WxChannelBaseResponse updateAddress(String orderId, AddressInfo userAddress) throws WxErrorException;
+
+ /**
+ * 修改物流信息
发货完成的订单可以修改,最多修改1次 拆包发货的订单暂不允许修改物流 虚拟商品订单暂不允许修改物流
+ *
+ * @param param 物流信息
+ * @return BaseResponse
+ *
+ * @throws WxErrorException 异常
+ */
+ WxChannelBaseResponse updateDelivery(DeliveryUpdateParam param) throws WxErrorException;
+
+ /**
+ * 同意用户修改收货地址请求
+ *
+ * @param orderId 订单id
+ * @return BaseResponse
+ *
+ * @throws WxErrorException 异常
+ */
+ WxChannelBaseResponse acceptAddressModify(String orderId) throws WxErrorException;
+
+ /**
+ * 拒接用户修改收货地址请求
+ *
+ * @param orderId 订单id
+ * @return BaseResponse
+ *
+ * @throws WxErrorException 异常
+ */
+ WxChannelBaseResponse rejectAddressModify(String orderId) throws WxErrorException;
+
+ /**
+ * 关闭订单 (需要订单状态为未付款状态)
+ *
+ * @param orderId 订单id
+ * @return BaseResponse
+ */
+ WxChannelBaseResponse closeOrder(String orderId);
+
+ /**
+ * 获取快递公司列表
+ *
+ * @return 快递公司列表
+ *
+ * @throws WxErrorException 异常
+ */
+ DeliveryCompanyResponse listDeliveryCompany() throws WxErrorException;
+
+ /**
+ * 订单发货
+ *
+ * @param orderId 订单id
+ * @param deliveryList 物流信息
+ * @return BaseResponse
+ *
+ * @throws WxErrorException 异常
+ */
+ WxChannelBaseResponse deliveryOrder(String orderId, List deliveryList) throws WxErrorException;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelProductService.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelProductService.java
new file mode 100644
index 0000000000..b962b9ec85
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelProductService.java
@@ -0,0 +1,171 @@
+package me.chanjar.weixin.channel.api;
+
+
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+import me.chanjar.weixin.channel.bean.limit.LimitTaskAddResponse;
+import me.chanjar.weixin.channel.bean.limit.LimitTaskListResponse;
+import me.chanjar.weixin.channel.bean.limit.LimitTaskParam;
+import me.chanjar.weixin.channel.bean.product.SkuStockResponse;
+import me.chanjar.weixin.channel.bean.product.SpuGetResponse;
+import me.chanjar.weixin.channel.bean.product.SpuInfo;
+import me.chanjar.weixin.channel.bean.product.SpuListResponse;
+import me.chanjar.weixin.channel.bean.product.SpuUpdateResponse;
+import me.chanjar.weixin.common.error.WxErrorException;
+
+/**
+ * 视频号小店 商品服务接口
+ *
+ * @author Zeyes
+ */
+public interface WxChannelProductService {
+
+ /**
+ * 添加商品
+ *
+ * @param info 商品信息
+ * @return 返回商品的状态和id
+ *
+ * @throws WxErrorException 异常
+ */
+ SpuUpdateResponse addProduct(SpuInfo info) throws WxErrorException;
+
+ /**
+ * 更新商品
+ *
+ * @param info 商品信息
+ * @return 返回商品的状态和id
+ *
+ * @throws WxErrorException 异常
+ */
+ SpuUpdateResponse updateProduct(SpuInfo info) throws WxErrorException;
+
+ /**
+ * 更新商品库存 (仅对edit_status != 2 的商品适用,其他状态的商品无法通过该接口修改库存)
+ *
+ * @param productId 内部商品ID
+ * @param skuId 内部sku_id
+ * @param diffType 修改类型 1增加 2减少 3设置
+ * @param num 增加、减少或者设置的库存值
+ * @return WxChannelBaseResponse
+ *
+ * @throws WxErrorException 异常
+ */
+ WxChannelBaseResponse updateStock(String productId, String skuId, Integer diffType, Integer num)
+ throws WxErrorException;
+
+ /**
+ * 删除商品
+ *
+ * @param productId 商品ID
+ * @return 是否成功
+ *
+ * @throws WxErrorException 异常
+ */
+ WxChannelBaseResponse deleteProduct(String productId) throws WxErrorException;
+
+ /**
+ * 撤回商品审核
+ *
+ * @param productId 商品ID
+ * @return 是否成功
+ *
+ * @throws WxErrorException 异常
+ */
+ WxChannelBaseResponse cancelProductAudit(String productId) throws WxErrorException;
+
+ /**
+ * 获取商品
+ *
+ * @param productId 商品ID
+ * @param dataType 默认取1 1:获取线上数据 2:获取草稿数据 3:同时获取线上和草稿数据(注意:需成功上架后才有线上数据)
+ * @return 商品信息
+ *
+ * @throws WxErrorException 异常
+ */
+ SpuGetResponse getProduct(String productId, Integer dataType) throws WxErrorException;
+
+ /**
+ * 获取商品列表
+ *
+ * @param pageSize 每页数量(默认10,不超过30)
+ * @param nextKey 由上次请求返回,记录翻页的上下文。传入时会从上次返回的结果往后翻一页,不传默认拉取第一页数据。
+ * @param status 商品状态,不填默认拉全部商品(不包含回收站) {@link me.chanjar.weixin.channel.enums.SpuStatus}
+ * @return List
+ *
+ * @throws WxErrorException 异常
+ */
+ SpuListResponse listProduct(Integer pageSize, String nextKey, Integer status) throws WxErrorException;
+
+ /**
+ * 上架商品
+ *
+ * @param productId 商品ID
+ * @return 是否成功
+ *
+ * @throws WxErrorException 异常
+ */
+ WxChannelBaseResponse upProduct(String productId) throws WxErrorException;
+
+ /**
+ * 下架商品
+ *
+ * @param productId 商品ID
+ * @return 是否成功
+ *
+ * @throws WxErrorException 异常
+ */
+ WxChannelBaseResponse downProduct(String productId) throws WxErrorException;
+
+ /**
+ * 获取商品实时库存
+ *
+ * @param productId 商品ID
+ * @param skuId skuId
+ * @return SkuStockResponse
+ *
+ * @throws WxErrorException 异常
+ */
+ SkuStockResponse getSkuStock(String productId, String skuId) throws WxErrorException;
+
+ /**
+ * 添加限时抢购任务
+ *
+ * @param param 限时抢购任务
+ * @return LimitTaskAddResponse
+ *
+ * @throws WxErrorException 异常
+ */
+ LimitTaskAddResponse addLimitTask(LimitTaskParam param) throws WxErrorException;
+
+ /**
+ * 拉取限时抢购任务列表
+ *
+ * @param pageSize 每页数量(默认10,不超过50)
+ * @param nextKey 由上次请求返回,记录翻页的上下文。传入时会从上次返回的结果往后翻一页,不传默认拉取第一页数据
+ * @param status 抢购活动状态
+ * @return LimitTaskListResponse
+ *
+ * @throws WxErrorException 异常
+ */
+ LimitTaskListResponse listLimitTask(Integer pageSize, String nextKey, Integer status) throws WxErrorException;
+
+ /**
+ * 停止限时抢购任务
+ *
+ * @param taskId 限时抢购任务ID
+ * @return BaseResponse
+ *
+ * @throws WxErrorException 异常
+ */
+ WxChannelBaseResponse stopLimitTask(String taskId) throws WxErrorException;
+
+ /**
+ * 停止限时抢购任务
+ *
+ * @param taskId 限时抢购任务ID
+ * @return BaseResponse
+ *
+ * @throws WxErrorException 异常
+ */
+ WxChannelBaseResponse deleteLimitTask(String taskId) throws WxErrorException;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelService.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelService.java
new file mode 100644
index 0000000000..8f960f4795
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelService.java
@@ -0,0 +1,122 @@
+package me.chanjar.weixin.channel.api;
+
+/**
+ * The interface Wx Channel service
+ *
+ * @author Zeyes
+ */
+public interface WxChannelService extends BaseWxChannelService {
+
+ /**
+ * 基础接口服务
+ *
+ * @return 基础接口服务
+ */
+ WxChannelBasicService getBasicService();
+
+ /**
+ * 商品类目服务
+ *
+ * @return 商品类目服务
+ */
+ WxChannelCategoryService getCategoryService();
+
+ /**
+ * 品牌服务
+ *
+ * @return 品牌服务
+ */
+ WxChannelBrandService getBrandService();
+
+ /**
+ * 商品服务
+ *
+ * @return 商品服务
+ */
+ WxChannelProductService getProductService();
+
+ /**
+ * 仓库服务
+ *
+ * @return 仓库服务
+ */
+ WxChannelWarehouseService getWarehouseService();
+
+ /**
+ * 订单服务
+ *
+ * @return 订单服务
+ */
+ WxChannelOrderService getOrderService();
+
+ /**
+ * 售后服务
+ *
+ * @return 售后服务
+ */
+ WxChannelAfterSaleService getAfterSaleService();
+
+ /**
+ * 运费模板服务
+ *
+ * @return 运费模板服务
+ */
+ WxChannelFreightTemplateService getFreightTemplateService();
+
+ /**
+ * 地址服务
+ *
+ * @return 地址服务
+ */
+ WxChannelAddressService getAddressService();
+
+ /**
+ * 优惠券服务
+ *
+ * @return 优惠券服务
+ */
+ WxChannelCouponService getCouponService();
+
+ /**
+ * 分享员服务
+ *
+ * @return 分享员服务
+ */
+ WxChannelSharerService getSharerService();
+
+ /**
+ * 资金服务
+ *
+ * @return 资金服务
+ */
+ WxChannelFundService getFundService();
+
+ /**
+ * 优选联盟-团长合作达人管理服务
+ *
+ * @return 团长合作达人管理服务
+ */
+ WxLeagueWindowService getLeagueWindowService();
+
+ /**
+ * 优选联盟-团长服务
+ *
+ * @return 团长服务
+ */
+ WxLeagueSupplierService getLeagueSupplierService();
+
+ /**
+ * 优选联盟-达人服务
+ *
+ * @return 达人服务
+ */
+ WxLeaguePromoterService getLeaguePromoterService();
+
+ /**
+ * 优选联盟-商品服务
+ *
+ * @return 商品服务
+ */
+ WxLeagueProductService getLeagueProductService();
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelSharerService.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelSharerService.java
new file mode 100644
index 0000000000..300493158b
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelSharerService.java
@@ -0,0 +1,71 @@
+package me.chanjar.weixin.channel.api;
+
+import java.util.List;
+import me.chanjar.weixin.channel.bean.sharer.SharerBindResponse;
+import me.chanjar.weixin.channel.bean.sharer.SharerInfoResponse;
+import me.chanjar.weixin.channel.bean.sharer.SharerOrderParam;
+import me.chanjar.weixin.channel.bean.sharer.SharerOrderResponse;
+import me.chanjar.weixin.channel.bean.sharer.SharerSearchResponse;
+import me.chanjar.weixin.channel.bean.sharer.SharerUnbindResponse;
+import me.chanjar.weixin.common.error.WxErrorException;
+
+/**
+ * 视频号小店 分享员服务接口
+ *
+ * @author Zeyes
+ */
+public interface WxChannelSharerService {
+
+ /**
+ * 邀请分享员
+ *
+ * @param username 邀请的用户微信号
+ * @return SharerBindResponse
+ *
+ * @throws WxErrorException 异常
+ */
+ SharerBindResponse bindSharer(String username) throws WxErrorException;
+
+ /**
+ * 获取绑定的分享员
+ *
+ * @param openid 分享员openid
+ * @param username 分享员微信号(二选一)
+ * @return SharerSearchResponse
+ *
+ * @throws WxErrorException 异常
+ */
+ SharerSearchResponse searchSharer(String openid, String username) throws WxErrorException;
+
+ /**
+ * 获取绑定的分享员列表
+ *
+ * @param page 分页参数,页数
+ * @param pageSize 分页参数,每页分享员数(不超过100
+ * @param sharerType 分享员类型
+ * @return 分享员列表
+ *
+ * @throws WxErrorException 异常
+ */
+ SharerInfoResponse listSharer(Integer page, Integer pageSize, Integer sharerType) throws WxErrorException;
+
+ /**
+ * 获取分享员订单列表
+ *
+ * @param param 参数
+ * @return 列表
+ *
+ * @throws WxErrorException 异常
+ */
+ SharerOrderResponse listSharerOrder(SharerOrderParam param) throws WxErrorException;
+
+ /**
+ * 解绑分享员
+ *
+ * @param openIds openid列表
+ * @return 状态
+ *
+ * @throws WxErrorException 异常
+ */
+ SharerUnbindResponse unbindSharer(List openIds) throws WxErrorException;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelWarehouseService.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelWarehouseService.java
new file mode 100644
index 0000000000..1bb00885f5
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelWarehouseService.java
@@ -0,0 +1,137 @@
+package me.chanjar.weixin.channel.api;
+
+
+import java.util.List;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+import me.chanjar.weixin.channel.bean.warehouse.LocationPriorityResponse;
+import me.chanjar.weixin.channel.bean.warehouse.PriorityLocationParam;
+import me.chanjar.weixin.channel.bean.warehouse.WarehouseIdsResponse;
+import me.chanjar.weixin.channel.bean.warehouse.WarehouseLocation;
+import me.chanjar.weixin.channel.bean.warehouse.WarehouseParam;
+import me.chanjar.weixin.channel.bean.warehouse.WarehouseResponse;
+import me.chanjar.weixin.channel.bean.warehouse.WarehouseStockParam;
+import me.chanjar.weixin.channel.bean.warehouse.WarehouseStockResponse;
+import me.chanjar.weixin.common.error.WxErrorException;
+
+
+/**
+ * 视频号小店 区域仓库服务
+ *
+ * @author Zeyes
+ */
+public interface WxChannelWarehouseService {
+
+ /**
+ * 创建仓库
+ *
+ * @param param 仓库信息
+ * @return 响应
+ *
+ * @throws WxErrorException 异常
+ */
+ WxChannelBaseResponse createWarehouse(WarehouseParam param) throws WxErrorException;
+
+ /**
+ * 查询仓库列表
+ *
+ * @param pageSize 每页数量(最大不超过10)
+ * @param nextKey 由上次请求返回,记录翻页的上下文。传入时会从上次返回的结果往后翻一页,不传默认拉取第一页数据
+ * @return 响应
+ *
+ * @throws WxErrorException 异常
+ */
+ WarehouseIdsResponse listWarehouse(Integer pageSize, String nextKey) throws WxErrorException;
+
+ /**
+ * 获取仓库详情
+ *
+ * @param outWarehouseId 外部仓库ID
+ * @return 响应
+ *
+ * @throws WxErrorException 异常
+ */
+ WarehouseResponse getWarehouse(String outWarehouseId) throws WxErrorException;
+
+ /**
+ * 修改仓库详情
+ *
+ * @param outWarehouseId 外部仓库ID
+ * @param name 仓库名称
+ * @param intro 仓库介绍
+ * @return 响应
+ *
+ * @throws WxErrorException 异常
+ */
+ WxChannelBaseResponse updateWarehouse(String outWarehouseId, String name, String intro) throws WxErrorException;
+
+ /**
+ * 批量增加覆盖区域
+ *
+ * @param outWarehouseId 外部仓库ID
+ * @param coverLocations 覆盖区域
+ * @return 响应
+ *
+ * @throws WxErrorException 异常
+ */
+ WxChannelBaseResponse addWarehouseArea(String outWarehouseId, List coverLocations)
+ throws WxErrorException;
+
+ /**
+ * 批量删除覆盖区域
+ *
+ * @param outWarehouseId 外部仓库ID
+ * @param coverLocations 覆盖区域
+ * @return 响应
+ *
+ * @throws WxErrorException 异常
+ */
+ WxChannelBaseResponse deleteWarehouseArea(String outWarehouseId, List coverLocations)
+ throws WxErrorException;
+
+ /**
+ * 设置指定地址下的仓的优先级
+ *
+ * @param param 参数
+ * @return 响应
+ *
+ * @throws WxErrorException 异常
+ */
+ WxChannelBaseResponse setWarehousePriority(PriorityLocationParam param) throws WxErrorException;
+
+ /**
+ * 获取指定地址下的仓的优先级
+ *
+ * @param addressId1 省份地址编码
+ * @param addressId2 市地址编码
+ * @param addressId3 区地址编码
+ * @param addressId4 街道地址编码
+ * @return 仓的优先级
+ *
+ * @throws WxErrorException 异常
+ */
+ LocationPriorityResponse getWarehousePriority(Integer addressId1, Integer addressId2, Integer addressId3,
+ Integer addressId4) throws WxErrorException;
+
+ /**
+ * 更新区域仓库存数量
+ *
+ * @param param 参数
+ * @return 响应
+ *
+ * @throws WxErrorException 异常
+ */
+ WxChannelBaseResponse updateWarehouseStock(WarehouseStockParam param) throws WxErrorException;
+
+ /**
+ * 获取区域仓库存数量
+ *
+ * @param productId 商品ID
+ * @param outWarehouseId 外部仓库ID
+ * @param skuId 商品skuId
+ * @return 响应
+ *
+ * @throws WxErrorException 异常
+ */
+ WarehouseStockResponse getWarehouseStock(String productId, String skuId, String outWarehouseId)
+ throws WxErrorException;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxLeagueProductService.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxLeagueProductService.java
new file mode 100644
index 0000000000..d8d6781505
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxLeagueProductService.java
@@ -0,0 +1,62 @@
+package me.chanjar.weixin.channel.api;
+
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+import me.chanjar.weixin.channel.bean.league.product.BatchAddParam;
+import me.chanjar.weixin.channel.bean.league.product.BatchAddResponse;
+import me.chanjar.weixin.channel.bean.league.product.ProductDetailParam;
+import me.chanjar.weixin.channel.bean.league.product.ProductDetailResponse;
+import me.chanjar.weixin.channel.bean.league.product.ProductListParam;
+import me.chanjar.weixin.channel.bean.league.product.ProductListResponse;
+import me.chanjar.weixin.channel.bean.league.product.ProductUpdateParam;
+import me.chanjar.weixin.channel.bean.league.product.ProductUpdateResponse;
+import me.chanjar.weixin.common.error.WxErrorException;
+
+/**
+ * 优选联盟 商品操作服务
+ *
+ * @author Zeyes
+ */
+public interface WxLeagueProductService {
+
+ /**
+ * 批量新增联盟商品
+ *
+ * @param param 参数
+ * @return 结果
+ */
+ BatchAddResponse batchAddProduct(BatchAddParam param) throws WxErrorException;
+
+ /**
+ * 更新联盟商品信息
+ *
+ * @param param 参数
+ * @return 结果
+ */
+ ProductUpdateResponse updateProduct(ProductUpdateParam param) throws WxErrorException;
+
+ /**
+ * 删除联盟商品
+ *
+ * @param type 1普通推广商品 2定向推广商品 3专属推广商品
+ * @param productId 商品id type为普通推广商品时必填
+ * @param infoId 特殊推广商品计划id type为特殊推广商品时必填
+ * @return
+ */
+ WxChannelBaseResponse deleteProduct(Integer type, String productId, String infoId) throws WxErrorException;
+
+ /**
+ * 拉取联盟商品详情
+ *
+ * @param param 参数
+ * @return 结果
+ */
+ ProductDetailResponse getProductDetail(ProductDetailParam param) throws WxErrorException;
+
+ /**
+ * 拉取联盟商品推广列表
+ *
+ * @param param 参数
+ * @return 结果
+ */
+ ProductListResponse listProduct(ProductListParam param) throws WxErrorException;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxLeaguePromoterService.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxLeaguePromoterService.java
new file mode 100644
index 0000000000..8a8ffb9acf
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxLeaguePromoterService.java
@@ -0,0 +1,57 @@
+package me.chanjar.weixin.channel.api;
+
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+import me.chanjar.weixin.channel.bean.league.promoter.PromoterInfoResponse;
+import me.chanjar.weixin.channel.bean.league.promoter.PromoterListResponse;
+import me.chanjar.weixin.common.error.WxErrorException;
+
+/**
+ * 优选联盟 达人服务
+ *
+ * @author Zeyes
+ */
+public interface WxLeaguePromoterService {
+
+ /**
+ * 新增达人
+ *
+ * @param finderId 视频号finder_id
+ * @return 结果
+ */
+ WxChannelBaseResponse addPromoter(String finderId) throws WxErrorException;
+
+ /**
+ * 编辑达人
+ *
+ * @param finderId 视频号finder_id
+ * @param type 操作 1取消邀请 2结束合作
+ * @return 结果
+ */
+ WxChannelBaseResponse updatePromoter(String finderId, int type) throws WxErrorException;
+
+ /**
+ * 删除达人
+ *
+ * @param finderId 视频号finder_id
+ * @return 结果
+ */
+ WxChannelBaseResponse deletePromoter(String finderId) throws WxErrorException;
+
+ /**
+ * 获取达人详情信息
+ *
+ * @param finderId 视频号finder_id
+ * @return 结果
+ */
+ PromoterInfoResponse getPromoterInfo(String finderId) throws WxErrorException;
+
+ /**
+ * 获取达人列表
+ *
+ * @param pageIndex 页面下标,下标从1开始,默认为1
+ * @param pageSize 单页达人数(不超过200)
+ * @param status 拉取该状态下的达人列表
+ * @return 结果
+ */
+ PromoterListResponse listPromoter(Integer pageIndex, Integer pageSize, Integer status) throws WxErrorException;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxLeagueSupplierService.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxLeagueSupplierService.java
new file mode 100644
index 0000000000..cde96843f1
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxLeagueSupplierService.java
@@ -0,0 +1,98 @@
+package me.chanjar.weixin.channel.api;
+
+import me.chanjar.weixin.channel.bean.league.supplier.CommissionOrderListParam;
+import me.chanjar.weixin.channel.bean.league.supplier.CommissionOrderListResponse;
+import me.chanjar.weixin.channel.bean.league.supplier.CommissionOrderResponse;
+import me.chanjar.weixin.channel.bean.league.supplier.CoopProductListResponse;
+import me.chanjar.weixin.channel.bean.league.supplier.CoopProductResponse;
+import me.chanjar.weixin.channel.bean.league.supplier.FlowListParam;
+import me.chanjar.weixin.channel.bean.league.supplier.ShopDetailResponse;
+import me.chanjar.weixin.channel.bean.league.supplier.ShopListResponse;
+import me.chanjar.weixin.channel.bean.league.supplier.SupplierBalanceResponse;
+import me.chanjar.weixin.channel.bean.league.supplier.SupplierFlowDetailResponse;
+import me.chanjar.weixin.channel.bean.league.supplier.SupplierFlowListResponse;
+import me.chanjar.weixin.common.error.WxErrorException;
+
+/**
+ * 优选联盟 团长数据服务
+ *
+ * @author Zeyes
+ */
+public interface WxLeagueSupplierService {
+
+ /**
+ * 获取团长账户余额
+ *
+ * @return 余额
+ */
+ SupplierBalanceResponse getBalanceInfo() throws WxErrorException;
+
+ /**
+ * 获取资金流水详情
+ *
+ * @param flowId 流水ID
+ * @return 流水详情
+ */
+ SupplierFlowDetailResponse getFlowDetail(String flowId) throws WxErrorException;
+
+ /**
+ * 获取团长资金流水列表
+ *
+ * @param param 查询参数
+ * @return 流水列表
+ */
+ SupplierFlowListResponse getFlowList(FlowListParam param) throws WxErrorException;
+
+ /**
+ * 获取合作商品详情
+ *
+ * @param productId 商品ID
+ * @param appId 团长商品 所属小店appid
+ * @return 商品详情
+ */
+ CoopProductResponse getProductDetail(String productId, String appId) throws WxErrorException;
+
+ /**
+ * 获取合作商品列表
+ *
+ * @param appid 团长商品 所属小店appid
+ * @param pageSize 单页商品数(不超过30)
+ * @param nextKey 由上次请求返回,顺序翻页时需要传入, 会从上次返回的结果往后翻一页
+ * @return 商品列表
+ */
+ CoopProductListResponse getProductList(String appid, Integer pageSize, String nextKey) throws WxErrorException;
+
+ /**
+ * 获取佣金单详情
+ *
+ * @param orderId 订单号,可从获取佣金单列表中获得
+ * @param skuId 商品skuId
+ * @return 订单详情
+ */
+ CommissionOrderResponse getCommissionOrder(String orderId, String skuId) throws WxErrorException;
+
+ /**
+ * 获取佣金单列表
+ *
+ * @param param 查询参数
+ * @return 佣金单列表
+ */
+ CommissionOrderListResponse getCommissionOrderList(CommissionOrderListParam param) throws WxErrorException;
+
+ /**
+ * 获取合作小店详情
+ *
+ * @param appid 小店appid
+ * @return 小店详情
+ */
+ ShopDetailResponse getShopDetail(String appid) throws WxErrorException;
+
+ /**
+ * 获取合作小店列表
+ *
+ * @param pageSize 单页小店数(不超过30)
+ * @param nextKey 由上次请求返回,顺序翻页时需要传入, 会从上次返回的结果往后翻一页
+ * @return 小店列表
+ */
+ ShopListResponse getShopList(Integer pageSize, String nextKey) throws WxErrorException;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxLeagueWindowService.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxLeagueWindowService.java
new file mode 100644
index 0000000000..c4af1571d0
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxLeagueWindowService.java
@@ -0,0 +1,72 @@
+package me.chanjar.weixin.channel.api;
+
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+import me.chanjar.weixin.channel.bean.league.window.AuthInfoResponse;
+import me.chanjar.weixin.channel.bean.league.window.AuthStatusResponse;
+import me.chanjar.weixin.channel.bean.league.window.ProductSearchParam;
+import me.chanjar.weixin.channel.bean.league.window.WindowProductListResponse;
+import me.chanjar.weixin.channel.bean.league.window.WindowProductResponse;
+import me.chanjar.weixin.common.error.WxErrorException;
+
+/**
+ * 优选联盟 团长合作达人管理服务
+ *
+ * @author Zeyes
+ */
+public interface WxLeagueWindowService {
+
+ /**
+ * 添加团长商品到橱窗
+ *
+ * @param appid 团长appid
+ * @param openfinderid 视频号openfinderid
+ * @param productId 团长商品ID
+ * @return 结果
+ */
+ WxChannelBaseResponse addProduct(String appid, String openfinderid, String productId) throws WxErrorException;
+
+ /**
+ * 查询橱窗上团长商品列表
+ *
+ * @param param 查询参数
+ * @return 团长商品列表
+ */
+ WindowProductListResponse listProduct(ProductSearchParam param) throws WxErrorException;
+
+ /**
+ * 从橱窗移除团长商品
+ *
+ * @param appid 团长appid
+ * @param openfinderid 视频号openfinderid
+ * @param productId 团长商品ID
+ * @return 结果
+ */
+ WxChannelBaseResponse removeProduct(String appid, String openfinderid, String productId) throws WxErrorException;
+
+ /**
+ * 查询橱窗上团长商品详情
+ *
+ * @param appid 团长appid
+ * @param openfinderid 视频号openfinderid
+ * @param productId 团长商品ID
+ * @return 结果
+ */
+ WindowProductResponse getProductDetail(String appid, String openfinderid, String productId)
+ throws WxErrorException;
+
+ /**
+ * 获取达人橱窗授权链接
+ *
+ * @param finderId 视频号finder_id
+ * @return 授权链接
+ */
+ AuthInfoResponse getWindowAuthInfo(String finderId) throws WxErrorException;
+
+ /**
+ * 获取达人橱窗授权状态
+ *
+ * @param finderId 视频号finder_id
+ * @return 授权链接
+ */
+ AuthStatusResponse getWindowAuthStatus(String finderId) throws WxErrorException;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/BaseWxChannelMessageServiceImpl.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/BaseWxChannelMessageServiceImpl.java
new file mode 100644
index 0000000000..008da958a9
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/BaseWxChannelMessageServiceImpl.java
@@ -0,0 +1,343 @@
+package me.chanjar.weixin.channel.api.impl;
+
+import static me.chanjar.weixin.channel.constant.MessageEventConstants.ACCOUNT_NOTIFY;
+import static me.chanjar.weixin.channel.constant.MessageEventConstants.AFTER_SALE_UPDATE;
+import static me.chanjar.weixin.channel.constant.MessageEventConstants.BRAND;
+import static me.chanjar.weixin.channel.constant.MessageEventConstants.COMPLAINT_NOTIFY;
+import static me.chanjar.weixin.channel.constant.MessageEventConstants.CREATE_COUPON;
+import static me.chanjar.weixin.channel.constant.MessageEventConstants.DELETE_COUPON;
+import static me.chanjar.weixin.channel.constant.MessageEventConstants.EXPIRE_COUPON;
+import static me.chanjar.weixin.channel.constant.MessageEventConstants.INVALID_COUPON;
+import static me.chanjar.weixin.channel.constant.MessageEventConstants.ORDER_CANCEL;
+import static me.chanjar.weixin.channel.constant.MessageEventConstants.ORDER_CONFIRM;
+import static me.chanjar.weixin.channel.constant.MessageEventConstants.ORDER_DELIVER;
+import static me.chanjar.weixin.channel.constant.MessageEventConstants.ORDER_EXT_INFO_UPDATE;
+import static me.chanjar.weixin.channel.constant.MessageEventConstants.ORDER_NEW;
+import static me.chanjar.weixin.channel.constant.MessageEventConstants.ORDER_PAY;
+import static me.chanjar.weixin.channel.constant.MessageEventConstants.ORDER_SETTLE;
+import static me.chanjar.weixin.channel.constant.MessageEventConstants.ORDER_STATUS_UPDATE;
+import static me.chanjar.weixin.channel.constant.MessageEventConstants.PRODUCT_CATEGORY_AUDIT;
+import static me.chanjar.weixin.channel.constant.MessageEventConstants.PRODUCT_SPU_AUDIT;
+import static me.chanjar.weixin.channel.constant.MessageEventConstants.PRODUCT_SPU_STATUS_UPDATE;
+import static me.chanjar.weixin.channel.constant.MessageEventConstants.PRODUCT_SPU_UPDATE;
+import static me.chanjar.weixin.channel.constant.MessageEventConstants.QRCODE_STATUS;
+import static me.chanjar.weixin.channel.constant.MessageEventConstants.RECEIVE_COUPON;
+import static me.chanjar.weixin.channel.constant.MessageEventConstants.SUPPLIER_ITEM_UPDATE;
+import static me.chanjar.weixin.channel.constant.MessageEventConstants.UPDATE_COUPON_INFO;
+import static me.chanjar.weixin.channel.constant.MessageEventConstants.USER_COUPON_EXPIRE;
+import static me.chanjar.weixin.channel.constant.MessageEventConstants.USER_COUPON_UNUSE;
+import static me.chanjar.weixin.channel.constant.MessageEventConstants.USER_COUPON_USE;
+import static me.chanjar.weixin.channel.constant.MessageEventConstants.WITHDRAW_NOTIFY;
+
+import java.util.Map;
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.channel.api.BaseWxChannelMessageService;
+import me.chanjar.weixin.channel.api.WxChannelService;
+import me.chanjar.weixin.channel.bean.message.after.AfterSaleMessage;
+import me.chanjar.weixin.channel.bean.message.after.ComplaintMessage;
+import me.chanjar.weixin.channel.bean.message.coupon.CouponActionMessage;
+import me.chanjar.weixin.channel.bean.message.coupon.CouponReceiveMessage;
+import me.chanjar.weixin.channel.bean.message.coupon.UserCouponExpireMessage;
+import me.chanjar.weixin.channel.bean.message.fund.AccountNotifyMessage;
+import me.chanjar.weixin.channel.bean.message.fund.QrNotifyMessage;
+import me.chanjar.weixin.channel.bean.message.fund.WithdrawNotifyMessage;
+import me.chanjar.weixin.channel.bean.message.order.OrderCancelMessage;
+import me.chanjar.weixin.channel.bean.message.order.OrderConfirmMessage;
+import me.chanjar.weixin.channel.bean.message.order.OrderDeliveryMessage;
+import me.chanjar.weixin.channel.bean.message.order.OrderExtMessage;
+import me.chanjar.weixin.channel.bean.message.order.OrderIdMessage;
+import me.chanjar.weixin.channel.bean.message.order.OrderPayMessage;
+import me.chanjar.weixin.channel.bean.message.order.OrderSettleMessage;
+import me.chanjar.weixin.channel.bean.message.order.OrderStatusMessage;
+import me.chanjar.weixin.channel.bean.message.product.BrandMessage;
+import me.chanjar.weixin.channel.bean.message.product.CategoryAuditMessage;
+import me.chanjar.weixin.channel.bean.message.product.SpuAuditMessage;
+import me.chanjar.weixin.channel.bean.message.supplier.SupplierItemMessage;
+import me.chanjar.weixin.channel.message.WxChannelMessage;
+import me.chanjar.weixin.channel.message.WxChannelMessageRouter;
+import me.chanjar.weixin.channel.message.WxChannelMessageRouterRule;
+import me.chanjar.weixin.channel.message.rule.HandlerConsumer;
+import me.chanjar.weixin.channel.util.JsonUtils;
+import me.chanjar.weixin.common.session.WxSessionManager;
+
+/**
+ * @author Zeyes
+ */
+@Slf4j
+public class BaseWxChannelMessageServiceImpl implements BaseWxChannelMessageService {
+
+ /** 消息路由器 */
+ protected WxChannelMessageRouter router;
+
+ public BaseWxChannelMessageServiceImpl(WxChannelMessageRouter router) {
+ this.router = router;
+ this.addDefaultRule();
+ }
+
+ /**
+ * 添加默认的回调规则
+ */
+ protected void addDefaultRule() {
+ /* 品牌资质事件回调 */
+ this.addRule(BrandMessage.class, BRAND, this::brandUpdate);
+ /* 商品审核结果 */
+ this.addRule(SpuAuditMessage.class, PRODUCT_SPU_AUDIT, this::spuAudit);
+ /* 商品上下架 */
+ this.addRule(SpuAuditMessage.class, PRODUCT_SPU_STATUS_UPDATE, this::spuStatusUpdate);
+ /* 商品更新 */
+ this.addRule(SpuAuditMessage.class, PRODUCT_SPU_UPDATE, this::spuUpdate);
+ /* 类目审核结果 */
+ this.addRule(CategoryAuditMessage.class, PRODUCT_CATEGORY_AUDIT, this::categoryAudit);
+ /* 订单下单 */
+ this.addRule(OrderIdMessage.class, ORDER_NEW, this::orderNew);
+ /* 订单取消 */
+ this.addRule(OrderCancelMessage.class, ORDER_CANCEL, this::orderCancel);
+ /* 订单支付成功 */
+ this.addRule(OrderPayMessage.class, ORDER_PAY, this::orderPay);
+ /* 订单发货 */
+ this.addRule(OrderDeliveryMessage.class, ORDER_DELIVER, this::orderDelivery);
+ /* 订单确认收货 */
+ this.addRule(OrderConfirmMessage.class, ORDER_CONFIRM, this::orderConfirm);
+ /* 订单结算成功 */
+ this.addRule(OrderSettleMessage.class, ORDER_SETTLE, this::orderSettle);
+ /* 订单其他信息更新 */
+ this.addRule(OrderExtMessage.class, ORDER_EXT_INFO_UPDATE, this::orderExtInfoUpdate);
+ /* 订单状态更新 */
+ this.addRule(OrderStatusMessage.class, ORDER_STATUS_UPDATE, this::orderStatusUpdate);
+ /* 售后单更新通知 */
+ this.addRule(AfterSaleMessage.class, AFTER_SALE_UPDATE, this::afterSaleStatusUpdate);
+ /* 纠纷更新通知 */
+ this.addRule(ComplaintMessage.class, COMPLAINT_NOTIFY, this::complaintNotify);
+ /* 优惠券领取通知 */
+ this.addRule(CouponReceiveMessage.class, RECEIVE_COUPON, this::couponReceive);
+ /* 优惠券使用通知 */
+ this.addRule(CouponActionMessage.class, CREATE_COUPON, this::couponCreate);
+ /* 优惠券删除通知 */
+ this.addRule(CouponActionMessage.class, DELETE_COUPON, this::couponDelete);
+ /* 优惠券过期通知 */
+ this.addRule(CouponActionMessage.class, EXPIRE_COUPON, this::couponExpire);
+ /* 更新优惠券信息通知 */
+ this.addRule(CouponActionMessage.class, UPDATE_COUPON_INFO, this::couponUpdate);
+ /* 更新优惠券信息通知 */
+ this.addRule(CouponActionMessage.class, INVALID_COUPON, this::couponInvalid);
+ /* 用户优惠券过期通知 */
+ this.addRule(UserCouponExpireMessage.class, USER_COUPON_EXPIRE, this::userCouponExpire);
+ /* 用户优惠券过期通知 */
+ this.addRule(UserCouponExpireMessage.class, USER_COUPON_UNUSE, this::userCouponUnuse);
+ /* 优惠券返还通知 */
+ this.addRule(UserCouponExpireMessage.class, USER_COUPON_USE, this::userCouponUse);
+ /* 结算账户变更回调 */
+ this.addRule(AccountNotifyMessage.class, ACCOUNT_NOTIFY, this::accountNotify);
+ /* 提现回调 */
+ this.addRule(WithdrawNotifyMessage.class, WITHDRAW_NOTIFY, this::withdrawNotify);
+ /* 提现二维码回调 */
+ this.addRule(QrNotifyMessage.class, QRCODE_STATUS, this::qrNotify);
+ /* 团长 */
+ this.addRule(SupplierItemMessage.class, SUPPLIER_ITEM_UPDATE, this::supplierItemUpdate);
+ }
+
+ /**
+ * 添加一条规则进入路由器
+ *
+ * @param clazz 消息类型
+ * @param event 事件类型
+ * @param consumer 处理器
+ * @param 消息类型
+ */
+ protected void addRule(Class clazz, String event,
+ HandlerConsumer, WxSessionManager> consumer) {
+ WxChannelMessageRouterRule rule = new WxChannelMessageRouterRule<>();
+ rule.setMessageClass(clazz).setEvent(event).setAsync(true);
+ rule.getHandlers().add((message, content, appId, context, sessionManager) -> {
+ consumer.accept(message, content, appId, context, sessionManager);
+ return "success";
+ });
+ this.addRule(rule);
+ }
+
+ @Override
+ public void addRule(WxChannelMessageRouterRule extends WxChannelMessage> rule) {
+ router.getRules().add(rule);
+ }
+
+ @Override
+ public Object route(WxChannelMessage message, String content, String appId, final WxChannelService service) {
+ return router.route(message, content, appId, service);
+ }
+
+
+ @Override
+ public void orderNew(OrderIdMessage message, String content, String appId,
+ Map context, WxSessionManager sessionManager) {
+ log.info("订单下单:{}", JsonUtils.encode(message));
+ }
+
+ @Override
+ public void orderCancel(OrderCancelMessage message, String content, String appId,
+ Map context, WxSessionManager sessionManager) {
+ log.info("订单取消:{}", JsonUtils.encode(message));
+ }
+
+ @Override
+ public void orderPay(OrderPayMessage message, String content, String appId,
+ Map context, WxSessionManager sessionManager) {
+ log.info("订单支付成功:{}", JsonUtils.encode(message));
+ }
+
+ @Override
+ public void orderDelivery(OrderDeliveryMessage message, String content, String appId,
+ Map context, WxSessionManager sessionManager) {
+ log.info("订单发货:{}", JsonUtils.encode(message));
+ }
+
+ @Override
+ public void orderConfirm(OrderConfirmMessage message, String content, String appId,
+ Map context, WxSessionManager sessionManager) {
+ log.info("订单确认收货:{}", JsonUtils.encode(message));
+ }
+
+ @Override
+ public void orderSettle(OrderSettleMessage message, String content, String appId,
+ Map context, WxSessionManager sessionManager) {
+ log.info("订单结算:{}", JsonUtils.encode(message));
+ }
+
+ @Override
+ public void orderExtInfoUpdate(OrderExtMessage message, String content, String appId,
+ Map context, WxSessionManager sessionManager) {
+ log.info("订单其他信息更新:{}", JsonUtils.encode(message));
+ }
+
+ @Override
+ public void orderStatusUpdate(OrderStatusMessage message, String content, String appId,
+ Map context, WxSessionManager sessionManager) {
+ log.info("订单状态更新:{}", JsonUtils.encode(message));
+ }
+
+ @Override
+ public void spuAudit(SpuAuditMessage message, String content, String appId,
+ Map context, WxSessionManager sessionManager) {
+ log.info("商品审核:{}", JsonUtils.encode(message));
+ }
+
+ @Override
+ public void spuStatusUpdate(SpuAuditMessage message, String content, String appId,
+ Map context, WxSessionManager sessionManager) {
+ log.info("商品状态更新:{}", JsonUtils.encode(message));
+ }
+
+ @Override
+ public void spuUpdate(SpuAuditMessage message, String content, String appId,
+ Map context, WxSessionManager sessionManager) {
+ log.info("商品更新:{}", JsonUtils.encode(message));
+ }
+
+ @Override
+ public void categoryAudit(CategoryAuditMessage message, String content, String appId,
+ Map context, WxSessionManager sessionManager) {
+ log.info("分类审核:{}", JsonUtils.encode(message));
+ }
+
+ @Override
+ public void brandUpdate(BrandMessage message, String content, String appId,
+ Map context, WxSessionManager sessionManager) {
+ log.info("品牌更新:{}", JsonUtils.encode(message));
+ }
+
+ @Override
+ public void afterSaleStatusUpdate(AfterSaleMessage message, String content, String appId,
+ Map context, WxSessionManager sessionManager) {
+ log.info("售后状态更新:{}", JsonUtils.encode(message));
+ }
+
+ @Override
+ public void complaintNotify(ComplaintMessage message, String content, String appId,
+ Map context, WxSessionManager sessionManager) {
+ log.info("投诉通知:{}", JsonUtils.encode(message));
+ }
+
+ @Override
+ public void couponReceive(CouponReceiveMessage message, String content, String appId,
+ Map context, WxSessionManager sessionManager) {
+ log.info("优惠券领取:{}", JsonUtils.encode(message));
+ }
+
+ @Override
+ public void couponCreate(CouponActionMessage message, String content, String appId,
+ Map context, WxSessionManager sessionManager) {
+ log.info("优惠券创建:{}", JsonUtils.encode(message));
+ }
+
+ @Override
+ public void couponDelete(CouponActionMessage message, String content, String appId,
+ Map context, WxSessionManager sessionManager) {
+ log.info("优惠券删除:{}", JsonUtils.encode(message));
+ }
+
+ @Override
+ public void couponExpire(CouponActionMessage message, String content, String appId,
+ Map context, WxSessionManager sessionManager) {
+ log.info("优惠券过期:{}", JsonUtils.encode(message));
+ }
+
+ @Override
+ public void couponUpdate(CouponActionMessage message, String content, String appId,
+ Map context, WxSessionManager sessionManager) {
+ log.info("优惠券更新:{}", JsonUtils.encode(message));
+ }
+
+ @Override
+ public void couponInvalid(CouponActionMessage message, String content, String appId,
+ Map context, WxSessionManager sessionManager) {
+ log.info("优惠券失效:{}", JsonUtils.encode(message));
+ }
+
+ @Override
+ public void userCouponExpire(UserCouponExpireMessage message, String content, String appId,
+ Map context, WxSessionManager sessionManager) {
+ log.info("用户优惠券过期:{}", JsonUtils.encode(message));
+ }
+
+ @Override
+ public void userCouponUse(UserCouponExpireMessage message, String content, String appId,
+ Map context, WxSessionManager sessionManager) {
+ log.info("用户优惠券使用:{}", JsonUtils.encode(message));
+ }
+
+ @Override
+ public void userCouponUnuse(UserCouponExpireMessage message, String content, String appId,
+ Map context, WxSessionManager sessionManager) {
+ log.info("用户优惠券取消使用:{}", JsonUtils.encode(message));
+ }
+
+ @Override
+ public void accountNotify(AccountNotifyMessage message, String content, String appId,
+ Map context, WxSessionManager sessionManager) {
+ log.info("账户通知:{}", JsonUtils.encode(message));
+ }
+
+ @Override
+ public void withdrawNotify(WithdrawNotifyMessage message, String content, String appId,
+ Map context, WxSessionManager sessionManager) {
+ log.info("提现通知:{}", JsonUtils.encode(message));
+ }
+
+ @Override
+ public void qrNotify(QrNotifyMessage message, String content, String appId,
+ Map context, WxSessionManager sessionManager) {
+ log.info("二维码通知:{}", JsonUtils.encode(message));
+ }
+
+ @Override
+ public void supplierItemUpdate(SupplierItemMessage message, String content, String appId,
+ Map context, WxSessionManager sessionManager) {
+ log.info("供应商商品更新:{}", JsonUtils.encode(message));
+ }
+
+ @Override
+ public Object defaultMessageHandler(WxChannelMessage message, String content, String appId,
+ Map context, WxSessionManager sessionManager) {
+ log.info("默认消息处理:{}", JsonUtils.encode(message));
+ return null;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/BaseWxChannelServiceImpl.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/BaseWxChannelServiceImpl.java
new file mode 100644
index 0000000000..6dd12a5b51
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/BaseWxChannelServiceImpl.java
@@ -0,0 +1,389 @@
+package me.chanjar.weixin.channel.api.impl;
+
+
+import com.google.gson.JsonObject;
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Lock;
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.channel.api.WxChannelAddressService;
+import me.chanjar.weixin.channel.api.WxChannelAfterSaleService;
+import me.chanjar.weixin.channel.api.WxChannelBasicService;
+import me.chanjar.weixin.channel.api.WxChannelBrandService;
+import me.chanjar.weixin.channel.api.WxChannelCategoryService;
+import me.chanjar.weixin.channel.api.WxChannelCouponService;
+import me.chanjar.weixin.channel.api.WxChannelFreightTemplateService;
+import me.chanjar.weixin.channel.api.WxChannelFundService;
+import me.chanjar.weixin.channel.api.WxChannelOrderService;
+import me.chanjar.weixin.channel.api.WxChannelProductService;
+import me.chanjar.weixin.channel.api.WxChannelService;
+import me.chanjar.weixin.channel.api.WxChannelSharerService;
+import me.chanjar.weixin.channel.api.WxChannelWarehouseService;
+import me.chanjar.weixin.channel.api.WxLeagueProductService;
+import me.chanjar.weixin.channel.api.WxLeaguePromoterService;
+import me.chanjar.weixin.channel.api.WxLeagueSupplierService;
+import me.chanjar.weixin.channel.api.WxLeagueWindowService;
+import me.chanjar.weixin.channel.config.WxChannelConfig;
+import me.chanjar.weixin.channel.util.JsonUtils;
+import me.chanjar.weixin.common.api.WxConsts;
+import me.chanjar.weixin.common.bean.ToJson;
+import me.chanjar.weixin.common.bean.WxAccessToken;
+import me.chanjar.weixin.common.enums.WxType;
+import me.chanjar.weixin.common.error.WxError;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.error.WxRuntimeException;
+import me.chanjar.weixin.common.util.DataUtils;
+import me.chanjar.weixin.common.util.crypto.SHA1;
+import me.chanjar.weixin.common.util.http.RequestExecutor;
+import me.chanjar.weixin.common.util.http.RequestHttp;
+import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor;
+import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * @author Zeyes
+ * @see #doGetAccessTokenRequest
+ */
+@Slf4j
+public abstract class BaseWxChannelServiceImpl implements WxChannelService, RequestHttp {
+
+ private final WxChannelBasicService basicService = new WxChannelBasicServiceImpl(this);
+ private final WxChannelCategoryService categoryService = new WxChannelCategoryServiceImpl(this);
+ private final WxChannelBrandService brandService = new WxChannelBrandServiceImpl(this);
+ private final WxChannelProductService productService = new WxChannelProductServiceImpl(this);
+ private final WxChannelWarehouseService warehouseService = new WxChannelWarehouseServiceImpl(this);
+ private final WxChannelOrderService orderService = new WxChannelOrderServiceImpl(this);
+ private final WxChannelAfterSaleService afterSaleService = new WxChannelAfterSaleServiceImpl(this);
+ private final WxChannelFreightTemplateService freightTemplateService =
+ new WxChannelFreightTemplateServiceImpl(this);
+ private final WxChannelAddressService addressService = new WxChannelAddressServiceImpl(this);
+ private final WxChannelCouponService couponService = new WxChannelCouponServiceImpl(this);
+ private final WxChannelSharerService sharerService = new WxChannelSharerServiceImpl(this);
+ private final WxChannelFundService fundService = new WxChannelFundServiceImpl(this);
+ private WxLeagueWindowService leagueWindowService = null;
+ private WxLeagueSupplierService leagueSupplierService = null;
+ private WxLeaguePromoterService leaguePromoterService = null;
+ private WxLeagueProductService leagueProductService = null;
+
+ protected WxChannelConfig config;
+ private int retrySleepMillis = 1000;
+ private int maxRetryTimes = 5;
+
+ @Override
+ public RequestHttp getRequestHttp() {
+ return this;
+ }
+
+ @Override
+ public boolean checkSignature(String timestamp, String nonce, String signature) {
+ try {
+ return SHA1.gen(this.getConfig().getToken(), timestamp, nonce).equals(signature);
+ } catch (Exception e) {
+ log.error("Checking signature failed, and the reason is :" + e.getMessage());
+ return false;
+ }
+ }
+
+ @Override
+ public String getAccessToken() throws WxErrorException {
+ return getAccessToken(false);
+ }
+
+ @Override
+ public String getAccessToken(boolean forceRefresh) throws WxErrorException {
+ if (!forceRefresh && !this.getConfig().isAccessTokenExpired()) {
+ return this.getConfig().getAccessToken();
+ }
+
+ Lock lock = this.getConfig().getAccessTokenLock();
+ boolean locked = false;
+ try {
+ do {
+ locked = lock.tryLock(100, TimeUnit.MILLISECONDS);
+ if (!forceRefresh && !this.getConfig().isAccessTokenExpired()) {
+ return this.getConfig().getAccessToken();
+ }
+ } while (!locked);
+ String response = doGetAccessTokenRequest();
+ return extractAccessToken(response);
+ } catch (IOException | InterruptedException e) {
+ throw new WxRuntimeException(e);
+ } finally {
+ if (locked) {
+ lock.unlock();
+ }
+ }
+ }
+
+ /**
+ * 通过网络请求获取AccessToken
+ *
+ * @return .
+ *
+ * @throws IOException .
+ */
+ protected abstract String doGetAccessTokenRequest() throws IOException;
+
+ @Override
+ public String get(String url, String queryParam) throws WxErrorException {
+ return execute(SimpleGetRequestExecutor.create(this), url, queryParam);
+ }
+
+ @Override
+ public String post(String url, String postData) throws WxErrorException {
+ return execute(SimplePostRequestExecutor.create(this), url, postData);
+ }
+
+ @Override
+ public String post(String url, Object obj) throws WxErrorException {
+ // 此处用JsonUtils.encode, 不用Gson
+ return this.execute(SimplePostRequestExecutor.create(this), url, JsonUtils.encode(obj));
+ }
+
+ @Override
+ public String post(String url, ToJson obj) throws WxErrorException {
+ return this.post(url, obj.toJson());
+ }
+
+ @Override
+ public String post(String url, JsonObject jsonObject) throws WxErrorException {
+ return this.post(url, jsonObject.toString());
+ }
+
+ /**
+ * 向微信端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求
+ */
+ @Override
+ public T execute(RequestExecutor executor, String uri, E data) throws WxErrorException {
+ return execute0(executor, uri, data, true);
+ }
+
+ @Override
+ public T executeWithoutLog(RequestExecutor executor, String uri, E data) throws WxErrorException {
+ return execute0(executor, uri, data, false);
+ }
+
+ protected T execute0(RequestExecutor executor, String uri, E data, boolean printResult)
+ throws WxErrorException {
+ int retryTimes = 0;
+ do {
+ try {
+ return this.executeInternal(executor, uri, data, false, printResult);
+ } catch (WxErrorException e) {
+ if (retryTimes + 1 > this.maxRetryTimes) {
+ log.warn("重试达到最大次数【{}】", maxRetryTimes);
+ //最后一次重试失败后,直接抛出异常,不再等待
+ throw new WxErrorException(WxError.builder()
+ .errorCode(e.getError().getErrorCode())
+ .errorMsg("微信服务端异常,超出重试次数!")
+ .build());
+ }
+
+ WxError error = e.getError();
+ // -1 系统繁忙, 1000ms后重试
+ if (error.getErrorCode() == -1) {
+ int sleepMillis = this.retrySleepMillis * (1 << retryTimes);
+ try {
+ log.warn("微信系统繁忙,{} ms 后重试(第{}次)", sleepMillis, retryTimes + 1);
+ Thread.sleep(sleepMillis);
+ } catch (InterruptedException e1) {
+ Thread.currentThread().interrupt();
+ }
+ } else {
+ throw e;
+ }
+ }
+ } while (retryTimes++ < this.maxRetryTimes);
+
+ log.warn("重试达到最大次数【{}】", this.maxRetryTimes);
+ throw new WxRuntimeException("微信服务端异常,超出重试次数");
+ }
+
+ protected T executeInternal(RequestExecutor executor, String uri, E data, boolean doNotAutoRefreshToken,
+ boolean printResult) throws WxErrorException {
+ E dataForLog = DataUtils.handleDataWithSecret(data);
+
+ if (uri.contains("access_token=")) {
+ throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri);
+ }
+ String accessToken = getAccessToken(false);
+
+ WxChannelConfig config = this.getConfig();
+ if (StringUtils.isNotEmpty(config.getApiHostUrl())) {
+ uri = uri.replace("https://api.weixin.qq.com", config.getApiHostUrl());
+ }
+
+ String uriWithAccessToken = uri + (uri.contains("?") ? "&" : "?") + "access_token=" + accessToken;
+
+ try {
+ T result = executor.execute(uriWithAccessToken, data, WxType.Channel);
+ log.debug("\n【请求地址】: {}\n【请求参数】:{}\n【响应数据】:{}", uriWithAccessToken, dataForLog,
+ printResult ? result : "...");
+ return result;
+ } catch (WxErrorException e) {
+ WxError error = e.getError();
+ if (WxConsts.ACCESS_TOKEN_ERROR_CODES.contains(error.getErrorCode())) {
+ // 强制设置WxMaConfig的access token过期了,这样在下一次请求里就会刷新access token
+ Lock lock = config.getAccessTokenLock();
+ lock.lock();
+ try {
+ if (StringUtils.equals(config.getAccessToken(), accessToken)) {
+ config.expireAccessToken();
+ }
+ } catch (Exception ex) {
+ config.expireAccessToken();
+ } finally {
+ lock.unlock();
+ }
+ if (config.autoRefreshToken() && !doNotAutoRefreshToken) {
+ log.warn("即将重新获取新的access_token,错误代码:{},错误信息:{}", error.getErrorCode(), error.getErrorMsg());
+ //下一次不再自动重试
+ //当小程序误调用第三方平台专属接口时,第三方无法使用小程序的access token,如果可以继续自动获取token会导致无限循环重试,直到栈溢出
+ return this.executeInternal(executor, uri, data, true, printResult);
+ }
+ }
+
+ if (error.getErrorCode() != 0) {
+ log.warn("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", uriWithAccessToken, dataForLog, error);
+ throw new WxErrorException(error, e);
+ }
+ return null;
+ } catch (IOException e) {
+ log.warn("\n【请求地址】: {}\n【请求参数】:{}\n【异常信息】:{}", uriWithAccessToken, dataForLog, e.getMessage());
+ throw new WxRuntimeException(e);
+ }
+ }
+
+ /**
+ * 设置当前的AccessToken
+ *
+ * @param resultContent 响应内容
+ * @return access token
+ *
+ * @throws WxErrorException 异常
+ */
+ protected String extractAccessToken(String resultContent) throws WxErrorException {
+ log.info("resultContent: " + resultContent);
+ WxChannelConfig config = this.getConfig();
+ WxError error = WxError.fromJson(resultContent, WxType.MiniApp);
+ if (error.getErrorCode() != 0) {
+ throw new WxErrorException(error);
+ }
+ WxAccessToken accessToken = WxAccessToken.fromJson(resultContent);
+ config.updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn());
+ return accessToken.getAccessToken();
+ }
+
+ @Override
+ public WxChannelConfig getConfig() {
+ return config;
+ }
+
+ @Override
+ public void setConfig(WxChannelConfig config) {
+ this.config = config;
+ initHttp();
+ }
+
+ @Override
+ public void setRetrySleepMillis(int retrySleepMillis) {
+ this.retrySleepMillis = retrySleepMillis;
+ }
+
+ @Override
+ public void setMaxRetryTimes(int maxRetryTimes) {
+ this.maxRetryTimes = maxRetryTimes;
+ }
+
+ @Override
+ public WxChannelBasicService getBasicService() {
+ return basicService;
+ }
+
+ @Override
+ public WxChannelCategoryService getCategoryService() {
+ return categoryService;
+ }
+
+ @Override
+ public WxChannelBrandService getBrandService() {
+ return brandService;
+ }
+
+ @Override
+ public WxChannelProductService getProductService() {
+ return productService;
+ }
+
+ @Override
+ public WxChannelWarehouseService getWarehouseService() {
+ return warehouseService;
+ }
+
+ @Override
+ public WxChannelOrderService getOrderService() {
+ return orderService;
+ }
+
+ @Override
+ public WxChannelAfterSaleService getAfterSaleService() {
+ return afterSaleService;
+ }
+
+ @Override
+ public WxChannelFreightTemplateService getFreightTemplateService() {
+ return freightTemplateService;
+ }
+
+ @Override
+ public WxChannelAddressService getAddressService() {
+ return addressService;
+ }
+
+ @Override
+ public WxChannelCouponService getCouponService() {
+ return couponService;
+ }
+
+ @Override
+ public WxChannelSharerService getSharerService() {
+ return sharerService;
+ }
+
+ @Override
+ public WxChannelFundService getFundService() {
+ return fundService;
+ }
+
+ @Override
+ public synchronized WxLeagueWindowService getLeagueWindowService() {
+ if (leagueWindowService == null) {
+ leagueWindowService = new WxLeagueWindowServiceImpl(this);
+ }
+ return leagueWindowService;
+ }
+
+ @Override
+ public synchronized WxLeagueSupplierService getLeagueSupplierService() {
+ if (leagueSupplierService == null) {
+ leagueSupplierService = new WxLeagueSupplierServiceImpl(this);
+ }
+ return leagueSupplierService;
+ }
+
+ @Override
+ public synchronized WxLeaguePromoterService getLeaguePromoterService() {
+ if (leaguePromoterService == null) {
+ leaguePromoterService = new WxLeaguePromoterServiceImpl(this);
+ }
+ return leaguePromoterService;
+ }
+
+ @Override
+ public synchronized WxLeagueProductService getLeagueProductService() {
+ if (leagueProductService == null) {
+ leagueProductService = new WxLeagueProductServiceImpl(this);
+ }
+ return leagueProductService;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelAddressServiceImpl.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelAddressServiceImpl.java
new file mode 100644
index 0000000000..53b9eb4d7a
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelAddressServiceImpl.java
@@ -0,0 +1,72 @@
+package me.chanjar.weixin.channel.api.impl;
+
+
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Address.ADD_ADDRESS_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Address.DELETE_ADDRESS_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Address.GET_ADDRESS_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Address.LIST_ADDRESS_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Address.UPDATE_ADDRESS_URL;
+
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.channel.api.WxChannelAddressService;
+import me.chanjar.weixin.channel.bean.address.AddressAddParam;
+import me.chanjar.weixin.channel.bean.address.AddressDetail;
+import me.chanjar.weixin.channel.bean.address.AddressIdParam;
+import me.chanjar.weixin.channel.bean.address.AddressIdResponse;
+import me.chanjar.weixin.channel.bean.address.AddressInfoResponse;
+import me.chanjar.weixin.channel.bean.address.AddressListParam;
+import me.chanjar.weixin.channel.bean.address.AddressListResponse;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+import me.chanjar.weixin.channel.util.ResponseUtils;
+import me.chanjar.weixin.common.error.WxErrorException;
+
+/**
+ * 视频号小店 地址管理服务实现
+ *
+ * @author Zeyes
+ */
+@Slf4j
+public class WxChannelAddressServiceImpl implements WxChannelAddressService {
+
+ /** 微信商店服务 */
+ private final BaseWxChannelServiceImpl shopService;
+
+ public WxChannelAddressServiceImpl(BaseWxChannelServiceImpl shopService) {
+ this.shopService = shopService;
+ }
+
+ @Override
+ public AddressListResponse listAddress(Integer offset, Integer limit) throws WxErrorException {
+ AddressListParam param = new AddressListParam(offset, limit);
+ String resJson = shopService.post(LIST_ADDRESS_URL, param);
+ return ResponseUtils.decode(resJson, AddressListResponse.class);
+ }
+
+ @Override
+ public AddressInfoResponse getAddress(String addressId) throws WxErrorException {
+ AddressIdParam param = new AddressIdParam(addressId);
+ String resJson = shopService.post(GET_ADDRESS_URL, param);
+ return ResponseUtils.decode(resJson, AddressInfoResponse.class);
+ }
+
+ @Override
+ public AddressIdResponse addAddress(AddressDetail addressDetail) throws WxErrorException {
+ AddressAddParam param = new AddressAddParam(addressDetail);
+ String resJson = shopService.post(ADD_ADDRESS_URL, param);
+ return ResponseUtils.decode(resJson, AddressIdResponse.class);
+ }
+
+ @Override
+ public WxChannelBaseResponse updateAddress(AddressDetail addressDetail) throws WxErrorException {
+ AddressAddParam param = new AddressAddParam(addressDetail);
+ String resJson = shopService.post(UPDATE_ADDRESS_URL, param);
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+ }
+
+ @Override
+ public WxChannelBaseResponse deleteAddress(String addressId) throws WxErrorException {
+ AddressIdParam param = new AddressIdParam(addressId);
+ String resJson = shopService.post(DELETE_ADDRESS_URL, param);
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelAfterSaleServiceImpl.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelAfterSaleServiceImpl.java
new file mode 100644
index 0000000000..c29ea49b34
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelAfterSaleServiceImpl.java
@@ -0,0 +1,103 @@
+package me.chanjar.weixin.channel.api.impl;
+
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.AfterSale.AFTER_SALE_ACCEPT_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.AfterSale.AFTER_SALE_GET_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.AfterSale.AFTER_SALE_LIST_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.AfterSale.AFTER_SALE_REJECT_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.AfterSale.AFTER_SALE_UPLOAD_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Complaint.ADD_COMPLAINT_MATERIAL_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Complaint.ADD_COMPLAINT_PROOF_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Complaint.GET_COMPLAINT_ORDER_URL;
+
+import java.util.List;
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.channel.api.WxChannelAfterSaleService;
+import me.chanjar.weixin.channel.bean.after.AfterSaleAcceptParam;
+import me.chanjar.weixin.channel.bean.after.AfterSaleIdParam;
+import me.chanjar.weixin.channel.bean.after.AfterSaleInfoResponse;
+import me.chanjar.weixin.channel.bean.after.AfterSaleListParam;
+import me.chanjar.weixin.channel.bean.after.AfterSaleListResponse;
+import me.chanjar.weixin.channel.bean.after.AfterSaleRejectParam;
+import me.chanjar.weixin.channel.bean.after.RefundEvidenceParam;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+import me.chanjar.weixin.channel.bean.complaint.ComplaintOrderResponse;
+import me.chanjar.weixin.channel.bean.complaint.ComplaintParam;
+import me.chanjar.weixin.channel.util.ResponseUtils;
+import me.chanjar.weixin.common.error.WxErrorException;
+
+/**
+ * 视频号小店 售后服务实现
+ *
+ * @author Zeyes
+ */
+@Slf4j
+public class WxChannelAfterSaleServiceImpl implements WxChannelAfterSaleService {
+
+ /** 微信商店服务 */
+ private final BaseWxChannelServiceImpl shopService;
+
+ public WxChannelAfterSaleServiceImpl(BaseWxChannelServiceImpl shopService) {
+ this.shopService = shopService;
+ }
+
+ @Override
+ public AfterSaleListResponse listIds(Long beginCreateTime, Long endCreateTime, String nextKey)
+ throws WxErrorException {
+ AfterSaleListParam param = new AfterSaleListParam(beginCreateTime, endCreateTime, nextKey);
+ String resJson = shopService.post(AFTER_SALE_LIST_URL, param);
+ return ResponseUtils.decode(resJson, AfterSaleListResponse.class);
+ }
+
+ @Override
+ public AfterSaleInfoResponse get(String afterSaleOrderId) throws WxErrorException {
+ AfterSaleIdParam param = new AfterSaleIdParam(afterSaleOrderId);
+ String resJson = shopService.post(AFTER_SALE_GET_URL, param);
+ return ResponseUtils.decode(resJson, AfterSaleInfoResponse.class);
+ }
+
+ @Override
+ public WxChannelBaseResponse accept(String afterSaleOrderId, String addressId) throws WxErrorException {
+ AfterSaleAcceptParam param = new AfterSaleAcceptParam(afterSaleOrderId, addressId);
+ String resJson = shopService.post(AFTER_SALE_ACCEPT_URL, param);
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+ }
+
+ @Override
+ public WxChannelBaseResponse reject(String afterSaleOrderId, String rejectReason) throws WxErrorException {
+ AfterSaleRejectParam param = new AfterSaleRejectParam(afterSaleOrderId, rejectReason);
+ String resJson = shopService.post(AFTER_SALE_REJECT_URL, param);
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+ }
+
+ @Override
+ public WxChannelBaseResponse uploadRefundEvidence(String afterSaleOrderId, String desc, List certificates)
+ throws WxErrorException {
+ RefundEvidenceParam param = new RefundEvidenceParam(afterSaleOrderId, desc, certificates);
+ String resJson = shopService.post(AFTER_SALE_UPLOAD_URL, param);
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+ }
+
+ @Override
+ public WxChannelBaseResponse addComplaintMaterial(String complaintId, String content, List mediaIds)
+ throws WxErrorException {
+ ComplaintParam param = new ComplaintParam(complaintId, content, mediaIds);
+ String resJson = shopService.post(ADD_COMPLAINT_MATERIAL_URL, param);
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+
+ }
+
+ @Override
+ public WxChannelBaseResponse addComplaintEvidence(String complaintId, String content, List mediaIds)
+ throws WxErrorException {
+ ComplaintParam param = new ComplaintParam(complaintId, content, mediaIds);
+ String resJson = shopService.post(ADD_COMPLAINT_PROOF_URL, param);
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+ }
+
+ @Override
+ public ComplaintOrderResponse getComplaint(String complaintId) throws WxErrorException {
+ String reqJson = "{\"complaint_id\":\"" + complaintId + "\"}";
+ String resJson = shopService.post(GET_COMPLAINT_ORDER_URL, reqJson);
+ return ResponseUtils.decode(resJson, ComplaintOrderResponse.class);
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelBasicServiceImpl.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelBasicServiceImpl.java
new file mode 100644
index 0000000000..cac5e9e513
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelBasicServiceImpl.java
@@ -0,0 +1,96 @@
+package me.chanjar.weixin.channel.api.impl;
+
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Basics.GET_ADDRESS_CODE;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Basics.GET_IMG_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Basics.GET_SHOP_INFO;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Basics.IMG_UPLOAD_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Basics.UPLOAD_QUALIFICATION_FILE;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.channel.api.WxChannelBasicService;
+import me.chanjar.weixin.channel.bean.address.AddressCodeResponse;
+import me.chanjar.weixin.channel.bean.image.ChannelImageInfo;
+import me.chanjar.weixin.channel.bean.image.ChannelImageResponse;
+import me.chanjar.weixin.channel.bean.image.QualificationFileResponse;
+import me.chanjar.weixin.channel.bean.image.UploadImageResponse;
+import me.chanjar.weixin.channel.bean.shop.ShopInfoResponse;
+import me.chanjar.weixin.channel.executor.ChannelFileUploadRequestExecutor;
+import me.chanjar.weixin.channel.executor.ChannelMediaDownloadRequestExecutor;
+import me.chanjar.weixin.channel.util.ResponseUtils;
+import me.chanjar.weixin.common.error.WxError;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.util.http.RequestExecutor;
+
+/**
+ * @author Zeyes
+ */
+@Slf4j
+public class WxChannelBasicServiceImpl implements WxChannelBasicService {
+
+ /** 微信商店服务 */
+ private final BaseWxChannelServiceImpl shopService;
+
+ public WxChannelBasicServiceImpl(BaseWxChannelServiceImpl shopService) {
+ this.shopService = shopService;
+ }
+
+ @Override
+ public ShopInfoResponse getShopInfo() throws WxErrorException {
+ String resJson = shopService.get(GET_SHOP_INFO, null);
+ return ResponseUtils.decode(resJson, ShopInfoResponse.class);
+ }
+
+ @Override
+ public ChannelImageInfo uploadImg(int respType, String imgUrl) throws WxErrorException {
+ String url = IMG_UPLOAD_URL + "?upload_type=1&resp_type=" + respType;
+ String reqJson = "{\"img_url\":\"" + imgUrl + "\"}";
+ String resJson = shopService.post(url, reqJson);
+ UploadImageResponse response = ResponseUtils.decode(resJson, UploadImageResponse.class);
+ return response.getImgInfo();
+ }
+
+ @Override
+ public ChannelImageInfo uploadImg(int respType, File file, int height, int width) throws WxErrorException {
+ String url = IMG_UPLOAD_URL + "?upload_type=0&resp_type=" + respType + "&height=" + height + "&width=" + width;
+ RequestExecutor executor = ChannelFileUploadRequestExecutor.create(shopService);
+ String resJson = (String) shopService.execute(executor, url, file);
+ UploadImageResponse response = ResponseUtils.decode(resJson, UploadImageResponse.class);
+ return response.getImgInfo();
+ }
+
+ @Override
+ public QualificationFileResponse uploadQualificationFile(File file) throws WxErrorException {
+ RequestExecutor executor = ChannelFileUploadRequestExecutor.create(shopService);
+ String resJson = (String) shopService.execute(executor, UPLOAD_QUALIFICATION_FILE, file);
+ return ResponseUtils.decode(resJson, QualificationFileResponse.class);
+ }
+
+ @Override
+ public ChannelImageResponse getImg(String mediaId) throws WxErrorException {
+ String appId = shopService.getConfig().getAppid();
+ ChannelImageResponse rs = null;
+ try {
+ String url = GET_IMG_URL + "?media_id=" + mediaId;
+ RequestExecutor executor = ChannelMediaDownloadRequestExecutor.create(shopService,
+ Files.createTempDirectory("wxjava-channel-" + appId).toFile());
+ rs = (ChannelImageResponse) shopService.execute(executor, url, null);
+ } catch (IOException e) {
+ throw new WxErrorException(WxError.builder().errorMsg(e.getMessage()).build(), e);
+ }
+ if (rs == null) {
+ rs = ResponseUtils.internalError(ChannelImageResponse.class);
+ }
+ return rs;
+ }
+
+ @Override
+ public AddressCodeResponse getAddressCode(Integer code) throws WxErrorException {
+ String reqJson = "{\"addr_code\": " + code + "}";
+ String resJson = shopService.post(GET_ADDRESS_CODE, reqJson);
+ return ResponseUtils.decode(resJson, AddressCodeResponse.class);
+ }
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelBrandServiceImpl.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelBrandServiceImpl.java
new file mode 100644
index 0000000000..19aadcc06e
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelBrandServiceImpl.java
@@ -0,0 +1,98 @@
+package me.chanjar.weixin.channel.api.impl;
+
+
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Brand.ADD_BRAND_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Brand.ALL_BRAND_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Brand.CANCEL_BRAND_AUDIT_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Brand.DELETE_BRAND_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Brand.GET_BRAND_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Brand.LIST_BRAND_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Brand.LIST_BRAND_VALID_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Brand.UPDATE_BRAND_URL;
+
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.channel.api.WxChannelBrandService;
+import me.chanjar.weixin.channel.bean.audit.AuditApplyResponse;
+import me.chanjar.weixin.channel.bean.base.StreamPageParam;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+import me.chanjar.weixin.channel.bean.brand.Brand;
+import me.chanjar.weixin.channel.bean.brand.BrandApplyListResponse;
+import me.chanjar.weixin.channel.bean.brand.BrandInfoResponse;
+import me.chanjar.weixin.channel.bean.brand.BrandListResponse;
+import me.chanjar.weixin.channel.bean.brand.BrandParam;
+import me.chanjar.weixin.channel.bean.brand.BrandSearchParam;
+import me.chanjar.weixin.channel.util.ResponseUtils;
+import me.chanjar.weixin.common.error.WxErrorException;
+
+/**
+ * 视频号小店 品牌服务实现
+ *
+ * @author Zeyes
+ */
+@Slf4j
+public class WxChannelBrandServiceImpl implements WxChannelBrandService {
+
+ /** 微信商店服务 */
+ private final BaseWxChannelServiceImpl shopService;
+
+ public WxChannelBrandServiceImpl(BaseWxChannelServiceImpl shopService) {
+ this.shopService = shopService;
+ }
+
+ @Override
+ public BrandListResponse listAllBrand(Integer pageSize, String nextKey) throws WxErrorException {
+ StreamPageParam param = new StreamPageParam(pageSize, nextKey);
+ String resJson = shopService.post(ALL_BRAND_URL, param);
+ return ResponseUtils.decode(resJson, BrandListResponse.class);
+ }
+
+ @Override
+ public AuditApplyResponse addBrandApply(Brand brand) throws WxErrorException {
+ BrandParam param = new BrandParam(brand);
+ String resJson = shopService.post(ADD_BRAND_URL, param);
+ return ResponseUtils.decode(resJson, AuditApplyResponse.class);
+ }
+
+ @Override
+ public AuditApplyResponse updateBrandApply(Brand brand) throws WxErrorException {
+ BrandParam param = new BrandParam(brand);
+ String resJson = shopService.post(UPDATE_BRAND_URL, param);
+ return ResponseUtils.decode(resJson, AuditApplyResponse.class);
+ }
+
+ @Override
+ public WxChannelBaseResponse cancelBrandApply(String brandId, String auditId) throws WxErrorException {
+ String reqJson = "{\"brand_id\":\"" + brandId + "\",\"audit_id\":\"" + auditId + "\"}";
+ String resJson = shopService.post(CANCEL_BRAND_AUDIT_URL, reqJson);
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+ }
+
+ @Override
+ public WxChannelBaseResponse deleteBrandApply(String brandId) throws WxErrorException {
+ String reqJson = "{\"brand_id\":\"" + brandId + "\"}";
+ String resJson = shopService.post(DELETE_BRAND_URL, reqJson);
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+ }
+
+ @Override
+ public BrandInfoResponse getBrandApply(String brandId) throws WxErrorException {
+ String reqJson = "{\"brand_id\":\"" + brandId + "\"}";
+ String resJson = shopService.post(GET_BRAND_URL, reqJson);
+ return ResponseUtils.decode(resJson, BrandInfoResponse.class);
+ }
+
+ @Override
+ public BrandApplyListResponse listBrandApply(Integer pageSize, String nextKey, Integer status)
+ throws WxErrorException {
+ BrandSearchParam param = new BrandSearchParam(pageSize, nextKey, status);
+ String resJson = shopService.post(LIST_BRAND_URL, param);
+ return ResponseUtils.decode(resJson, BrandApplyListResponse.class);
+ }
+
+ @Override
+ public BrandApplyListResponse listValidBrandApply(Integer pageSize, String nextKey) throws WxErrorException {
+ StreamPageParam param = new StreamPageParam(pageSize, nextKey);
+ String resJson = shopService.post(LIST_BRAND_VALID_URL, param);
+ return ResponseUtils.decode(resJson, BrandApplyListResponse.class);
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelCategoryServiceImpl.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelCategoryServiceImpl.java
new file mode 100644
index 0000000000..52fdf3cdf8
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelCategoryServiceImpl.java
@@ -0,0 +1,119 @@
+package me.chanjar.weixin.channel.api.impl;
+
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Category.ADD_CATEGORY_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Category.AVAILABLE_CATEGORY_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Category.CANCEL_CATEGORY_AUDIT_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Category.GET_CATEGORY_AUDIT_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Category.GET_CATEGORY_DETAIL_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Category.LIST_ALL_CATEGORY_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Category.LIST_PASS_CATEGORY_URL;
+
+import java.util.Collections;
+import java.util.List;
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.channel.api.WxChannelCategoryService;
+import me.chanjar.weixin.channel.bean.audit.AuditApplyResponse;
+import me.chanjar.weixin.channel.bean.audit.AuditResponse;
+import me.chanjar.weixin.channel.bean.audit.CategoryAuditInfo;
+import me.chanjar.weixin.channel.bean.audit.CategoryAuditRequest;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+import me.chanjar.weixin.channel.bean.category.CategoryDetailResult;
+import me.chanjar.weixin.channel.bean.category.CategoryQualificationResponse;
+import me.chanjar.weixin.channel.bean.category.PassCategoryResponse;
+import me.chanjar.weixin.channel.bean.category.ShopCategory;
+import me.chanjar.weixin.channel.bean.category.ShopCategoryResponse;
+import me.chanjar.weixin.channel.util.JsonUtils;
+import me.chanjar.weixin.channel.util.ResponseUtils;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor;
+import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor;
+
+/**
+ * 视频号小店 商品类目相关接口
+ *
+ * @author Zeyes
+ */
+@Slf4j
+public class WxChannelCategoryServiceImpl implements WxChannelCategoryService {
+
+ /** 微信商店服务 */
+ private final BaseWxChannelServiceImpl shopService;
+
+ public WxChannelCategoryServiceImpl(BaseWxChannelServiceImpl shopService) {
+ this.shopService = shopService;
+ }
+
+ @Override
+ public CategoryQualificationResponse listAllCategory() throws WxErrorException {
+ // 数据量太大了,不记录日志
+ String resJson = (String) shopService.executeWithoutLog(SimpleGetRequestExecutor.create(shopService),
+ LIST_ALL_CATEGORY_URL, null);
+ return ResponseUtils.decode(resJson, CategoryQualificationResponse.class);
+ }
+
+ public List listAvailableCategory(String parentId) throws WxErrorException {
+ Long pid = null;
+ try {
+ pid = Long.parseLong(parentId);
+ } catch (Throwable e) {
+ log.error("parentId必须为数字, " + parentId, e);
+ return Collections.emptyList();
+ }
+ String reqJson = "{\"f_cat_id\": " + pid + "}";
+ String resJson = (String) shopService.executeWithoutLog(SimplePostRequestExecutor.create(shopService),
+ AVAILABLE_CATEGORY_URL, reqJson);
+ ShopCategoryResponse response = ResponseUtils.decode(resJson, ShopCategoryResponse.class);
+ return response.getCategories();
+ }
+
+ @Override
+ public CategoryDetailResult getCategoryDetail(String id) throws WxErrorException {
+ Long catId = null;
+ try {
+ catId = Long.parseLong(id);
+ } catch (Throwable e) {
+ log.error("id必须为数字, " + id, e);
+ return ResponseUtils.internalError(CategoryDetailResult.class);
+ }
+ String reqJson = "{\"cat_id\": " + catId + "}";
+ String resJson = (String) shopService.executeWithoutLog(SimplePostRequestExecutor.create(shopService),
+ GET_CATEGORY_DETAIL_URL, reqJson);
+ return ResponseUtils.decode(resJson, CategoryDetailResult.class);
+ }
+
+ @Override
+ public AuditApplyResponse addCategory(String level1, String level2, String level3, List certificate)
+ throws WxErrorException {
+ String reqJson = null;
+ try {
+ Long l1 = Long.parseLong(level1);
+ Long l2 = Long.parseLong(level2);
+ Long l3 = Long.parseLong(level3);
+ CategoryAuditInfo categoryInfo = new CategoryAuditInfo(l1, l2, l3, certificate);
+ reqJson = JsonUtils.encode(new CategoryAuditRequest(categoryInfo));
+ } catch (Throwable e) {
+ log.error("微信请求异常", e);
+ }
+ String resJson = shopService.post(ADD_CATEGORY_URL, reqJson);
+ return ResponseUtils.decode(resJson, AuditApplyResponse.class);
+ }
+
+ @Override
+ public WxChannelBaseResponse cancelCategoryAudit(String auditId) throws WxErrorException {
+ String resJson = shopService.post(CANCEL_CATEGORY_AUDIT_URL, "{\"audit_id\": \"" + auditId + "\"}");
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+ }
+
+ @Override
+ public AuditResponse getAudit(String auditId) throws WxErrorException {
+ String resJson = shopService.post(GET_CATEGORY_AUDIT_URL, "{\"audit_id\": \"" + auditId + "\"}");
+ return ResponseUtils.decode(resJson, AuditResponse.class);
+ }
+
+ @Override
+ public PassCategoryResponse listPassCategory() throws WxErrorException {
+ String resJson = shopService.get(LIST_PASS_CATEGORY_URL, null);
+ return ResponseUtils.decode(resJson, PassCategoryResponse.class);
+ }
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelCouponServiceImpl.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelCouponServiceImpl.java
new file mode 100644
index 0000000000..174626f4a9
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelCouponServiceImpl.java
@@ -0,0 +1,88 @@
+package me.chanjar.weixin.channel.api.impl;
+
+
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Coupon.CREATE_COUPON_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Coupon.GET_COUPON_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Coupon.GET_USER_COUPON_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Coupon.LIST_COUPON_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Coupon.LIST_USER_COUPON_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Coupon.UPDATE_COUPON_STATUS_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Coupon.UPDATE_COUPON_URL;
+
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.channel.api.WxChannelCouponService;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+import me.chanjar.weixin.channel.bean.coupon.CouponIdInfo;
+import me.chanjar.weixin.channel.bean.coupon.CouponIdResponse;
+import me.chanjar.weixin.channel.bean.coupon.CouponInfoResponse;
+import me.chanjar.weixin.channel.bean.coupon.CouponListParam;
+import me.chanjar.weixin.channel.bean.coupon.CouponListResponse;
+import me.chanjar.weixin.channel.bean.coupon.CouponParam;
+import me.chanjar.weixin.channel.bean.coupon.CouponStatusParam;
+import me.chanjar.weixin.channel.bean.coupon.UserCouponIdParam;
+import me.chanjar.weixin.channel.bean.coupon.UserCouponListParam;
+import me.chanjar.weixin.channel.bean.coupon.UserCouponListResponse;
+import me.chanjar.weixin.channel.bean.coupon.UserCouponResponse;
+import me.chanjar.weixin.channel.util.ResponseUtils;
+import me.chanjar.weixin.common.error.WxErrorException;
+
+/**
+ * 视频号小店 优惠券服务实现
+ *
+ * @author Zeyes
+ */
+@Slf4j
+public class WxChannelCouponServiceImpl implements WxChannelCouponService {
+
+ /** 微信商店服务 */
+ private final BaseWxChannelServiceImpl shopService;
+
+ public WxChannelCouponServiceImpl(BaseWxChannelServiceImpl shopService) {
+ this.shopService = shopService;
+ }
+
+ @Override
+ public CouponIdResponse createCoupon(CouponParam coupon) throws WxErrorException {
+ String resJson = shopService.post(CREATE_COUPON_URL, coupon);
+ return ResponseUtils.decode(resJson, CouponIdResponse.class);
+ }
+
+ @Override
+ public CouponIdResponse updateCoupon(CouponParam coupon) throws WxErrorException {
+ String resJson = shopService.post(UPDATE_COUPON_URL, coupon);
+ return ResponseUtils.decode(resJson, CouponIdResponse.class);
+ }
+
+ @Override
+ public WxChannelBaseResponse updateCouponStatus(String couponId, Integer status) throws WxErrorException {
+ CouponStatusParam param = new CouponStatusParam(couponId, status);
+ String resJson = shopService.post(UPDATE_COUPON_STATUS_URL, param);
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+ }
+
+ @Override
+ public CouponInfoResponse getCoupon(String couponId) throws WxErrorException {
+ CouponIdInfo param = new CouponIdInfo(couponId);
+ String resJson = shopService.post(GET_COUPON_URL, param);
+ return ResponseUtils.decode(resJson, CouponInfoResponse.class);
+ }
+
+ @Override
+ public CouponListResponse getCouponList(CouponListParam param) throws WxErrorException {
+ String resJson = shopService.post(LIST_COUPON_URL, param);
+ return ResponseUtils.decode(resJson, CouponListResponse.class);
+ }
+
+ @Override
+ public UserCouponResponse getUserCoupon(String openId, String userCouponId) throws WxErrorException {
+ UserCouponIdParam param = new UserCouponIdParam(openId, userCouponId);
+ String resJson = shopService.post(GET_USER_COUPON_URL, param);
+ return ResponseUtils.decode(resJson, UserCouponResponse.class);
+ }
+
+ @Override
+ public UserCouponListResponse getUserCouponList(UserCouponListParam param) throws WxErrorException {
+ String resJson = shopService.post(LIST_USER_COUPON_URL, param);
+ return ResponseUtils.decode(resJson, UserCouponListResponse.class);
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelFreightTemplateServiceImpl.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelFreightTemplateServiceImpl.java
new file mode 100644
index 0000000000..8fbfbd09c3
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelFreightTemplateServiceImpl.java
@@ -0,0 +1,61 @@
+package me.chanjar.weixin.channel.api.impl;
+
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.FreightTemplate.ADD_TEMPLATE_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.FreightTemplate.GET_TEMPLATE_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.FreightTemplate.LIST_TEMPLATE_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.FreightTemplate.UPDATE_TEMPLATE_URL;
+
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.channel.api.WxChannelFreightTemplateService;
+import me.chanjar.weixin.channel.bean.freight.FreightTemplate;
+import me.chanjar.weixin.channel.bean.freight.TemplateAddParam;
+import me.chanjar.weixin.channel.bean.freight.TemplateIdResponse;
+import me.chanjar.weixin.channel.bean.freight.TemplateInfoResponse;
+import me.chanjar.weixin.channel.bean.freight.TemplateListParam;
+import me.chanjar.weixin.channel.bean.freight.TemplateListResponse;
+import me.chanjar.weixin.channel.util.ResponseUtils;
+import me.chanjar.weixin.common.error.WxErrorException;
+
+/**
+ * 视频号小店 运费模板服务实现
+ *
+ * @author Zeyes
+ */
+@Slf4j
+public class WxChannelFreightTemplateServiceImpl implements WxChannelFreightTemplateService {
+ /** 微信商店服务 */
+ private final BaseWxChannelServiceImpl shopService;
+
+ public WxChannelFreightTemplateServiceImpl(BaseWxChannelServiceImpl shopService) {
+ this.shopService = shopService;
+ }
+
+ @Override
+ public TemplateListResponse listTemplate(Integer offset, Integer limit) throws WxErrorException {
+ TemplateListParam param = new TemplateListParam(offset, limit);
+ String resJson = shopService.post(LIST_TEMPLATE_URL, param);
+ return ResponseUtils.decode(resJson, TemplateListResponse.class);
+
+ }
+
+ @Override
+ public TemplateInfoResponse getTemplate(String templateId) throws WxErrorException {
+ String reqJson = "{\"template_id\": \"" + templateId + "\"}";
+ String resJson = shopService.post(GET_TEMPLATE_URL, reqJson);
+ return ResponseUtils.decode(resJson, TemplateInfoResponse.class);
+ }
+
+ @Override
+ public TemplateIdResponse addTemplate(FreightTemplate template) throws WxErrorException {
+ TemplateAddParam param = new TemplateAddParam(template);
+ String resJson = shopService.post(ADD_TEMPLATE_URL, param);
+ return ResponseUtils.decode(resJson, TemplateIdResponse.class);
+ }
+
+ @Override
+ public TemplateIdResponse updateTemplate(FreightTemplate template) throws WxErrorException {
+ TemplateAddParam param = new TemplateAddParam(template);
+ String resJson = shopService.post(UPDATE_TEMPLATE_URL, param);
+ return ResponseUtils.decode(resJson, TemplateIdResponse.class);
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelFundServiceImpl.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelFundServiceImpl.java
new file mode 100644
index 0000000000..050a19f44d
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelFundServiceImpl.java
@@ -0,0 +1,167 @@
+package me.chanjar.weixin.channel.api.impl;
+
+
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Fund.CHECK_QRCODE_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Fund.GET_BALANCE_FLOW_DETAIL_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Fund.GET_BALANCE_FLOW_LIST_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Fund.GET_BALANCE_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Fund.GET_BANK_ACCOUNT_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Fund.GET_BANK_BY_NUM_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Fund.GET_BANK_LIST_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Fund.GET_CITY_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Fund.GET_PROVINCE_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Fund.GET_QRCODE_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Fund.GET_SUB_BANK_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Fund.GET_WITHDRAW_DETAIL_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Fund.GET_WITHDRAW_LIST_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Fund.SET_BANK_ACCOUNT_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Fund.WITHDRAW_URL;
+
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.channel.api.WxChannelFundService;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+import me.chanjar.weixin.channel.bean.fund.AccountInfo;
+import me.chanjar.weixin.channel.bean.fund.AccountInfoParam;
+import me.chanjar.weixin.channel.bean.fund.AccountInfoResponse;
+import me.chanjar.weixin.channel.bean.fund.BalanceInfoResponse;
+import me.chanjar.weixin.channel.bean.fund.FlowListResponse;
+import me.chanjar.weixin.channel.bean.fund.FundsFlowResponse;
+import me.chanjar.weixin.channel.bean.fund.FundsListParam;
+import me.chanjar.weixin.channel.bean.fund.WithdrawDetailResponse;
+import me.chanjar.weixin.channel.bean.fund.WithdrawListParam;
+import me.chanjar.weixin.channel.bean.fund.WithdrawListResponse;
+import me.chanjar.weixin.channel.bean.fund.WithdrawSubmitParam;
+import me.chanjar.weixin.channel.bean.fund.WithdrawSubmitResponse;
+import me.chanjar.weixin.channel.bean.fund.bank.BankCityResponse;
+import me.chanjar.weixin.channel.bean.fund.bank.BankInfoResponse;
+import me.chanjar.weixin.channel.bean.fund.bank.BankListResponse;
+import me.chanjar.weixin.channel.bean.fund.bank.BankProvinceResponse;
+import me.chanjar.weixin.channel.bean.fund.bank.BankSearchParam;
+import me.chanjar.weixin.channel.bean.fund.bank.BranchInfoResponse;
+import me.chanjar.weixin.channel.bean.fund.bank.BranchSearchParam;
+import me.chanjar.weixin.channel.bean.fund.qrcode.QrCheckResponse;
+import me.chanjar.weixin.channel.bean.fund.qrcode.QrCodeResponse;
+import me.chanjar.weixin.channel.util.ResponseUtils;
+import me.chanjar.weixin.common.error.WxErrorException;
+
+/**
+ * 视频号小店 资金服务实现
+ *
+ * @author Zeyes
+ */
+@Slf4j
+public class WxChannelFundServiceImpl implements WxChannelFundService {
+
+
+ /** 微信商店服务 */
+ private final BaseWxChannelServiceImpl shopService;
+
+ public WxChannelFundServiceImpl(BaseWxChannelServiceImpl shopService) {
+ this.shopService = shopService;
+ }
+
+ @Override
+ public BalanceInfoResponse getBalance() throws WxErrorException {
+ String resJson = shopService.post(GET_BALANCE_URL, "{}");
+ return ResponseUtils.decode(resJson, BalanceInfoResponse.class);
+ }
+
+ @Override
+ public AccountInfoResponse getBankAccount() throws WxErrorException {
+ String resJson = shopService.post(GET_BANK_ACCOUNT_URL, "{}");
+ return ResponseUtils.decode(resJson, AccountInfoResponse.class);
+ }
+
+ @Override
+ public FundsFlowResponse getFundsFlowDetail(String flowId) throws WxErrorException {
+ String reqJson = "{\"flow_id\":\"" + flowId + "\"}";
+ String resJson = shopService.post(GET_BALANCE_FLOW_DETAIL_URL, reqJson);
+ return ResponseUtils.decode(resJson, FundsFlowResponse.class);
+ }
+
+ @Override
+ public FlowListResponse listFundsFlow(FundsListParam param) throws WxErrorException {
+ String resJson = shopService.post(GET_BALANCE_FLOW_LIST_URL, param);
+ return ResponseUtils.decode(resJson, FlowListResponse.class);
+ }
+
+ @Override
+ public WithdrawDetailResponse getWithdrawDetail(String withdrawId) throws WxErrorException {
+ String reqJson = "{\"withdraw_id\":\"" + withdrawId + "\"}";
+ String resJson = shopService.post(GET_WITHDRAW_DETAIL_URL, reqJson);
+ return ResponseUtils.decode(resJson, WithdrawDetailResponse.class);
+ }
+
+ @Override
+ public WithdrawListResponse listWithdraw(Integer pageNum, Integer pageSize, Long startTime, Long endTime)
+ throws WxErrorException {
+ WithdrawListParam param = new WithdrawListParam(pageNum, pageSize, startTime, endTime);
+ String resJson = shopService.post(GET_WITHDRAW_LIST_URL, param);
+ return ResponseUtils.decode(resJson, WithdrawListResponse.class);
+ }
+
+ @Override
+ public WxChannelBaseResponse setBankAccount(AccountInfo accountInfo) throws WxErrorException {
+ AccountInfoParam param = new AccountInfoParam(accountInfo);
+ String resJson = shopService.post(SET_BANK_ACCOUNT_URL, param);
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+ }
+
+ @Override
+ public WithdrawSubmitResponse submitWithdraw(Integer amount, String remark, String bankMemo)
+ throws WxErrorException {
+ WithdrawSubmitParam param = new WithdrawSubmitParam(amount, remark, bankMemo);
+ String resJson = shopService.post(WITHDRAW_URL, param);
+ return ResponseUtils.decode(resJson, WithdrawSubmitResponse.class);
+ }
+
+ @Override
+ public BankInfoResponse getBankInfoByCardNo(String accountNumber) throws WxErrorException {
+ String reqJson = "{\"account_number\":\"" + accountNumber + "\"}";
+ String resJson = shopService.post(GET_BANK_BY_NUM_URL, reqJson);
+ return ResponseUtils.decode(resJson, BankInfoResponse.class);
+ }
+
+ @Override
+ public BankListResponse searchBankList(Integer offset, Integer limit, String keywords, Integer bankType)
+ throws WxErrorException {
+ BankSearchParam param = new BankSearchParam(offset, limit, keywords, bankType);
+ String resJson = shopService.post(GET_BANK_LIST_URL, param);
+ return ResponseUtils.decode(resJson, BankListResponse.class);
+ }
+
+ @Override
+ public BankCityResponse searchCityList(String provinceCode) throws WxErrorException {
+ String reqJson = "{\"province_code\":\"" + provinceCode + "\"}";
+ String resJson = shopService.post(GET_CITY_URL, reqJson);
+ return ResponseUtils.decode(resJson, BankCityResponse.class);
+ }
+
+ @Override
+ public BankProvinceResponse getProvinceList() throws WxErrorException {
+ String resJson = shopService.post(GET_PROVINCE_URL, "{}");
+ return ResponseUtils.decode(resJson, BankProvinceResponse.class);
+ }
+
+ @Override
+ public BranchInfoResponse searchBranchList(String bankCode, String cityCode, Integer offset, Integer limit)
+ throws WxErrorException {
+ BranchSearchParam param = new BranchSearchParam(bankCode, cityCode, offset, limit);
+ String resJson = shopService.post(GET_SUB_BANK_URL, param);
+ return ResponseUtils.decode(resJson, BranchInfoResponse.class);
+ }
+
+ @Override
+ public QrCodeResponse getQrCode(String qrcodeTicket) throws WxErrorException {
+ String reqJson = "{\"qrcode_ticket\":\"" + qrcodeTicket + "\"}";
+ String resJson = shopService.post(GET_QRCODE_URL, reqJson);
+ return ResponseUtils.decode(resJson, QrCodeResponse.class);
+ }
+
+ @Override
+ public QrCheckResponse checkQrStatus(String qrcodeTicket) throws WxErrorException {
+ String reqJson = "{\"qrcode_ticket\":\"" + qrcodeTicket + "\"}";
+ String resJson = shopService.post(CHECK_QRCODE_URL, reqJson);
+ return ResponseUtils.decode(resJson, QrCheckResponse.class);
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelOrderServiceImpl.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelOrderServiceImpl.java
new file mode 100644
index 0000000000..65eec5dd29
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelOrderServiceImpl.java
@@ -0,0 +1,125 @@
+package me.chanjar.weixin.channel.api.impl;
+
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Delivery.DELIVERY_SEND_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Delivery.GET_DELIVERY_COMPANY_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Order.*;
+
+import java.util.List;
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.channel.api.WxChannelOrderService;
+import me.chanjar.weixin.channel.bean.base.AddressInfo;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+import me.chanjar.weixin.channel.bean.delivery.DeliveryCompanyResponse;
+import me.chanjar.weixin.channel.bean.delivery.DeliveryInfo;
+import me.chanjar.weixin.channel.bean.delivery.DeliverySendParam;
+import me.chanjar.weixin.channel.bean.order.ChangeOrderInfo;
+import me.chanjar.weixin.channel.bean.order.DeliveryUpdateParam;
+import me.chanjar.weixin.channel.bean.order.OrderAddressParam;
+import me.chanjar.weixin.channel.bean.order.OrderIdParam;
+import me.chanjar.weixin.channel.bean.order.OrderInfoResponse;
+import me.chanjar.weixin.channel.bean.order.OrderListParam;
+import me.chanjar.weixin.channel.bean.order.OrderListResponse;
+import me.chanjar.weixin.channel.bean.order.OrderPriceParam;
+import me.chanjar.weixin.channel.bean.order.OrderRemarkParam;
+import me.chanjar.weixin.channel.bean.order.OrderSearchParam;
+import me.chanjar.weixin.channel.util.ResponseUtils;
+import me.chanjar.weixin.common.error.WxErrorException;
+
+
+/**
+ * 视频号小店订单服务
+ *
+ * @author Zeyes
+ */
+@Slf4j
+public class WxChannelOrderServiceImpl implements WxChannelOrderService {
+
+ /** 微信商店服务 */
+ private final BaseWxChannelServiceImpl shopService;
+
+ public WxChannelOrderServiceImpl(BaseWxChannelServiceImpl shopService) {
+ this.shopService = shopService;
+ }
+
+ @Override
+ public OrderInfoResponse getOrder(String orderId) throws WxErrorException {
+ OrderIdParam param = new OrderIdParam(orderId);
+ String resJson = shopService.post(ORDER_GET_URL, param);
+ return ResponseUtils.decode(resJson, OrderInfoResponse.class);
+ }
+
+ @Override
+ public OrderListResponse getOrders(OrderListParam param) throws WxErrorException {
+ String resJson = shopService.post(ORDER_LIST_URL, param);
+ return ResponseUtils.decode(resJson, OrderListResponse.class);
+ }
+
+ @Override
+ public OrderListResponse searchOrder(OrderSearchParam param) throws WxErrorException {
+ String resJson = shopService.post(ORDER_SEARCH_URL, param);
+ return ResponseUtils.decode(resJson, OrderListResponse.class);
+ }
+
+ @Override
+ public WxChannelBaseResponse updatePrice(String orderId, Integer expressFee, List changeOrderInfos)
+ throws WxErrorException {
+ OrderPriceParam param = new OrderPriceParam(orderId, expressFee, changeOrderInfos);
+ String resJson = shopService.post(UPDATE_PRICE_URL, param);
+ ;
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+ }
+
+ @Override
+ public WxChannelBaseResponse updateRemark(String orderId, String merchantNotes) throws WxErrorException {
+ OrderRemarkParam param = new OrderRemarkParam(orderId, merchantNotes);
+ String resJson = shopService.post(UPDATE_REMARK_URL, param);
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+ }
+
+ @Override
+ public WxChannelBaseResponse updateAddress(String orderId, AddressInfo userAddress) throws WxErrorException {
+ OrderAddressParam param = new OrderAddressParam(orderId, userAddress);
+ String resJson = shopService.post(UPDATE_ADDRESS_URL, param);
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+ }
+
+ @Override
+ public WxChannelBaseResponse updateDelivery(DeliveryUpdateParam param) throws WxErrorException {
+ String resJson = shopService.post(UPDATE_EXPRESS_URL, param);
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+ }
+
+ @Override
+ public WxChannelBaseResponse acceptAddressModify(String orderId) throws WxErrorException {
+ OrderIdParam param = new OrderIdParam(orderId);
+ String resJson = shopService.post(ACCEPT_ADDRESS_MODIFY_URL, param);
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+ }
+
+ @Override
+ public WxChannelBaseResponse rejectAddressModify(String orderId) throws WxErrorException {
+ OrderIdParam param = new OrderIdParam(orderId);
+ String resJson = shopService.post(REJECT_ADDRESS_MODIFY_URL, param);
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+ }
+
+ @Override
+ public WxChannelBaseResponse closeOrder(String orderId) {
+ // 暂不支持
+ return ResponseUtils.internalError(WxChannelBaseResponse.class);
+ }
+
+ @Override
+ public DeliveryCompanyResponse listDeliveryCompany() throws WxErrorException {
+ String resJson = shopService.post(GET_DELIVERY_COMPANY_URL, "{}");
+ return ResponseUtils.decode(resJson, DeliveryCompanyResponse.class);
+ }
+
+ @Override
+ public WxChannelBaseResponse deliveryOrder(String orderId, List deliveryList)
+ throws WxErrorException {
+ DeliverySendParam param = new DeliverySendParam(orderId, deliveryList);
+ String resJson = shopService.post(DELIVERY_SEND_URL, param);
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelProductServiceImpl.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelProductServiceImpl.java
new file mode 100644
index 0000000000..eb168a09e3
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelProductServiceImpl.java
@@ -0,0 +1,180 @@
+package me.chanjar.weixin.channel.api.impl;
+
+
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.ADD_LIMIT_TASK_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.CANCEL_AUDIT_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.DELETE_LIMIT_TASK_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.LIST_LIMIT_TASK_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_ADD_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_DELISTING_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_DEL_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_GET_STOCK_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_GET_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_LISTING_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_LIST_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_UPDATE_STOCK_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_UPDATE_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.STOP_LIMIT_TASK_URL;
+
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.channel.api.WxChannelProductService;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+import me.chanjar.weixin.channel.bean.limit.LimitTaskAddResponse;
+import me.chanjar.weixin.channel.bean.limit.LimitTaskListParam;
+import me.chanjar.weixin.channel.bean.limit.LimitTaskListResponse;
+import me.chanjar.weixin.channel.bean.limit.LimitTaskParam;
+import me.chanjar.weixin.channel.bean.product.SkuStockParam;
+import me.chanjar.weixin.channel.bean.product.SkuStockResponse;
+import me.chanjar.weixin.channel.bean.product.SpuGetResponse;
+import me.chanjar.weixin.channel.bean.product.SpuInfo;
+import me.chanjar.weixin.channel.bean.product.SpuListParam;
+import me.chanjar.weixin.channel.bean.product.SpuListResponse;
+import me.chanjar.weixin.channel.bean.product.SpuUpdateResponse;
+import me.chanjar.weixin.channel.util.JsonUtils;
+import me.chanjar.weixin.channel.util.ResponseUtils;
+import me.chanjar.weixin.common.error.WxErrorException;
+
+/**
+ * 视频号小店商品服务
+ *
+ * @author Zeyes
+ */
+@Slf4j
+public class WxChannelProductServiceImpl implements WxChannelProductService {
+
+ /** 微信商店服务 */
+ private final BaseWxChannelServiceImpl shopService;
+
+ public WxChannelProductServiceImpl(BaseWxChannelServiceImpl shopService) {
+ this.shopService = shopService;
+ }
+
+ @Override
+ public SpuUpdateResponse addProduct(SpuInfo info) throws WxErrorException {
+ String reqJson = JsonUtils.encode(info);
+ String resJson = shopService.post(SPU_ADD_URL, reqJson);
+ return ResponseUtils.decode(resJson, SpuUpdateResponse.class);
+ }
+
+ @Override
+ public SpuUpdateResponse updateProduct(SpuInfo info) throws WxErrorException {
+ String reqJson = JsonUtils.encode(info);
+ String resJson = shopService.post(SPU_UPDATE_URL, reqJson);
+ return ResponseUtils.decode(resJson, SpuUpdateResponse.class);
+ }
+
+ @Override
+ public WxChannelBaseResponse updateStock(String productId, String skuId, Integer diffType, Integer num)
+ throws WxErrorException {
+ SkuStockParam param = new SkuStockParam(productId, skuId, diffType, num);
+ String reqJson = JsonUtils.encode(param);
+ String resJson = shopService.post(SPU_UPDATE_STOCK_URL, reqJson);
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+ }
+
+ /**
+ * 生成商品id Json
+ *
+ * @param productId 商品ID
+ * @param dataType 默认取1。1:获取线上数据, 2:获取草稿数据, 3:同时获取线上和草稿数据(注意:需成功上架后才有线上数据)
+ * @return json
+ */
+ protected String generateProductIdJson(String productId, Integer dataType) {
+ StringBuilder sb = new StringBuilder();
+ sb.append('{');
+ if (productId != null) {
+ sb.append("\"product_id\":").append(productId);
+ }
+
+ if (dataType != null) {
+ sb.append(",").append("\"data_type\":").append(dataType);
+ }
+ sb.append('}');
+ return sb.toString();
+ }
+
+ /**
+ * 简单的商品请求 参数是商品id 只返回基本结果
+ *
+ * @param url 资源路径
+ * @param productId 商品ID
+ * @return 是否成功
+ */
+ protected WxChannelBaseResponse simpleProductRequest(String url, String productId) throws WxErrorException {
+ String reqJson = this.generateProductIdJson(productId, null);
+ String resJson = shopService.post(url, reqJson);
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+ }
+
+ @Override
+ public WxChannelBaseResponse deleteProduct(String productId) throws WxErrorException {
+ return simpleProductRequest(SPU_DEL_URL, productId);
+ }
+
+ @Override
+ public WxChannelBaseResponse cancelProductAudit(String productId) throws WxErrorException {
+ return simpleProductRequest(CANCEL_AUDIT_URL, productId);
+ }
+
+ @Override
+ public SpuGetResponse getProduct(String productId, Integer dataType) throws WxErrorException {
+ String reqJson = this.generateProductIdJson(productId, dataType);
+ String resJson = shopService.post(SPU_GET_URL, reqJson);
+ return ResponseUtils.decode(resJson, SpuGetResponse.class);
+ }
+
+ @Override
+ public SpuListResponse listProduct(Integer pageSize, String nextKey, Integer status) throws WxErrorException {
+ SpuListParam param = new SpuListParam(pageSize, nextKey, status);
+ String reqJson = JsonUtils.encode(param);
+ String resJson = shopService.post(SPU_LIST_URL, reqJson);
+ return ResponseUtils.decode(resJson, SpuListResponse.class);
+ }
+
+ @Override
+ public WxChannelBaseResponse upProduct(String productId) throws WxErrorException {
+ return simpleProductRequest(SPU_LISTING_URL, productId);
+ }
+
+ @Override
+ public WxChannelBaseResponse downProduct(String productId) throws WxErrorException {
+ return simpleProductRequest(SPU_DELISTING_URL, productId);
+ }
+
+ @Override
+ public SkuStockResponse getSkuStock(String productId, String skuId) throws WxErrorException {
+ String reqJson = "{\"product_id\":\"" + productId + "\",\"sku_id\":\"" + skuId + "\"}";
+ String resJson = shopService.post(SPU_GET_STOCK_URL, reqJson);
+ return ResponseUtils.decode(resJson, SkuStockResponse.class);
+ }
+
+ @Override
+ public LimitTaskAddResponse addLimitTask(LimitTaskParam param) throws WxErrorException {
+ String reqJson = JsonUtils.encode(param);
+ String resJson = shopService.post(ADD_LIMIT_TASK_URL, reqJson);
+ return ResponseUtils.decode(resJson, LimitTaskAddResponse.class);
+ }
+
+ @Override
+ public LimitTaskListResponse listLimitTask(Integer pageSize, String nextKey, Integer status)
+ throws WxErrorException {
+ LimitTaskListParam param = new LimitTaskListParam(pageSize, nextKey, status);
+ String reqJson = JsonUtils.encode(param);
+ String resJson = shopService.post(LIST_LIMIT_TASK_URL, reqJson);
+ return ResponseUtils.decode(resJson, LimitTaskListResponse.class);
+ }
+
+ @Override
+ public WxChannelBaseResponse stopLimitTask(String taskId) throws WxErrorException {
+ String reqJson = "{\"task_id\": \"" + taskId + "\"}";
+ String resJson = shopService.post(STOP_LIMIT_TASK_URL, reqJson);
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+ }
+
+ @Override
+ public WxChannelBaseResponse deleteLimitTask(String taskId) throws WxErrorException {
+ String reqJson = "{\"task_id\": \"" + taskId + "\"}";
+ String resJson = shopService.post(DELETE_LIMIT_TASK_URL, reqJson);
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelServiceHttpClientImpl.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelServiceHttpClientImpl.java
new file mode 100644
index 0000000000..bbe8865269
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelServiceHttpClientImpl.java
@@ -0,0 +1,100 @@
+package me.chanjar.weixin.channel.api.impl;
+
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.GET_ACCESS_TOKEN_URL;
+
+import java.io.IOException;
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.channel.config.WxChannelConfig;
+import me.chanjar.weixin.common.util.http.HttpType;
+import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder;
+import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.http.HttpHost;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.client.BasicResponseHandler;
+import org.apache.http.impl.client.CloseableHttpClient;
+
+/**
+ * @author Zeyes
+ */
+@Slf4j
+public class WxChannelServiceHttpClientImpl extends BaseWxChannelServiceImpl {
+
+ private CloseableHttpClient httpClient;
+ private HttpHost httpProxy;
+
+ public WxChannelServiceHttpClientImpl() {
+
+ }
+
+ @Override
+ public void initHttp() {
+ WxChannelConfig config = this.getConfig();
+ ApacheHttpClientBuilder apacheHttpClientBuilder = config.getApacheHttpClientBuilder();
+ if (null == apacheHttpClientBuilder) {
+ apacheHttpClientBuilder = DefaultApacheHttpClientBuilder.get();
+ }
+
+ apacheHttpClientBuilder.httpProxyHost(config.getHttpProxyHost())
+ .httpProxyPort(config.getHttpProxyPort())
+ .httpProxyUsername(config.getHttpProxyUsername())
+ .httpProxyPassword(config.getHttpProxyPassword());
+
+ if (config.getHttpProxyHost() != null && config.getHttpProxyPort() > 0) {
+ this.httpProxy = new HttpHost(config.getHttpProxyHost(), config.getHttpProxyPort());
+ }
+
+ this.httpClient = apacheHttpClientBuilder.build();
+ }
+
+ @Override
+ public CloseableHttpClient getRequestHttpClient() {
+ return httpClient;
+ }
+
+ @Override
+ public HttpHost getRequestHttpProxy() {
+ return httpProxy;
+ }
+
+ @Override
+ public HttpType getRequestType() {
+ return HttpType.APACHE_HTTP;
+ }
+
+ @Override
+ protected String doGetAccessTokenRequest() throws IOException {
+ WxChannelConfig config = this.getConfig();
+ String url = StringUtils.isNotEmpty(config.getAccessTokenUrl()) ? config.getAccessTokenUrl() :
+ StringUtils.isNotEmpty(config.getApiHostUrl()) ?
+ GET_ACCESS_TOKEN_URL.replace("https://api.weixin.qq.com", config.getApiHostUrl()) : GET_ACCESS_TOKEN_URL;
+
+ url = String.format(url, config.getAppid(), config.getSecret());
+
+ HttpGet httpGet = null;
+ CloseableHttpResponse response = null;
+ try {
+ httpGet = new HttpGet(url);
+ if (this.getRequestHttpProxy() != null) {
+ RequestConfig requestConfig = RequestConfig.custom().setProxy(this.getRequestHttpProxy()).build();
+ httpGet.setConfig(requestConfig);
+ }
+ response = getRequestHttpClient().execute(httpGet);
+ return new BasicResponseHandler().handleResponse(response);
+ } finally {
+ if (httpGet != null) {
+ httpGet.releaseConnection();
+ }
+ if (response != null) {
+ try {
+ response.close();
+ } catch (IOException ignored) {
+ }
+ }
+ }
+ }
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelServiceImpl.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelServiceImpl.java
new file mode 100644
index 0000000000..e3e749dca5
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelServiceImpl.java
@@ -0,0 +1,13 @@
+package me.chanjar.weixin.channel.api.impl;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 视频号小店服务实现
+ *
+ * @author Zeyes
+ */
+@Slf4j
+public class WxChannelServiceImpl extends WxChannelServiceHttpClientImpl {
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelSharerServiceImpl.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelSharerServiceImpl.java
new file mode 100644
index 0000000000..676b310288
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelSharerServiceImpl.java
@@ -0,0 +1,76 @@
+package me.chanjar.weixin.channel.api.impl;
+
+
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Share.BIND_SHARER_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Share.LIST_SHARER_ORDER_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Share.LIST_SHARER_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Share.SEARCH_SHARER_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Share.UNBIND_SHARER_URL;
+
+import com.google.gson.JsonObject;
+import java.util.List;
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.channel.api.WxChannelSharerService;
+import me.chanjar.weixin.channel.bean.sharer.SharerBindResponse;
+import me.chanjar.weixin.channel.bean.sharer.SharerInfoResponse;
+import me.chanjar.weixin.channel.bean.sharer.SharerListParam;
+import me.chanjar.weixin.channel.bean.sharer.SharerOrderParam;
+import me.chanjar.weixin.channel.bean.sharer.SharerOrderResponse;
+import me.chanjar.weixin.channel.bean.sharer.SharerSearchParam;
+import me.chanjar.weixin.channel.bean.sharer.SharerSearchResponse;
+import me.chanjar.weixin.channel.bean.sharer.SharerUnbindParam;
+import me.chanjar.weixin.channel.bean.sharer.SharerUnbindResponse;
+import me.chanjar.weixin.channel.util.ResponseUtils;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.util.json.GsonHelper;
+
+/**
+ * 视频号小店 分享员服务实现
+ *
+ * @author Zeyes
+ */
+@Slf4j
+public class WxChannelSharerServiceImpl implements WxChannelSharerService {
+
+ /** 微信商店服务 */
+ private final BaseWxChannelServiceImpl shopService;
+
+ public WxChannelSharerServiceImpl(BaseWxChannelServiceImpl shopService) {
+ this.shopService = shopService;
+ }
+
+ @Override
+ public SharerBindResponse bindSharer(String username) throws WxErrorException {
+ JsonObject jsonObject = GsonHelper.buildJsonObject("username", username);
+
+ String resJson = shopService.post(BIND_SHARER_URL, jsonObject);
+ return ResponseUtils.decode(resJson, SharerBindResponse.class);
+ }
+
+ @Override
+ public SharerSearchResponse searchSharer(String openid, String username) throws WxErrorException {
+ SharerSearchParam param = new SharerSearchParam(openid, username);
+ String resJson = shopService.post(SEARCH_SHARER_URL, param);
+ return ResponseUtils.decode(resJson, SharerSearchResponse.class);
+ }
+
+ @Override
+ public SharerInfoResponse listSharer(Integer page, Integer pageSize, Integer sharerType) throws WxErrorException {
+ SharerListParam param = new SharerListParam(page, pageSize, sharerType);
+ String resJson = shopService.post(LIST_SHARER_URL, param);
+ return ResponseUtils.decode(resJson, SharerInfoResponse.class);
+ }
+
+ @Override
+ public SharerOrderResponse listSharerOrder(SharerOrderParam param) throws WxErrorException {
+ String resJson = shopService.post(LIST_SHARER_ORDER_URL, param);
+ return ResponseUtils.decode(resJson, SharerOrderResponse.class);
+ }
+
+ @Override
+ public SharerUnbindResponse unbindSharer(List openIds) throws WxErrorException {
+ SharerUnbindParam param = new SharerUnbindParam(openIds);
+ String resJson = shopService.post(UNBIND_SHARER_URL, param);
+ return ResponseUtils.decode(resJson, SharerUnbindResponse.class);
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelWarehouseServiceImpl.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelWarehouseServiceImpl.java
new file mode 100644
index 0000000000..b9609e5c6b
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelWarehouseServiceImpl.java
@@ -0,0 +1,123 @@
+package me.chanjar.weixin.channel.api.impl;
+
+
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Warehouse.ADD_COVER_AREA_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Warehouse.ADD_WAREHOUSE_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Warehouse.DELETE_COVER_AREA_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Warehouse.GET_WAREHOUSE_PRIORITY_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Warehouse.GET_WAREHOUSE_STOCK_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Warehouse.GET_WAREHOUSE_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Warehouse.LIST_WAREHOUSE_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Warehouse.SET_WAREHOUSE_PRIORITY_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Warehouse.UPDATE_WAREHOUSE_STOCK_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Warehouse.UPDATE_WAREHOUSE_URL;
+
+import java.util.List;
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.channel.api.WxChannelWarehouseService;
+import me.chanjar.weixin.channel.bean.base.StreamPageParam;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+import me.chanjar.weixin.channel.bean.warehouse.LocationPriorityResponse;
+import me.chanjar.weixin.channel.bean.warehouse.PriorityLocationParam;
+import me.chanjar.weixin.channel.bean.warehouse.StockGetParam;
+import me.chanjar.weixin.channel.bean.warehouse.UpdateLocationParam;
+import me.chanjar.weixin.channel.bean.warehouse.WarehouseIdsResponse;
+import me.chanjar.weixin.channel.bean.warehouse.WarehouseLocation;
+import me.chanjar.weixin.channel.bean.warehouse.WarehouseLocationParam;
+import me.chanjar.weixin.channel.bean.warehouse.WarehouseParam;
+import me.chanjar.weixin.channel.bean.warehouse.WarehouseResponse;
+import me.chanjar.weixin.channel.bean.warehouse.WarehouseStockParam;
+import me.chanjar.weixin.channel.bean.warehouse.WarehouseStockResponse;
+import me.chanjar.weixin.channel.util.ResponseUtils;
+import me.chanjar.weixin.common.error.WxErrorException;
+
+/**
+ * 视频号小店 区域仓库服务实现
+ *
+ * @author Zeyes
+ */
+@Slf4j
+public class WxChannelWarehouseServiceImpl implements WxChannelWarehouseService {
+
+ /** 微信商店服务 */
+ private final BaseWxChannelServiceImpl shopService;
+
+ public WxChannelWarehouseServiceImpl(BaseWxChannelServiceImpl shopService) {
+ this.shopService = shopService;
+ }
+
+ @Override
+ public WxChannelBaseResponse createWarehouse(WarehouseParam param) throws WxErrorException {
+ String resJson = shopService.post(ADD_WAREHOUSE_URL, param);
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+ }
+
+ @Override
+ public WarehouseIdsResponse listWarehouse(Integer pageSize, String nextKey) throws WxErrorException {
+ StreamPageParam param = new StreamPageParam(pageSize, nextKey);
+ String resJson = shopService.post(LIST_WAREHOUSE_URL, param);
+ return ResponseUtils.decode(resJson, WarehouseIdsResponse.class);
+ }
+
+ @Override
+ public WarehouseResponse getWarehouse(String outWarehouseId) throws WxErrorException {
+ String reqJson = "{\"out_warehouse_id\":\"" + outWarehouseId + "\"}";
+ String resJson = shopService.post(GET_WAREHOUSE_URL, reqJson);
+ return ResponseUtils.decode(resJson, WarehouseResponse.class);
+ }
+
+ @Override
+ public WxChannelBaseResponse updateWarehouse(String outWarehouseId, String name, String intro)
+ throws WxErrorException {
+ String reqJson = "{\"out_warehouse_id\":\"" + outWarehouseId +
+ "\",\"name\":\"" + name + "\",\"intro\":\"" + intro + "\"}";
+ String resJson = shopService.post(UPDATE_WAREHOUSE_URL, reqJson);
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+ }
+
+ @Override
+ public WxChannelBaseResponse addWarehouseArea(String outWarehouseId, List coverLocations)
+ throws WxErrorException {
+ UpdateLocationParam param = new UpdateLocationParam(outWarehouseId, coverLocations);
+ String resJson = shopService.post(ADD_COVER_AREA_URL, param);
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+ }
+
+ @Override
+ public WxChannelBaseResponse deleteWarehouseArea(String outWarehouseId, List coverLocations)
+ throws WxErrorException {
+ UpdateLocationParam param = new UpdateLocationParam(outWarehouseId, coverLocations);
+ String resJson = shopService.post(DELETE_COVER_AREA_URL, param);
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+
+ }
+
+ @Override
+ public WxChannelBaseResponse setWarehousePriority(PriorityLocationParam param) throws WxErrorException {
+ String resJson = shopService.post(SET_WAREHOUSE_PRIORITY_URL, param);
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+
+ }
+
+ @Override
+ public LocationPriorityResponse getWarehousePriority(Integer addressId1, Integer addressId2, Integer addressId3,
+ Integer addressId4) throws WxErrorException {
+ WarehouseLocationParam param = new WarehouseLocationParam(addressId1, addressId2, addressId3, addressId4);
+ String resJson = shopService.post(GET_WAREHOUSE_PRIORITY_URL, param);
+ return ResponseUtils.decode(resJson, LocationPriorityResponse.class);
+ }
+
+ @Override
+ public WxChannelBaseResponse updateWarehouseStock(WarehouseStockParam param) throws WxErrorException {
+ String resJson = shopService.post(UPDATE_WAREHOUSE_STOCK_URL, param);
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+ }
+
+ @Override
+ public WarehouseStockResponse getWarehouseStock(String productId, String skuId, String outWarehouseId)
+ throws WxErrorException {
+ StockGetParam param = new StockGetParam(productId, skuId, outWarehouseId);
+ String resJson = shopService.post(GET_WAREHOUSE_STOCK_URL, param);
+ return ResponseUtils.decode(resJson, WarehouseStockResponse.class);
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxLeagueProductServiceImpl.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxLeagueProductServiceImpl.java
new file mode 100644
index 0000000000..29620874e2
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxLeagueProductServiceImpl.java
@@ -0,0 +1,71 @@
+package me.chanjar.weixin.channel.api.impl;
+
+
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.League.BATCH_ADD_LEAGUE_ITEM_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.League.DELETE_LEAGUE_ITEM_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.League.GET_LEAGUE_ITEM_LIST_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.League.GET_LEAGUE_ITEM_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.League.UPDATE_LEAGUE_ITEM_URL;
+
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.channel.api.WxLeagueProductService;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+import me.chanjar.weixin.channel.bean.league.product.BatchAddParam;
+import me.chanjar.weixin.channel.bean.league.product.BatchAddResponse;
+import me.chanjar.weixin.channel.bean.league.product.ProductDeleteParam;
+import me.chanjar.weixin.channel.bean.league.product.ProductDetailParam;
+import me.chanjar.weixin.channel.bean.league.product.ProductDetailResponse;
+import me.chanjar.weixin.channel.bean.league.product.ProductListParam;
+import me.chanjar.weixin.channel.bean.league.product.ProductListResponse;
+import me.chanjar.weixin.channel.bean.league.product.ProductUpdateParam;
+import me.chanjar.weixin.channel.bean.league.product.ProductUpdateResponse;
+import me.chanjar.weixin.channel.util.ResponseUtils;
+import me.chanjar.weixin.common.error.WxErrorException;
+
+
+/**
+ * 视频号小店 商品服务
+ *
+ * @author Zeyes
+ */
+@Slf4j
+public class WxLeagueProductServiceImpl implements WxLeagueProductService {
+
+ /** 微信商店服务 */
+ private final BaseWxChannelServiceImpl shopService;
+
+ public WxLeagueProductServiceImpl(BaseWxChannelServiceImpl shopService) {
+ this.shopService = shopService;
+ }
+
+ @Override
+ public BatchAddResponse batchAddProduct(BatchAddParam param) throws WxErrorException {
+ String resJson = shopService.post(BATCH_ADD_LEAGUE_ITEM_URL, param);
+ return ResponseUtils.decode(resJson, BatchAddResponse.class);
+ }
+
+ @Override
+ public ProductUpdateResponse updateProduct(ProductUpdateParam param) throws WxErrorException {
+ String resJson = shopService.post(UPDATE_LEAGUE_ITEM_URL, param);
+ return ResponseUtils.decode(resJson, ProductUpdateResponse.class);
+ }
+
+ @Override
+ public WxChannelBaseResponse deleteProduct(Integer type, String productId, String infoId) throws WxErrorException {
+ ProductDeleteParam param = new ProductDeleteParam(type, productId, infoId);
+ String resJson = shopService.post(DELETE_LEAGUE_ITEM_URL, param);
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+ }
+
+ @Override
+ public ProductDetailResponse getProductDetail(ProductDetailParam param) throws WxErrorException {
+ String resJson = shopService.post(GET_LEAGUE_ITEM_URL, param);
+ return ResponseUtils.decode(resJson, ProductDetailResponse.class);
+ }
+
+ @Override
+ public ProductListResponse listProduct(ProductListParam param) throws WxErrorException {
+ String resJson = shopService.post(GET_LEAGUE_ITEM_LIST_URL, param);
+ return ResponseUtils.decode(resJson, ProductListResponse.class);
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxLeaguePromoterServiceImpl.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxLeaguePromoterServiceImpl.java
new file mode 100644
index 0000000000..a6bfddfbef
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxLeaguePromoterServiceImpl.java
@@ -0,0 +1,69 @@
+package me.chanjar.weixin.channel.api.impl;
+
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.League.ADD_PROMOTER_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.League.DELETE_PROMOTER_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.League.EDIT_PROMOTER_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.League.GET_PROMOTER_LIST_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.League.GET_PROMOTER_URL;
+
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.channel.api.WxLeaguePromoterService;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+import me.chanjar.weixin.channel.bean.league.promoter.PromoterInfoResponse;
+import me.chanjar.weixin.channel.bean.league.promoter.PromoterListParam;
+import me.chanjar.weixin.channel.bean.league.promoter.PromoterListResponse;
+import me.chanjar.weixin.channel.util.ResponseUtils;
+import me.chanjar.weixin.common.error.WxErrorException;
+
+/**
+ * 视频号小店 达人服务
+ *
+ * @author Zeyes
+ */
+@Slf4j
+public class WxLeaguePromoterServiceImpl implements WxLeaguePromoterService {
+
+ /** 微信商店服务 */
+ private final BaseWxChannelServiceImpl shopService;
+
+ public WxLeaguePromoterServiceImpl(BaseWxChannelServiceImpl shopService) {
+ this.shopService = shopService;
+ }
+
+ @Override
+ public WxChannelBaseResponse addPromoter(String finderId) throws WxErrorException {
+ String reqJson = "{\"finder_id\":\"" + finderId + "\"}";
+ String resJson = shopService.post(ADD_PROMOTER_URL, reqJson);
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+ }
+
+ @Override
+ public WxChannelBaseResponse updatePromoter(String finderId, int type) throws WxErrorException {
+ String reqJson = "{\"finder_id\":\"" + finderId + "\",\"type\":" + type + "}";
+ String resJson = shopService.post(EDIT_PROMOTER_URL, reqJson);
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+ }
+
+ @Override
+ public WxChannelBaseResponse deletePromoter(String finderId) throws WxErrorException {
+ String reqJson = "{\"finder_id\":\"" + finderId + "\"}";
+ String resJson = shopService.post(DELETE_PROMOTER_URL, reqJson);
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+ }
+
+ @Override
+ public PromoterInfoResponse getPromoterInfo(String finderId) throws WxErrorException {
+ String reqJson = "{\"finder_id\":\"" + finderId + "\"}";
+ String resJson = shopService.post(GET_PROMOTER_URL, reqJson);
+ return ResponseUtils.decode(resJson, PromoterInfoResponse.class);
+ }
+
+ @Override
+ public PromoterListResponse listPromoter(Integer pageIndex, Integer pageSize, Integer status)
+ throws WxErrorException {
+ PromoterListParam param = new PromoterListParam(pageIndex, pageSize, status);
+ String resJson = shopService.post(GET_PROMOTER_LIST_URL, param);
+ return ResponseUtils.decode(resJson, PromoterListResponse.class);
+
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxLeagueSupplierServiceImpl.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxLeagueSupplierServiceImpl.java
new file mode 100644
index 0000000000..d69296bd0f
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxLeagueSupplierServiceImpl.java
@@ -0,0 +1,107 @@
+package me.chanjar.weixin.channel.api.impl;
+
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.League.GET_SUPPLIER_BALANCE_FLOW_DETAIL_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.League.GET_SUPPLIER_BALANCE_FLOW_LIST_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.League.GET_SUPPLIER_BALANCE_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.League.GET_SUPPLIER_ITEM_LIST_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.League.GET_SUPPLIER_ITEM_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.League.GET_SUPPLIER_ORDER_LIST_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.League.GET_SUPPLIER_ORDER_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.League.GET_SUPPLIER_SHOP_LIST_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.League.GET_SUPPLIER_SHOP_URL;
+
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.channel.api.WxLeagueSupplierService;
+import me.chanjar.weixin.channel.bean.base.StreamPageParam;
+import me.chanjar.weixin.channel.bean.league.supplier.CommissionOrderListParam;
+import me.chanjar.weixin.channel.bean.league.supplier.CommissionOrderListResponse;
+import me.chanjar.weixin.channel.bean.league.supplier.CommissionOrderResponse;
+import me.chanjar.weixin.channel.bean.league.supplier.CoopProductDetailParam;
+import me.chanjar.weixin.channel.bean.league.supplier.CoopProductListParam;
+import me.chanjar.weixin.channel.bean.league.supplier.CoopProductListResponse;
+import me.chanjar.weixin.channel.bean.league.supplier.CoopProductResponse;
+import me.chanjar.weixin.channel.bean.league.supplier.FlowListParam;
+import me.chanjar.weixin.channel.bean.league.supplier.ShopDetailResponse;
+import me.chanjar.weixin.channel.bean.league.supplier.ShopListResponse;
+import me.chanjar.weixin.channel.bean.league.supplier.SupplierBalanceResponse;
+import me.chanjar.weixin.channel.bean.league.supplier.SupplierFlowDetailResponse;
+import me.chanjar.weixin.channel.bean.league.supplier.SupplierFlowListResponse;
+import me.chanjar.weixin.channel.util.ResponseUtils;
+import me.chanjar.weixin.common.error.WxErrorException;
+
+/**
+ * 视频号小店 优选联盟 团长数据服务
+ *
+ * @author Zeyes
+ */
+@Slf4j
+public class WxLeagueSupplierServiceImpl implements WxLeagueSupplierService {
+
+ /** 微信商店服务 */
+ private final BaseWxChannelServiceImpl shopService;
+
+ public WxLeagueSupplierServiceImpl(BaseWxChannelServiceImpl shopService) {
+ this.shopService = shopService;
+ }
+
+ @Override
+ public SupplierBalanceResponse getBalanceInfo() throws WxErrorException {
+ String resJson = shopService.post(GET_SUPPLIER_BALANCE_URL, "{}");
+ return ResponseUtils.decode(resJson, SupplierBalanceResponse.class);
+ }
+
+ @Override
+ public SupplierFlowDetailResponse getFlowDetail(String flowId) throws WxErrorException {
+ String reqJson = "{\"flow_id\":\"" + flowId + "\"}";
+ String resJson = shopService.post(GET_SUPPLIER_BALANCE_FLOW_DETAIL_URL, reqJson);
+ return ResponseUtils.decode(resJson, SupplierFlowDetailResponse.class);
+ }
+
+ @Override
+ public SupplierFlowListResponse getFlowList(FlowListParam param) throws WxErrorException {
+ String resJson = shopService.post(GET_SUPPLIER_BALANCE_FLOW_LIST_URL, param);
+ return ResponseUtils.decode(resJson, SupplierFlowListResponse.class);
+ }
+
+ @Override
+ public CoopProductResponse getProductDetail(String productId, String appId) throws WxErrorException {
+ CoopProductDetailParam param = new CoopProductDetailParam(productId, appId);
+ String resJson = shopService.post(GET_SUPPLIER_ITEM_URL, param);
+ return ResponseUtils.decode(resJson, CoopProductResponse.class);
+ }
+
+ @Override
+ public CoopProductListResponse getProductList(String appid, Integer pageSize, String nextKey)
+ throws WxErrorException {
+ CoopProductListParam param = new CoopProductListParam(appid, pageSize, nextKey);
+ String resJson = shopService.post(GET_SUPPLIER_ITEM_LIST_URL, param);
+ return ResponseUtils.decode(resJson, CoopProductListResponse.class);
+ }
+
+ @Override
+ public CommissionOrderResponse getCommissionOrder(String orderId, String skuId) throws WxErrorException {
+ String reqJson = "{\"order_id\":\"" + orderId + "\",\"sku_id\":\"" + skuId + "\"}";
+ String resJson = shopService.post(GET_SUPPLIER_ORDER_URL, reqJson);
+ return ResponseUtils.decode(resJson, CommissionOrderResponse.class);
+ }
+
+ @Override
+ public CommissionOrderListResponse getCommissionOrderList(CommissionOrderListParam param) throws WxErrorException {
+ String resJson = shopService.post(GET_SUPPLIER_ORDER_LIST_URL, param);
+ return ResponseUtils.decode(resJson, CommissionOrderListResponse.class);
+ }
+
+ @Override
+ public ShopDetailResponse getShopDetail(String appid) throws WxErrorException {
+ String reqJson = "{\"appid\":\"" + appid + "\"}";
+ String resJson = shopService.post(GET_SUPPLIER_SHOP_URL, reqJson);
+ return ResponseUtils.decode(resJson, ShopDetailResponse.class);
+ }
+
+ @Override
+ public ShopListResponse getShopList(Integer pageSize, String nextKey) throws WxErrorException {
+ StreamPageParam param = new StreamPageParam(pageSize, nextKey);
+ String resJson = shopService.post(GET_SUPPLIER_SHOP_LIST_URL, param);
+ return ResponseUtils.decode(resJson, ShopListResponse.class);
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxLeagueWindowServiceImpl.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxLeagueWindowServiceImpl.java
new file mode 100644
index 0000000000..a59fc6efa5
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxLeagueWindowServiceImpl.java
@@ -0,0 +1,81 @@
+package me.chanjar.weixin.channel.api.impl;
+
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.League.ADD_SUPPLIER_GOODS_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.League.GET_SUPPLIER_AUTH_STATUS_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.League.GET_SUPPLIER_AUTH_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.League.GET_SUPPLIER_GOODS_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.League.LIST_SUPPLIER_GOODS_URL;
+import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.League.REMOVE_SUPPLIER_GOODS_URL;
+
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.channel.api.WxLeagueWindowService;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+import me.chanjar.weixin.channel.bean.league.window.AuthInfoResponse;
+import me.chanjar.weixin.channel.bean.league.window.AuthStatusResponse;
+import me.chanjar.weixin.channel.bean.league.window.ProductSearchParam;
+import me.chanjar.weixin.channel.bean.league.window.WindowProductListResponse;
+import me.chanjar.weixin.channel.bean.league.window.WindowProductParam;
+import me.chanjar.weixin.channel.bean.league.window.WindowProductResponse;
+import me.chanjar.weixin.channel.util.ResponseUtils;
+import me.chanjar.weixin.common.error.WxErrorException;
+
+
+/**
+ * 视频号小店 优选联盟 团长合作达人管理服务
+ *
+ * @author Zeyes
+ */
+@Slf4j
+public class WxLeagueWindowServiceImpl implements WxLeagueWindowService {
+
+ /** 微信商店服务 */
+ private final BaseWxChannelServiceImpl shopService;
+
+ public WxLeagueWindowServiceImpl(BaseWxChannelServiceImpl shopService) {
+ this.shopService = shopService;
+ }
+
+ @Override
+ public WxChannelBaseResponse addProduct(String appid, String openfinderid, String productId)
+ throws WxErrorException {
+ WindowProductParam param = new WindowProductParam(appid, openfinderid, productId);
+ String resJson = shopService.post(ADD_SUPPLIER_GOODS_URL, param);
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+ }
+
+ @Override
+ public WindowProductListResponse listProduct(ProductSearchParam param) throws WxErrorException {
+ String resJson = shopService.post(LIST_SUPPLIER_GOODS_URL, param);
+ return ResponseUtils.decode(resJson, WindowProductListResponse.class);
+ }
+
+ @Override
+ public WxChannelBaseResponse removeProduct(String appid, String openfinderid, String productId)
+ throws WxErrorException {
+ WindowProductParam param = new WindowProductParam(appid, openfinderid, productId);
+ String resJson = shopService.post(REMOVE_SUPPLIER_GOODS_URL, param);
+ return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
+ }
+
+ @Override
+ public WindowProductResponse getProductDetail(String appid, String openfinderid, String productId)
+ throws WxErrorException {
+ WindowProductParam param = new WindowProductParam(appid, openfinderid, productId);
+ String resJson = shopService.post(GET_SUPPLIER_GOODS_URL, param);
+ return ResponseUtils.decode(resJson, WindowProductResponse.class);
+ }
+
+ @Override
+ public AuthInfoResponse getWindowAuthInfo(String finderId) throws WxErrorException {
+ String reqJson = "{\"finder_id\":\"" + finderId + "\"}";
+ String resJson = shopService.post(GET_SUPPLIER_AUTH_URL, reqJson);
+ return ResponseUtils.decode(resJson, AuthInfoResponse.class);
+ }
+
+ @Override
+ public AuthStatusResponse getWindowAuthStatus(String finderId) throws WxErrorException {
+ String reqJson = "{\"finder_id\":\"" + finderId + "\"}";
+ String resJson = shopService.post(GET_SUPPLIER_AUTH_STATUS_URL, reqJson);
+ return ResponseUtils.decode(resJson, AuthStatusResponse.class);
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/address/AddressAddParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/address/AddressAddParam.java
new file mode 100644
index 0000000000..a831de6655
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/address/AddressAddParam.java
@@ -0,0 +1,27 @@
+package me.chanjar.weixin.channel.bean.address;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 地址 请求参数
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonInclude(Include.NON_NULL)
+public class AddressAddParam implements Serializable {
+
+ private static final long serialVersionUID = 6778585213498438738L;
+
+ /** 地址id */
+ @JsonProperty("address_detail")
+ private AddressDetail addressDetail;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/address/AddressCode.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/address/AddressCode.java
new file mode 100644
index 0000000000..c7c885f0ab
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/address/AddressCode.java
@@ -0,0 +1,30 @@
+package me.chanjar.weixin.channel.bean.address;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 地址编码
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class AddressCode implements Serializable {
+
+ private static final long serialVersionUID = -6782328785056142627L;
+
+ /** 地址名称 */
+ @JsonProperty("name")
+ private String name;
+
+ /** 地址行政编码 */
+ @JsonProperty("code")
+ private Integer code;
+
+ /** 地址级别 1-省级 2-市级 3-区县级 4-街道 */
+ @JsonProperty("level")
+ private Integer level;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/address/AddressCodeResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/address/AddressCodeResponse.java
new file mode 100644
index 0000000000..09ede50c38
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/address/AddressCodeResponse.java
@@ -0,0 +1,29 @@
+package me.chanjar.weixin.channel.bean.address;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 地址编码 响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class AddressCodeResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -8994407971295563982L;
+
+ /** 本行政编码地址信息 */
+ @JsonProperty("addrs_msg")
+ private AddressCode current;
+
+ /** 下一级所有地址信息 */
+ @JsonProperty("next_level_addrs")
+ private List list;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/address/AddressDetail.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/address/AddressDetail.java
new file mode 100644
index 0000000000..88f4945e20
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/address/AddressDetail.java
@@ -0,0 +1,66 @@
+package me.chanjar.weixin.channel.bean.address;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.AddressInfo;
+
+/**
+ * 用户地址
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class AddressDetail implements Serializable {
+
+ private static final long serialVersionUID = -7839578838482198641L;
+
+ /** 地址id */
+ @JsonProperty("address_id")
+ private String addressId;
+
+ /** 联系人姓名 */
+ @JsonProperty("name")
+ private String name;
+
+ /** 地区信息 */
+ @JsonProperty("address_info")
+ private AddressInfo addressInfo;
+
+ /** 座机 */
+ @JsonProperty("landline")
+ private String landline;
+
+ /** 是否为发货地址 */
+ @JsonProperty("send_addr")
+ private Boolean sendAddr;
+
+ /** 是否为收货地址 */
+ @JsonProperty("recv_addr")
+ private Boolean recvAddr;
+
+ /** 是否为默认发货地址 */
+ @JsonProperty("default_send")
+ private Boolean defaultSend;
+
+ /** 是否为默认收货地址 */
+ @JsonProperty("default_recv")
+ private Boolean defaultRecv;
+
+ /** 创建时间戳(秒) */
+ @JsonProperty("create_time")
+ private Long createTime;
+
+ /** 更新时间戳(秒) */
+ @JsonProperty("update_time")
+ private Long updateTime;
+
+ /** 线下配送地址类型 */
+ @JsonProperty("address_type")
+ private OfflineAddressType addressType;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/address/AddressIdParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/address/AddressIdParam.java
new file mode 100644
index 0000000000..d1eb7e0b46
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/address/AddressIdParam.java
@@ -0,0 +1,27 @@
+package me.chanjar.weixin.channel.bean.address;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 地址id 请求参数
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonInclude(Include.NON_NULL)
+public class AddressIdParam implements Serializable {
+
+ private static final long serialVersionUID = -7001183932180608746L;
+
+ /** 地址id */
+ @JsonProperty("address_id")
+ private String addressId;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/address/AddressIdResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/address/AddressIdResponse.java
new file mode 100644
index 0000000000..f6505efa15
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/address/AddressIdResponse.java
@@ -0,0 +1,26 @@
+package me.chanjar.weixin.channel.bean.address;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 地址id 响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class AddressIdResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -9218327846685744008L;
+
+ /** 地址id */
+ @JsonProperty("address_id")
+ private String addressId;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/address/AddressInfoResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/address/AddressInfoResponse.java
new file mode 100644
index 0000000000..957d0162a8
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/address/AddressInfoResponse.java
@@ -0,0 +1,24 @@
+package me.chanjar.weixin.channel.bean.address;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 地址id 响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class AddressInfoResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 8203853673226715673L;
+
+ /** 地址详情 */
+ @JsonProperty("address_detail")
+ private AddressDetail addressDetail;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/address/AddressListParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/address/AddressListParam.java
new file mode 100644
index 0000000000..c62cf39fb8
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/address/AddressListParam.java
@@ -0,0 +1,26 @@
+package me.chanjar.weixin.channel.bean.address;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.OffsetParam;
+
+/**
+ * 用户地址 列表 请求参数
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@JsonInclude(Include.NON_NULL)
+public class AddressListParam extends OffsetParam {
+
+ private static final long serialVersionUID = -4434287264623932176L;
+
+ public AddressListParam(Integer offset, Integer limit) {
+ super(offset, limit);
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/address/AddressListResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/address/AddressListResponse.java
new file mode 100644
index 0000000000..b8846f9aa3
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/address/AddressListResponse.java
@@ -0,0 +1,26 @@
+package me.chanjar.weixin.channel.bean.address;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 地址列表 响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class AddressListResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -3997164605170764105L;
+
+ /** 地址详情 */
+ @JsonProperty("address_id_list")
+ private List ids;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/address/OfflineAddressType.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/address/OfflineAddressType.java
new file mode 100644
index 0000000000..81dd169399
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/address/OfflineAddressType.java
@@ -0,0 +1,28 @@
+package me.chanjar.weixin.channel.bean.address;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 线下配送地址类型
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class OfflineAddressType implements Serializable {
+
+ private static final long serialVersionUID = 636850757572901377L;
+
+ /** 1表示同城配送 */
+ @JsonProperty("same_city")
+ private Integer sameCity;
+
+ /** 1表示用户自提 */
+ @JsonProperty("pickup")
+ private Integer pickup;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/AfterSaleAcceptParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/AfterSaleAcceptParam.java
new file mode 100644
index 0000000000..ebc63a2190
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/AfterSaleAcceptParam.java
@@ -0,0 +1,29 @@
+package me.chanjar.weixin.channel.bean.after;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+/**
+ * 售后单同意信息
+ *
+ * @author Zeyes
+ */
+@Data
+@JsonInclude(Include.NON_NULL)
+public class AfterSaleAcceptParam extends AfterSaleIdParam {
+
+ private static final long serialVersionUID = -4352801757159074950L;
+ /** 同意退货时传入地址id */
+ @JsonProperty("address_id")
+ private String addressId;
+
+ public AfterSaleAcceptParam() {
+ }
+
+ public AfterSaleAcceptParam(String afterSaleOrderId, String addressId) {
+ super(afterSaleOrderId);
+ this.addressId = addressId;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/AfterSaleDetail.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/AfterSaleDetail.java
new file mode 100644
index 0000000000..aa1e7b400f
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/AfterSaleDetail.java
@@ -0,0 +1,42 @@
+package me.chanjar.weixin.channel.bean.after;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 售后详情
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class AfterSaleDetail implements Serializable {
+
+ private static final long serialVersionUID = -8130659179770831047L;
+ /** 售后描述 */
+ @JsonProperty("desc")
+ private String desc;
+
+ /** 是否已经收到货 */
+ @JsonProperty("receive_product")
+ private Boolean receiveProduct;
+
+ /** 是否已经收到货 */
+ @JsonProperty("cancel_time")
+ private Long cancelTime;
+
+ /** 举证图片media_id列表,根据mediaid获取文件内容接口 */
+ @JsonProperty("prove_imgs")
+ private List proveImgs;
+
+ /** 联系电话 */
+ @JsonProperty("tel_number")
+ private String telNumber;
+
+ /** 举证图片media_id列表,根据mediaid获取文件内容接口 */
+ @JsonProperty("media_id_list")
+ private List mediaIdList;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/AfterSaleIdParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/AfterSaleIdParam.java
new file mode 100644
index 0000000000..1e16a72395
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/AfterSaleIdParam.java
@@ -0,0 +1,26 @@
+package me.chanjar.weixin.channel.bean.after;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 售后单id信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonInclude(Include.NON_NULL)
+public class AfterSaleIdParam implements Serializable {
+
+ private static final long serialVersionUID = 4974332291476116540L;
+ /** 售后单号 */
+ @JsonProperty("after_sale_order_id")
+ private String afterSaleOrderId;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/AfterSaleInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/AfterSaleInfo.java
new file mode 100644
index 0000000000..b0d668b30e
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/AfterSaleInfo.java
@@ -0,0 +1,85 @@
+package me.chanjar.weixin.channel.bean.after;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 售后单信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class AfterSaleInfo implements Serializable {
+
+ private static final long serialVersionUID = 6595670817781635247L;
+ /** 售后单号 */
+ @JsonProperty("after_sale_order_id")
+ private String afterSaleOrderId;
+
+ /** 售后状态 {@link me.chanjar.weixin.channel.enums.AfterSaleStatus} */
+ @JsonProperty("status")
+ private String status;
+
+ /** 订单id */
+ @JsonProperty("order_id")
+ private String orderId;
+
+ /** 买家身份标识 */
+ @JsonProperty("openid")
+ private String openid;
+
+ /** 买家在开放平台的唯一标识符,若当前视频号小店已绑定到微信开放平台帐号下会返回 */
+ @JsonProperty("unionid")
+ private String unionid;
+
+ /** 售后相关商品信息 */
+ @JsonProperty("product_info")
+ private AfterSaleProductInfo productInfo;
+
+ /** 售后详情 */
+ @JsonProperty("details")
+ private AfterSaleDetail details;
+
+ /** 退款详情 */
+ @JsonProperty("refund_info")
+ private RefundInfo refundInfo;
+
+ /** 用户退货信息 */
+ @JsonProperty("return_info")
+ private ReturnInfo returnInfo;
+
+ /** 商家上传的信息 */
+ @JsonProperty("merchant_upload_info")
+ private MerchantUploadInfo merchantUploadInfo;
+
+ /** 创建时间 时间戳 秒 */
+ @JsonProperty("create_time")
+ private Long createTime;
+
+ /** 更新时间 时间戳 秒 */
+ @JsonProperty("update_time")
+ private Long updateTime;
+
+ /** 退款原因(后续新增的原因将不再有字面含义,请参考reason_text) */
+ @JsonProperty("reason")
+ private String reason;
+
+ /** 退款原因解释 */
+ @JsonProperty("reason_text")
+ private String reasonText;
+
+ /** 退款结果 */
+ @JsonProperty("refund_resp")
+ private RefundResp refundResp;
+
+ /** 售后类型。REFUND:退款;RETURN:退货退款 */
+ @JsonProperty("type")
+ private String type;
+
+ /** 纠纷id,该字段可用于获取纠纷信息 */
+ @JsonProperty("complaint_id")
+ private String complaintId;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/AfterSaleInfoResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/AfterSaleInfoResponse.java
new file mode 100644
index 0000000000..adedf72f03
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/AfterSaleInfoResponse.java
@@ -0,0 +1,23 @@
+package me.chanjar.weixin.channel.bean.after;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 售后单 响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class AfterSaleInfoResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -752661975153491902L;
+ /** 售后单 */
+ @JsonProperty("after_sale_order")
+ private AfterSaleInfo info;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/AfterSaleListParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/AfterSaleListParam.java
new file mode 100644
index 0000000000..78cc394085
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/AfterSaleListParam.java
@@ -0,0 +1,34 @@
+package me.chanjar.weixin.channel.bean.after;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 售后单列表 请求参数
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonInclude(Include.NON_NULL)
+public class AfterSaleListParam implements Serializable {
+
+ private static final long serialVersionUID = -103549981452112069L;
+ /** 订单创建启始时间 unix时间戳 */
+ @JsonProperty("begin_create_time")
+ private Long beginCreateTime;
+
+ /** 订单创建结束时间,end_create_time减去begin_create_time不得大于24小时 unix时间戳 */
+ @JsonProperty("end_create_time")
+ private Long endCreateTime;
+
+ /** 翻页参数,从第二页开始传,来源于上一页的返回值 */
+ @JsonProperty("next_key")
+ private String nextKey;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/AfterSaleListResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/AfterSaleListResponse.java
new file mode 100644
index 0000000000..3ad67cffcf
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/AfterSaleListResponse.java
@@ -0,0 +1,31 @@
+package me.chanjar.weixin.channel.bean.after;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 售后单列表 响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode
+public class AfterSaleListResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 5033313416948732123L;
+ /** 售后单号列表 */
+ @JsonProperty("after_sale_order_id_list")
+ private List ids;
+
+ /** 翻页参数 */
+ private String nextKey;
+
+ /** 是否还有数据 */
+ @JsonProperty("has_more")
+ private Boolean hasMore;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/AfterSaleProductInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/AfterSaleProductInfo.java
new file mode 100644
index 0000000000..ffcaf320ca
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/AfterSaleProductInfo.java
@@ -0,0 +1,29 @@
+package me.chanjar.weixin.channel.bean.after;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 售后相关商品信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class AfterSaleProductInfo implements Serializable {
+
+ private static final long serialVersionUID = 4205179093262757775L;
+ /** 商品spu id */
+ @JsonProperty("product_id")
+ private String productId;
+
+ /** 商品sku id */
+ @JsonProperty("sku_id")
+ private String skuId;
+
+ /** 售后数量 */
+ @JsonProperty("count")
+ private Integer count;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/AfterSaleRejectParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/AfterSaleRejectParam.java
new file mode 100644
index 0000000000..080665ac00
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/AfterSaleRejectParam.java
@@ -0,0 +1,29 @@
+package me.chanjar.weixin.channel.bean.after;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+/**
+ * 售后单拒绝信息
+ *
+ * @author Zeyes
+ */
+@Data
+@JsonInclude(Include.NON_NULL)
+public class AfterSaleRejectParam extends AfterSaleIdParam {
+
+ private static final long serialVersionUID = -7507483859864253314L;
+ /** 拒绝原因 */
+ @JsonProperty("reject_reason")
+ private String rejectReason;
+
+ public AfterSaleRejectParam() {
+ }
+
+ public AfterSaleRejectParam(String afterSaleOrderId, String rejectReason) {
+ super(afterSaleOrderId);
+ this.rejectReason = rejectReason;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/AfterSaleReturnParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/AfterSaleReturnParam.java
new file mode 100644
index 0000000000..47e815c8dd
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/AfterSaleReturnParam.java
@@ -0,0 +1,36 @@
+package me.chanjar.weixin.channel.bean.after;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import me.chanjar.weixin.channel.bean.base.AddressInfo;
+
+/**
+ * 退货信息
+ *
+ * @author Zeyes
+ */
+@Data
+public class AfterSaleReturnParam implements Serializable {
+
+ private static final long serialVersionUID = -1101993925465293521L;
+ /** 微信侧售后单号 */
+ @JsonProperty("aftersale_id")
+ private Long afterSaleId;
+
+ /** 外部售后单号,和aftersale_id二选一 */
+ @JsonProperty("out_aftersale_id")
+ private String outAfterSaleId;
+
+ /** 商家收货地址 */
+ @JsonProperty("address_info")
+ private AddressInfo addressInfo;
+
+ public AfterSaleReturnParam() {
+ }
+
+ public AfterSaleReturnParam(Long afterSaleId, String outAfterSaleId) {
+ this.outAfterSaleId = outAfterSaleId;
+ this.afterSaleId = afterSaleId;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/MerchantUploadInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/MerchantUploadInfo.java
new file mode 100644
index 0000000000..805c3a3f6e
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/MerchantUploadInfo.java
@@ -0,0 +1,27 @@
+package me.chanjar.weixin.channel.bean.after;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 商家上传的信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class MerchantUploadInfo implements Serializable {
+
+ private static final long serialVersionUID = 373513419356603563L;
+ /** 拒绝原因 */
+ @JsonProperty("reject_reason")
+ private String rejectReason;
+
+ /** 退款凭证 */
+ @JsonProperty("refund_certificates")
+ private List refundCertificates;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/RefundEvidenceParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/RefundEvidenceParam.java
new file mode 100644
index 0000000000..c81ae042d4
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/RefundEvidenceParam.java
@@ -0,0 +1,35 @@
+package me.chanjar.weixin.channel.bean.after;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 退款凭证信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class RefundEvidenceParam implements Serializable {
+
+ private static final long serialVersionUID = 2117305897849528009L;
+ /** 售后单号 */
+ @JsonProperty("after_sale_order_id")
+ private String afterSaleOrderId;
+
+ /** 描述 */
+ @JsonProperty("desc")
+ private String desc;
+
+ /** 凭证图片列表 */
+ @JsonProperty("refund_certificates")
+ private List certificates;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/RefundInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/RefundInfo.java
new file mode 100644
index 0000000000..9837b72b28
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/RefundInfo.java
@@ -0,0 +1,21 @@
+package me.chanjar.weixin.channel.bean.after;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 退款信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class RefundInfo implements Serializable {
+
+ private static final long serialVersionUID = -6994243947898889309L;
+ /** 退款金额(分) */
+ @JsonProperty("amount")
+ private Integer amount;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/RefundResp.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/RefundResp.java
new file mode 100644
index 0000000000..83b7039a77
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/RefundResp.java
@@ -0,0 +1,30 @@
+package me.chanjar.weixin.channel.bean.after;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 退款结果
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class RefundResp implements Serializable {
+
+ private static final long serialVersionUID = 6549707043779644156L;
+ /** code */
+ @JsonProperty("code")
+ private String code;
+
+ /** ret */
+ @JsonProperty("ret")
+ private Integer ret;
+
+ /** message */
+ @JsonProperty("message")
+ private String message;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/ReturnInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/ReturnInfo.java
new file mode 100644
index 0000000000..08238d5484
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/after/ReturnInfo.java
@@ -0,0 +1,29 @@
+package me.chanjar.weixin.channel.bean.after;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 用户退货信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class ReturnInfo implements Serializable {
+
+ private static final long serialVersionUID = 1643844664701376892L;
+ /** 快递单号 */
+ @JsonProperty("waybill_id")
+ private String waybillId;
+
+ /** 物流公司id */
+ @JsonProperty("delivery_id")
+ private String deliveryId;
+
+ /** 物流公司名称 */
+ @JsonProperty("delivery_name")
+ private String deliveryName;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/audit/AuditApplyResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/audit/AuditApplyResponse.java
new file mode 100644
index 0000000000..547207c82b
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/audit/AuditApplyResponse.java
@@ -0,0 +1,24 @@
+package me.chanjar.weixin.channel.bean.audit;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 审核提交结果响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class AuditApplyResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -3950614749162384497L;
+
+ /** 类目列表 */
+ @JsonProperty("audit_id")
+ private String auditId;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/audit/AuditResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/audit/AuditResponse.java
new file mode 100644
index 0000000000..3ef07387d1
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/audit/AuditResponse.java
@@ -0,0 +1,24 @@
+package me.chanjar.weixin.channel.bean.audit;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 审核结果响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class AuditResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 9218713381520774914L;
+
+ /** 审核结果 1:审核中,3:审核成功,2:审核拒绝,12:主动取消申请单 */
+ @JsonProperty("data")
+ private AuditResult data;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/audit/AuditResult.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/audit/AuditResult.java
new file mode 100644
index 0000000000..89aaa8a267
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/audit/AuditResult.java
@@ -0,0 +1,26 @@
+package me.chanjar.weixin.channel.bean.audit;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 审核结果
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class AuditResult implements Serializable {
+
+ private static final long serialVersionUID = 1846416634865665240L;
+
+ /** 审核状态, 0:审核中,1:审核成功,9:审核拒绝, 12:主动取消 */
+ @JsonProperty("status")
+ private Integer status;
+
+ /** 如果审核拒绝,返回拒绝原因 */
+ @JsonProperty("reject_reason")
+ private String rejectReason;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/audit/CategoryAuditInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/audit/CategoryAuditInfo.java
new file mode 100644
index 0000000000..72a84bc922
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/audit/CategoryAuditInfo.java
@@ -0,0 +1,37 @@
+package me.chanjar.weixin.channel.bean.audit;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 类目审核信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class CategoryAuditInfo implements Serializable {
+
+ private static final long serialVersionUID = -8792967130645424788L;
+
+ /** 一级类目,字符类型,最长不超过10 */
+ @JsonProperty("level1")
+ private Long level1;
+
+ /** 二级类目,字符类型,最长不超过10 */
+ @JsonProperty("level2")
+ private Long level2;
+
+ /** 三级类目,字符类型,最长不超过10 */
+ @JsonProperty("level3")
+ private Long level3;
+
+ /** 资质材料,图片url,图片类型,最多不超过10张 */
+ @JsonProperty("certificate")
+ private List certificates;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/audit/CategoryAuditRequest.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/audit/CategoryAuditRequest.java
new file mode 100644
index 0000000000..a311bf0d2f
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/audit/CategoryAuditRequest.java
@@ -0,0 +1,23 @@
+package me.chanjar.weixin.channel.bean.audit;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 类目审核信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class CategoryAuditRequest implements Serializable {
+
+ private static final long serialVersionUID = -1151634735247657643L;
+
+ @JsonProperty("category_info")
+ private CategoryAuditInfo categoryInfo;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/audit/ProductAuditInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/audit/ProductAuditInfo.java
new file mode 100644
index 0000000000..7693f23ed3
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/audit/ProductAuditInfo.java
@@ -0,0 +1,37 @@
+package me.chanjar.weixin.channel.bean.audit;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 商品审核信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class ProductAuditInfo implements Serializable {
+
+ private static final long serialVersionUID = -5264206679057480206L;
+
+ /** 审核单id */
+ @JsonProperty("audit_id")
+ private String auditId;
+
+ /** 上一次提交时间, yyyy-MM-dd HH:mm:ss */
+ @JsonProperty("submit_time")
+ private String submitTime;
+
+ /** 上一次审核时间, yyyy-MM-dd HH:mm:ss */
+ @JsonProperty("audit_time")
+ private String auditTime;
+
+ /** 拒绝理由,只有edit_status为3时出现 */
+ @JsonProperty("reject_reason")
+ private String rejectReason;
+
+ @JsonProperty("func_type")
+ private Integer funcType;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/base/AddressInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/base/AddressInfo.java
new file mode 100644
index 0000000000..3c713840a4
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/base/AddressInfo.java
@@ -0,0 +1,70 @@
+package me.chanjar.weixin.channel.bean.base;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+/**
+ * 地址信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@Accessors(chain = true)
+public class AddressInfo implements Serializable {
+
+ private static final long serialVersionUID = 6928300709804576100L;
+
+ /** 收件人姓名 */
+ @JsonProperty("user_name")
+ private String userName;
+
+ /** 收件人手机号码 */
+ @JsonProperty("tel_number")
+ private String telNumber;
+
+ /** 邮编 */
+ @JsonProperty("postal_code")
+ private String postalCode;
+
+ /** 省份 */
+ @JsonProperty("province_name")
+ private String provinceName;
+
+ /** 城市 */
+ @JsonProperty("city_name")
+ private String cityName;
+
+ /** 区 */
+ @JsonProperty("county_name")
+ private String countyName;
+
+ /** 详细地址 */
+ @JsonProperty("detail_info")
+ private String detailInfo;
+
+ /** 国家码 */
+ @JsonProperty("national_code")
+ private String nationalCode;
+
+ /** 门牌号码 */
+ @JsonProperty("house_number")
+ private String houseNumber;
+
+ /** 纬度 */
+ @JsonProperty("lat")
+ private Double lat;
+
+ /** 经度 */
+ @JsonProperty("lng")
+ private Double lng;
+
+ public AddressInfo(String provinceName, String cityName, String countyName) {
+ this.provinceName = provinceName;
+ this.cityName = cityName;
+ this.countyName = countyName;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/base/AttrInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/base/AttrInfo.java
new file mode 100644
index 0000000000..ca6ce7a750
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/base/AttrInfo.java
@@ -0,0 +1,28 @@
+package me.chanjar.weixin.channel.bean.base;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 属性
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class AttrInfo implements Serializable {
+
+ private static final long serialVersionUID = -790859309885311785L;
+
+ /** 销售属性key(自定义),字符类型,最长不超过40 */
+ @JsonProperty("attr_key")
+ private String key;
+
+ /** 销售属性value(自定义),字符类型,最长不超过40,相同key下不能超过100个不同value */
+ @JsonProperty("attr_value")
+ private String value;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/base/OffsetParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/base/OffsetParam.java
new file mode 100644
index 0000000000..ebfad1bf21
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/base/OffsetParam.java
@@ -0,0 +1,30 @@
+package me.chanjar.weixin.channel.bean.base;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 偏移参数
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonInclude(Include.NON_NULL)
+public class OffsetParam implements Serializable {
+
+ private static final long serialVersionUID = -1268796871980541662L;
+
+ /** 起始位置 */
+ @JsonProperty("offset")
+ private Integer offset;
+ /** 拉取个数 */
+ @JsonProperty("limit")
+ private Integer limit;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/base/PageParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/base/PageParam.java
new file mode 100644
index 0000000000..d76e48d3b6
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/base/PageParam.java
@@ -0,0 +1,28 @@
+package me.chanjar.weixin.channel.bean.base;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 分页参数
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class PageParam implements Serializable {
+
+ private static final long serialVersionUID = -2606033044242617845L;
+
+ /** 页码 */
+ @JsonProperty("page")
+ protected Integer page;
+
+ /** 每页订单数,上限100 */
+ @JsonProperty("page_size")
+ protected Integer pageSize;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/base/StreamPageParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/base/StreamPageParam.java
new file mode 100644
index 0000000000..6f3fb76d71
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/base/StreamPageParam.java
@@ -0,0 +1,28 @@
+package me.chanjar.weixin.channel.bean.base;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 流式分页参数
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class StreamPageParam implements Serializable {
+
+ private static final long serialVersionUID = -4098060161712929196L;
+
+ /** 每页订单数,上限100 */
+ @JsonProperty("page_size")
+ protected Integer pageSize;
+
+ /** 分页参数,上一页请求返回 */
+ @JsonProperty("next_key")
+ protected String nextKey;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/base/TimeRange.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/base/TimeRange.java
new file mode 100644
index 0000000000..f681794835
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/base/TimeRange.java
@@ -0,0 +1,26 @@
+package me.chanjar.weixin.channel.bean.base;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 时间范围
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class TimeRange implements Serializable {
+
+ private static final long serialVersionUID = -8149679871789511479L;
+
+ /** 开始时间 秒级时间戳 */
+ @JsonProperty("start_time")
+ private Long startTime;
+
+ /** 结束时间 秒级时间戳 */
+ @JsonProperty("end_time")
+ private Long endTime;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/base/WxChannelBaseResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/base/WxChannelBaseResponse.java
new file mode 100644
index 0000000000..b20d7f4b33
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/base/WxChannelBaseResponse.java
@@ -0,0 +1,68 @@
+package me.chanjar.weixin.channel.bean.base;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.StringJoiner;
+
+/**
+ * 视频号小店 基础响应
+ *
+ * @author Zeyes
+ */
+public class WxChannelBaseResponse implements Serializable {
+
+ private static final long serialVersionUID = 3141420881984171781L;
+
+ /** 请求成功状态码 */
+ public static final int SUCCESS_CODE = 0;
+ public static final int INTERNAL_ERROR_CODE = -99;
+
+ /**
+ * 错误码
+ */
+ @JsonProperty("errcode")
+ protected int errCode;
+
+ /**
+ * 错误消息
+ */
+ @JsonProperty("errmsg")
+ protected String errMsg;
+
+ /**
+ * 错误代码 + 错误消息
+ *
+ * @return String
+ */
+ public String errorMessage() {
+ return "errcode: " + errCode + ", errmsg: " + errMsg;
+ }
+
+ public boolean isSuccess() {
+ return errCode == SUCCESS_CODE;
+ }
+
+ public int getErrCode() {
+ return errCode;
+ }
+
+ public void setErrCode(int errCode) {
+ this.errCode = errCode;
+ }
+
+ public String getErrMsg() {
+ return errMsg;
+ }
+
+ public void setErrMsg(String errMsg) {
+ this.errMsg = errMsg;
+ }
+
+ @Override
+ public String toString() {
+ return new StringJoiner(", ", WxChannelBaseResponse.class.getSimpleName() + "[", "]")
+ .add("errCode=" + errCode)
+ .add("errMsg='" + errMsg + "'")
+ .toString();
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/brand/BasicBrand.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/brand/BasicBrand.java
new file mode 100644
index 0000000000..714740f843
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/brand/BasicBrand.java
@@ -0,0 +1,30 @@
+package me.chanjar.weixin.channel.bean.brand;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 基础品牌信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class BasicBrand implements Serializable {
+
+ private static final long serialVersionUID = -1991771439710177859L;
+
+ /** 品牌库中的品牌编号(Long) */
+ @JsonProperty("brand_id")
+ private String brandId;
+
+ /** 品牌商标中文名 */
+ @JsonProperty("ch_name")
+ private String chName;
+
+ /** 品牌商标英文名 */
+ @JsonProperty("en_name")
+ private String enName;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/brand/Brand.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/brand/Brand.java
new file mode 100644
index 0000000000..92f4f41acc
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/brand/Brand.java
@@ -0,0 +1,45 @@
+package me.chanjar.weixin.channel.bean.brand;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+/**
+ * 品牌信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class Brand extends BasicBrand {
+
+ private static final long serialVersionUID = 4648597514861057019L;
+
+ /** 商标分类号, 取值范围1-45 */
+ @JsonProperty("classification_no")
+ private String classificationNo;
+
+ /** 商标类型, 取值1:R标; 2: TM标 */
+ @JsonProperty("trade_mark_symbol")
+ private Integer tradeMarkSymbol;
+
+ /** 商标注册信息 */
+ @JsonProperty("register_details")
+ private BrandRegisterDetail registerDetail;
+
+ /** 商标申请信息 */
+ @JsonProperty("application_details")
+ private BrandApplicationDetail applicationDetail;
+
+ /** 商标授权信息, 取值1:自有品牌; 2: 授权品牌 */
+ @JsonProperty("grant_type")
+ private Integer grantType;
+
+ /** 授权品牌信息 */
+ @JsonProperty("grant_details")
+ private BrandGrantDetail grantDetail;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/brand/BrandApplicationDetail.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/brand/BrandApplicationDetail.java
new file mode 100644
index 0000000000..48575f27cd
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/brand/BrandApplicationDetail.java
@@ -0,0 +1,31 @@
+package me.chanjar.weixin.channel.bean.brand;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 商标申请信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class BrandApplicationDetail implements Serializable {
+
+ private static final long serialVersionUID = 2145344855482129473L;
+
+ /** 商标申请受理时间, TM标时必填 */
+ @JsonProperty("acceptance_time")
+ private Long acceptanceTime;
+
+ /** 商标注册申请受理书file_id, TM标时必填, 限制最多传1张, 需要先调用“资质上传”接口上传资质图片 */
+ @JsonProperty("acceptance_certification")
+ private List acceptanceCertification;
+
+ /** 商标申请号, TM标时必填 */
+ @JsonProperty("acceptance_no")
+ private String acceptanceNo;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/brand/BrandApplyListResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/brand/BrandApplyListResponse.java
new file mode 100644
index 0000000000..16e7f3ae82
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/brand/BrandApplyListResponse.java
@@ -0,0 +1,33 @@
+package me.chanjar.weixin.channel.bean.brand;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 品牌申请列表响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class BrandApplyListResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 243021267020609148L;
+
+ /** 品牌资质申请信息 */
+ @JsonProperty("brands")
+ private List brands;
+
+ /** 本次翻页的上下文,用于请求下一页 */
+ @JsonProperty("next_key")
+ private String nextKey;
+
+ /** 品牌资质总数 */
+ @JsonProperty("total_num")
+ private Integer totalNum;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/brand/BrandGrantDetail.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/brand/BrandGrantDetail.java
new file mode 100644
index 0000000000..6b4826fcd4
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/brand/BrandGrantDetail.java
@@ -0,0 +1,44 @@
+package me.chanjar.weixin.channel.bean.brand;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 商标授权信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class BrandGrantDetail implements Serializable {
+
+ private static final long serialVersionUID = 3537812707384823606L;
+
+ /** 品牌销售授权书的file_id, 授权品牌必填, 限制最多传9张, 需要先调用“资质上传”接口上传资质图片 */
+ @JsonProperty("grant_certifications")
+ private List grantCertifications;
+
+ /** 授权级数, 授权品牌必填, 取值1-3 */
+ @JsonProperty("grant_level")
+ private Integer grantLevel;
+
+ /** 授权有效期, 开始时间, 长期有效可不填 */
+ @JsonProperty("start_time")
+ private Long startTime;
+
+ /** 授权有效期, 结束时间, 长期有效可不填 */
+ @JsonProperty("end_time")
+ private Long endTime;
+
+ /** 是否长期有效 */
+ @JsonProperty("is_permanent")
+ private boolean permanent;
+
+ /** 品牌权利人证件照的file_id, 限制最多传2张, 需要先调用“资质上传”接口上传资质图片 */
+ @JsonProperty("brand_owner_id_photos")
+ private List brandOwnerIdPhotos;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/brand/BrandInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/brand/BrandInfo.java
new file mode 100644
index 0000000000..799002369d
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/brand/BrandInfo.java
@@ -0,0 +1,52 @@
+package me.chanjar.weixin.channel.bean.brand;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+/**
+ * 品牌信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class BrandInfo extends Brand {
+
+ private static final long serialVersionUID = 5464505958132626159L;
+
+ /** 申请单状态 1审核中 2审核失败 3已生效 4已撤回 5即将过期(不影响商品售卖) 6已过期 */
+ @JsonProperty("status")
+ private Integer status;
+
+ /** 创建时间 */
+ @JsonProperty("create_time")
+ private Long createTime;
+
+ /** 更新时间 */
+ @JsonProperty("update_time")
+ private Long updateTime;
+
+ /** 审核结果 */
+ @JsonProperty("audit_result")
+ private AuditResult auditResult;
+
+ /** 审核结果 */
+ @Data
+ @NoArgsConstructor
+ public static class AuditResult implements Serializable {
+
+ private static final long serialVersionUID = 3936802571381636820L;
+ /** 提审的审核单ID */
+ @JsonProperty("audit_id")
+ private String auditId;
+
+ /** 审核不通过的原因, 审核成功不返回 */
+ @JsonProperty("reject_reason")
+ private String rejectReason;
+ }
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/brand/BrandInfoResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/brand/BrandInfoResponse.java
new file mode 100644
index 0000000000..20536b5a07
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/brand/BrandInfoResponse.java
@@ -0,0 +1,24 @@
+package me.chanjar.weixin.channel.bean.brand;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 品牌响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class BrandInfoResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 2105745692451683517L;
+
+ /** 品牌信息 */
+ @JsonProperty("brand")
+ private BrandInfo brand;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/brand/BrandListResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/brand/BrandListResponse.java
new file mode 100644
index 0000000000..c6cff6f317
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/brand/BrandListResponse.java
@@ -0,0 +1,33 @@
+package me.chanjar.weixin.channel.bean.brand;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 品牌列表响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class BrandListResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -5335449078706304920L;
+
+ /** 品牌库中的品牌信息 */
+ @JsonProperty("brands")
+ private List brands;
+
+ /** 本次翻页的上下文,用于请求下一页 */
+ @JsonProperty("next_key")
+ private String nextKey;
+
+ /** 是否还有下一页内容 */
+ @JsonProperty("continue_flag")
+ private boolean continueFlag;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/brand/BrandParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/brand/BrandParam.java
new file mode 100644
index 0000000000..05f8d89b42
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/brand/BrandParam.java
@@ -0,0 +1,26 @@
+package me.chanjar.weixin.channel.bean.brand;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 品牌参数
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class BrandParam implements Serializable {
+
+ private static final long serialVersionUID = -4894709391464428613L;
+
+ /** 品牌信息 */
+ @JsonProperty("brand")
+ private Brand brand;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/brand/BrandRegisterDetail.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/brand/BrandRegisterDetail.java
new file mode 100644
index 0000000000..28b417f38c
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/brand/BrandRegisterDetail.java
@@ -0,0 +1,48 @@
+package me.chanjar.weixin.channel.bean.brand;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 品牌注册信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class BrandRegisterDetail implements Serializable {
+
+ private static final long serialVersionUID = 1169957179510362405L;
+
+ /** 商标注册人, R标时必填 */
+ @JsonProperty("registrant")
+ private String registrant;
+
+ /** 商标注册号, R标时必填 */
+ @JsonProperty("register_no")
+ private String registerNo;
+
+ /** 商标注册有效期(时间戳秒), 开始时间, 长期有效可不填 */
+ @JsonProperty("start_time")
+ private Long startTime;
+
+ /** 商标注册有效期(时间戳秒), 结束时间, 长期有效可不填 */
+ @JsonProperty("end_time")
+ private Long endTime;
+
+ /** 是否长期有效 */
+ @JsonProperty("is_permanent")
+ private boolean permanent;
+
+ /** 商标注册证的file_id, R标时必填, 限制最多传1张, 需要先调用“资质上传”接口上传资质图片 */
+ @JsonProperty("register_certifications")
+ private List registerCertifications;
+
+ /** 变更/续展证明的file_id, 限制最多传5张, 需要先调用“资质上传”接口上传资质图片 */
+ @JsonProperty("renew_certifications")
+ private List renewCertifications;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/brand/BrandSearchParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/brand/BrandSearchParam.java
new file mode 100644
index 0000000000..e73ed4f54e
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/brand/BrandSearchParam.java
@@ -0,0 +1,31 @@
+package me.chanjar.weixin.channel.bean.brand;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import me.chanjar.weixin.channel.bean.base.StreamPageParam;
+
+/**
+ * 品牌搜索参数
+ *
+ * @author Zeyes
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class BrandSearchParam extends StreamPageParam {
+
+ private static final long serialVersionUID = 5961201403338269712L;
+ /** 审核单状态, 不填默认拉全部商品 */
+ @JsonProperty("status")
+ private Integer status;
+
+ public BrandSearchParam() {
+ }
+
+ public BrandSearchParam(Integer pageSize, String nextKey, Integer status) {
+ super(pageSize, nextKey);
+ this.status = status;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/category/AccountCategoryResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/category/AccountCategoryResponse.java
new file mode 100644
index 0000000000..3db7c74cec
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/category/AccountCategoryResponse.java
@@ -0,0 +1,25 @@
+package me.chanjar.weixin.channel.bean.category;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 分类响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class AccountCategoryResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 3486089711447908477L;
+
+ /** 类目列表 */
+ @JsonProperty("data")
+ private List categories;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/category/CategoryAndQualificationList.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/category/CategoryAndQualificationList.java
new file mode 100644
index 0000000000..c9e973c8b8
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/category/CategoryAndQualificationList.java
@@ -0,0 +1,23 @@
+package me.chanjar.weixin.channel.bean.category;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 分类资质响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class CategoryAndQualificationList implements Serializable {
+
+ private static final long serialVersionUID = 4245906598437404655L;
+
+ /** 分类列表 */
+ @JsonProperty("cat_and_qua")
+ private List list;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/category/CategoryDetailResult.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/category/CategoryDetailResult.java
new file mode 100644
index 0000000000..8819e94312
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/category/CategoryDetailResult.java
@@ -0,0 +1,132 @@
+package me.chanjar.weixin.channel.bean.category;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class CategoryDetailResult extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 4657778764371047619L;
+
+ @JsonProperty("info")
+ private Info info;
+
+ @JsonProperty("attr")
+ private Attr attr;
+
+
+ @Data
+ @NoArgsConstructor
+ public static class Info implements Serializable {
+
+ /** 类目ID */
+ @JsonProperty("cat_id")
+ private String id;
+ /** 类目名称 */
+ @JsonProperty("name")
+ private String name;
+ }
+
+ @Data
+ @NoArgsConstructor
+ public static class Attr implements Serializable {
+
+ /** 是否支持虚拟发货 */
+ @JsonProperty("shop_no_shipment")
+ private Boolean shopNoShipment;
+
+ /** 是否定向准入 */
+ @JsonProperty("access_permit_required")
+ private Boolean accessPermitRequired;
+
+ /** 是否支持预售 */
+ @JsonProperty("pre_sale")
+ private Boolean preSale;
+
+ /** 是否必须支持7天无理由退货 */
+ @JsonProperty("seven_day_return")
+ private Boolean sevenDayReturn;
+
+ /** 定准类目的品牌ID */
+ @JsonProperty("brand_list")
+ private List brands;
+
+ /** 类目关联的保证金,单位分 */
+ @JsonProperty("deposit")
+ private Long deposit;
+
+ /** 产品属性 */
+ @JsonProperty("product_attr_list")
+ private List productAttrs;
+
+ /** 销售属性 */
+ @JsonProperty("sale_attr_list")
+ private List saleAttrs;
+
+ /** 佣金信息 */
+ @JsonProperty("transactionfee_info")
+ private FeeInfo feeInfo;
+ }
+
+ @Data
+ @NoArgsConstructor
+ public static class BrandInfo implements Serializable {
+
+ /** 定准类目的品牌ID */
+ @JsonProperty("brand_id")
+ private String id;
+ }
+
+ @Data
+ @NoArgsConstructor
+ public static class ProductAttr implements Serializable {
+
+ /** 类目必填项名称 */
+ @JsonProperty("name")
+ private String name;
+
+ /** 类目必填项类型,string为自定义,select_one为多选一 */
+ @JsonProperty("type")
+ private String type;
+
+ /** 类目必填项值 */
+ @JsonProperty("value")
+ private String value;
+
+ /** 是否类目必填项 */
+ @JsonProperty("is_required")
+ private Boolean required;
+
+
+ }
+
+ @Data
+ @NoArgsConstructor
+ public static class FeeInfo implements Serializable {
+
+ /** 类目实收的交易佣金比例,单位万分比 */
+ @JsonProperty("basis_point")
+ private Integer basisPoint;
+
+ /** 类目原始佣金比例,单位万分比 */
+ @JsonProperty("original_basis_point")
+ private Integer originalBasisPoint;
+
+ /** 佣金激励类型,0:无激励措施,1:新店佣金减免 */
+ @JsonProperty("incentive_type")
+ private Integer incentiveType;
+
+ }
+}
+
+
+
+
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/category/CategoryQualification.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/category/CategoryQualification.java
new file mode 100644
index 0000000000..f384eaae45
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/category/CategoryQualification.java
@@ -0,0 +1,31 @@
+package me.chanjar.weixin.channel.bean.category;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 分类资质信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class CategoryQualification implements Serializable {
+
+ private static final long serialVersionUID = 6495550078851408381L;
+
+ /** 类目 */
+ @JsonProperty("cat")
+ private ShopCategory category;
+
+ /** 资质信息 */
+ @JsonProperty("qua")
+ private QualificationInfo info;
+
+ /** 商品资质信息 */
+ @JsonProperty("product_qua")
+ private QualificationInfo productInfo;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/category/CategoryQualificationResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/category/CategoryQualificationResponse.java
new file mode 100644
index 0000000000..984a3ad79b
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/category/CategoryQualificationResponse.java
@@ -0,0 +1,25 @@
+package me.chanjar.weixin.channel.bean.category;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 分类资质响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class CategoryQualificationResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -7869091908852685830L;
+
+ @JsonProperty("cats")
+ private List list;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/category/PassCategoryInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/category/PassCategoryInfo.java
new file mode 100644
index 0000000000..82b16c0188
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/category/PassCategoryInfo.java
@@ -0,0 +1,26 @@
+package me.chanjar.weixin.channel.bean.category;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 审核通过的分类和资质信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class PassCategoryInfo implements Serializable {
+
+ private static final long serialVersionUID = 1152077957498898216L;
+
+ /** 类目ID */
+ @JsonProperty("cat_id")
+ private String catId;
+
+ /** 资质ID */
+ @JsonProperty("qua_id")
+ private String quaId;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/category/PassCategoryResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/category/PassCategoryResponse.java
new file mode 100644
index 0000000000..af6f484254
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/category/PassCategoryResponse.java
@@ -0,0 +1,23 @@
+package me.chanjar.weixin.channel.bean.category;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 审核通过的分类和资质信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class PassCategoryResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -3674591447273025743L;
+
+ /** 类目和资质信息列表 */
+ @JsonProperty("list")
+ private List list;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/category/QualificationInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/category/QualificationInfo.java
new file mode 100644
index 0000000000..197ac46528
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/category/QualificationInfo.java
@@ -0,0 +1,32 @@
+package me.chanjar.weixin.channel.bean.category;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 资质信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class QualificationInfo implements Serializable {
+
+ /** 资质ID */
+ @JsonProperty("qua_id")
+ private String id;
+
+ /** 是否需要申请 */
+ @JsonProperty("need_to_apply")
+ private Boolean needToApply;
+
+ /** 资质信息 */
+ @JsonProperty("tips")
+ private String tips;
+
+ /** 该类目申请的时候是否一定要提交资质 */
+ @JsonProperty("mandatory")
+ private Boolean mandatory;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/category/ShopCategory.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/category/ShopCategory.java
new file mode 100644
index 0000000000..b36edfa9e2
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/category/ShopCategory.java
@@ -0,0 +1,32 @@
+package me.chanjar.weixin.channel.bean.category;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 商品类目
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class ShopCategory implements Serializable {
+
+ /** 类目ID */
+ @JsonProperty("cat_id")
+ private String id;
+
+ /** 类目父ID */
+ @JsonProperty("f_cat_id")
+ private String parentId;
+
+ /** 类目名称 */
+ @JsonProperty("name")
+ private String name;
+
+ /** 层级 */
+ @JsonProperty("level")
+ private Integer level;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/category/ShopCategoryResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/category/ShopCategoryResponse.java
new file mode 100644
index 0000000000..2af64ad1c3
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/category/ShopCategoryResponse.java
@@ -0,0 +1,27 @@
+package me.chanjar.weixin.channel.bean.category;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 分类响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class ShopCategoryResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 3871098948660947422L;
+
+ /** 类目列表 */
+ @JsonProperty("cat_list")
+ private List categories;
+
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/complaint/ComplaintHistory.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/complaint/ComplaintHistory.java
new file mode 100644
index 0000000000..4570fdc615
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/complaint/ComplaintHistory.java
@@ -0,0 +1,46 @@
+package me.chanjar.weixin.channel.bean.complaint;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 纠纷历史
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class ComplaintHistory implements Serializable {
+
+ private static final long serialVersionUID = -4706637116597650133L;
+ /** 历史操作类型,见 {@link me.chanjar.weixin.channel.enums.ComplaintItemType } */
+ @JsonProperty("item_type")
+ private Integer itemType;
+
+ /** 操作时间,Unix时间戳 */
+ @JsonProperty("time")
+ private Long time;
+
+ /** 用户联系电话 */
+ @JsonProperty("phone_number")
+ private Integer phoneNumber;
+
+ /** 相关文本内容 */
+ @JsonProperty("content")
+ private String content;
+
+ /** 相关图片media_id列表 */
+ @JsonProperty("media_id_list")
+ private List mediaIds;
+
+ /** 售后类型, 1-仅退款 2-退货退款 */
+ @JsonProperty("after_sale_type")
+ private Integer afterSaleType;
+
+ /** 售后原因,见 {@link me.chanjar.weixin.channel.enums.AfterSalesReason} */
+ @JsonProperty("after_sale_reason")
+ private Integer afterSaleReason;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/complaint/ComplaintOrderResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/complaint/ComplaintOrderResponse.java
new file mode 100644
index 0000000000..a0a8ec1e18
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/complaint/ComplaintOrderResponse.java
@@ -0,0 +1,35 @@
+package me.chanjar.weixin.channel.bean.complaint;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 纠纷单响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class ComplaintOrderResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 1968530826349555367L;
+ /** 售后单号 */
+ @JsonProperty("after_sale_order_id")
+ private String afterSaleOrderId;
+
+ /** 订单号 */
+ @JsonProperty("order_id")
+ private String orderId;
+
+ /** 纠纷历史 */
+ @JsonProperty("history")
+ private List history;
+
+ /** 纠纷单状态, 见 {@link me.chanjar.weixin.channel.enums.ComplaintStatus} */
+ @JsonProperty("status")
+ private Integer status;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/complaint/ComplaintParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/complaint/ComplaintParam.java
new file mode 100644
index 0000000000..0090348efe
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/complaint/ComplaintParam.java
@@ -0,0 +1,34 @@
+package me.chanjar.weixin.channel.bean.complaint;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 纠纷单留言
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class ComplaintParam implements Serializable {
+
+ private static final long serialVersionUID = 6146118590005718327L;
+ /** 纠纷单号 */
+ @JsonProperty("complaint_id")
+ private String complaintId;
+
+ /** 留言内容,最多500字 */
+ @JsonProperty("content")
+ private String content;
+
+ /** 图片media_id列表,所有留言总图片数量最多20张 */
+ @JsonProperty("media_id_list")
+ private List mediaIds;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/AutoValidInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/AutoValidInfo.java
new file mode 100644
index 0000000000..73c09def1e
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/AutoValidInfo.java
@@ -0,0 +1,21 @@
+package me.chanjar.weixin.channel.bean.coupon;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 自动生效信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class AutoValidInfo implements Serializable {
+
+ private static final long serialVersionUID = 1702505613539861103L;
+ /** 优惠券开启自动生效类型 0不启用自动生效 1启用自动生效,按领券开始时间(自动生效时间为 receive_info.start_time) */
+ @JsonProperty("auto_valid_type")
+ private Integer autoValidType;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/CouponDetailInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/CouponDetailInfo.java
new file mode 100644
index 0000000000..34f76716f9
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/CouponDetailInfo.java
@@ -0,0 +1,43 @@
+package me.chanjar.weixin.channel.bean.coupon;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 优惠券信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+
+public class CouponDetailInfo implements Serializable {
+
+ private static final long serialVersionUID = 5994815232349181577L;
+ /** 优惠券名称 **/
+ @JsonProperty("name")
+ private String name;
+
+ /** 优惠券有效信息 **/
+ @JsonProperty("valid_info")
+ private ValidInfo validInfo;
+
+ /** 推广信息 **/
+ @JsonProperty("promote_info")
+ private PromoteInfo promoteInfo;
+
+ /** 优惠信息 **/
+ @JsonProperty("discount_info")
+ private DiscountInfo discountInfo;
+
+ /** 额外信息 **/
+ @JsonProperty("ext_info")
+ private ExtInfo extInfo;
+
+ /** 领取信息 **/
+ @JsonProperty("receive_info")
+ private ReceiveInfo receiveInfo;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/CouponIdInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/CouponIdInfo.java
new file mode 100644
index 0000000000..b787016a09
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/CouponIdInfo.java
@@ -0,0 +1,24 @@
+package me.chanjar.weixin.channel.bean.coupon;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 优惠券id
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class CouponIdInfo implements Serializable {
+
+ private static final long serialVersionUID = 6284609705855608275L;
+ /** 优惠券ID */
+ @JsonProperty("coupon_id")
+ private String couponId;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/CouponIdResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/CouponIdResponse.java
new file mode 100644
index 0000000000..7556fa6f11
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/CouponIdResponse.java
@@ -0,0 +1,21 @@
+package me.chanjar.weixin.channel.bean.coupon;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+
+/**
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class CouponIdResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -3263189706802013651L;
+ @JsonProperty("data")
+ private CouponIdInfo data;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/CouponInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/CouponInfo.java
new file mode 100644
index 0000000000..cd247f9d71
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/CouponInfo.java
@@ -0,0 +1,38 @@
+package me.chanjar.weixin.channel.bean.coupon;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class CouponInfo extends CouponIdInfo {
+
+ private static final long serialVersionUID = -5862063828870424262L;
+ /** 优惠券类型 **/
+ @JsonProperty("type")
+ private Integer type;
+
+ /** 优惠券状态 **/
+ @JsonProperty("status")
+ private Integer status;
+
+ /** 优惠券创建时间 */
+ @JsonProperty("create_time")
+ private Long createTime;
+
+ /** 优惠券更新时间 */
+ @JsonProperty("update_time")
+ private Long updateTime;
+
+ /** 优惠券信息 */
+ @JsonProperty("coupon_info")
+ private CouponDetailInfo detail;
+
+ /** 库存信息 */
+ @JsonProperty("stock_info")
+ private StockInfo stockInfo;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/CouponInfoResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/CouponInfoResponse.java
new file mode 100644
index 0000000000..801843025e
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/CouponInfoResponse.java
@@ -0,0 +1,20 @@
+package me.chanjar.weixin.channel.bean.coupon;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class CouponInfoResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 5261320058699488529L;
+ @JsonProperty("coupon")
+ private CouponInfo coupon;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/CouponListParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/CouponListParam.java
new file mode 100644
index 0000000000..6c7fc03a6e
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/CouponListParam.java
@@ -0,0 +1,45 @@
+package me.chanjar.weixin.channel.bean.coupon;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * 获取优惠券ID列表接口的请求参数
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@JsonInclude(Include.NON_NULL)
+public class CouponListParam implements Serializable {
+ private static final long serialVersionUID = 7123047113279657365L;
+
+ /**
+ * 优惠券状态 {@link me.chanjar.weixin.channel.enums.WxCouponStatus}
+ */
+ @JsonProperty("status")
+ private Integer status;
+
+ /**
+ * 第几页(最小填1)
+ */
+ @JsonProperty("page")
+ private Integer page;
+
+ /**
+ * 每页数量(不超过200)
+ */
+ @JsonProperty("page_size")
+ private Integer pageSize;
+
+ /**
+ * 分页上下文
+ */
+ @JsonProperty("page_ctx")
+ private String pageCtx;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/CouponListResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/CouponListResponse.java
new file mode 100644
index 0000000000..66d6f63eef
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/CouponListResponse.java
@@ -0,0 +1,31 @@
+package me.chanjar.weixin.channel.bean.coupon;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class CouponListResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -5330296358041282751L;
+ /** 优惠券id列表 */
+ @JsonProperty("coupons")
+ private List coupons;
+
+ /** 优惠券总数 */
+ @JsonProperty("total_num")
+ private Integer totalNum;
+
+ /** 优惠券上下文 */
+ @JsonProperty("page_ctx")
+ private String pageCtx;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/CouponParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/CouponParam.java
new file mode 100644
index 0000000000..fa89b0a1e4
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/CouponParam.java
@@ -0,0 +1,50 @@
+package me.chanjar.weixin.channel.bean.coupon;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+/**
+ * 优惠券参数
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class CouponParam extends CouponIdInfo {
+
+ private static final long serialVersionUID = -3663331372622943337L;
+ /** 优惠券类型 **/
+ @JsonProperty("type")
+ private Integer type;
+
+ /** 优惠券名称,最长10个中文字符 */
+ @JsonProperty("name")
+ private String name;
+
+ /** 优惠信息 **/
+ @JsonProperty("discount_info")
+ private DiscountInfo discountInfo;
+
+ /** 额外信息 **/
+ @JsonProperty("ext_info")
+ private ExtInfo extInfo;
+
+ /** 推广信息 **/
+ @JsonProperty("promote_info")
+ private PromoteInfo promoteInfo;
+
+ /** 领取信息 **/
+ @JsonProperty("receive_info")
+ private ReceiveInfo receiveInfo;
+
+ /** 优惠券有效信息 **/
+ @JsonProperty("valid_info")
+ private ValidInfo validInfo;
+
+ /** 优惠券自动生效信息 **/
+ @JsonProperty("auto_valid_info")
+ private AutoValidInfo autoValidInfo;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/CouponStatusParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/CouponStatusParam.java
new file mode 100644
index 0000000000..405ad52400
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/CouponStatusParam.java
@@ -0,0 +1,28 @@
+package me.chanjar.weixin.channel.bean.coupon;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * @author Zeyes
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class CouponStatusParam extends CouponIdInfo {
+
+ private static final long serialVersionUID = -7108348049925634704L;
+ /** 状态 */
+ @JsonProperty("status")
+ private Integer status;
+
+ public CouponStatusParam() {
+ }
+
+ public CouponStatusParam(String couponId, Integer status) {
+ super(couponId);
+ this.status = status;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/DiscountCondition.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/DiscountCondition.java
new file mode 100644
index 0000000000..e249455526
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/DiscountCondition.java
@@ -0,0 +1,30 @@
+package me.chanjar.weixin.channel.bean.coupon;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 折扣条件
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class DiscountCondition implements Serializable {
+
+ private static final long serialVersionUID = 3250293381093835082L;
+ /** 优惠券使用条件, 满 x 件商品可用 */
+ @JsonProperty("product_cnt")
+ private Integer productCnt;
+
+ /** 优惠券使用条件, 价格满 x 可用,单位分 */
+ @JsonProperty("product_price")
+ private Integer productPrice;
+
+ /** 优惠券使用条件, 指定商品 id 可用 */
+ @JsonProperty("product_ids")
+ private List productIds;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/DiscountInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/DiscountInfo.java
new file mode 100644
index 0000000000..7988e47ce6
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/DiscountInfo.java
@@ -0,0 +1,29 @@
+package me.chanjar.weixin.channel.bean.coupon;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 优惠信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class DiscountInfo implements Serializable {
+
+ private static final long serialVersionUID = 3660070880545144112L;
+ /** 优惠券折扣数 * 1000, 例如 5.1折-> 5100 */
+ @JsonProperty("discount_num")
+ private Integer discountNum;
+
+ /** 优惠券减少金额, 单位分, 例如0.5元-> 50 */
+ @JsonProperty("discount_fee")
+ private Integer discountFee;
+
+ /** 优惠条件 */
+ @JsonProperty("discount_condition")
+ private DiscountCondition discountCondition;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/ExtInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/ExtInfo.java
new file mode 100644
index 0000000000..69cf3dc073
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/ExtInfo.java
@@ -0,0 +1,33 @@
+package me.chanjar.weixin.channel.bean.coupon;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 额外信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class ExtInfo implements Serializable {
+
+ private static final long serialVersionUID = 9053035437087423233L;
+ /** 商品折扣券领取后跳转的商品id **/
+ @JsonProperty("jump_product_id")
+ private String jumpProductId;
+
+ /** 备注信息 **/
+ @JsonProperty("notes")
+ private String notes;
+
+ /** 优惠券有效时间 **/
+ @JsonProperty("valid_time")
+ private Long validTime;
+
+ /** 优惠券失效时间戳 **/
+ @JsonProperty("invalid_time")
+ private Long invalidTime;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/PromoteInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/PromoteInfo.java
new file mode 100644
index 0000000000..75d48e6d3e
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/PromoteInfo.java
@@ -0,0 +1,21 @@
+package me.chanjar.weixin.channel.bean.coupon;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 推广信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class PromoteInfo implements Serializable {
+
+ private static final long serialVersionUID = -3030639750899957382L;
+ /** 推广类型 {@link me.chanjar.weixin.channel.enums.PromoteType} */
+ @JsonProperty("promote_type")
+ private Integer promoteType;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/ReceiveInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/ReceiveInfo.java
new file mode 100644
index 0000000000..9a602ac390
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/ReceiveInfo.java
@@ -0,0 +1,33 @@
+package me.chanjar.weixin.channel.bean.coupon;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 领取信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class ReceiveInfo implements Serializable {
+
+ private static final long serialVersionUID = 755956808504040633L;
+ /** 优惠券领用结束时间 **/
+ @JsonProperty("end_time")
+ private Long endTime;
+
+ /** 单人限领张数 **/
+ @JsonProperty("limit_num_one_person")
+ private Integer limitNumOnePerson;
+
+ /** 优惠券领用开始时间 **/
+ @JsonProperty("start_time")
+ private Long startTime;
+
+ /** 优惠券领用总数 **/
+ @JsonProperty("total_num")
+ private Integer totalNum;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/StockInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/StockInfo.java
new file mode 100644
index 0000000000..07aaf4a1ec
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/StockInfo.java
@@ -0,0 +1,29 @@
+package me.chanjar.weixin.channel.bean.coupon;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 库存信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class StockInfo implements Serializable {
+
+ private static final long serialVersionUID = -6078383881065929862L;
+ /** 优惠券剩余量 */
+ @JsonProperty("issued_num")
+ private Integer issuedNum;
+
+ /** 优惠券领用量 */
+ @JsonProperty("receive_num")
+ private Integer receiveNum;
+
+ /** 优惠券已用量 */
+ @JsonProperty("used_num")
+ private Integer usedNum;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/UserCoupon.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/UserCoupon.java
new file mode 100644
index 0000000000..06436a9e73
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/UserCoupon.java
@@ -0,0 +1,50 @@
+package me.chanjar.weixin.channel.bean.coupon;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+/**
+ * 用户优惠券
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class UserCoupon extends UserCouponIdInfo {
+
+ private static final long serialVersionUID = -4777537717885622888L;
+ /** 优惠券状态 {@link me.chanjar.weixin.channel.enums.UserCouponStatus} */
+ @JsonProperty("status")
+ private Integer status;
+
+ /** 优惠券派发时间 */
+ @JsonProperty("create_time")
+ private Long createTime;
+
+ /** 优惠券更新时间 */
+ @JsonProperty("update_time")
+ private Long updateTime;
+
+ /** 优惠券生效时间 */
+ @JsonProperty("start_time")
+ private Long startTime;
+
+ /** 优惠券失效时间 */
+ @JsonProperty("end_time")
+ private Long endTime;
+
+ /** 附加信息 */
+ @JsonProperty("ext_info")
+ private UserExtInfo extInfo;
+
+ /** 优惠券使用的订单id */
+ @JsonProperty("order_id")
+ private String orderId;
+
+ /** 优惠券金额 */
+ @JsonProperty("discount_fee")
+ private Integer discountFee;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/UserCouponIdInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/UserCouponIdInfo.java
new file mode 100644
index 0000000000..d68d881c98
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/UserCouponIdInfo.java
@@ -0,0 +1,20 @@
+package me.chanjar.weixin.channel.bean.coupon;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 用户优惠券id
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class UserCouponIdInfo extends CouponIdInfo {
+
+ private static final long serialVersionUID = -8285585134793264542L;
+ /** 用户优惠券ID */
+ @JsonProperty("user_coupon_id")
+ private String userCouponId;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/UserCouponIdParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/UserCouponIdParam.java
new file mode 100644
index 0000000000..aa2eb15421
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/UserCouponIdParam.java
@@ -0,0 +1,29 @@
+package me.chanjar.weixin.channel.bean.coupon;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+
+/**
+ * @author Zeyes
+ */
+@Data
+public class UserCouponIdParam implements Serializable {
+
+ private static final long serialVersionUID = 3967276158727848348L;
+ /** 用户openid */
+ @JsonProperty("openid")
+ private String openid;
+
+ /** 用户优惠券ID */
+ @JsonProperty("user_coupon_id")
+ private String userCouponId;
+
+ public UserCouponIdParam() {
+ }
+
+ public UserCouponIdParam(String openid, String userCouponId) {
+ this.openid = openid;
+ this.userCouponId = userCouponId;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/UserCouponListParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/UserCouponListParam.java
new file mode 100644
index 0000000000..f14f5d7f6e
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/UserCouponListParam.java
@@ -0,0 +1,24 @@
+package me.chanjar.weixin.channel.bean.coupon;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class UserCouponListParam extends CouponListParam {
+ private static final long serialVersionUID = -1056132009327357435L;
+
+ /**
+ * openId
+ */
+ @JsonProperty("openid")
+ private String openId;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/UserCouponListResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/UserCouponListResponse.java
new file mode 100644
index 0000000000..2c3582e678
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/UserCouponListResponse.java
@@ -0,0 +1,30 @@
+package me.chanjar.weixin.channel.bean.coupon;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class UserCouponListResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 5201633937239352879L;
+ /** 优惠券id列表 */
+ @JsonProperty("user_coupon_list")
+ private List coupons;
+
+ /** 优惠券总数 */
+ @JsonProperty("total_num")
+ private Integer totalNum;
+
+ /** 优惠券上下文 */
+ @JsonProperty("page_ctx")
+ private String pageCtx;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/UserCouponResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/UserCouponResponse.java
new file mode 100644
index 0000000000..aeb9d89afb
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/UserCouponResponse.java
@@ -0,0 +1,27 @@
+package me.chanjar.weixin.channel.bean.coupon;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class UserCouponResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 1434098386857953234L;
+ @JsonProperty("user_coupon")
+ private UserCoupon coupon;
+
+ @JsonProperty("openid")
+ private String openid;
+
+ @JsonProperty("unionid")
+ private String unionid;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/UserExtInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/UserExtInfo.java
new file mode 100644
index 0000000000..18962361ec
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/UserExtInfo.java
@@ -0,0 +1,21 @@
+package me.chanjar.weixin.channel.bean.coupon;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 用户优惠券附加信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class UserExtInfo implements Serializable {
+
+ private static final long serialVersionUID = 8304922825230343409L;
+ /** 优惠券核销时间 */
+ @JsonProperty("use_time")
+ private Long useTime;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/ValidInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/ValidInfo.java
new file mode 100644
index 0000000000..10df794324
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/coupon/ValidInfo.java
@@ -0,0 +1,33 @@
+package me.chanjar.weixin.channel.bean.coupon;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 优惠券有效信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class ValidInfo implements Serializable {
+
+ private static final long serialVersionUID = -4550516248380285635L;
+ /** 优惠券有效期类型 {@link me.chanjar.weixin.channel.enums.CouponValidType} */
+ @JsonProperty("valid_type")
+ private Integer validType;
+
+ /** 优惠券有效天数,valid_type=2时才有意义 */
+ @JsonProperty("valid_day_num")
+ private Integer validDayNum;
+
+ /** 优惠券有效期开始时间,valid_type=1时才有意义 */
+ @JsonProperty("start_time")
+ private Long startTime;
+
+ /** 优惠券有效期结束时间,valid_type=1时才有意义 */
+ @JsonProperty("end_time")
+ private Long endTime;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/delivery/DeliveryCompanyInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/delivery/DeliveryCompanyInfo.java
new file mode 100644
index 0000000000..349d70cbb1
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/delivery/DeliveryCompanyInfo.java
@@ -0,0 +1,25 @@
+package me.chanjar.weixin.channel.bean.delivery;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 快递公司信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class DeliveryCompanyInfo implements Serializable {
+
+ private static final long serialVersionUID = 4225666604513570564L;
+ /** 快递公司id */
+ @JsonProperty("delivery_id")
+ private String id;
+
+ /** 快递公司名称 */
+ @JsonProperty("delivery_name")
+ private String name;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/delivery/DeliveryCompanyResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/delivery/DeliveryCompanyResponse.java
new file mode 100644
index 0000000000..d74a9439ea
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/delivery/DeliveryCompanyResponse.java
@@ -0,0 +1,22 @@
+package me.chanjar.weixin.channel.bean.delivery;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 快递公司列表响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class DeliveryCompanyResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -7695903997951385166L;
+ /** 快递公司 */
+ @JsonProperty("company_list")
+ private List companyList;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/delivery/DeliveryInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/delivery/DeliveryInfo.java
new file mode 100644
index 0000000000..23ab8dad2c
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/delivery/DeliveryInfo.java
@@ -0,0 +1,34 @@
+package me.chanjar.weixin.channel.bean.delivery;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 物流信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class DeliveryInfo implements Serializable {
+
+ private static final long serialVersionUID = -6205626967305385248L;
+ /** 快递单号 */
+ @JsonProperty("waybill_id")
+ private String waybillId;
+
+ /** 快递公司id,通过【获取快递公司列表】接口获得,非主流快递公司可以填OTHER */
+ @JsonProperty("delivery_id")
+ private String deliveryId;
+
+ /** 发货方式,1:自寄快递发货,3:虚拟商品无需物流发货(只有deliver_method=1的订单可以使用虚拟发货) */
+ @JsonProperty("deliver_type")
+ private Integer deliverType;
+
+ /** 包裹中商品信息 */
+ @JsonProperty("product_infos")
+ private List productInfos;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/delivery/DeliverySendParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/delivery/DeliverySendParam.java
new file mode 100644
index 0000000000..f486032bc4
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/delivery/DeliverySendParam.java
@@ -0,0 +1,31 @@
+package me.chanjar.weixin.channel.bean.delivery;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 订单发货信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonInclude(Include.NON_NULL)
+public class DeliverySendParam implements Serializable {
+
+ private static final long serialVersionUID = 4555821308266899135L;
+ /** 订单ID */
+ @JsonProperty("order_id")
+ private String orderId;
+
+ /** 物流信息 */
+ @JsonProperty("delivery_list")
+ private List deliveryList;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/delivery/FreightProductInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/delivery/FreightProductInfo.java
new file mode 100644
index 0000000000..2a7c7dd3c6
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/delivery/FreightProductInfo.java
@@ -0,0 +1,36 @@
+package me.chanjar.weixin.channel.bean.delivery;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * 包裹中商品信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class FreightProductInfo implements Serializable {
+ private static final long serialVersionUID = -3751269707150372172L;
+
+ /**
+ * 商品id
+ */
+ @JsonProperty("product_id")
+ private String productId;
+
+ /**
+ * sku_id
+ */
+ @JsonProperty("sku_id")
+ private String skuId;
+
+ /**
+ * 商品数量
+ */
+ @JsonProperty("product_cnt")
+ private Integer productCnt;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/AddressInfoList.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/AddressInfoList.java
new file mode 100644
index 0000000000..4d8c7ec4a5
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/AddressInfoList.java
@@ -0,0 +1,23 @@
+package me.chanjar.weixin.channel.bean.freight;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.AddressInfo;
+
+/**
+ * 地址列表
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class AddressInfoList implements Serializable {
+
+ private static final long serialVersionUID = 5923805297331862706L;
+ /** 地址列表 */
+ @JsonProperty("address_infos")
+ private List addressInfos;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/AllConditionFreeDetail.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/AllConditionFreeDetail.java
new file mode 100644
index 0000000000..fd9aee451d
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/AllConditionFreeDetail.java
@@ -0,0 +1,32 @@
+package me.chanjar.weixin.channel.bean.freight;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 计费规则列表
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class AllConditionFreeDetail implements Serializable {
+
+ private static final long serialVersionUID = -1649520737632417036L;
+ /** 计费规则列表 */
+ @JsonProperty("condition_free_detail_list")
+ private List list;
+
+ @JsonIgnore
+ public void addDetail(ConditionFreeDetail detail) {
+ if (list == null) {
+ list = new ArrayList<>(16);
+ }
+ list.add(detail);
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/AllFreightCalcMethod.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/AllFreightCalcMethod.java
new file mode 100644
index 0000000000..2c5523ebe4
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/AllFreightCalcMethod.java
@@ -0,0 +1,31 @@
+package me.chanjar.weixin.channel.bean.freight;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import lombok.Data;
+
+/**
+ * 具体计费方法,默认运费,指定地区运费等
+ *
+ * @author Zeyes
+ */
+@Data
+public class AllFreightCalcMethod implements Serializable {
+
+ private static final long serialVersionUID = 6330919525271991949L;
+ /** 计算方法列表 */
+ @JsonProperty("freight_calc_method_list")
+ private List list;
+
+ public AllFreightCalcMethod() {
+ }
+
+ public void addDetail(FreightCalcMethod detail) {
+ if (list == null) {
+ list = new ArrayList<>(16);
+ }
+ list.add(detail);
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/ConditionFreeDetail.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/ConditionFreeDetail.java
new file mode 100644
index 0000000000..68cb3b146e
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/ConditionFreeDetail.java
@@ -0,0 +1,38 @@
+package me.chanjar.weixin.channel.bean.freight;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+/**
+ * 计费规则
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class ConditionFreeDetail extends AddressInfoList {
+
+ private static final long serialVersionUID = 9204578767029379142L;
+ /** 最低件数 */
+ @JsonProperty("min_piece")
+ private Integer minPiece;
+
+ /** 最低重量 */
+ @JsonProperty("min_weight")
+ private Double minWeight;
+
+ /** 最低金额 */
+ @JsonProperty("min_amount")
+ private Integer minAmount;
+
+ /** 计费方式对应的选项是否已设置 */
+ @JsonProperty("valuation_flag")
+ private Integer valuationFlag;
+
+ /** 金额是否设置 */
+ @JsonProperty("amount_flag")
+ private Integer amountFlag;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/FreightCalcMethod.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/FreightCalcMethod.java
new file mode 100644
index 0000000000..aab949bc44
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/FreightCalcMethod.java
@@ -0,0 +1,43 @@
+package me.chanjar.weixin.channel.bean.freight;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+/**
+ * 运费计算方法
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class FreightCalcMethod extends AddressInfoList {
+
+ private static final long serialVersionUID = -8857987538121721376L;
+ /** 是否默认运费 */
+ @JsonProperty("is_default")
+ private Boolean isDefault;
+
+ /** 快递公司 */
+ @JsonProperty("delivery_id")
+ private String deliveryId;
+
+ /** 首段运费需要满足的数量 */
+ @JsonProperty("first_val_amount")
+ private Integer firstValAmount;
+
+ /** 首段运费的金额 */
+ @JsonProperty("first_price")
+ private Integer firstPrice;
+
+ /** 续费的数量 */
+ @JsonProperty("second_val_amount")
+ private Integer secondValAmount;
+
+ /** 续费的金额 */
+ @JsonProperty("second_price")
+ private Integer secondPrice;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/FreightTemplate.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/FreightTemplate.java
new file mode 100644
index 0000000000..e28f90ad41
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/FreightTemplate.java
@@ -0,0 +1,71 @@
+package me.chanjar.weixin.channel.bean.freight;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.AddressInfo;
+
+/**
+ * 运费模板
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class FreightTemplate implements Serializable {
+
+ private static final long serialVersionUID = -7876281924385999053L;
+ /** 模板id */
+ @JsonProperty("template_id")
+ private String templateId;
+
+ /** 模板名称 */
+ @JsonProperty("name")
+ private String name;
+
+ /** 计费类型,PIECE:按件数,WEIGHT:按重量 */
+ @JsonProperty("valuation_type")
+ private String valuationType;
+
+ /** 发货时间期限 {@link me.chanjar.weixin.channel.enums.SendTime} */
+ @JsonProperty("send_time")
+ private String sendTime;
+
+ /** 发货地址 */
+ @JsonProperty("address_info")
+ private AddressInfo addressInfo;
+
+ /** 运输方式,EXPRESS:快递 */
+ @JsonProperty("delivery_type")
+ private String deliveryType;
+
+ /** 计费方式:FREE包邮 CONDITION_FREE条件包邮 NO_FREE不包邮 */
+ @JsonProperty("shipping_method")
+ private String shippingMethod;
+
+ /** 条件包邮详情 */
+ @JsonProperty("all_condition_free_detail")
+ private AllConditionFreeDetail allConditionFreeDetail;
+
+ /** 具体计费方法,默认运费,指定地区运费等 */
+ @JsonProperty("all_freight_calc_method")
+ private AllFreightCalcMethod allFreightCalcMethod;
+
+ /** 创建时间戳 */
+ @JsonProperty("create_time")
+ private Long createTime;
+
+ /** 更新时间戳 */
+ @JsonProperty("update_time")
+ private Long updateTime;
+
+ /** 是否默认模板 */
+ @JsonProperty("is_default")
+ private Boolean isDefault;
+
+ /** 不发货区域 */
+ @JsonProperty("not_send_area")
+ private NotSendArea notSendArea;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/NotSendArea.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/NotSendArea.java
new file mode 100644
index 0000000000..1c480fc227
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/NotSendArea.java
@@ -0,0 +1,18 @@
+package me.chanjar.weixin.channel.bean.freight;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+/**
+ * 不发货区域
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class NotSendArea extends AddressInfoList {
+
+ private static final long serialVersionUID = -1836467830293286560L;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/TemplateAddParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/TemplateAddParam.java
new file mode 100644
index 0000000000..9c400533bf
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/TemplateAddParam.java
@@ -0,0 +1,26 @@
+package me.chanjar.weixin.channel.bean.freight;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 运费模板 请求参数
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonInclude(Include.NON_NULL)
+public class TemplateAddParam implements Serializable {
+
+ private static final long serialVersionUID = 2602919369418149309L;
+ /** 起始位置 */
+ @JsonProperty("freight_template")
+ private FreightTemplate template;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/TemplateIdResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/TemplateIdResponse.java
new file mode 100644
index 0000000000..e895d066cb
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/TemplateIdResponse.java
@@ -0,0 +1,24 @@
+package me.chanjar.weixin.channel.bean.freight;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 运费模板 列表 响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class TemplateIdResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 5179651364165620640L;
+ /** 运费模板id */
+ @JsonProperty("template_id")
+ private String templateId;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/TemplateInfoResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/TemplateInfoResponse.java
new file mode 100644
index 0000000000..f37e3dc2d1
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/TemplateInfoResponse.java
@@ -0,0 +1,24 @@
+package me.chanjar.weixin.channel.bean.freight;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 运费模板 响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class TemplateInfoResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -8381510839783330617L;
+ /** 运费模板id */
+ @JsonProperty("freight_template")
+ private FreightTemplate template;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/TemplateListParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/TemplateListParam.java
new file mode 100644
index 0000000000..628d907eb1
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/TemplateListParam.java
@@ -0,0 +1,27 @@
+package me.chanjar.weixin.channel.bean.freight;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import me.chanjar.weixin.channel.bean.base.OffsetParam;
+
+/**
+ * 运费模板 列表 请求参数
+ *
+ * @author Zeyes
+ */
+@Data
+@JsonInclude(Include.NON_NULL)
+@EqualsAndHashCode(callSuper = true)
+public class TemplateListParam extends OffsetParam {
+
+ private static final long serialVersionUID = -6716154891499581562L;
+
+ public TemplateListParam() {
+ }
+
+ public TemplateListParam(Integer offset, Integer limit) {
+ super(offset, limit);
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/TemplateListResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/TemplateListResponse.java
new file mode 100644
index 0000000000..a6fcd7d3e3
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/freight/TemplateListResponse.java
@@ -0,0 +1,24 @@
+package me.chanjar.weixin.channel.bean.freight;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 运费模板 列表 响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class TemplateListResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 5375602442595264719L;
+ /** 运费模板 id 列表 */
+ @JsonProperty("template_id_list")
+ private List ids;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/AccountInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/AccountInfo.java
new file mode 100644
index 0000000000..f6248f96ba
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/AccountInfo.java
@@ -0,0 +1,53 @@
+package me.chanjar.weixin.channel.bean.fund;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 账户信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class AccountInfo implements Serializable {
+
+ private static final long serialVersionUID = -2107134853480093451L;
+ /** 账户类型 {@link me.chanjar.weixin.channel.enums.AccountType} */
+ @JsonProperty("bank_account_type")
+ private String bankAccountType;
+
+ /** 开户银行 */
+ @JsonProperty("account_bank")
+ private String accountBank;
+
+ /** 开户银行省市编码 */
+ @JsonProperty("bank_address_code")
+ private String bankAddressCode;
+
+ /** 开户银行联行号 */
+ @JsonProperty("bank_branch_id")
+ private String bankBranchId;
+
+ /** 开户银行全称 */
+ @JsonProperty("bank_name")
+ private String bankName;
+
+ /** 银行账号 */
+ @JsonProperty("account_number")
+ private String accountNumber;
+
+ /** 开户银行名称前端展示值 */
+ @JsonProperty("account_bank4show")
+ private String accountBank4show;
+
+ /** 账户名称 */
+ @JsonProperty("account_name")
+ private String accountName;
+
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/AccountInfoParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/AccountInfoParam.java
new file mode 100644
index 0000000000..ec6010bd07
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/AccountInfoParam.java
@@ -0,0 +1,25 @@
+package me.chanjar.weixin.channel.bean.fund;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 账户信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class AccountInfoParam implements Serializable {
+
+ private static final long serialVersionUID = 1689204583402779134L;
+ @JsonProperty("account_info")
+ private AccountInfo accountInfo;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/AccountInfoResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/AccountInfoResponse.java
new file mode 100644
index 0000000000..b54a34a2e7
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/AccountInfoResponse.java
@@ -0,0 +1,23 @@
+package me.chanjar.weixin.channel.bean.fund;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 账户信息响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class AccountInfoResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -8316068503468969533L;
+ /** 账户信息 */
+ @JsonProperty("account_info")
+ private AccountInfo accountInfo;
+
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/BalanceInfoResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/BalanceInfoResponse.java
new file mode 100644
index 0000000000..def7e86675
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/BalanceInfoResponse.java
@@ -0,0 +1,30 @@
+package me.chanjar.weixin.channel.bean.fund;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 账户余额信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class BalanceInfoResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 4480496860612566921L;
+ /** 可提现余额 */
+ @JsonProperty("available_amount")
+ private Integer availableAmount;
+
+ /** 待结算余额 */
+ @JsonProperty("pending_amount")
+ private Integer pendingAmount;
+
+ /** 二级商户号 */
+ @JsonProperty("sub_mchid")
+ private String subMchid;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/FlowListResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/FlowListResponse.java
new file mode 100644
index 0000000000..9306b4516a
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/FlowListResponse.java
@@ -0,0 +1,30 @@
+package me.chanjar.weixin.channel.bean.fund;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 流水列表响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class FlowListResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 8017827444308973489L;
+ /** 流水单号列表 */
+ @JsonProperty("flow_ids")
+ private List flowIds;
+
+ /** 是否还有下一页 */
+ @JsonProperty("has_more")
+ private boolean hasMore;
+
+ /** 分页参数,深翻页时使用 */
+ @JsonProperty("next_key")
+ private String nextKey;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/FlowRelatedInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/FlowRelatedInfo.java
new file mode 100644
index 0000000000..4edecbb3b1
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/FlowRelatedInfo.java
@@ -0,0 +1,45 @@
+package me.chanjar.weixin.channel.bean.fund;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 流水关联信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class FlowRelatedInfo implements Serializable {
+
+ private static final long serialVersionUID = 3757839018198212504L;
+ /** 关联类型, 1 订单, 2售后,3 提现,4 运费险 */
+ @JsonProperty("related_type")
+ private Integer relatedType;
+
+ /** 关联订单号 */
+ @JsonProperty("order_id")
+ private String orderId;
+
+ /** 关联售后单号 */
+ @JsonProperty("aftersale_id")
+ private String afterSaleId;
+
+ /** 关联提现单号 */
+ @JsonProperty("withdraw_id")
+ private String withdrawId;
+
+ /** 记账时间 */
+ @JsonProperty("bookkeeping_time")
+ private String bookkeepingTime;
+
+ /** 关联运费险单号 */
+ @JsonProperty("insurance_id")
+ private String insuranceId;
+
+ /** 关联支付单号 */
+ @JsonProperty("transaction_id")
+ private String transactionId;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/FundsFlow.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/FundsFlow.java
new file mode 100644
index 0000000000..9b01e820fa
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/FundsFlow.java
@@ -0,0 +1,51 @@
+package me.chanjar.weixin.channel.bean.fund;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 资金流水
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class FundsFlow implements Serializable {
+
+ private static final long serialVersionUID = -2785498655066305510L;
+ /** 流水id */
+ @JsonProperty("flow_id")
+ private String flowId;
+
+ /** 资金类型,见 {@link me.chanjar.weixin.channel.enums.FundsType} */
+ @JsonProperty("funds_type")
+ private Integer fundsType;
+
+ /** 流水类型, 1 收入,2 支出 */
+ @JsonProperty("flow_type")
+ private Integer flowType;
+
+ /** 流水金额 */
+ @JsonProperty("amount")
+ private Integer amount;
+
+ /** 余额 */
+ @JsonProperty("balance")
+ private Integer balance;
+
+ /** 流水关联信息 */
+ @JsonProperty("related_info_list")
+ private List relatedInfos;
+
+ /** 记账时间 */
+ @JsonProperty("bookkeeping_time")
+ private String bookkeepingTime;
+
+ /** 备注 */
+ @JsonProperty("remark")
+ private String remark;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/FundsFlowResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/FundsFlowResponse.java
new file mode 100644
index 0000000000..7db351263f
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/FundsFlowResponse.java
@@ -0,0 +1,23 @@
+package me.chanjar.weixin.channel.bean.fund;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 资金流水响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class FundsFlowResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -1130785908352355914L;
+ /** 流水信息 */
+ @JsonProperty("funds_flow")
+ private FundsFlow fundsFlow;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/FundsListParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/FundsListParam.java
new file mode 100644
index 0000000000..b5312e3a2a
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/FundsListParam.java
@@ -0,0 +1,49 @@
+package me.chanjar.weixin.channel.bean.fund;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 资金流水参数
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class FundsListParam implements Serializable {
+
+ private static final long serialVersionUID = 2998955690332382229L;
+ /** 页码,从1开始 */
+ @JsonProperty("page")
+ private Integer page;
+
+ /** 页数,不填默认为10 */
+ @JsonProperty("page_size")
+ protected Integer pageSize;
+
+ /** 流水产生的开始时间,uinx时间戳 */
+ @JsonProperty("start_time")
+ private Long startTime;
+
+ /** 流水产生的结束时间,unix时间戳 */
+ @JsonProperty("end_time")
+ private Long endTime;
+
+ /** 流水类型, 1 收入,2 支出 */
+ @JsonProperty("flow_type")
+ private Integer flowType;
+
+ /** 关联支付单号 */
+ @JsonProperty("transaction_id")
+ private String transactionId;
+
+ /**
+ * 分页参数,翻页时写入上一页返回的next_key(page为上一页加一, 并且page_size与上一页相同的时候才生效),page * page_size >= 10000时必填
+ */
+ @JsonProperty("next_key")
+ private String nextKey;
+
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/WithdrawDetailResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/WithdrawDetailResponse.java
new file mode 100644
index 0000000000..a1e726fb51
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/WithdrawDetailResponse.java
@@ -0,0 +1,55 @@
+package me.chanjar.weixin.channel.bean.fund;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 提现详情响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class WithdrawDetailResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 1473346677401168323L;
+ /** 金额 */
+ @JsonProperty("amount")
+ private Integer amount;
+
+ /** 创建时间 */
+ @JsonProperty("create_time")
+ private Long createTime;
+
+ /** 更新时间 */
+ @JsonProperty("update_time")
+ private Long updateTime;
+
+ /** 失败原因 */
+ @JsonProperty("reason")
+ private String reason;
+
+ /** 备注 */
+ @JsonProperty("remark")
+ private String remark;
+
+ /** 银行附言 */
+ @JsonProperty("bank_memo")
+ private String bankMemo;
+
+ /** 银行名称 */
+ @JsonProperty("bank_name")
+ private String bankName;
+
+ /** 银行账户 */
+ @JsonProperty("bank_num")
+ private String bankNum;
+
+ /** 提现状态 {@link me.chanjar.weixin.channel.enums.WithdrawStatus} */
+ @JsonProperty("status")
+ private String status;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/WithdrawListParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/WithdrawListParam.java
new file mode 100644
index 0000000000..a44b68567d
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/WithdrawListParam.java
@@ -0,0 +1,36 @@
+package me.chanjar.weixin.channel.bean.fund;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 提现列表参数
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class WithdrawListParam implements Serializable {
+
+ private static final long serialVersionUID = -672422656564313999L;
+ /** 页码,从1开始 */
+ @JsonProperty("page_num")
+ private Integer pageNum;
+
+ /** 页数 */
+ @JsonProperty("page_size")
+ private Integer pageSize;
+
+ /** 开始时间 */
+ @JsonProperty("start_time")
+ private Long startTime;
+
+ /** 结束时间 */
+ @JsonProperty("end_time")
+ private Long endTime;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/WithdrawListResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/WithdrawListResponse.java
new file mode 100644
index 0000000000..b1dabc2a4b
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/WithdrawListResponse.java
@@ -0,0 +1,23 @@
+package me.chanjar.weixin.channel.bean.fund;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 提现列表响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class WithdrawListResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -7950467108750325235L;
+ /** 提现单号列表 */
+ @JsonProperty("withdraw_ids")
+ private List withdrawIds;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/WithdrawSubmitParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/WithdrawSubmitParam.java
new file mode 100644
index 0000000000..65b8cdd12c
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/WithdrawSubmitParam.java
@@ -0,0 +1,32 @@
+package me.chanjar.weixin.channel.bean.fund;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 提现提交参数
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class WithdrawSubmitParam implements Serializable {
+
+ private static final long serialVersionUID = 5801338663530567830L;
+ /** 提现金额(单位:分) */
+ @JsonProperty("amount")
+ private Integer amount;
+
+ /** 提现备注 */
+ @JsonProperty("remark")
+ private String remark;
+
+ /** 银行附言 */
+ @JsonProperty("bank_memo")
+ private String bankMemo;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/WithdrawSubmitResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/WithdrawSubmitResponse.java
new file mode 100644
index 0000000000..0002b158d2
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/WithdrawSubmitResponse.java
@@ -0,0 +1,23 @@
+package me.chanjar.weixin.channel.bean.fund;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 提现提交响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class WithdrawSubmitResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -8269579250564427758L;
+ /** 二维码ticket,可用于获取二维码和查询二维码状态 */
+ @JsonProperty("qrcode_ticket")
+ private String qrcodeTicket;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/bank/BankCityInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/bank/BankCityInfo.java
new file mode 100644
index 0000000000..04a69a8e87
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/bank/BankCityInfo.java
@@ -0,0 +1,29 @@
+package me.chanjar.weixin.channel.bean.fund.bank;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 银行城市信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class BankCityInfo implements Serializable {
+
+ private static final long serialVersionUID = 374087891799491196L;
+ /** 城市名称 */
+ @JsonProperty("city_name")
+ private String cityName;
+
+ /** 城市编号 */
+ @JsonProperty("city_code")
+ private Integer cityCode;
+
+ /** 开户银行省市编码 */
+ @JsonProperty("bank_address_code")
+ private String bankAddressCode;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/bank/BankCityResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/bank/BankCityResponse.java
new file mode 100644
index 0000000000..5cb148c79b
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/bank/BankCityResponse.java
@@ -0,0 +1,28 @@
+package me.chanjar.weixin.channel.bean.fund.bank;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 银行城市信息响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class BankCityResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -6212360101083304631L;
+ /** 银行城市信息列表 */
+ @JsonProperty("data")
+ private List data;
+
+ /** 总数 */
+ @JsonProperty("total_count")
+ private Integer totalCount;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/bank/BankInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/bank/BankInfo.java
new file mode 100644
index 0000000000..1bb58badb4
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/bank/BankInfo.java
@@ -0,0 +1,46 @@
+package me.chanjar.weixin.channel.bean.fund.bank;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 银行信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class BankInfo implements Serializable {
+
+ private static final long serialVersionUID = -4837989875996346711L;
+ /** 开户银行 */
+ @JsonProperty("account_bank")
+ private String accountBank;
+
+ /** 银行编码 */
+ @JsonProperty("bank_code")
+ private String bankCode;
+
+ /** 银行联号 */
+ @JsonProperty("bank_id")
+ private String bankId;
+
+ /** 银行名称(不包括支行) */
+ @JsonProperty("bank_name")
+ private String bankName;
+
+ /** 银行类型(1.对公,2.对私) */
+ @JsonProperty("bank_type")
+ private Integer bankType;
+
+ /** 是否需要填写支行信息 */
+ @JsonProperty("need_branch")
+ private Boolean needBranch;
+
+ /** 支行联号 */
+ @JsonProperty("branch_id")
+ private String branchId;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/bank/BankInfoResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/bank/BankInfoResponse.java
new file mode 100644
index 0000000000..499d9fcbb5
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/bank/BankInfoResponse.java
@@ -0,0 +1,28 @@
+package me.chanjar.weixin.channel.bean.fund.bank;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 银行信息响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class BankInfoResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 8583893898929290526L;
+ /** 银行信息列表 */
+ @JsonProperty("data")
+ private List data;
+
+ /** 总数 */
+ @JsonProperty("total_count")
+ private Integer totalCount;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/bank/BankListResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/bank/BankListResponse.java
new file mode 100644
index 0000000000..9517859c42
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/bank/BankListResponse.java
@@ -0,0 +1,24 @@
+package me.chanjar.weixin.channel.bean.fund.bank;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 银行信息响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class BankListResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 7912035853286944260L;
+ /** 银行信息列表 */
+ @JsonProperty("data")
+ private List data;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/bank/BankProvinceInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/bank/BankProvinceInfo.java
new file mode 100644
index 0000000000..955a25e8ad
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/bank/BankProvinceInfo.java
@@ -0,0 +1,25 @@
+package me.chanjar.weixin.channel.bean.fund.bank;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 银行省份信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class BankProvinceInfo implements Serializable {
+
+ private static final long serialVersionUID = -3409931656361300144L;
+ /** 省份名称 */
+ @JsonProperty("province_name")
+ private String provinceName;
+
+ /** 省份编码 */
+ @JsonProperty("province_code")
+ private Integer provinceCode;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/bank/BankProvinceResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/bank/BankProvinceResponse.java
new file mode 100644
index 0000000000..f509d24304
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/bank/BankProvinceResponse.java
@@ -0,0 +1,26 @@
+package me.chanjar.weixin.channel.bean.fund.bank;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 银行省份信息响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class BankProvinceResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -6187805847136359892L;
+ /** 银行省份信息列表 */
+ @JsonProperty("data")
+ private List data;
+
+ /** 总数 */
+ @JsonProperty("total_count")
+ private Integer totalCount;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/bank/BankSearchParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/bank/BankSearchParam.java
new file mode 100644
index 0000000000..abc9c1ec77
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/bank/BankSearchParam.java
@@ -0,0 +1,37 @@
+package me.chanjar.weixin.channel.bean.fund.bank;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 银行查询参数
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class BankSearchParam implements Serializable {
+
+ private static final long serialVersionUID = 6070269209439188188L;
+ /** 偏移量 */
+ @JsonProperty("offset")
+ private Integer offset;
+
+ /** 每页数据大小 */
+ @JsonProperty("limit")
+ private Integer limit;
+
+ /** 银行关键字 */
+ @JsonProperty("key_words")
+ private String keyWords;
+
+ /** 银行类型(1:对私银行,2:对公银行; 默认对公) */
+ @JsonProperty("bank_type")
+ private Integer bankType;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/bank/BranchInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/bank/BranchInfo.java
new file mode 100644
index 0000000000..c4cec9bc76
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/bank/BranchInfo.java
@@ -0,0 +1,25 @@
+package me.chanjar.weixin.channel.bean.fund.bank;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 分店信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class BranchInfo implements Serializable {
+
+ private static final long serialVersionUID = -2744729367131146892L;
+ /** 支行联号 */
+ @JsonProperty("branch_id")
+ private Integer branchId;
+
+ /** 银行全称(含支行) */
+ @JsonProperty("branch_name")
+ private String branchName;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/bank/BranchInfoResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/bank/BranchInfoResponse.java
new file mode 100644
index 0000000000..c7cfda4646
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/bank/BranchInfoResponse.java
@@ -0,0 +1,49 @@
+package me.chanjar.weixin.channel.bean.fund.bank;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 支行信息响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class BranchInfoResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -1419832502854175767L;
+ /** 总数 */
+ @JsonProperty("total_count")
+ private Integer totalCount;
+
+ /** 当前分页数量 */
+ @JsonProperty("count")
+ private Integer count;
+
+ /** 银行名称 */
+ @JsonProperty("account_bank")
+ private String accountBank;
+
+ /** 银行编码 */
+ @JsonProperty("account_bank_code")
+ private String accountBankCode;
+
+ /** 银行别名 */
+ @JsonProperty("bank_alias")
+ private String bankAlias;
+
+ /** 银行别名编码 */
+ @JsonProperty("bank_alias_code")
+ private String bankAliasCode;
+
+ /** 支行信息列表 */
+ @JsonProperty("data")
+ private List data;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/bank/BranchSearchParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/bank/BranchSearchParam.java
new file mode 100644
index 0000000000..47527efe1e
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/bank/BranchSearchParam.java
@@ -0,0 +1,35 @@
+package me.chanjar.weixin.channel.bean.fund.bank;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 银行支行信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class BranchSearchParam implements Serializable {
+
+ private static final long serialVersionUID = -8800316690160248833L;
+ /** 银行编码,通过查询银行信息或者搜索银行信息获取 */
+ @JsonProperty("bank_code")
+ private String bankCode;
+
+ /** 城市编号,通过查询城市列表获取 */
+ @JsonProperty("city_code")
+ private String cityCode;
+
+ /** 偏移量 */
+ @JsonProperty("offset")
+ private Integer offset;
+
+ /** 限制个数 */
+ @JsonProperty("limit")
+ private Integer limit;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/qrcode/QrCheckResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/qrcode/QrCheckResponse.java
new file mode 100644
index 0000000000..e1a52ab9a3
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/qrcode/QrCheckResponse.java
@@ -0,0 +1,36 @@
+package me.chanjar.weixin.channel.bean.fund.qrcode;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 二维码校验响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class QrCheckResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -3860756719827268969L;
+ /** 扫码状态 {@link me.chanjar.weixin.channel.enums.QrCheckStatus} */
+ @JsonProperty("status")
+ private Integer status;
+
+ /** 业务返回错误码 */
+ @JsonProperty("self_check_err_code")
+ private Integer selfCheckErrCode;
+
+ /** 业务返回错误信息 */
+ @JsonProperty("self_check_err_msg")
+ private String selfCheckErrMsg;
+
+ /** 扫码者身份 0非管理员 1管理员 2次管理员 */
+ @JsonProperty("scan_user_type")
+ private Integer scanUserType;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/qrcode/QrCodeResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/qrcode/QrCodeResponse.java
new file mode 100644
index 0000000000..d6c015c0cd
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/fund/qrcode/QrCodeResponse.java
@@ -0,0 +1,24 @@
+package me.chanjar.weixin.channel.bean.fund.qrcode;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 二维码响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class QrCodeResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 4521008628337929496L;
+ /** 二维码(base64编码二进制,需要base64解码) */
+ @JsonProperty("qrcode_buf")
+ private String qrcodeBuf;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/image/ChannelImageInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/image/ChannelImageInfo.java
new file mode 100644
index 0000000000..3e12c7e830
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/image/ChannelImageInfo.java
@@ -0,0 +1,30 @@
+package me.chanjar.weixin.channel.bean.image;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 微信图片信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class ChannelImageInfo implements Serializable {
+
+ private static final long serialVersionUID = 8883519290965944530L;
+
+ /** 开放平台media_id */
+ @JsonProperty("media_id")
+ private String mediaId;
+
+ /** 图片链接,有访问频率限制 */
+ @JsonProperty("img_url")
+ private String url;
+
+ /** 微信支付media_id */
+ @JsonProperty("pay_media_id")
+ private String payMediaId;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/image/ChannelImageResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/image/ChannelImageResponse.java
new file mode 100644
index 0000000000..903af375af
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/image/ChannelImageResponse.java
@@ -0,0 +1,32 @@
+package me.chanjar.weixin.channel.bean.image;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import java.io.File;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * @author Zeyes
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class ChannelImageResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -4163511427507976489L;
+
+ @JsonIgnore
+ private File file;
+
+ private String contentType;
+
+ public ChannelImageResponse() {
+ }
+
+ public ChannelImageResponse(File file, String contentType) {
+ this.errCode = SUCCESS_CODE;
+ this.errMsg = "ok";
+ this.file = file;
+ this.contentType = contentType;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/image/QualificationFileId.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/image/QualificationFileId.java
new file mode 100644
index 0000000000..905720a8dc
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/image/QualificationFileId.java
@@ -0,0 +1,24 @@
+package me.chanjar.weixin.channel.bean.image;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 资质文件id
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class QualificationFileId implements Serializable {
+
+ private static final long serialVersionUID = -546135264746778249L;
+
+ /** 文件id */
+ @JsonProperty("file_id")
+ private String id;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/image/QualificationFileResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/image/QualificationFileResponse.java
new file mode 100644
index 0000000000..5a4332885c
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/image/QualificationFileResponse.java
@@ -0,0 +1,24 @@
+package me.chanjar.weixin.channel.bean.image;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 资质文件id响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class QualificationFileResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 5172377567441096813L;
+
+ /** 文件数据 */
+ @JsonProperty("data")
+ private QualificationFileId data;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/image/UploadImageResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/image/UploadImageResponse.java
new file mode 100644
index 0000000000..f1625bd3c4
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/image/UploadImageResponse.java
@@ -0,0 +1,24 @@
+package me.chanjar.weixin.channel.bean.image;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 微信图片信息响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class UploadImageResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -609315696774437877L;
+
+ /** 图片信息 */
+ @JsonProperty("pic_file")
+ private ChannelImageInfo imgInfo;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/AddressInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/AddressInfo.java
new file mode 100644
index 0000000000..1ffb01677c
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/AddressInfo.java
@@ -0,0 +1,33 @@
+package me.chanjar.weixin.channel.bean.league;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 地址信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class AddressInfo implements Serializable {
+
+ private static final long serialVersionUID = -5719456688033731919L;
+ /** 邮编 */
+ @JsonProperty("postal_code")
+ private String postalCode;
+
+ /** 国标收货地址第一级地址 */
+ @JsonProperty("province_name")
+ private String provinceName;
+
+ /** 国标收货地址第二级地址 */
+ @JsonProperty("city_name")
+ private String cityName;
+
+ /** 国标收货地址第三级地址 */
+ @JsonProperty("county_name")
+ private String countyName;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/CatInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/CatInfo.java
new file mode 100644
index 0000000000..4fc2cfc95b
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/CatInfo.java
@@ -0,0 +1,22 @@
+package me.chanjar.weixin.channel.bean.league;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 商品分类信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class CatInfo implements Serializable {
+
+ private static final long serialVersionUID = 8449223922139383888L;
+ /** 类目id */
+ @JsonProperty("cat_id")
+ private String catId;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/DescInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/DescInfo.java
new file mode 100644
index 0000000000..a29b07a294
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/DescInfo.java
@@ -0,0 +1,26 @@
+package me.chanjar.weixin.channel.bean.league;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 商详信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class DescInfo implements Serializable {
+
+ private static final long serialVersionUID = 5319244341160446531L;
+ /** 商品详情图片(最多20张)。如果添加时没录入,回包可能不包含该字段 */
+ @JsonProperty("imgs")
+ private List imgs;
+
+ /** 商品详情文字。如果添加时没录入,回包可能不包含该字 */
+ @JsonProperty("desc")
+ private String desc;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/ExpressInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/ExpressInfo.java
new file mode 100644
index 0000000000..6fbecac866
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/ExpressInfo.java
@@ -0,0 +1,30 @@
+package me.chanjar.weixin.channel.bean.league;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 物流信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class ExpressInfo implements Serializable {
+
+ private static final long serialVersionUID = -4604691645808459334L;
+ /** 发货时间期限 */
+ @JsonProperty("send_time")
+ private String sendTime;
+
+ /** 发货地址 */
+ @JsonProperty("address_info")
+ private AddressInfo addressInfo;
+
+ /** 计费方式:FREE:包邮CONDITION_FREE:条件包邮NO_FREE:不包邮 */
+ @JsonProperty("shipping_method")
+ private String shippingMethod;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/SimpleProductInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/SimpleProductInfo.java
new file mode 100644
index 0000000000..9de16b849e
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/SimpleProductInfo.java
@@ -0,0 +1,39 @@
+package me.chanjar.weixin.channel.bean.league;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 商品信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class SimpleProductInfo implements Serializable {
+
+ private static final long serialVersionUID = -2444641123422095497L;
+ /** 标题 */
+ @JsonProperty("title")
+ protected String title;
+
+ /** 副标题 */
+ @JsonProperty("sub_title")
+ protected String subTitle;
+
+ /** 主图,多张,列表,最多9张,每张不超过2MB */
+ @JsonProperty("head_imgs")
+ protected List headImgs;
+
+ /** 商详信息 */
+ @JsonProperty("desc_info")
+ protected DescInfo descInfo;
+
+ /** 类目信息 */
+ @JsonProperty("cats")
+ protected List cats;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/product/BatchAddParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/product/BatchAddParam.java
new file mode 100644
index 0000000000..c22563359a
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/product/BatchAddParam.java
@@ -0,0 +1,63 @@
+package me.chanjar.weixin.channel.bean.league.product;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 批量添加商品参数
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class BatchAddParam implements Serializable {
+
+ private static final long serialVersionUID = -87989229725625901L;
+ /** 商品推广类别 */
+ @JsonProperty("type")
+ private Integer type;
+
+ /** 商品列表 */
+ @JsonProperty("list")
+ private List list;
+
+ /** 推广达人列表 */
+ @JsonProperty("finder_ids")
+ private List finderIds;
+
+ /** 推广开始时间戳 */
+ @JsonProperty("begin_time")
+ private Long beginTime;
+
+ /** 推广结束时间戳 */
+ @JsonProperty("end_time")
+ private Long endTime;
+
+ /** 是否永久推广 */
+ @JsonProperty("is_forerver")
+ private Boolean forever;
+
+
+ @Data
+ @NoArgsConstructor
+ @AllArgsConstructor
+ @JsonInclude(JsonInclude.Include.NON_NULL)
+ public static class Product implements Serializable {
+
+ private static final long serialVersionUID = 9025105293896488093L;
+ /** 商品id,不可重复数量不超过20 */
+ @JsonProperty("product_id")
+ private String productId;
+
+ /** 推广佣金[0, 90]% */
+ @JsonProperty("ratio")
+ private Integer ratio;
+
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/product/BatchAddResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/product/BatchAddResponse.java
new file mode 100644
index 0000000000..7a2f4f6840
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/product/BatchAddResponse.java
@@ -0,0 +1,44 @@
+package me.chanjar.weixin.channel.bean.league.product;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 批量添加商品响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class BatchAddResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 2686612709939873527L;
+ /** 商品id信息 */
+ @JsonProperty("result_info_list")
+ private List resultInfoList;
+
+
+ @Data
+ @NoArgsConstructor
+ @EqualsAndHashCode(callSuper = true)
+ public static class ResultInfo extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -534890760974302155L;
+ /** 商品id */
+ @JsonProperty("product_id")
+ private String productId;
+
+ /** 特殊推广商品计划id */
+ @JsonProperty("info_id")
+ private String infoId;
+
+ /** 推广失败达人列表 */
+ @JsonProperty("fail_finder_ids")
+ private List failFinderIds;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/product/ProductDeleteParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/product/ProductDeleteParam.java
new file mode 100644
index 0000000000..ccdf3ef0b4
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/product/ProductDeleteParam.java
@@ -0,0 +1,33 @@
+package me.chanjar.weixin.channel.bean.league.product;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 商品删除请求
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class ProductDeleteParam implements Serializable {
+
+ private static final long serialVersionUID = 9129737170370664633L;
+ /** 获取商品推广类别 */
+ @JsonProperty("type")
+ private Integer type;
+
+ /** 商品id type为普通推广商品时必填 */
+ @JsonProperty("product_id")
+ private String productId;
+
+ /** 特殊推广商品计划id type为特殊推广商品时必填 */
+ @JsonProperty("info_id")
+ private String infoId;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/product/ProductDetailParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/product/ProductDetailParam.java
new file mode 100644
index 0000000000..7b2c6ae6f7
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/product/ProductDetailParam.java
@@ -0,0 +1,48 @@
+package me.chanjar.weixin.channel.bean.league.product;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 商品详情请求
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class ProductDetailParam implements Serializable {
+
+ private static final long serialVersionUID = 7624234965127527565L;
+ /** 获取商品推广类别 */
+ @JsonProperty("type")
+ private Integer type;
+
+ /** 商品id type为普通推广商品时必填 */
+ @JsonProperty("product_id")
+ private String productId;
+
+ /** 特殊推广商品计划id type为特殊推广商品时必填 */
+ @JsonProperty("info_id")
+ private String infoId;
+
+ /** 是否获取特殊推广商品绑定的达人列表, type为特殊推广商品时有效 */
+ @JsonProperty("need_relation")
+ private Boolean needRelation;
+
+ /** 拉取达人数 need_relation为真时必填 不超过50 */
+ @JsonProperty("page_size")
+ private Integer pageSize;
+
+ /** need_relation为真时有效,页面下标,下标从1开始,默认为1 */
+ @JsonProperty("page_index")
+ private Integer pageIndex;
+
+ /** need_relation为真时有效,是否需要返回该计划绑定达人总数 */
+ @JsonProperty("need_total_num")
+ private Boolean needTotalNum;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/product/ProductDetailResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/product/ProductDetailResponse.java
new file mode 100644
index 0000000000..05ea00c055
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/product/ProductDetailResponse.java
@@ -0,0 +1,96 @@
+package me.chanjar.weixin.channel.bean.league.product;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 商品详情响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class ProductDetailResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 5306524707144232861L;
+ /** 推广商品信息 */
+ @JsonProperty("item")
+ private Item item;
+
+
+ @Data
+ @NoArgsConstructor
+ public static class Item implements Serializable {
+
+ private static final long serialVersionUID = 9112142704638318861L;
+ /** 商品id */
+ @JsonProperty("product_id")
+ private String productId;
+
+ /** 商品推广类别 1普通推广商品 2定向推广商品 3专属推广商品 */
+ @JsonProperty("type")
+ private Integer type;
+
+ /** 商品推广状态 1已上架推广 2已下架推广 4已删除 5未达到准入标准 10待生效 */
+ @JsonProperty("status")
+ private Integer status;
+
+ /** 推广佣金[0, 90]% */
+ @JsonProperty("ratio")
+ private Integer ratio;
+
+ /** 特殊推广信息 */
+ @JsonProperty("exclusive_info")
+ private ExclusiveInfo exclusiveInfo;
+
+ /** 扩展信息 */
+ @JsonProperty("ext_info")
+ private ExtInfo extInfo;
+ }
+
+ @Data
+ @NoArgsConstructor
+ public static class ExclusiveInfo implements Serializable {
+
+ private static final long serialVersionUID = 6583124869090013797L;
+ /** 特殊推广商品计划id */
+ @JsonProperty("info_id")
+ private String infoId;
+
+ /** 推广开始时间戳 */
+ @JsonProperty("begin_time")
+ private Long beginTime;
+
+ /** 推广结束时间戳 */
+ @JsonProperty("end_time")
+ private Long endTime;
+
+ /** 是否永久推广 */
+ @JsonProperty("is_forerver")
+ private Boolean forever;
+
+ /** 推广达人视频号列表 */
+ @JsonProperty("finder_ids")
+ private List finderIds;
+
+ }
+
+ @Data
+ @NoArgsConstructor
+ public static class ExtInfo implements Serializable {
+
+ /** 是否类目禁售 */
+ @JsonProperty("is_sale_forbidden")
+ private Boolean saleForbidden;
+
+ /** 是否被官方封禁 */
+ @JsonProperty("is_banned")
+ private Boolean banned;
+
+ }
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/product/ProductListParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/product/ProductListParam.java
new file mode 100644
index 0000000000..18d52c82d6
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/product/ProductListParam.java
@@ -0,0 +1,47 @@
+package me.chanjar.weixin.channel.bean.league.product;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 商品列表请求
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class ProductListParam implements Serializable {
+
+ private static final long serialVersionUID = -1914139382459786057L;
+ /** 商品推广类别 */
+ @JsonProperty("type")
+ private Integer type;
+
+ /** 单页商品数(不超过100) */
+ @JsonProperty("page_size")
+ private Integer pageSize;
+
+ /** 页面下标,下标从1开始,默认为1 */
+ @JsonProperty("page_index")
+ private Integer pageIndex;
+
+ /** 商品id,拉取特殊推广商品时有效 */
+ @JsonProperty("product_id")
+ private String productId;
+
+ /** 视频号id,拉取特殊推广商品时有效 */
+ @JsonProperty("finder_id")
+ private String finderId;
+
+ /** 由上次请求返回,顺序翻页时需要传入, 会从上次返回的结果往后翻一页(填了该值后page_index不生效) */
+ @JsonProperty("last_buffer")
+ private String lastBuffer;
+
+ /** 是否需要返回满足筛选条件的商品总数(填last_buffer后该值无效) */
+ @JsonProperty("need_total_num")
+ private Boolean needTotalNum;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/product/ProductListResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/product/ProductListResponse.java
new file mode 100644
index 0000000000..642884ce63
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/product/ProductListResponse.java
@@ -0,0 +1,52 @@
+package me.chanjar.weixin.channel.bean.league.product;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 商品更新响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class ProductListResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -6192518391380515045L;
+ /** 商品列表 */
+ @JsonProperty("items")
+ private List- items;
+
+ /** 本次翻页的上下文,用于顺序翻页请求 */
+ @JsonProperty("last_buffer")
+ private String lastBuffer;
+
+ /** 商品总数 */
+ @JsonProperty("total_num")
+ private Integer totalNum;
+
+ /** 是否还有剩余商品 */
+ @JsonProperty("has_more")
+ private Boolean hasMore;
+
+ @Data
+ @NoArgsConstructor
+ public static class Item implements Serializable {
+
+ private static final long serialVersionUID = 5094378518992196239L;
+ /** 商品id */
+ @JsonProperty("product_id")
+ private String productId;
+
+ /** 特殊推广商品计划id */
+ @JsonProperty("info_id")
+ private String infoId;
+
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/product/ProductUpdateParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/product/ProductUpdateParam.java
new file mode 100644
index 0000000000..8188911519
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/product/ProductUpdateParam.java
@@ -0,0 +1,72 @@
+package me.chanjar.weixin.channel.bean.league.product;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 商品更新请求
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class ProductUpdateParam implements Serializable {
+
+ private static final long serialVersionUID = -3519313269193693460L;
+ /** 获取商品推广类别 */
+ @JsonProperty("type")
+ private Integer type;
+
+ /** 商品id type为普通推广商品时必填 */
+ @JsonProperty("product_id")
+ private String productId;
+
+ /** 特殊推广商品计划id type为特殊推广商品时必填 */
+ @JsonProperty("info_id")
+ private String infoId;
+
+ /** 更新操作类别 */
+ @JsonProperty("operate_type")
+ private Integer operateType;
+
+ /** 推广佣金[0, 90]% */
+ @JsonProperty("ratio")
+ private Integer ratio;
+
+ /** 特殊推广信息 */
+ @JsonProperty("exclusive_info")
+ private ExclusiveInfo exclusiveInfo;
+
+
+ /** 特殊推广信息 */
+ @Data
+ @NoArgsConstructor
+ public static class ExclusiveInfo implements Serializable {
+
+ private static final long serialVersionUID = -8120260214345369170L;
+ /** 推广开始时间戳 */
+ @JsonProperty("begin_time")
+ private Long beginTime;
+
+ /** 推广结束时间戳 */
+ @JsonProperty("end_time")
+ private Long endTime;
+
+ /** 是否永久推广 */
+ @JsonProperty("is_forerver")
+ private Boolean forever;
+
+ /** 新增推广达人视频号列表,不超过30个 */
+ @JsonProperty("add_finder_ids")
+ private List addFinderIds;
+
+ /** 删除推广达人视频号列表,不超过30个 */
+ @JsonProperty("del_finder_ids")
+ private List delFinderIds;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/product/ProductUpdateResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/product/ProductUpdateResponse.java
new file mode 100644
index 0000000000..7dae90569e
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/product/ProductUpdateResponse.java
@@ -0,0 +1,23 @@
+package me.chanjar.weixin.channel.bean.league.product;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 商品更新响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class ProductUpdateResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 2144233059960259829L;
+ /** 特殊推广商品计划id */
+ @JsonProperty("info_id")
+ private String infoId;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/promoter/PromoterInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/promoter/PromoterInfo.java
new file mode 100644
index 0000000000..7f817c6633
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/promoter/PromoterInfo.java
@@ -0,0 +1,37 @@
+package me.chanjar.weixin.channel.bean.league.promoter;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 达人
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class PromoterInfo implements Serializable {
+
+ private static final long serialVersionUID = -8851711325343107780L;
+ /** 视频号finder_id */
+ @JsonProperty("finder_id")
+ private String finderId;
+
+ /** 合作状态 0初始值 1邀请中 2达人已接受邀请 3达人已拒绝邀请 4已取消邀请 5已取消合作 10已删除 */
+ @JsonProperty("status")
+ private Integer status;
+
+ /** 达人邀请秒级时间戳 */
+ @JsonProperty("invite_time")
+ private Long inviteTime;
+
+ /** 累计合作商品数 */
+ @JsonProperty("sale_product_number")
+ private Integer saleProductNumber;
+
+ /** 合作动销GMV */
+ @JsonProperty("sale_gmv")
+ private Integer saleGmv;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/promoter/PromoterInfoResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/promoter/PromoterInfoResponse.java
new file mode 100644
index 0000000000..bebe6a6fcc
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/promoter/PromoterInfoResponse.java
@@ -0,0 +1,23 @@
+package me.chanjar.weixin.channel.bean.league.promoter;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 达人信息响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class PromoterInfoResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 6475158486029216487L;
+ /** 达人信息 */
+ @JsonProperty("promoter")
+ private PromoterInfo promoter;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/promoter/PromoterListParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/promoter/PromoterListParam.java
new file mode 100644
index 0000000000..128797bda8
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/promoter/PromoterListParam.java
@@ -0,0 +1,30 @@
+package me.chanjar.weixin.channel.bean.league.promoter;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 达人列表请求
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class PromoterListParam implements Serializable {
+
+ private static final long serialVersionUID = -6179472484874537538L;
+ /** 页面下标,下标从1开始,默认为1 */
+ @JsonProperty("page_index")
+ protected Integer pageIndex;
+
+ /** 页面下标,下标从1开始,默认为1 */
+ @JsonProperty("page_size")
+ protected Integer pageSize;
+
+ /** 拉取该状态下的达人列表 */
+ private Integer status;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/promoter/PromoterListResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/promoter/PromoterListResponse.java
new file mode 100644
index 0000000000..c193550369
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/promoter/PromoterListResponse.java
@@ -0,0 +1,28 @@
+package me.chanjar.weixin.channel.bean.league.promoter;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 达人列表响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class PromoterListResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 1411870432999885996L;
+ /** 达人finder_id列表 */
+ @JsonProperty("finder_ids")
+ private List finderIds;
+
+ /** 达人总数 */
+ @JsonProperty("total_num")
+ private Integer totalNum;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/BizBaseInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/BizBaseInfo.java
new file mode 100644
index 0000000000..39b77daa32
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/BizBaseInfo.java
@@ -0,0 +1,29 @@
+package me.chanjar.weixin.channel.bean.league.supplier;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 小店基础信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class BizBaseInfo implements Serializable {
+
+ private static final long serialVersionUID = 3713638025924977002L;
+ /** 小店appid */
+ @JsonProperty("appid")
+ private String appid;
+
+ /** 小店头像 */
+ @JsonProperty("headimg_url")
+ private String headimgUrl;
+
+ /** 小店昵称 */
+ @JsonProperty("nickname")
+ private String nickname;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/CommissionInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/CommissionInfo.java
new file mode 100644
index 0000000000..356a058684
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/CommissionInfo.java
@@ -0,0 +1,41 @@
+package me.chanjar.weixin.channel.bean.league.supplier;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 跟佣信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class CommissionInfo implements Serializable {
+
+ private static final long serialVersionUID = 3027131215096984236L;
+ /** 商品带货状态 1已上架推广 2已下架推广 5已清退 */
+ @JsonProperty("status")
+ private Integer status;
+
+ /** 服务费率[0, 1000000] */
+ @JsonProperty("service_ratio")
+ private Integer serviceRatio;
+
+ /** 佣金费率[0, 1000000] */
+ @JsonProperty("ratio")
+ private Integer ratio;
+
+ /** unix时间戳,合作开始时间 */
+ @JsonProperty("start_time")
+ private Long startTime;
+
+ /** unix时间戳,合作结束时间 */
+ @JsonProperty("end_time")
+ private Long endTime;
+
+ /** 带货链接 */
+ @JsonProperty("link")
+ private String link;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/CommissionOrderListParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/CommissionOrderListParam.java
new file mode 100644
index 0000000000..2f8d27f52e
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/CommissionOrderListParam.java
@@ -0,0 +1,53 @@
+package me.chanjar.weixin.channel.bean.league.supplier;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.TimeRange;
+
+/**
+ * 佣金单列表请求参数
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class CommissionOrderListParam implements Serializable {
+
+ private static final long serialVersionUID = 2805783646567362357L;
+ /** 佣金单所属小店appid */
+ @JsonProperty("appid")
+ private String appid;
+
+ /** 视频号finder_id */
+ @JsonProperty("finder_id")
+ private String finderId;
+
+ /** 视频号openfinderid */
+ @JsonProperty("openfinderid")
+ private String openfinderid;
+
+ /** 佣金单创建时间范围 */
+ @JsonProperty("create_time_range")
+ private TimeRange createTimeRange;
+
+ /** 佣金单更新时间范围 */
+ @JsonProperty("update_time_range")
+ private TimeRange updateTimeRange;
+
+ /** 订单ID,填此参数后其他过滤参数无效 */
+ @JsonProperty("order_id")
+ private String orderId;
+
+ /** 单页佣金单数(不超过30) */
+ @JsonProperty("page_size")
+ private Integer pageSize;
+
+ /** 由上次请求返回,顺序翻页时需要传入, 会从上次返回的结果往后翻一页 */
+ @JsonProperty("next_key")
+ private String nextKey;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/CommissionOrderListResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/CommissionOrderListResponse.java
new file mode 100644
index 0000000000..6d7e1be4f8
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/CommissionOrderListResponse.java
@@ -0,0 +1,50 @@
+package me.chanjar.weixin.channel.bean.league.supplier;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+
+/**
+ * 团长订单列表响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class CommissionOrderListResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 1143184321517598592L;
+ /** 商品id信息 */
+ @JsonProperty("list")
+ private List list;
+
+ /** 本次翻页的上下文,用于顺序翻页请求 */
+ @JsonProperty("next_key")
+ private String nextKey;
+
+ /** 是否还有剩余商品 */
+ @JsonProperty("has_more")
+ private Boolean hasMore;
+
+
+ @Data
+ @NoArgsConstructor
+ public static class ProductIdInfo implements Serializable {
+
+ private static final long serialVersionUID = -691189837681217282L;
+ /** 商品id */
+ @JsonProperty("order_id")
+ private String orderId;
+
+ /** skuid */
+ @JsonProperty("sku_id")
+ private String skuId;
+
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/CommissionOrderResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/CommissionOrderResponse.java
new file mode 100644
index 0000000000..d8c84e1473
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/CommissionOrderResponse.java
@@ -0,0 +1,174 @@
+package me.chanjar.weixin.channel.bean.league.supplier;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 佣金订单响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class CommissionOrderResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 7004553990771819977L;
+ /** 佣金单 */
+ @JsonProperty("commssion_order")
+ private CommissionOrder commissionOrder;
+
+
+ /** 佣金单 */
+ @Data
+ @NoArgsConstructor
+ public static class CommissionOrder implements Serializable {
+
+ private static final long serialVersionUID = 735931726521944716L;
+ /** 订单号 */
+ @JsonProperty("order_id")
+ private String orderId;
+
+ /** 商品skuid */
+ @JsonProperty("sku_id")
+ private String skuId;
+
+ /** 秒级时间戳 */
+ @JsonProperty("create_time")
+ private Long createTime;
+
+ /** 秒级时间戳 */
+ @JsonProperty("update_time")
+ private Long updateTime;
+
+ /** 佣金单状态,见{@link me.chanjar.weixin.channel.enums.CommissionOrderStatus} */
+ @JsonProperty("status")
+ private Integer status;
+
+ /** 订单详情 */
+ @JsonProperty("order_detail")
+ private OrderDetail orderDetail;
+ }
+
+ /** 订单详情 */
+ @Data
+ @NoArgsConstructor
+ public static class OrderDetail implements Serializable {
+
+ private static final long serialVersionUID = 8349635368396073000L;
+ /** 小店商家信息 */
+ @JsonProperty("shop_info")
+ private BizInfo shopInfo;
+
+ /** 佣金单商品信息 */
+ @JsonProperty("product_info")
+ private ProductInfo productInfo;
+
+ /** 订单信息 */
+ @JsonProperty("order_info")
+ private OrderInfo orderInfo;
+
+ /** 分佣信息 */
+ @JsonProperty("commission_info")
+ private CommissionInfo commissionInfo;
+
+ }
+
+ /** 小店商家信息 */
+ @Data
+ @NoArgsConstructor
+ public static class BizInfo implements Serializable {
+
+ private static final long serialVersionUID = -8229584987720782974L;
+ /** 所属小店appid */
+ @JsonProperty("appid")
+ private String appid;
+
+ }
+
+ /** 佣金单商品信息 */
+ @Data
+ @NoArgsConstructor
+ public static class ProductInfo implements Serializable {
+
+ private static final long serialVersionUID = -2790410903073956864L;
+ /** 商品id */
+ @JsonProperty("product_id")
+ private String productId;
+
+ /** sku小图 */
+ @JsonProperty("thumb_img")
+ private String thumbImg;
+
+ /** 可分佣金额 */
+ @JsonProperty("actual_payment")
+ private Integer actualPayment;
+
+ /** 商品标题 */
+ @JsonProperty("title")
+ private String title;
+
+ }
+
+ /** 订单信息 */
+ @Data
+ @NoArgsConstructor
+ public static class OrderInfo implements Serializable {
+
+ private static final long serialVersionUID = 7610425518539999170L;
+ /** 订单状态,枚举值见OrderStatus */
+ @JsonProperty("order_status")
+ private Integer status;
+
+ }
+
+ /** 分佣信息 */
+ @Data
+ @NoArgsConstructor
+ public static class CommissionInfo implements Serializable {
+
+ private static final long serialVersionUID = -2114290318872427720L;
+ /** 带货达人信息 */
+ @JsonProperty("finder_info")
+ private FinderInfo finderInfo;
+
+ /** 服务费率[0, 1000000] */
+ @JsonProperty("service_ratio")
+ private Integer serviceRatio;
+
+ /** 服务费金额 */
+ @JsonProperty("service_amount")
+ private Integer serviceAmount;
+
+ /** 服务费结算时间 */
+ @JsonProperty("profit_sharding_suc_time")
+ private Long profitShardingSucTime;
+
+ }
+
+ /** 带货达人信息 */
+ @Data
+ @NoArgsConstructor
+ public static class FinderInfo implements Serializable {
+
+ private static final long serialVersionUID = 7383486670949864257L;
+ /** 达人昵称 */
+ @JsonProperty("nickname")
+ private String nickname;
+
+ /** 佣金率[0, 1000000] */
+ @JsonProperty("ratio")
+ private Integer ratio;
+ /** 佣金 */
+ @JsonProperty("amount")
+ private Integer amount;
+
+ /** 视频号openfinderid */
+ @JsonProperty("openfinderid")
+ private String openfinderid;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/CoopProductDetailParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/CoopProductDetailParam.java
new file mode 100644
index 0000000000..494e86f999
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/CoopProductDetailParam.java
@@ -0,0 +1,29 @@
+package me.chanjar.weixin.channel.bean.league.supplier;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 合作商品详情请求
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class CoopProductDetailParam implements Serializable {
+
+ private static final long serialVersionUID = 3515221514742929207L;
+ /** 商品id */
+ @JsonProperty("product_id")
+ private String productId;
+
+ /** 团长商品 所属小店appid */
+ @JsonProperty("appid")
+ private String appId;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/CoopProductListParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/CoopProductListParam.java
new file mode 100644
index 0000000000..81743b51f2
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/CoopProductListParam.java
@@ -0,0 +1,34 @@
+package me.chanjar.weixin.channel.bean.league.supplier;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 合作商品详情请求
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class CoopProductListParam implements Serializable {
+
+ private static final long serialVersionUID = -9023029707828535352L;
+ /** 团长商品 所属小店appid */
+ @JsonProperty("appid")
+ private String appid;
+
+ /** 单页商品数(不超过30) */
+ @JsonProperty("page_size")
+ private Integer pageSize;
+
+ /** 由上次请求返回,顺序翻页时需要传入, 会从上次返回的结果往后翻一页 */
+ @JsonProperty("next_key")
+ private String nextKey;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/CoopProductListResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/CoopProductListResponse.java
new file mode 100644
index 0000000000..39bf2bb96e
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/CoopProductListResponse.java
@@ -0,0 +1,49 @@
+package me.chanjar.weixin.channel.bean.league.supplier;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 团长商品列表响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class CoopProductListResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -5440144076389135839L;
+ /** 商品id信息 */
+ @JsonProperty("list")
+ private List list;
+
+ /** 本次翻页的上下文,用于顺序翻页请求 */
+ @JsonProperty("next_key")
+ private String nextKey;
+
+ /** 是否还有剩余商品 */
+ @JsonProperty("has_more")
+ private Boolean hasMore;
+
+
+ @Data
+ @NoArgsConstructor
+ public static class ProductIdInfo implements Serializable {
+
+ private static final long serialVersionUID = -7136011408769169462L;
+ /** 商品id */
+ @JsonProperty("product_id")
+ private String productId;
+
+ /** 所属小店appid */
+ @JsonProperty("appid")
+ private String appid;
+
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/CoopProductResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/CoopProductResponse.java
new file mode 100644
index 0000000000..eee78937b2
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/CoopProductResponse.java
@@ -0,0 +1,47 @@
+package me.chanjar.weixin.channel.bean.league.supplier;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 合作商品详情响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class CoopProductResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -4066427847985394479L;
+ /** 商品信息 */
+ @JsonProperty("item")
+ private Item item;
+
+
+ @Data
+ @NoArgsConstructor
+ public static class Item implements Serializable {
+
+ private static final long serialVersionUID = 6123572874440025928L;
+ /** 所属小店appid */
+ @JsonProperty("appid")
+ private String appid;
+
+ /** 商品id */
+ @JsonProperty("product_id")
+ private String productId;
+
+ /** 商品信息 */
+ @JsonProperty("product_info")
+ private ProductInfo productInfo;
+
+ /** 跟佣信息 */
+ @JsonProperty("commission_info")
+ private CommissionInfo commissionInfo;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/FlowListParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/FlowListParam.java
new file mode 100644
index 0000000000..99d2bf107f
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/FlowListParam.java
@@ -0,0 +1,43 @@
+package me.chanjar.weixin.channel.bean.league.supplier;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 团长流水列表请求参数
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class FlowListParam implements Serializable {
+
+ private static final long serialVersionUID = 3128695806885851134L;
+ /** 页码,从1开始 */
+ @JsonProperty("page")
+ private Integer page;
+
+ /** 页数,不填默认为10 */
+ @JsonProperty("page_size")
+ private Integer pageSize;
+
+ /** 资金类型, 见 {@link me.chanjar.weixin.channel.enums.FundsType} */
+ @JsonProperty("funds_type")
+ private Integer fundsType;
+
+ /** 流水产生的开始时间,uinx时间戳 */
+ @JsonProperty("start_time")
+ private Long startTime;
+
+ /** 流水产生的结束时间,unix时间戳 */
+ @JsonProperty("end_time")
+ private Long endTime;
+
+ /** 分页参数,翻页时写入上一页返回的next_key(page为上一页加一,并且page_size与上一页相同的时候才生效),page * page_size >= 5000时必填 */
+ @JsonProperty("next_key")
+ private String nextKey;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/FundsFlowInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/FundsFlowInfo.java
new file mode 100644
index 0000000000..089c7048d5
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/FundsFlowInfo.java
@@ -0,0 +1,51 @@
+package me.chanjar.weixin.channel.bean.league.supplier;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+
+/**
+ * 团长资金流水详情
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class FundsFlowInfo implements Serializable {
+
+ private static final long serialVersionUID = 102705878551490327L;
+ /** 流水id */
+ @JsonProperty("flow_id")
+ private String flowId;
+
+ /** 资金类型, 1提现 2分账 */
+ @JsonProperty("funds_type")
+ private Integer fundsType;
+
+ /** 流水金额 单位:分 */
+ @JsonProperty("amount")
+ private Integer amount;
+
+ /** 余额 单位:分 */
+ @JsonProperty("balance")
+ private Integer balance;
+
+ /** 记账时间 */
+ @JsonProperty("bookkeeping_time")
+ private String bookkeepingTime;
+
+ /** 备注 */
+ @JsonProperty("remark")
+ private String remark;
+
+ /** 关联订单号 */
+ @JsonProperty("order_id")
+ private String orderId;
+
+ /** 关联提现单号 */
+ @JsonProperty("withdraw_id")
+ private String withdrawId;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/ProductInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/ProductInfo.java
new file mode 100644
index 0000000000..0c2dcae7a6
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/ProductInfo.java
@@ -0,0 +1,29 @@
+package me.chanjar.weixin.channel.bean.league.supplier;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.league.ExpressInfo;
+import me.chanjar.weixin.channel.bean.league.SimpleProductInfo;
+
+/**
+ * 商品信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class ProductInfo extends SimpleProductInfo {
+
+ private static final long serialVersionUID = 5352334936089828219L;
+ /** 快递信息 */
+ @JsonProperty("express_info")
+ private ExpressInfo expressInfo;
+
+ /** sku信息 */
+ @JsonProperty("skus")
+ private List skus;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/ShopDetailResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/ShopDetailResponse.java
new file mode 100644
index 0000000000..14eaacb567
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/ShopDetailResponse.java
@@ -0,0 +1,89 @@
+package me.chanjar.weixin.channel.bean.league.supplier;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 合作小店详情响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class ShopDetailResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 188954608418544735L;
+ /** 小店详情 */
+ @JsonProperty("shop_detail")
+ private ShopDetail shopDetail;
+
+ /** 本次翻页的上下文,用于顺序翻页请求 */
+ @JsonProperty("next_key")
+ private String nextKey;
+
+ /** 是否还有剩余小店 */
+ @JsonProperty("has_more")
+ private Boolean hasMore;
+
+ /** 小店详情 */
+ @Data
+ @NoArgsConstructor
+ public static class ShopDetail implements Serializable {
+
+ private static final long serialVersionUID = -3454074422563804378L;
+ /** 小店基础信息 */
+ @JsonProperty("base_info")
+ private BizBaseInfo baseInfo;
+
+ /** 小店数据信息 */
+ @JsonProperty("data_info")
+ private ShopDataInfo dataInfo;
+
+ /** 合作状态Status 1邀请中 2已接受邀请 3已拒绝邀请 4取消邀请 5取消合作 */
+ @JsonProperty("status")
+ private Integer status;
+
+ /** 开始合作时间戳 */
+ @JsonProperty("approved_time")
+ private Long approvedTime;
+
+ }
+
+
+ /** 小店数据信息 */
+ @Data
+ @NoArgsConstructor
+ public static class ShopDataInfo implements Serializable {
+
+ private static final long serialVersionUID = 6603460255046252283L;
+ /** 合作动销GMV,单位:分 */
+ @JsonProperty("gmv")
+ private Integer gmv;
+
+ /** 历史合作商品数 */
+ @JsonProperty("product_number")
+ private Integer productNumber;
+
+ /** 已结算服务费,单位:分 */
+ @JsonProperty("settle_amount")
+ private Integer settleAmount;
+
+ /** 预计待结算服务费,单位:分 */
+ @JsonProperty("unsettle_amount")
+ private Integer unsettleAmount;
+
+ /** 今日新增合作商品数 */
+ @JsonProperty("product_number_today")
+ private Integer productNumberToday;
+
+ /** 今日动销商品数 */
+ @JsonProperty("product_number_sold_today")
+ private Integer productNumberSoldToday;
+ }
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/ShopListResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/ShopListResponse.java
new file mode 100644
index 0000000000..1c7de7c4a7
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/ShopListResponse.java
@@ -0,0 +1,50 @@
+package me.chanjar.weixin.channel.bean.league.supplier;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 合作小店列表响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class ShopListResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 1736467471867767456L;
+ /** 小店详情 */
+ @JsonProperty("shop_list")
+ private List shopList;
+
+ /** 本次翻页的上下文,用于顺序翻页请求 */
+ @JsonProperty("next_key")
+ private String nextKey;
+
+ /** 是否还有剩余小店 */
+ @JsonProperty("has_more")
+ private Boolean hasMore;
+
+ /** 小店详情 */
+ @Data
+ @NoArgsConstructor
+ public static class ShopDetail implements Serializable {
+
+ private static final long serialVersionUID = 8421286426372052694L;
+ /** 小店基础信息 */
+ @JsonProperty("base_info")
+ private BizBaseInfo baseInfo;
+
+ /** 小店状态 */
+ @JsonProperty("status")
+ private Integer status;
+ }
+
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/SkuInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/SkuInfo.java
new file mode 100644
index 0000000000..6c51910d47
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/SkuInfo.java
@@ -0,0 +1,40 @@
+package me.chanjar.weixin.channel.bean.league.supplier;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.AttrInfo;
+
+
+/**
+ * SkuInfo
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class SkuInfo implements Serializable {
+
+ private static final long serialVersionUID = 197261426211990640L;
+ /** skuID */
+ @JsonProperty("sku_id")
+ private String skuId;
+
+ /** sku小图。如果添加时没录入,回包可能不包含该字段 */
+ @JsonProperty("thumb_img")
+ private String thumbImg;
+
+ /** 售卖价格,以分为单位 */
+ @JsonProperty("sale_price")
+ private Integer salePrice;
+
+ /** sku库存 */
+ @JsonProperty("stock_num")
+ private Integer stockNum;
+
+ /** sku属性 */
+ @JsonProperty("sku_attrs")
+ private List skuAttrs;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/SupplierBalanceResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/SupplierBalanceResponse.java
new file mode 100644
index 0000000000..eaa45027da
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/SupplierBalanceResponse.java
@@ -0,0 +1,27 @@
+package me.chanjar.weixin.channel.bean.league.supplier;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 团长余额响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class SupplierBalanceResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 5584817726976222436L;
+ /** 可提现余额 */
+ @JsonProperty("available_amount")
+ private Integer availableAmount;
+
+ /** 待结算余额 */
+ @JsonProperty("pending_amount")
+ private Integer pendingAmount;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/SupplierFlowDetailResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/SupplierFlowDetailResponse.java
new file mode 100644
index 0000000000..5ab0745fab
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/SupplierFlowDetailResponse.java
@@ -0,0 +1,23 @@
+package me.chanjar.weixin.channel.bean.league.supplier;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 团长流水明细响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class SupplierFlowDetailResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -3962482396458765234L;
+ /** 流水信息 */
+ @JsonProperty("funds_flow")
+ private FundsFlowInfo fundsFlow;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/SupplierFlowListResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/SupplierFlowListResponse.java
new file mode 100644
index 0000000000..468985fe3e
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/supplier/SupplierFlowListResponse.java
@@ -0,0 +1,31 @@
+package me.chanjar.weixin.channel.bean.league.supplier;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 资金流水列表 响应
+ *
+ * @author LiXiZe
+ * @since 2023-04-16
+ */
+@Data
+@NoArgsConstructor
+public class SupplierFlowListResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -2954427554226407544L;
+ /** 流水单号列表 */
+ @JsonProperty("funds_flow_ids")
+ private List ids;
+
+ /** 是否还有下一页 */
+ @JsonProperty("has_more")
+ private Boolean hasMore;
+
+ /** 分页参数,深翻页时使用 */
+ @JsonProperty("next_key")
+ private String nextKey;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/window/AuthInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/window/AuthInfo.java
new file mode 100644
index 0000000000..22facd7a84
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/window/AuthInfo.java
@@ -0,0 +1,33 @@
+package me.chanjar.weixin.channel.bean.league.window;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 授权信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class AuthInfo implements Serializable {
+
+ private static final long serialVersionUID = 6265034296219892453L;
+ /** 授权链接 */
+ @JsonProperty("auth_url")
+ private String authUrl;
+
+ /** 授权路径 */
+ @JsonProperty("auth_wxa_path")
+ private String authWxaPath;
+
+ /** appid */
+ @JsonProperty("auth_wxa_appid")
+ private String authWxaAppid;
+
+ /** 小程序name */
+ @JsonProperty("auth_wxa_username")
+ private String authWxaUsername;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/window/AuthInfoResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/window/AuthInfoResponse.java
new file mode 100644
index 0000000000..941762aecd
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/window/AuthInfoResponse.java
@@ -0,0 +1,27 @@
+package me.chanjar.weixin.channel.bean.league.window;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 授权信息响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class AuthInfoResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 8336998502585278489L;
+ /** 授权链接信息 */
+ @JsonProperty("auth_info")
+ private AuthInfo authInfo;
+
+ /** 视频号openfinderid */
+ @JsonProperty("openfinderid")
+ private String openfinderid;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/window/AuthStatusResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/window/AuthStatusResponse.java
new file mode 100644
index 0000000000..b42bb0d179
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/window/AuthStatusResponse.java
@@ -0,0 +1,22 @@
+package me.chanjar.weixin.channel.bean.league.window;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 授权状态响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class AuthStatusResponse extends WxChannelBaseResponse {
+
+ /** 是否授权,0: 未授权, 1: 已授权 */
+ @JsonProperty("window_auth_status")
+ private Integer windowAuthStatus;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/window/ProductSearchParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/window/ProductSearchParam.java
new file mode 100644
index 0000000000..e43d450c6d
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/window/ProductSearchParam.java
@@ -0,0 +1,40 @@
+package me.chanjar.weixin.channel.bean.league.window;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 团长商品搜索参数
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class ProductSearchParam implements Serializable {
+
+ private static final long serialVersionUID = -4771046746777827382L;
+ /** 团长appid */
+ @JsonProperty("appid")
+ private String appid;
+
+ /** 视频号openfinderid */
+ @JsonProperty("openfinderid")
+ private String openfinderid;
+
+ /** 起始位置(从0开始) */
+ @JsonProperty("offset")
+ private Integer offset;
+
+ /** page_size(默认100, 最大500) */
+ @JsonProperty("page_size")
+ private Integer pageSize;
+
+ /** 默认为false */
+ @JsonProperty("need_total_num")
+ private Boolean needTotalNum;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/window/WindowProductListResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/window/WindowProductListResponse.java
new file mode 100644
index 0000000000..60b5a4a44d
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/window/WindowProductListResponse.java
@@ -0,0 +1,56 @@
+package me.chanjar.weixin.channel.bean.league.window;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 商品列表响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class WindowProductListResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -1160519267422259848L;
+ /** 商品概要列表 */
+ @JsonProperty("list")
+ private List list;
+
+ /** 下一页的位置 */
+ @JsonProperty("next_offset")
+ private Integer nextOffset;
+
+ /** 后面是否还有商品 */
+ @JsonProperty("have_more")
+ private Boolean haveMore;
+
+ /** 商品总数 */
+ @JsonProperty("total_num")
+ private Integer totalNum;
+
+ /** 商品概要列表 */
+ @Data
+ @NoArgsConstructor
+ public static class ItemKey implements Serializable {
+
+ /** 团长appid */
+ @JsonProperty("appid")
+ private String appid;
+
+ /** 团长商品ID */
+ @JsonProperty("product_id")
+ private String productId;
+
+ /** 团长ID */
+ @JsonProperty("head_supplier_id")
+ private String headSupplierId;
+ }
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/window/WindowProductParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/window/WindowProductParam.java
new file mode 100644
index 0000000000..c0e062fd2a
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/window/WindowProductParam.java
@@ -0,0 +1,34 @@
+package me.chanjar.weixin.channel.bean.league.window;
+
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 团长商品
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class WindowProductParam implements Serializable {
+
+ private static final long serialVersionUID = 363738166094927337L;
+ /** 团长appid */
+ @JsonProperty("appid")
+ private String appid;
+
+ /** 视频号openfinderid */
+ @JsonProperty("openfinderid")
+ private String openfinderid;
+
+ /** 团长商品ID */
+ @JsonProperty("product_id")
+ private String productId;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/window/WindowProductResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/window/WindowProductResponse.java
new file mode 100644
index 0000000000..071e0b2350
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/league/window/WindowProductResponse.java
@@ -0,0 +1,49 @@
+package me.chanjar.weixin.channel.bean.league.window;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+import me.chanjar.weixin.channel.bean.league.SimpleProductInfo;
+
+/**
+ * 商品详情响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class WindowProductResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -4671578350314241014L;
+ /** 商品详情 */
+ @JsonProperty("product_detail")
+ private ProductDetail productDetail;
+
+
+ /**
+ * 商品详情
+ */
+ @Data
+ @NoArgsConstructor
+ public static class ProductDetail implements Serializable {
+
+ private static final long serialVersionUID = -6574563870972328273L;
+ /** 所属小店appid */
+ @JsonProperty("appid")
+ private String appid;
+
+ /** 商品id */
+ @JsonProperty("product_id")
+ private String productId;
+
+ /** 商品信息 */
+ @JsonProperty("product_info")
+ private SimpleProductInfo productInfo;
+
+
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/limit/LimitSku.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/limit/LimitSku.java
new file mode 100644
index 0000000000..29ffbf921e
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/limit/LimitSku.java
@@ -0,0 +1,30 @@
+package me.chanjar.weixin.channel.bean.limit;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class LimitSku implements Serializable {
+
+ private static final long serialVersionUID = -1819737633227427482L;
+
+ /** 参与抢购的商品 ID 下,不同规格(SKU)的商品信息 */
+ @JsonProperty("sku_id")
+ private String skuId;
+
+ /** SKU的抢购价格,必须小于原价(原价为1分钱的商品无法创建抢购任务) */
+ @JsonProperty("sale_price")
+ private Integer salePrice;
+
+ /** 参与抢购的商品库存,必须小于等于现有库存 */
+ @JsonProperty("sale_stock")
+ private Integer saleStock;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/limit/LimitTaskAddResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/limit/LimitTaskAddResponse.java
new file mode 100644
index 0000000000..35ea00d68d
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/limit/LimitTaskAddResponse.java
@@ -0,0 +1,23 @@
+package me.chanjar.weixin.channel.bean.limit;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class LimitTaskAddResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -4742165348862157618L;
+
+ /** 限时抢购任务ID 创建成功后返回 */
+ @JsonProperty("task_id")
+ private String taskId;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/limit/LimitTaskInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/limit/LimitTaskInfo.java
new file mode 100644
index 0000000000..aefc4b8136
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/limit/LimitTaskInfo.java
@@ -0,0 +1,45 @@
+package me.chanjar.weixin.channel.bean.limit;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class LimitTaskInfo implements Serializable {
+
+ private static final long serialVersionUID = 3032226931637189351L;
+
+ /** 限时抢购任务ID */
+ @JsonProperty("task_id")
+ private String taskId;
+
+ /** 抢购商品ID */
+ @JsonProperty("product_id")
+ private String productId;
+
+ /** 限时抢购任务状态 */
+ @JsonProperty("status")
+ private Integer status;
+
+ /** 限时抢购任务创建时间(秒级时间戳) */
+ @JsonProperty("create_time")
+ private Long createTime;
+
+ /** 限时抢购任务开始时间(秒级时间戳) */
+ @JsonProperty("start_time")
+ private Long startTime;
+
+ /** 限时抢购任务结束时间(秒级时间戳) */
+ @JsonProperty("end_time")
+ private Long endTime;
+
+ /** sku列表 */
+ @JsonProperty("limited_discount_skus")
+ private List skus;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/limit/LimitTaskListParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/limit/LimitTaskListParam.java
new file mode 100644
index 0000000000..d608c8231e
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/limit/LimitTaskListParam.java
@@ -0,0 +1,28 @@
+package me.chanjar.weixin.channel.bean.limit;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import me.chanjar.weixin.channel.bean.base.StreamPageParam;
+
+/**
+ * @author Zeyes
+ */
+@Data
+public class LimitTaskListParam extends StreamPageParam {
+
+ private static final long serialVersionUID = -7227161890365102302L;
+
+
+ /** 抢购活动状态 */
+ @JsonProperty("status")
+ private Integer status;
+
+ public LimitTaskListParam() {
+ }
+
+ public LimitTaskListParam(Integer pageSize, String nextKey, Integer status) {
+ this.pageSize = pageSize;
+ this.nextKey = nextKey;
+ this.status = status;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/limit/LimitTaskListResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/limit/LimitTaskListResponse.java
new file mode 100644
index 0000000000..688fd158dc
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/limit/LimitTaskListResponse.java
@@ -0,0 +1,32 @@
+package me.chanjar.weixin.channel.bean.limit;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class LimitTaskListResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 3604657299385130217L;
+
+
+ /** 限时抢购任务 */
+ @JsonProperty("limited_discount_tasks")
+ private List tasks;
+
+ /** 本次翻页的上下文,用于请求下一页 */
+ @JsonProperty("next_key")
+ private String nextKey;
+
+ /** 商品总数 */
+ @JsonProperty("total_num")
+ private Integer totalNum;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/limit/LimitTaskParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/limit/LimitTaskParam.java
new file mode 100644
index 0000000000..b89c072944
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/limit/LimitTaskParam.java
@@ -0,0 +1,36 @@
+package me.chanjar.weixin.channel.bean.limit;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class LimitTaskParam implements Serializable {
+
+ private static final long serialVersionUID = 3885409806249022528L;
+
+ /** 抢购商品ID */
+ @JsonProperty("product_id")
+ private String productId;
+
+ /** 限时抢购任务开始时间(秒级时间戳) */
+ @JsonProperty("start_time")
+ private Date startTime;
+
+ /** 限时抢购任务结束时间(秒级时间戳) */
+ @JsonProperty("end_time")
+ private Date endTime;
+
+ /** sku列表 */
+ @JsonProperty("limited_discount_skus")
+ private List skus;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/SessionMessage.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/SessionMessage.java
new file mode 100644
index 0000000000..9b97cbf09d
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/SessionMessage.java
@@ -0,0 +1,27 @@
+package me.chanjar.weixin.channel.bean.message;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.message.WxChannelMessage;
+
+/**
+ * 会话消息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@JacksonXmlRootElement(localName = "xml")
+public class SessionMessage extends WxChannelMessage {
+
+ private static final long serialVersionUID = -429381568555605309L;
+
+ @JsonProperty("SessionFrom")
+ @JacksonXmlProperty(localName = "SessionFrom")
+ private String from;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/after/AfterSaleMessage.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/after/AfterSaleMessage.java
new file mode 100644
index 0000000000..52beec7932
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/after/AfterSaleMessage.java
@@ -0,0 +1,27 @@
+package me.chanjar.weixin.channel.bean.message.after;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.message.WxChannelMessage;
+
+/**
+ * 售后消息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@JacksonXmlRootElement(localName = "xml")
+public class AfterSaleMessage extends WxChannelMessage {
+
+ private static final long serialVersionUID = -7263404451639198126L;
+ /** 状态信息 */
+ @JsonProperty("finder_shop_aftersale_status_update")
+ @JacksonXmlProperty(localName = "finder_shop_aftersale_status_update")
+ private AfterSaleStatusInfo info;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/after/AfterSaleStatusInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/after/AfterSaleStatusInfo.java
new file mode 100644
index 0000000000..06fd349da8
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/after/AfterSaleStatusInfo.java
@@ -0,0 +1,33 @@
+package me.chanjar.weixin.channel.bean.message.after;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 售后信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class AfterSaleStatusInfo implements Serializable {
+
+ private static final long serialVersionUID = -7309656340583314591L;
+ /** 售后单号 */
+ @JsonProperty("after_sale_order_id")
+ @JacksonXmlProperty(localName = "after_sale_order_id")
+ private String afterSaleOrderId;
+
+ /** 售后单状态 */
+ @JsonProperty("status")
+ @JacksonXmlProperty(localName = "status")
+ private String status;
+
+ /** 订单id */
+ @JsonProperty("order_id")
+ @JacksonXmlProperty(localName = "order_id")
+ private String orderId;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/after/ComplaintInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/after/ComplaintInfo.java
new file mode 100644
index 0000000000..adb0b7b392
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/after/ComplaintInfo.java
@@ -0,0 +1,33 @@
+package me.chanjar.weixin.channel.bean.message.after;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 纠纷信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class ComplaintInfo implements Serializable {
+
+ private static final long serialVersionUID = 3988395560953978239L;
+ /** 纠纷单号 */
+ @JsonProperty("complaint_id")
+ @JacksonXmlProperty(localName = "complaint_id")
+ private String complaintId;
+
+ /** 小店售后单号 */
+ @JsonProperty("after_sale_order_id")
+ @JacksonXmlProperty(localName = "after_sale_order_id")
+ private String afterSaleOrderId;
+
+ /** 纠纷单状态 */
+ @JsonProperty("status")
+ @JacksonXmlProperty(localName = "status")
+ private Integer status;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/after/ComplaintMessage.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/after/ComplaintMessage.java
new file mode 100644
index 0000000000..e10a9b365a
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/after/ComplaintMessage.java
@@ -0,0 +1,28 @@
+package me.chanjar.weixin.channel.bean.message.after;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.message.WxChannelMessage;
+
+/**
+ * 纠纷消息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@JacksonXmlRootElement(localName = "xml")
+public class ComplaintMessage extends WxChannelMessage {
+
+ private static final long serialVersionUID = 5358093415172409157L;
+ /** 状态信息 */
+ @JsonProperty("finder_shop_complaint")
+ @JacksonXmlProperty(localName = "finder_shop_complaint")
+ private ComplaintInfo info;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/coupon/CouponActionInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/coupon/CouponActionInfo.java
new file mode 100644
index 0000000000..f7a55ce0fb
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/coupon/CouponActionInfo.java
@@ -0,0 +1,48 @@
+package me.chanjar.weixin.channel.bean.message.coupon;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 优惠券操作消息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class CouponActionInfo implements Serializable {
+
+ private static final long serialVersionUID = -4456716511656569552L;
+ /** 优惠券ID */
+ @JsonProperty("coupon_id")
+ @JacksonXmlProperty(localName = "coupon_id")
+ private String couponId;
+
+ /** 领券时间 */
+ @JsonProperty("create_time")
+ @JacksonXmlProperty(localName = "create_time")
+ private String createTime;
+
+ /** 删除时间 */
+ @JsonProperty("delete_time")
+ @JacksonXmlProperty(localName = "delete_time")
+ private String deleteTime;
+
+ /** 过期时间 */
+ @JsonProperty("expire_time")
+ @JacksonXmlProperty(localName = "expire_time")
+ private String expireTime;
+
+ /** 更新时间 */
+ @JsonProperty("change_time")
+ @JacksonXmlProperty(localName = "change_time")
+ private String changeTime;
+
+ /** 作废时间 */
+ @JsonProperty("invalid_time")
+ @JacksonXmlProperty(localName = "invalid_time")
+ private String invalidTime;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/coupon/CouponActionMessage.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/coupon/CouponActionMessage.java
new file mode 100644
index 0000000000..7433b7a6c2
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/coupon/CouponActionMessage.java
@@ -0,0 +1,29 @@
+package me.chanjar.weixin.channel.bean.message.coupon;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.message.WxChannelMessage;
+
+
+/**
+ * 卡券操作 消息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@JacksonXmlRootElement(localName = "xml")
+public class CouponActionMessage extends WxChannelMessage {
+
+ private static final long serialVersionUID = 4910461800721504462L;
+ /** 优惠券信息 */
+ @JsonProperty("coupon_info")
+ @JacksonXmlProperty(localName = "coupon_info")
+ private CouponActionInfo couponInfo;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/coupon/CouponReceiveMessage.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/coupon/CouponReceiveMessage.java
new file mode 100644
index 0000000000..448d815a58
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/coupon/CouponReceiveMessage.java
@@ -0,0 +1,60 @@
+package me.chanjar.weixin.channel.bean.message.coupon;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import java.util.Map;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.message.WxChannelMessage;
+
+
+/**
+ * 用户领券 消息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@JacksonXmlRootElement(localName = "xml")
+public class CouponReceiveMessage extends WxChannelMessage {
+
+ private static final long serialVersionUID = 5121347165246528730L;
+ /** 领取的优惠券ID */
+ @JsonProperty("coupon_id")
+ @JacksonXmlProperty(localName = "coupon_id")
+ private String couponId;
+
+ /** 生成的用户券ID */
+ @JsonProperty("user_coupon_id")
+ @JacksonXmlProperty(localName = "user_coupon_id")
+ private String userCouponId;
+
+ /** 领券时间 */
+ @JsonProperty("receive_time")
+ @JacksonXmlProperty(localName = "receive_time")
+ private String receiveTime;
+
+ @JsonProperty("receive_info")
+ @JacksonXmlProperty(localName = "receive_info")
+ private void unpackNameFromNestedObject(Map map) {
+ if (map == null) {
+ return;
+ }
+ Object obj = null;
+ obj = map.get("coupon_id");
+ if (obj != null) {
+ this.couponId = (obj instanceof String ? (String) obj : String.valueOf(obj));
+ }
+ obj = map.get("user_coupon_id");
+ if (obj != null) {
+ this.userCouponId = (obj instanceof String ? (String) obj : String.valueOf(obj));
+ }
+ obj = map.get("receive_time");
+ if (obj != null) {
+ this.receiveTime = (obj instanceof String ? (String) obj : String.valueOf(obj));
+ }
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/coupon/UserCouponActionInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/coupon/UserCouponActionInfo.java
new file mode 100644
index 0000000000..1356c47fca
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/coupon/UserCouponActionInfo.java
@@ -0,0 +1,45 @@
+package me.chanjar.weixin.channel.bean.message.coupon;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 用户优惠券操作消息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class UserCouponActionInfo implements Serializable {
+
+ private static final long serialVersionUID = -5948836918972669529L;
+ /** 优惠券ID */
+ @JsonProperty("coupon_id")
+ @JacksonXmlProperty(localName = "coupon_id")
+ private String couponId;
+
+ /** 用户券ID */
+ @JsonProperty("user_coupon_id")
+ @JacksonXmlProperty(localName = "user_coupon_id")
+ private String userCouponId;
+
+ /** 过期时间 */
+ @JsonProperty("expire_time")
+ @JacksonXmlProperty(localName = "expire_time")
+ private String expireTime;
+
+ /** 使用时间 */
+ @JsonProperty("use_time")
+ @JacksonXmlProperty(localName = "use_time")
+ private String useTime;
+
+ /** 返还时间 */
+ @JsonProperty("unuse_time")
+ @JacksonXmlProperty(localName = "unuse_time")
+ private String unuseTime;
+
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/coupon/UserCouponExpireMessage.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/coupon/UserCouponExpireMessage.java
new file mode 100644
index 0000000000..26370e5142
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/coupon/UserCouponExpireMessage.java
@@ -0,0 +1,29 @@
+package me.chanjar.weixin.channel.bean.message.coupon;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.message.WxChannelMessage;
+
+
+/**
+ * 用户卡券过期 消息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@JacksonXmlRootElement(localName = "xml")
+public class UserCouponExpireMessage extends WxChannelMessage {
+
+ private static final long serialVersionUID = -2557475297107588372L;
+ /** 用户优惠券信息 */
+ @JsonProperty("user_coupon_info")
+ @JacksonXmlProperty(localName = "user_coupon_info")
+ private UserCouponActionInfo userCouponInfo;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/coupon/UserCouponUseMessage.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/coupon/UserCouponUseMessage.java
new file mode 100644
index 0000000000..7b436743c3
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/coupon/UserCouponUseMessage.java
@@ -0,0 +1,28 @@
+package me.chanjar.weixin.channel.bean.message.coupon;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.message.WxChannelMessage;
+
+
+/**
+ * 用户卡券使用 消息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@JacksonXmlRootElement(localName = "xml")
+public class UserCouponUseMessage extends WxChannelMessage {
+
+ private static final long serialVersionUID = -1051142666438578628L;
+ /** 用户优惠券信息 */
+ @JsonProperty("user_info")
+ @JacksonXmlProperty(localName = "user_info")
+ private UserCouponActionInfo userCouponInfo;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/fund/AccountNotifyMessage.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/fund/AccountNotifyMessage.java
new file mode 100644
index 0000000000..b5a02ac834
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/fund/AccountNotifyMessage.java
@@ -0,0 +1,27 @@
+package me.chanjar.weixin.channel.bean.message.fund;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.message.WxChannelMessage;
+
+/**
+ * 账户变更通知 消息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@JacksonXmlRootElement(localName = "xml")
+public class AccountNotifyMessage extends WxChannelMessage {
+
+ private static final long serialVersionUID = 3846692537729725664L;
+ /** 账户信息 */
+ @JsonProperty("account_info")
+ @JacksonXmlProperty(localName = "account_info")
+ private BankNotifyInfo accountInfo;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/fund/BankNotifyInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/fund/BankNotifyInfo.java
new file mode 100644
index 0000000000..44ef398f8b
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/fund/BankNotifyInfo.java
@@ -0,0 +1,24 @@
+package me.chanjar.weixin.channel.bean.message.fund;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 账户信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class BankNotifyInfo implements Serializable {
+
+ private static final long serialVersionUID = 4192569196686180014L;
+ /** 结算账户变更事件, 1.修改结算账户 */
+ @JsonProperty("event")
+ @JacksonXmlProperty(localName = "event")
+ private Integer event;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/fund/QrNotifyInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/fund/QrNotifyInfo.java
new file mode 100644
index 0000000000..83b466f07e
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/fund/QrNotifyInfo.java
@@ -0,0 +1,34 @@
+package me.chanjar.weixin.channel.bean.message.fund;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 提现二维码回调 消息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class QrNotifyInfo implements Serializable {
+
+ private static final long serialVersionUID = 2470016408300157273L;
+ /** 二维码ticket */
+ @JsonProperty("ticket")
+ @JacksonXmlProperty(localName = "ticket")
+ private String ticket;
+
+ /** 二维码状态,1.已确认 2.已取消 3.已失效 4.已扫码 */
+ @JsonProperty("status")
+ @JacksonXmlProperty(localName = "status")
+ private Integer status;
+
+ /** 扫码者身份, 0.非管理员 1.管理员 */
+ @JsonProperty("scan_user_type")
+ @JacksonXmlProperty(localName = "scan_user_type")
+ private Integer scanUserType;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/fund/QrNotifyMessage.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/fund/QrNotifyMessage.java
new file mode 100644
index 0000000000..56e906a641
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/fund/QrNotifyMessage.java
@@ -0,0 +1,27 @@
+package me.chanjar.weixin.channel.bean.message.fund;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.message.WxChannelMessage;
+
+/**
+ * 提现二维码回调 消息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@JacksonXmlRootElement(localName = "xml")
+public class QrNotifyMessage extends WxChannelMessage {
+
+ private static final long serialVersionUID = -4705790895359679423L;
+ /** 账户信息 */
+ @JsonProperty("qrcode_info")
+ @JacksonXmlProperty(localName = "qrcode_info")
+ private QrNotifyInfo qrcodeInfo;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/fund/WithdrawNotifyInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/fund/WithdrawNotifyInfo.java
new file mode 100644
index 0000000000..810f40c95c
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/fund/WithdrawNotifyInfo.java
@@ -0,0 +1,29 @@
+package me.chanjar.weixin.channel.bean.message.fund;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 提现通知信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class WithdrawNotifyInfo implements Serializable {
+
+ private static final long serialVersionUID = 2987401114254821956L;
+ /** 1.发起提现,生成二维码 2.扫码验证成功,申请提现 3.提现成功 4.提现失败 */
+ @JsonProperty("event")
+ @JacksonXmlProperty(localName = "event")
+ private Integer event;
+
+ /** 提现单号 */
+ @JsonProperty("withdraw_id")
+ @JacksonXmlProperty(localName = "withdraw_id")
+ private String withdrawId;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/fund/WithdrawNotifyMessage.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/fund/WithdrawNotifyMessage.java
new file mode 100644
index 0000000000..ff45e73ec6
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/fund/WithdrawNotifyMessage.java
@@ -0,0 +1,27 @@
+package me.chanjar.weixin.channel.bean.message.fund;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.message.WxChannelMessage;
+
+/**
+ * 账户变更通知 消息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@JacksonXmlRootElement(localName = "xml")
+public class WithdrawNotifyMessage extends WxChannelMessage {
+
+ private static final long serialVersionUID = -2504086242143523430L;
+ /** 账户信息 */
+ @JsonProperty("withdraw_info")
+ @JacksonXmlProperty(localName = "withdraw_info")
+ private WithdrawNotifyInfo withdrawInfo;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderCancelInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderCancelInfo.java
new file mode 100644
index 0000000000..8ff3ead54e
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderCancelInfo.java
@@ -0,0 +1,24 @@
+package me.chanjar.weixin.channel.bean.message.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+/**
+ * 订单取消信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class OrderCancelInfo extends OrderIdInfo {
+
+ private static final long serialVersionUID = -8022876997578127873L;
+ /** 1:用户取消;2:超时取消;3:全部商品售后完成,订单取消;4:超卖商家取消订单 */
+ @JsonProperty("cancel_type")
+ @JacksonXmlProperty(localName = "cancel_type")
+ private Integer cancelType;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderCancelMessage.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderCancelMessage.java
new file mode 100644
index 0000000000..8e6b33c2ee
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderCancelMessage.java
@@ -0,0 +1,27 @@
+package me.chanjar.weixin.channel.bean.message.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.message.WxChannelMessage;
+
+/**
+ * 订单取消消息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@JacksonXmlRootElement(localName = "xml")
+public class OrderCancelMessage extends WxChannelMessage {
+
+ private static final long serialVersionUID = 5389546516473919310L;
+ /** 订单信息 */
+ @JsonProperty("order_info")
+ @JacksonXmlProperty(localName = "order_info")
+ private OrderCancelInfo orderInfo;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderConfirmInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderConfirmInfo.java
new file mode 100644
index 0000000000..bd212092a5
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderConfirmInfo.java
@@ -0,0 +1,24 @@
+package me.chanjar.weixin.channel.bean.message.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+/**
+ * 订单确认收货信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class OrderConfirmInfo extends OrderIdInfo {
+
+ private static final long serialVersionUID = -2569494642832261346L;
+ /** 1:用户确认收货;2:超时自动确认收货 */
+ @JsonProperty("confirm_type")
+ @JacksonXmlProperty(localName = "confirm_type")
+ private Integer confirmType;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderConfirmMessage.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderConfirmMessage.java
new file mode 100644
index 0000000000..dda35041b2
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderConfirmMessage.java
@@ -0,0 +1,27 @@
+package me.chanjar.weixin.channel.bean.message.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.message.WxChannelMessage;
+
+/**
+ * 订单确认收货消息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@JacksonXmlRootElement(localName = "xml")
+public class OrderConfirmMessage extends WxChannelMessage {
+
+ private static final long serialVersionUID = 4219477394934480425L;
+ /** 订单信息 */
+ @JsonProperty("order_info")
+ @JacksonXmlProperty(localName = "order_info")
+ private OrderConfirmInfo orderInfo;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderDeliveryInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderDeliveryInfo.java
new file mode 100644
index 0000000000..ca3d26736a
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderDeliveryInfo.java
@@ -0,0 +1,25 @@
+package me.chanjar.weixin.channel.bean.message.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+/**
+ * 订单发货信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class OrderDeliveryInfo extends OrderIdInfo {
+
+ private static final long serialVersionUID = 117962754344887556L;
+ /** 0:尚未全部发货;1:全部商品发货完成 */
+ @JsonProperty("finish_delivery")
+ @JacksonXmlProperty(localName = "finish_delivery")
+ private Integer finishDelivery;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderDeliveryMessage.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderDeliveryMessage.java
new file mode 100644
index 0000000000..25d79e2c4d
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderDeliveryMessage.java
@@ -0,0 +1,27 @@
+package me.chanjar.weixin.channel.bean.message.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.message.WxChannelMessage;
+
+/**
+ * 订单发货消息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@JacksonXmlRootElement(localName = "xml")
+public class OrderDeliveryMessage extends WxChannelMessage {
+
+ private static final long serialVersionUID = -1440834047566984402L;
+ /** 订单信息 */
+ @JsonProperty("order_info")
+ @JacksonXmlProperty(localName = "order_info")
+ private OrderDeliveryInfo orderInfo;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderExtInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderExtInfo.java
new file mode 100644
index 0000000000..b4986f35c4
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderExtInfo.java
@@ -0,0 +1,24 @@
+package me.chanjar.weixin.channel.bean.message.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+/**
+ * 订单其他信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class OrderExtInfo extends OrderIdInfo {
+
+ private static final long serialVersionUID = 4723533858047219828L;
+ /** 类型 1:联盟佣金信息 */
+ @JsonProperty("type")
+ @JacksonXmlProperty(localName = "type")
+ private Integer type;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderExtMessage.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderExtMessage.java
new file mode 100644
index 0000000000..c5ede6c6bd
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderExtMessage.java
@@ -0,0 +1,27 @@
+package me.chanjar.weixin.channel.bean.message.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.message.WxChannelMessage;
+
+/**
+ * 订单状态消息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@JacksonXmlRootElement(localName = "xml")
+public class OrderExtMessage extends WxChannelMessage {
+
+ private static final long serialVersionUID = -3183077256476798756L;
+ /** 订单信息 */
+ @JsonProperty("order_info")
+ @JacksonXmlProperty(localName = "order_info")
+ private OrderExtInfo orderInfo;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderIdInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderIdInfo.java
new file mode 100644
index 0000000000..b9ac33b376
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderIdInfo.java
@@ -0,0 +1,23 @@
+package me.chanjar.weixin.channel.bean.message.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 订单id信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class OrderIdInfo implements Serializable {
+
+ private static final long serialVersionUID = 5547544436235032051L;
+ /** 订单ID */
+ @JsonProperty("order_id")
+ @JacksonXmlProperty(localName = "order_id")
+ private String orderId;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderIdMessage.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderIdMessage.java
new file mode 100644
index 0000000000..398c29bde4
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderIdMessage.java
@@ -0,0 +1,27 @@
+package me.chanjar.weixin.channel.bean.message.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.message.WxChannelMessage;
+
+/**
+ * 订单id消息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@JacksonXmlRootElement(localName = "xml")
+public class OrderIdMessage extends WxChannelMessage {
+
+ private static final long serialVersionUID = 3793987364799712798L;
+ /** 订单信息 */
+ @JsonProperty("order_info")
+ @JacksonXmlProperty(localName = "order_info")
+ private OrderIdInfo orderInfo;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderPayInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderPayInfo.java
new file mode 100644
index 0000000000..d916c14a21
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderPayInfo.java
@@ -0,0 +1,24 @@
+package me.chanjar.weixin.channel.bean.message.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+/**
+ * 订单支付信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class OrderPayInfo extends OrderIdInfo {
+
+ private static final long serialVersionUID = -3502786073769735831L;
+ /** 支付时间,秒级时间戳 */
+ @JsonProperty("pay_time")
+ @JacksonXmlProperty(localName = "pay_time")
+ private Long payTime;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderPayMessage.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderPayMessage.java
new file mode 100644
index 0000000000..ee1f458aba
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderPayMessage.java
@@ -0,0 +1,27 @@
+package me.chanjar.weixin.channel.bean.message.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.message.WxChannelMessage;
+
+/**
+ * 订单支付成功消息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@JacksonXmlRootElement(localName = "xml")
+public class OrderPayMessage extends WxChannelMessage {
+
+ private static final long serialVersionUID = 1083018549119427808L;
+ /** 订单信息 */
+ @JsonProperty("order_info")
+ @JacksonXmlProperty(localName = "order_info")
+ private OrderPayInfo orderInfo;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderSettleInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderSettleInfo.java
new file mode 100644
index 0000000000..b4f48b6fb8
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderSettleInfo.java
@@ -0,0 +1,24 @@
+package me.chanjar.weixin.channel.bean.message.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+/**
+ * 订单结算信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class OrderSettleInfo extends OrderIdInfo {
+
+ private static final long serialVersionUID = -1817955568383872053L;
+ /** 结算时间 */
+ @JsonProperty("settle_time")
+ @JacksonXmlProperty(localName = "settle_time")
+ private Long settleTime;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderSettleMessage.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderSettleMessage.java
new file mode 100644
index 0000000000..2d3d1d96d6
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderSettleMessage.java
@@ -0,0 +1,27 @@
+package me.chanjar.weixin.channel.bean.message.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.message.WxChannelMessage;
+
+/**
+ * 订单结算消息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@JacksonXmlRootElement(localName = "xml")
+public class OrderSettleMessage extends WxChannelMessage {
+
+ private static final long serialVersionUID = -4001189226630840548L;
+ /** 订单信息 */
+ @JsonProperty("order_info")
+ @JacksonXmlProperty(localName = "order_info")
+ private OrderSettleInfo orderInfo;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderStatusMessage.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderStatusMessage.java
new file mode 100644
index 0000000000..4a06ccc99c
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/order/OrderStatusMessage.java
@@ -0,0 +1,54 @@
+package me.chanjar.weixin.channel.bean.message.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import java.util.Map;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.message.WxChannelMessage;
+
+/**
+ * 订单状态消息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@JacksonXmlRootElement(localName = "xml")
+public class OrderStatusMessage extends WxChannelMessage {
+
+ private static final long serialVersionUID = -356717038344749283L;
+ /** 订单ID */
+ @JsonProperty("order_id")
+ @JacksonXmlProperty(localName = "order_id")
+ private String orderId;
+
+ /** 订单状态 {@link me.chanjar.weixin.channel.enums.WxOrderStatus} */
+ @JsonProperty("status")
+ @JacksonXmlProperty(localName = "status")
+ private Integer status;
+
+ @JsonProperty("ProductOrderStatusUpdate")
+ @JacksonXmlProperty(localName = "ProductOrderStatusUpdate")
+ private void unpackNameFromNestedObject(Map map) {
+ if (map == null) {
+ return;
+ }
+ Object obj = null;
+ obj = map.get("order_id");
+ if (obj != null) {
+ this.orderId = obj.toString();
+ }
+ obj = map.get("status");
+ if (obj != null) {
+ if (obj instanceof Integer) {
+ this.status = (Integer) obj;
+ } else if (obj instanceof String) {
+ this.status = Integer.parseInt((String) obj);
+ }
+ }
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/product/BrandMessage.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/product/BrandMessage.java
new file mode 100644
index 0000000000..9a7c021c9d
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/product/BrandMessage.java
@@ -0,0 +1,72 @@
+package me.chanjar.weixin.channel.bean.message.product;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import java.util.Map;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.message.WxChannelMessage;
+
+/**
+ * 品牌消息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@JacksonXmlRootElement(localName = "xml")
+public class BrandMessage extends WxChannelMessage {
+
+ private static final long serialVersionUID = -3773902704930003105L;
+ /** 品牌库中的品牌编号 */
+ @JsonProperty("brand_id")
+ @JacksonXmlProperty(localName = "brand_id")
+ private String brandId;
+
+ /** 审核id */
+ @JsonProperty("audit_id")
+ @JacksonXmlProperty(localName = "audit_id")
+ private String auditId;
+
+ /** 审核状态, 1新增品牌 2更新品牌 3撤回品牌审核 4审核成功 5审核失败 6删除品牌 7品牌资质被系统撤销 */
+ @JsonProperty("status")
+ @JacksonXmlProperty(localName = "status")
+ private Integer status;
+
+ /** 相关信息 */
+ @JsonProperty("reason")
+ @JacksonXmlProperty(localName = "reason")
+ private String reason;
+
+ @JsonProperty("BrandEvent")
+ @JacksonXmlProperty(localName = "BrandEvent")
+ private void unpackNameFromNestedObject(Map map) {
+ if (map == null) {
+ return;
+ }
+ Object obj = null;
+ obj = map.get("brand_id");
+ if (obj != null) {
+ this.brandId = (obj instanceof String ? (String) obj : String.valueOf(obj));
+ }
+ obj = map.get("audit_id");
+ if (obj != null) {
+ this.auditId = (obj instanceof String ? (String) obj : String.valueOf(obj));
+ }
+ obj = map.get("status");
+ if (obj != null) {
+ if (obj instanceof Integer) {
+ this.status = (Integer) obj;
+ } else if (obj instanceof String) {
+ this.status = Integer.parseInt((String) obj);
+ }
+ }
+ obj = map.get("reason");
+ if (obj != null) {
+ this.reason = (obj instanceof String ? (String) obj : String.valueOf(obj));
+ }
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/product/CategoryAuditMessage.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/product/CategoryAuditMessage.java
new file mode 100644
index 0000000000..f6d696d5c1
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/product/CategoryAuditMessage.java
@@ -0,0 +1,63 @@
+package me.chanjar.weixin.channel.bean.message.product;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import java.util.Map;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.message.WxChannelMessage;
+
+/**
+ * 类目审核消息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@JacksonXmlRootElement(localName = "xml")
+public class CategoryAuditMessage extends WxChannelMessage {
+
+ private static final long serialVersionUID = 3192582751919917223L;
+ /** 审核id */
+ @JsonProperty("audit_id")
+ @JacksonXmlProperty(localName = "audit_id")
+ private String auditId;
+
+ /** 审核状态, 1:审核中, 2:审核拒绝, 3:审核通过, 12:主动取消申请单 */
+ @JsonProperty("status")
+ @JacksonXmlProperty(localName = "status")
+ private Integer status;
+
+ /** 相关信息 */
+ @JsonProperty("reason")
+ @JacksonXmlProperty(localName = "reason")
+ private String reason;
+
+ @JsonProperty("ProductCategoryAudit")
+ @JacksonXmlProperty(localName = "ProductCategoryAudit")
+ private void unpackNameFromNestedObject(Map map) {
+ if (map == null) {
+ return;
+ }
+ Object obj = null;
+ obj = map.get("audit_id");
+ if (obj != null) {
+ this.auditId = (obj instanceof String ? (String) obj : String.valueOf(obj));
+ }
+ obj = map.get("status");
+ if (obj != null) {
+ if (obj instanceof Integer) {
+ this.status = (Integer) obj;
+ } else if (obj instanceof String) {
+ this.status = Integer.parseInt((String) obj);
+ }
+ }
+ obj = map.get("reason");
+ if (obj != null) {
+ this.reason = (obj instanceof String ? (String) obj : String.valueOf(obj));
+ }
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/product/SpuAuditMessage.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/product/SpuAuditMessage.java
new file mode 100644
index 0000000000..569b53781e
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/product/SpuAuditMessage.java
@@ -0,0 +1,83 @@
+package me.chanjar.weixin.channel.bean.message.product;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import java.util.Map;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.message.WxChannelMessage;
+
+/**
+ * SPU审核消息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@JacksonXmlRootElement(localName = "xml")
+public class SpuAuditMessage extends WxChannelMessage {
+
+ private static final long serialVersionUID = 1763291928383078102L;
+ /** 商品id */
+ @JsonProperty("product_id")
+ @JacksonXmlProperty(localName = "product_id")
+ private String productId;
+
+ /**
+ * 审核状态, 2:审核不通过;3:审核通过 商品状态, 5:上架;11:自主下架;13:系统下架
+ */
+ @JsonProperty("status")
+ @JacksonXmlProperty(localName = "status")
+ private Integer status;
+
+ /** 审核/下架原因,非必填字段 */
+ @JsonProperty("reason")
+ @JacksonXmlProperty(localName = "reason")
+ private String reason;
+
+
+
+ @JsonProperty("ProductSpuAudit")
+ @JacksonXmlProperty(localName = "ProductSpuAudit")
+ public void ProductSpuAudit(Map map) {
+ this.unpackNameFromNestedObject(map);
+ }
+
+ @JsonProperty("ProductSpuUpdate")
+ @JacksonXmlProperty(localName = "ProductSpuUpdate")
+ public void ProductSpuUpdate(Map map) {
+ this.unpackNameFromNestedObject(map);
+ }
+
+ @JsonProperty("ProductSpuListing")
+ @JacksonXmlProperty(localName = "ProductSpuListing")
+ public void ProductSpuListing(Map map) {
+ this.unpackNameFromNestedObject(map);
+ }
+
+ private void unpackNameFromNestedObject(Map map) {
+ if (map == null) {
+ return;
+ }
+ Object obj = null;
+ obj = map.get("product_id");
+ if (obj != null) {
+ this.productId = (obj instanceof String ? (String) obj : String.valueOf(obj));
+ }
+ obj = map.get("status");
+ if (obj != null) {
+ if (obj instanceof Integer) {
+ this.status = (Integer) obj;
+ } else if (obj instanceof String) {
+ this.status = Integer.parseInt((String) obj);
+ }
+ }
+ obj = map.get("reason");
+ if (obj != null) {
+ this.reason = (obj instanceof String ? (String) obj : String.valueOf(obj));
+ }
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/product/SpuStatusMessage.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/product/SpuStatusMessage.java
new file mode 100644
index 0000000000..7fb9f272e8
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/product/SpuStatusMessage.java
@@ -0,0 +1,72 @@
+package me.chanjar.weixin.channel.bean.message.product;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import java.util.Map;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.message.WxChannelMessage;
+
+/**
+ * SPU状态消息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@JacksonXmlRootElement(localName = "xml")
+public class SpuStatusMessage extends WxChannelMessage {
+
+ private static final long serialVersionUID = 6872830451279856492L;
+ /** 商家自定义商品id */
+ @JsonProperty("out_product_id")
+ @JacksonXmlProperty(localName = "out_product_id")
+ private String outProductId;
+
+ /** 平台商品id */
+ @JsonProperty("product_id")
+ @JacksonXmlProperty(localName = "product_id")
+ private String productId;
+
+ /** 当前商品上下架状态 参考 {@link me.chanjar.weixin.channel.enums.SpuStatus } */
+ @JsonProperty("status")
+ @JacksonXmlProperty(localName = "status")
+ private Integer status;
+
+ /** 相关信息 */
+ @JsonProperty("reason")
+ @JacksonXmlProperty(localName = "reason")
+ private String reason;
+
+ @JsonProperty("OpenProductSpuStatusUpdate")
+ @JacksonXmlProperty(localName = "OpenProductSpuStatusUpdate")
+ private void unpackNameFromNestedObject(Map map) {
+ if (map == null) {
+ return;
+ }
+ Object obj = null;
+ obj = map.get("out_product_id");
+ if (obj != null) {
+ this.outProductId = (obj instanceof String ? (String) obj : String.valueOf(obj));
+ }
+ obj = map.get("product_id");
+ if (obj != null) {
+ this.productId = (obj instanceof String ? (String) obj : String.valueOf(obj));
+ }
+ obj = map.get("status");
+ if (obj != null) {
+ if (obj instanceof Integer) {
+ this.status = (Integer) obj;
+ } else if (obj instanceof String) {
+ this.status = Integer.parseInt((String) obj);
+ }
+ }
+ obj = map.get("reason");
+ if (obj != null) {
+ this.reason = (obj instanceof String ? (String) obj : String.valueOf(obj));
+ }
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/supplier/SupplierItemInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/supplier/SupplierItemInfo.java
new file mode 100644
index 0000000000..49bbb0548b
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/supplier/SupplierItemInfo.java
@@ -0,0 +1,44 @@
+package me.chanjar.weixin.channel.bean.message.supplier;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 团长商品变更信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class SupplierItemInfo implements Serializable {
+
+ private static final long serialVersionUID = -1971161027976024360L;
+ /** 商品变更类型,1:新增商品;2:更新商品 */
+ @JsonProperty("event_type")
+ @JacksonXmlProperty(localName = "event_type")
+ private Integer eventType;
+
+ /** 团长商品所属小店appid */
+ @JsonProperty("appid")
+ @JacksonXmlProperty(localName = "appid")
+ private String appid;
+
+ /** 商品id */
+ @JsonProperty("product_id")
+ @JacksonXmlProperty(localName = "product_id")
+ private String productId;
+
+ /** 商品版本号 */
+ @JsonProperty("version")
+ @JacksonXmlProperty(localName = "version")
+ private String version;
+
+ /** 商品更新字段,当event_type = 2时有值。commission_ratio、service_ratio、status、active_time分别表示佣金、服务费、商品状态和合作生效时间有变更 */
+ @JsonProperty("update_fields")
+ @JacksonXmlProperty(localName = "update_fields")
+ private List updateFields;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/supplier/SupplierItemMessage.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/supplier/SupplierItemMessage.java
new file mode 100644
index 0000000000..2403aa0c60
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/message/supplier/SupplierItemMessage.java
@@ -0,0 +1,27 @@
+package me.chanjar.weixin.channel.bean.message.supplier;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.message.WxChannelMessage;
+
+/**
+ * 团长商品变更 消息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@JacksonXmlRootElement(localName = "xml")
+public class SupplierItemMessage extends WxChannelMessage {
+
+ private static final long serialVersionUID = -4520611382070764349L;
+ /** 账户信息 */
+ @JsonProperty("item_info")
+ @JacksonXmlProperty(localName = "item_info")
+ private SupplierItemInfo itemInfo;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/AfterSaleDetail.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/AfterSaleDetail.java
new file mode 100644
index 0000000000..5401a588bf
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/AfterSaleDetail.java
@@ -0,0 +1,27 @@
+package me.chanjar.weixin.channel.bean.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 售后信息详情
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class AfterSaleDetail implements Serializable {
+
+ private static final long serialVersionUID = -3786573982841041144L;
+
+ /** 正在售后流程的售后单数 */
+ @JsonProperty("on_aftersale_order_cnt")
+ private Integer onAfterSaleOrderCnt;
+
+ /** 售后单列表 */
+ @JsonProperty("aftersale_order_list")
+ private List afterSaleOrderList;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/AfterSaleOrderInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/AfterSaleOrderInfo.java
new file mode 100644
index 0000000000..118feba35b
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/AfterSaleOrderInfo.java
@@ -0,0 +1,30 @@
+package me.chanjar.weixin.channel.bean.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 售后信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class AfterSaleOrderInfo implements Serializable {
+
+ private static final long serialVersionUID = 3938545222231426455L;
+
+ /** 售后单ID */
+ @JsonProperty("aftersale_order_id")
+ private String afterSaleOrderId;
+
+ public String getAfterSaleOrderId() {
+ return afterSaleOrderId;
+ }
+
+ public void setAfterSaleOrderId(String afterSaleOrderId) {
+ this.afterSaleOrderId = afterSaleOrderId;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/ChangeOrderInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/ChangeOrderInfo.java
new file mode 100644
index 0000000000..f6485085bb
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/ChangeOrderInfo.java
@@ -0,0 +1,31 @@
+package me.chanjar.weixin.channel.bean.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 订单修改信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class ChangeOrderInfo implements Serializable {
+
+ private static final long serialVersionUID = 4932726847720452340L;
+
+ /** 商品id */
+ @JsonProperty("product_id")
+ private String productId;
+
+ /** 商品sku */
+ @JsonProperty("sku_id")
+ private String skuId;
+
+ /** 订单中该商品修改后的总价,以分为单位 */
+ @JsonProperty("change_price")
+ private String changePrice;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/DeliveryProductInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/DeliveryProductInfo.java
new file mode 100644
index 0000000000..5427a49839
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/DeliveryProductInfo.java
@@ -0,0 +1,48 @@
+package me.chanjar.weixin.channel.bean.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.delivery.FreightProductInfo;
+
+/**
+ * 发货物流信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class DeliveryProductInfo implements Serializable {
+
+ private static final long serialVersionUID = -8110532854439612471L;
+ /** 快递单号 */
+ @JsonProperty("waybill_id")
+ private String waybillId;
+
+ /** 快递公司编码 */
+ @JsonProperty("delivery_id")
+ private String deliveryId;
+
+ /** 包裹中商品信息 */
+ @JsonProperty("product_infos")
+ private List productInfos;
+
+ /** 快递公司名称 */
+ @JsonProperty("delivery_name")
+ private String deliveryName;
+
+ /** 发货时间,秒级时间戳 */
+ @JsonProperty("delivery_time")
+ private Long deliveryTime;
+
+ /** 配送方式,枚举值见DeliveryType {@link me.chanjar.weixin.channel.enums.DeliveryType} */
+ @JsonProperty("deliver_type")
+ private Integer deliverType;
+
+ /** 发货地址 */
+ @JsonProperty("delivery_address")
+ private OrderAddressInfo deliveryAddress;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/DeliveryUpdateParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/DeliveryUpdateParam.java
new file mode 100644
index 0000000000..6aca6feed4
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/DeliveryUpdateParam.java
@@ -0,0 +1,51 @@
+package me.chanjar.weixin.channel.bean.order;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.delivery.FreightProductInfo;
+
+/**
+ * 修改物流参数
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class DeliveryUpdateParam implements Serializable {
+
+ /** 订单ID */
+ @JsonProperty("order_id")
+ private String orderId;
+
+ /** 物流公司ID */
+ @JsonProperty("delivery_list")
+ private List deliveryList;
+
+ @Data
+ @NoArgsConstructor
+ @JsonInclude(JsonInclude.Include.NON_NULL)
+ public static class DeliveryInfo implements Serializable {
+
+ private static final long serialVersionUID = 1348000697768633889L;
+ /** 快递单号 */
+ @JsonProperty("waybill_id")
+ private String waybillId;
+
+ /** 快递公司编码 */
+ @JsonProperty("delivery_id")
+ private String deliveryId;
+
+ /** 配送方式,枚举值见DeliveryType {@link me.chanjar.weixin.channel.enums.DeliveryType} */
+ @JsonProperty("deliver_type")
+ private Integer deliverType;
+
+ /** 包裹中商品信息 */
+ @JsonProperty("product_infos")
+ private List productInfos;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderAddressInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderAddressInfo.java
new file mode 100644
index 0000000000..ff3e1ba332
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderAddressInfo.java
@@ -0,0 +1,23 @@
+package me.chanjar.weixin.channel.bean.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.AddressInfo;
+
+/**
+ * 地址信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class OrderAddressInfo extends AddressInfo {
+
+ private static final long serialVersionUID = 3062707865189774795L;
+ /** 虚拟发货订单联系方式(deliver_method=1时返回) */
+ @JsonProperty("virtual_order_tel_number")
+ private String virtualOrderTelNumber;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderAddressParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderAddressParam.java
new file mode 100644
index 0000000000..55eb6a8655
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderAddressParam.java
@@ -0,0 +1,32 @@
+package me.chanjar.weixin.channel.bean.order;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.AddressInfo;
+
+/**
+ * 订单地址参数
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonInclude(Include.NON_NULL)
+public class OrderAddressParam implements Serializable {
+
+ private static final long serialVersionUID = 2277618297276466650L;
+
+ /** 订单id */
+ @JsonProperty("order_id")
+ private String orderId;
+
+ /** 地址信息 */
+ @JsonProperty("user_address")
+ private AddressInfo userAddress;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderCommissionInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderCommissionInfo.java
new file mode 100644
index 0000000000..78e391e774
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderCommissionInfo.java
@@ -0,0 +1,45 @@
+package me.chanjar.weixin.channel.bean.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 分佣信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class OrderCommissionInfo implements Serializable {
+
+ private static final long serialVersionUID = -3046852309683467272L;
+ /** 商品skuid */
+ @JsonProperty("sku_id")
+ private String skuId;
+
+ /** 分账方昵称 */
+ @JsonProperty("nickname")
+ private String nickname;
+
+ /** 分账方类型,0:达人,1:团长 */
+ @JsonProperty("type")
+ private Integer type;
+
+ /** 分账状态, 1:未结算,2:已结算 */
+ @JsonProperty("status")
+ private Integer status;
+
+ /** 分账金额 */
+ @JsonProperty("amount")
+ private Integer amount;
+
+ /** 达人视频号id */
+ @JsonProperty("finder_id")
+ private String finderId;
+
+ /** 达人openfinderid */
+ @JsonProperty("openfinderid")
+ private String openFinderId;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderCouponInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderCouponInfo.java
new file mode 100644
index 0000000000..a8f020c0ef
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderCouponInfo.java
@@ -0,0 +1,21 @@
+package me.chanjar.weixin.channel.bean.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 卡券信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class OrderCouponInfo implements Serializable {
+
+ private static final long serialVersionUID = -2033350505767196339L;
+ /** 用户优惠券id */
+ @JsonProperty("user_coupon_id")
+ private String userCouponId;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderDeliveryInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderDeliveryInfo.java
new file mode 100644
index 0000000000..9f3d72feac
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderDeliveryInfo.java
@@ -0,0 +1,47 @@
+package me.chanjar.weixin.channel.bean.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 物流信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class OrderDeliveryInfo implements Serializable {
+
+ private static final long serialVersionUID = -5348922760017557397L;
+ /** 地址信息 */
+ @JsonProperty("address_info")
+ private OrderAddressInfo addressInfo;
+
+ /** 发货物流信息 */
+ @JsonProperty("delivery_product_info")
+ private List deliveryProductInfos;
+
+ /** 发货完成时间,秒级时间戳 */
+ @JsonProperty("ship_done_time")
+ private Long shipDoneTime;
+
+ /** 订单发货方式,0普通物流 1虚拟发货,由商品的同名字段决定 */
+ @JsonProperty("deliver_method")
+ private Integer deliverMethod;
+
+ /** 用户下单后申请修改收货地址,商家同意后该字段会覆盖订单地址信息 */
+ @JsonProperty("address_under_review")
+ private OrderAddressInfo addressUnderReview;
+
+ /** 修改地址申请时间,秒级时间戳 */
+ @JsonProperty("address_apply_time")
+ private Long addressApplyTime;
+
+ /** 电子面单代发时的订单密文 */
+ @JsonProperty("ewaybill_order_code")
+ private String ewaybillOrderCode;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderDetailInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderDetailInfo.java
new file mode 100644
index 0000000000..8a17140cc1
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderDetailInfo.java
@@ -0,0 +1,59 @@
+package me.chanjar.weixin.channel.bean.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 订单详细数据
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class OrderDetailInfo implements Serializable {
+
+ private static final long serialVersionUID = 3916307299998005676L;
+ /** 商品列表 */
+ @JsonProperty("product_infos")
+ private List productInfos;
+
+ /** 支付信息 */
+ @JsonProperty("pay_info")
+ private OrderPayInfo payInfo;
+
+ /** 价格信息 */
+ @JsonProperty("price_info")
+ private OrderPriceInfo priceInfo;
+
+ /** 配送信息 */
+ @JsonProperty("delivery_info")
+ private OrderDeliveryInfo deliveryInfo;
+
+ /** 优惠券信息 */
+ @JsonProperty("coupon_info")
+ private OrderCouponInfo couponInfo;
+
+ /** 额外信息 */
+ @JsonProperty("ext_info")
+ private OrderExtInfo extInfo;
+
+ /** 分佣信息 */
+ @JsonProperty("commission_infos")
+ private List commissionInfos;
+
+ /** 分享信息 */
+ @JsonProperty("sharer_info")
+ private OrderSharerInfo sharerInfo;
+
+ /** 结算信息 */
+ @JsonProperty("settle_info")
+ private OrderSettleInfo settleInfo;
+
+ /** 分享员信息 */
+ @JsonProperty("sku_sharer_infos")
+ private List skuSharerInfos;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderExtInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderExtInfo.java
new file mode 100644
index 0000000000..3338d1a428
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderExtInfo.java
@@ -0,0 +1,26 @@
+package me.chanjar.weixin.channel.bean.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 订单备注信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class OrderExtInfo implements Serializable {
+
+ private static final long serialVersionUID = 4568097877621455429L;
+ /** 用户备注 */
+ @JsonProperty("customer_notes")
+ private String customerNotes;
+
+ /** 商家备注 */
+ @JsonProperty("merchant_notes")
+ private String merchantNotes;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderIdParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderIdParam.java
new file mode 100644
index 0000000000..f1e92e1339
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderIdParam.java
@@ -0,0 +1,27 @@
+package me.chanjar.weixin.channel.bean.order;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 订单id参数
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonInclude(Include.NON_NULL)
+public class OrderIdParam implements Serializable {
+
+ private static final long serialVersionUID = -8616582197963359789L;
+ /** 订单ID */
+ @JsonProperty("order_id")
+ private String orderId;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderInfo.java
new file mode 100644
index 0000000000..894b36f7af
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderInfo.java
@@ -0,0 +1,50 @@
+package me.chanjar.weixin.channel.bean.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 视频号小店订单
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class OrderInfo implements Serializable {
+
+ private static final long serialVersionUID = -4562618835611282016L;
+ /** 订单号 */
+ @JsonProperty("order_id")
+ protected String orderId;
+
+ /** 订单状态,枚举值见 {@link me.chanjar.weixin.channel.enums.WxOrderStatus} */
+ @JsonProperty("status")
+ protected Integer status;
+
+ /** 买家身份标识 */
+ @JsonProperty("openid")
+ protected String openid;
+
+ /** union id */
+ @JsonProperty("unionid")
+ protected String unionid;
+
+ /** 订单详细数据信息 */
+ @JsonProperty("order_detail")
+ protected OrderDetailInfo orderDetail;
+
+ /** 售后信息 */
+ @JsonProperty("aftersale_detail")
+ protected AfterSaleDetail afterSaleDetail;
+
+ /** 创建时间 秒级时间戳 */
+ @JsonProperty("create_time")
+ protected Integer createTime;
+
+ /** 更新时间 秒级时间戳 */
+ @JsonProperty("update_time")
+ protected Integer updateTime;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderInfoResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderInfoResponse.java
new file mode 100644
index 0000000000..0b6fd53c17
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderInfoResponse.java
@@ -0,0 +1,23 @@
+package me.chanjar.weixin.channel.bean.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 订单信息响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class OrderInfoResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 935829924760021624L;
+ /** 订单信息 */
+ @JsonProperty("order")
+ private OrderInfo order;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderListParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderListParam.java
new file mode 100644
index 0000000000..a84da3d2e8
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderListParam.java
@@ -0,0 +1,39 @@
+package me.chanjar.weixin.channel.bean.order;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.StreamPageParam;
+import me.chanjar.weixin.channel.bean.base.TimeRange;
+
+/**
+ * 获取订单列表参数
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@JsonInclude(Include.NON_NULL)
+public class OrderListParam extends StreamPageParam {
+
+ private static final long serialVersionUID = 3780097459964746890L;
+ /** 订单创建时间范围 */
+ @JsonProperty("create_time_range")
+ private TimeRange createTimeRange;
+
+ /** 订单更新时间范围 */
+ @JsonProperty("update_time_range")
+ private TimeRange updateTimeRange;
+
+ /** 订单状态,枚举值见 {@link me.chanjar.weixin.channel.enums.WxOrderStatus} */
+ @JsonProperty("status")
+ private Integer status;
+
+ /** 买家身份标识 */
+ @JsonProperty("openid")
+ private Integer openid;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderListResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderListResponse.java
new file mode 100644
index 0000000000..454abc59d9
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderListResponse.java
@@ -0,0 +1,32 @@
+package me.chanjar.weixin.channel.bean.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 订单列表 响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class OrderListResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -6198624448684807852L;
+ /** 订单id列表 */
+ @JsonProperty("order_id_list")
+ private List ids;
+
+ /** 分页参数,下一页请求回传 */
+ @JsonProperty("next_key")
+ private String nextKey;
+
+ /** 是否还有下一页,true:有下一页;false:已经结束,没有下一页。 */
+ @JsonProperty("has_more")
+ private Boolean hasMore;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderPayInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderPayInfo.java
new file mode 100644
index 0000000000..6c912f7c45
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderPayInfo.java
@@ -0,0 +1,34 @@
+package me.chanjar.weixin.channel.bean.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 支付信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class OrderPayInfo implements Serializable {
+
+ private static final long serialVersionUID = -5085386252699113948L;
+ /** 预支付id */
+ @JsonProperty("prepayId")
+ private String prepayId;
+
+ /** 预支付时间,秒级时间戳 */
+ @JsonProperty("prepay_time")
+ private Long prepayTime;
+
+ /** 支付时间,秒级时间戳 */
+ @JsonProperty("pay_time")
+ private Long payTime;
+
+ /** 支付单号 */
+ @JsonProperty("transaction_id")
+ private String transactionId;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderPriceInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderPriceInfo.java
new file mode 100644
index 0000000000..64e6690a66
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderPriceInfo.java
@@ -0,0 +1,66 @@
+package me.chanjar.weixin.channel.bean.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 商店订单价格信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class OrderPriceInfo implements Serializable {
+
+ private static final long serialVersionUID = 5216506688949493432L;
+ /** 商品总价,单位为分 */
+ @JsonProperty("product_price")
+ private Integer productPrice;
+
+ /** 订单金额,单位为分 */
+ @JsonProperty("order_price")
+ private Integer orderPrice;
+
+ /** 运费,单位为分 */
+ @JsonProperty("freight")
+ private Integer freight;
+
+ /** 优惠金额,单位为分 */
+ @JsonProperty("discounted_price")
+ private Integer discountedPrice;
+
+ /** 是否有优惠 */
+ @JsonProperty("is_discounted")
+ private Boolean isDiscounted;
+
+ /** 订单原始价格,单位为分 */
+ @JsonProperty("original_order_price")
+ private Integer originalOrderPrice;
+
+ /** 商品预估价格,单位为分 */
+ @JsonProperty("estimate_product_price")
+ private Integer estimateProductPrice;
+
+ /** 改价后降低金额,单位为分 */
+ @JsonProperty("change_down_price")
+ private Integer changeDownPrice;
+
+ /** 改价后运费,单位为分 */
+ @JsonProperty("change_freight")
+ private Integer changeFreight;
+
+ /** 是否修改运费 */
+ @JsonProperty("is_change_freight")
+ private Boolean changeFreighted;
+
+ /** 是否使用了会员积分抵扣 */
+ @JsonProperty("use_deduction")
+ private Boolean useDeduction;
+
+ /** 会员积分抵扣金额,单位为分 */
+ @JsonProperty("deduction_price")
+ private Integer deductionPrice;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderPriceParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderPriceParam.java
new file mode 100644
index 0000000000..30f74501c4
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderPriceParam.java
@@ -0,0 +1,46 @@
+package me.chanjar.weixin.channel.bean.order;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+
+/**
+ * 订单价格参数
+ *
+ * @author Zeyes
+ */
+@Data
+@JsonInclude(Include.NON_NULL)
+public class OrderPriceParam implements Serializable {
+
+ private static final long serialVersionUID = -7925819981481556218L;
+ /** 订单id */
+ @JsonProperty("order_id")
+ private String orderId;
+
+ /** 是否修改运费 */
+ @JsonProperty("change_express")
+ private Boolean changeExpress;
+
+ /** 修改后的运费价格(change_express=true时必填),以分为单位 */
+ @JsonProperty("express_fee")
+ private Integer expressFee;
+
+ /** 改价列表 */
+ @JsonProperty("change_order_infos")
+ private List changeOrderInfos;
+
+ public OrderPriceParam() {
+ }
+
+ public OrderPriceParam(String orderId, Integer expressFee, List changeOrderInfos) {
+ this.orderId = orderId;
+ // expressFee不为空时,表示修改运费
+ this.changeExpress = (expressFee != null);
+ this.expressFee = expressFee;
+ this.changeOrderInfos = changeOrderInfos;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderProductExtraService.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderProductExtraService.java
new file mode 100644
index 0000000000..ff413a9646
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderProductExtraService.java
@@ -0,0 +1,28 @@
+package me.chanjar.weixin.channel.bean.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * 商品额外服务信息
+ *
+ * @author 北鹤M
+ */
+@Data
+@NoArgsConstructor
+public class OrderProductExtraService implements Serializable {
+
+ private static final long serialVersionUID = -8752053507170277156L;
+
+ /** 7天无理由:0:不支持,1:支持 */
+ @JsonProperty("seven_day_return")
+ private Integer sevenDayReturn;
+
+ /** 商家运费险:0:不支持,1:支持 */
+ @JsonProperty("freight_insurance")
+ private Integer freightInsurance;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderProductInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderProductInfo.java
new file mode 100644
index 0000000000..acef8cc4f6
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderProductInfo.java
@@ -0,0 +1,112 @@
+package me.chanjar.weixin.channel.bean.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.AttrInfo;
+
+/**
+ * 订单商品信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class OrderProductInfo implements Serializable {
+
+ private static final long serialVersionUID = -2193536732955185928L;
+ /** 商品spu id */
+ @JsonProperty("product_id")
+ private String productId;
+
+ /** sku_id */
+ @JsonProperty("sku_id")
+ private String skuId;
+
+ /** sku小图 */
+ @JsonProperty("thumb_img")
+ private String thumbImg;
+
+ /** sku数量 */
+ @JsonProperty("sku_cnt")
+ private Integer skuCnt;
+
+ /** 售卖价格(单位:分) */
+ @JsonProperty("sale_price")
+ private Integer salePrice;
+
+ /** 商品标题 */
+ @JsonProperty("title")
+ private String title;
+
+ /** 正在售后/退款流程中的 sku 数量 */
+ @JsonProperty("on_aftersale_sku_cnt")
+ private Integer onAfterSaleSkuCnt;
+
+ /** 完成售后/退款的 sku 数量 */
+ @JsonProperty("finish_aftersale_sku_cnt")
+ private Integer finishAfterSaleSkuCnt;
+
+ /** 商品编码 */
+ @JsonProperty("sku_code")
+ private String skuCode;
+
+ /** 市场价格(单位:分) */
+ @JsonProperty("market_price")
+ private Integer marketPrice;
+
+ /** sku属性 */
+ @JsonProperty("sku_attrs")
+ private List skuAttrs;
+
+ /** sku实付价格 */
+ @JsonProperty("real_price")
+ private Integer realPrice;
+
+ /** 商品外部spu id */
+ @JsonProperty("out_product_id")
+ private String outProductId;
+
+ /** 商品外部sku id */
+ @JsonProperty("out_sku_id")
+ private String outSkuId;
+
+ /** 是否有优惠金额,非必填,默认为false */
+ @JsonProperty("is_discounted")
+ private Boolean isDiscounted;
+
+ /** 优惠后 sku 价格,非必填,is_discounted为 true 时有值 */
+ @JsonProperty("estimate_price")
+ private Integer estimatePrice;
+
+ /** 是否修改过价格,非必填,默认为false */
+ @JsonProperty("is_change_price")
+ private Boolean changePriced;
+
+ /** 改价后 sku 价格,非必填,is_change_price为 true 时有值 */
+ @JsonProperty("change_price")
+ private Integer changePrice;
+
+ /** 区域库存id */
+ @JsonProperty("out_warehouse_id")
+ private String outWarehouseId;
+
+ /** 商品发货信息 */
+ @JsonProperty("sku_deliver_info")
+ private OrderSkuDeliverInfo skuDeliverInfo;
+
+ /** 商品额外服务信息 */
+ @JsonProperty("extra_service")
+ private OrderProductExtraService extraService;
+
+ /** 是否使用了会员积分抵扣 */
+ @JsonProperty("use_deduction")
+ private Boolean useDeduction;
+
+ /** 会员积分抵扣金额,单位为分 */
+ @JsonProperty("deduction_price")
+ private Integer deductionPrice;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderRemarkParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderRemarkParam.java
new file mode 100644
index 0000000000..707ec0d96b
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderRemarkParam.java
@@ -0,0 +1,28 @@
+package me.chanjar.weixin.channel.bean.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 订单备注
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class OrderRemarkParam implements Serializable {
+
+ private static final long serialVersionUID = 2285714780419948468L;
+ /** 订单id */
+ @JsonProperty("order_id")
+ private String orderId;
+
+ /** 备注内容 */
+ @JsonProperty("merchant_notes")
+ private String merchantNotes;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderSearchCondition.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderSearchCondition.java
new file mode 100644
index 0000000000..012b0fca49
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderSearchCondition.java
@@ -0,0 +1,41 @@
+package me.chanjar.weixin.channel.bean.order;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 订单 搜索条件
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@JsonInclude(Include.NON_EMPTY)
+public class OrderSearchCondition implements Serializable {
+
+ private static final long serialVersionUID = 5492584333971883140L;
+ /** 商品标题关键词 */
+ @JsonProperty("title")
+ private String title;
+
+ /** 商品编码 */
+ @JsonProperty("sku_code")
+ private String skuCode;
+
+ /** 收件人 */
+ @JsonProperty("user_name")
+ private String userName;
+
+ /** 收件人电话 */
+ @JsonProperty("tel_number")
+ private String telNumber;
+
+ /** 选填,只搜一个订单时使用 */
+ @JsonProperty("order_id")
+ private String orderId;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderSearchParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderSearchParam.java
new file mode 100644
index 0000000000..0a9483e0d5
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderSearchParam.java
@@ -0,0 +1,30 @@
+package me.chanjar.weixin.channel.bean.order;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.StreamPageParam;
+
+/**
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@JsonInclude(Include.NON_EMPTY)
+public class OrderSearchParam extends StreamPageParam {
+
+ private static final long serialVersionUID = 5737520097455135218L;
+ /** 商品标题关键词 */
+ @JsonProperty("search_condition")
+ private OrderSearchCondition searchCondition;
+
+ /** 不填该参数:全部订单 0:没有正在售后的订单, 1:正在售后单数量大于等于1的订单 */
+ @JsonProperty("on_aftersale_order_exist")
+ private Integer onAfterSaleOrderExist;
+
+ /** 订单状态 {@link me.chanjar.weixin.channel.enums.WxOrderStatus} */
+ @JsonProperty("on_aftersale_order_exist")
+ private Integer status;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderSettleInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderSettleInfo.java
new file mode 100644
index 0000000000..c264a6289a
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderSettleInfo.java
@@ -0,0 +1,26 @@
+package me.chanjar.weixin.channel.bean.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 结算信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class OrderSettleInfo implements Serializable {
+
+ private static final long serialVersionUID = 2140632631448343656L;
+ /** 预计技术服务费(单位为分) */
+ @JsonProperty("predict_commission_fee")
+ private Integer predictCommissionFee;
+
+ /** 实际技术服务费(单位为分)(未结算时本字段为空) */
+ @JsonProperty("commission_fee")
+ private Integer commissionFee;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderSharerInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderSharerInfo.java
new file mode 100644
index 0000000000..be66463445
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderSharerInfo.java
@@ -0,0 +1,33 @@
+package me.chanjar.weixin.channel.bean.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 分享信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class OrderSharerInfo implements Serializable {
+
+ private static final long serialVersionUID = 7183259072254660971L;
+ /** 分享员openid */
+ @JsonProperty("sharer_openid")
+ private String sharerOpenid;
+
+ /** 分享员unionid */
+ @JsonProperty("sharer_unionid")
+ private String sharerUnionid;
+
+ /** 分享员类型,0:普通分享员,1:店铺分享员 */
+ @JsonProperty("sharer_type")
+ private Integer sharerType;
+
+ /** 分享场景 {@link me.chanjar.weixin.channel.enums.ShareScene} */
+ @JsonProperty("share_scene")
+ private Integer shareScene;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderSkuDeliverInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderSkuDeliverInfo.java
new file mode 100644
index 0000000000..6dd46c9a39
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderSkuDeliverInfo.java
@@ -0,0 +1,28 @@
+package me.chanjar.weixin.channel.bean.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * 商品发货信息
+ *
+ * @author 北鹤M
+ */
+@Data
+@NoArgsConstructor
+public class OrderSkuDeliverInfo implements Serializable {
+
+ private static final long serialVersionUID = 4075897806362929800L;
+
+ /** 商品发货类型:0:现货,1:全款预售 */
+ @JsonProperty("stock_type")
+ private Integer stockType;
+
+ /** 预计发货时间(stock_type=1时返回该字段) */
+ @JsonProperty("predict_delivery_time")
+ private String predictDeliveryTime;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderSkuShareInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderSkuShareInfo.java
new file mode 100644
index 0000000000..7912e53348
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/order/OrderSkuShareInfo.java
@@ -0,0 +1,44 @@
+package me.chanjar.weixin.channel.bean.order;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * Sku层分享信息
+ *
+ * @author 北鹤M
+ */
+@Data
+@NoArgsConstructor
+public class OrderSkuShareInfo implements Serializable {
+
+ private static final long serialVersionUID = 705312408112124476L;
+
+ /** 分享员openid */
+ @JsonProperty("sharer_openid")
+ private String sharerOpenid;
+
+ /** 分享员unionid */
+ @JsonProperty("sharer_unionid")
+ private String sharerUnionid;
+
+ /** 分享员类型,0:普通分享员,1:店铺分享员 */
+ @JsonProperty("sharer_type")
+ private Integer sharerType;
+
+ /** 分享场景 {@link me.chanjar.weixin.channel.enums.ShareScene} */
+ @JsonProperty("share_scene")
+ private Integer shareScene;
+
+ /** 商品skuid */
+ @JsonProperty("sku_id")
+ private String skuId;
+
+ /** 是否来自企微分享 */
+ @JsonProperty("from_wecom")
+ private Boolean fromWecom;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/DescriptionInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/DescriptionInfo.java
new file mode 100644
index 0000000000..b97473e3d3
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/DescriptionInfo.java
@@ -0,0 +1,27 @@
+package me.chanjar.weixin.channel.bean.product;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 商品详情
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class DescriptionInfo implements Serializable {
+
+ private static final long serialVersionUID = 3402153796734747882L;
+
+ /** 商品详情图文,字符类型,最长不超过2000 */
+ @JsonProperty("desc")
+ private String desc;
+
+ /** 商品详情图片,图片类型,最多不超过50张 */
+ @JsonProperty("imgs")
+ private List imgs;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ExpressInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ExpressInfo.java
new file mode 100644
index 0000000000..0c21d9610e
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ExpressInfo.java
@@ -0,0 +1,28 @@
+package me.chanjar.weixin.channel.bean.product;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 运费信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class ExpressInfo implements Serializable {
+
+ private static final long serialVersionUID = 3274035362148612426L;
+
+ /** 运费模板ID(先通过获取运费模板接口merchant/getfreighttemplatelist拿到),若deliver_method=1,则不用填写 */
+ @JsonProperty("template_id")
+ private String templateId;
+
+ /** 商品重量,单位克,若当前运费模版计价方式为[按重量],则必填 */
+ @JsonProperty("weight")
+ private Integer weight;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ExtraServiceInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ExtraServiceInfo.java
new file mode 100644
index 0000000000..aeaf1a8cd6
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ExtraServiceInfo.java
@@ -0,0 +1,23 @@
+package me.chanjar.weixin.channel.bean.product;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class ExtraServiceInfo implements Serializable {
+
+ private static final long serialVersionUID = -5517806977282063174L;
+
+ /**
+ * 是否支持七天无理由退货,0-不支持七天无理由, 1-支持七天无理由, 2-支持七天无理由(定制商品除外)。 管理规则请参见七天无理由退货管理规则。类目是否必须支持七天无理由退货,
+ * 可参考文档获取类目信息中的字段attr.seven_day_return
+ */
+ @JsonProperty("seven_day_return")
+ private Integer sevenDayReturn;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/LimitInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/LimitInfo.java
new file mode 100644
index 0000000000..389773d5e7
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/LimitInfo.java
@@ -0,0 +1,28 @@
+package me.chanjar.weixin.channel.bean.product;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 限时购信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class LimitInfo implements Serializable {
+
+ private static final long serialVersionUID = -4670198322237114719L;
+
+ /** 限购周期类型,0无限购(默认),1按自然日限购,2按自然周限购,3按自然月限购 */
+ @JsonProperty("period_type")
+ private Integer periodType;
+
+ /** 限购周期类型,0无限购(默认),1按自然日限购,2按自然周限购,3按自然月限购 */
+ @JsonProperty("limited_buy_num")
+ private Integer num;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SkuDeliverInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SkuDeliverInfo.java
new file mode 100644
index 0000000000..d1f10dc5f8
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SkuDeliverInfo.java
@@ -0,0 +1,43 @@
+package me.chanjar.weixin.channel.bean.product;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * sku发货信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class SkuDeliverInfo implements Serializable {
+
+ private static final long serialVersionUID = 8046963723772755406L;
+
+ /** sku库存情况。0:现货(默认),1:全款预售。部分类目支持全款预售,具体参考文档获取类目信息中的字段attr.pre_sale */
+ @JsonProperty("stock_type")
+ private Integer stockType;
+
+ /** sku发货节点,该字段仅对stock_type=1有效。0:付款后n天发货,1:预售结束后n天发货 */
+ @JsonProperty("full_payment_presale_delivery_type")
+ private Integer fullPaymentPresaleDeliveryType;
+
+ /** sku预售周期开始时间,秒级时间戳,该字段仅对delivery_type=1有效。 */
+ @JsonProperty("presale_begin_time")
+ private Long presaleBeginTime;
+
+ /**
+ * sku预售周期结束时间,秒级时间戳,该字段仅对delivery_type=1有效。限制:预售结束时间距离现在<=30天, 即presale_end_time - now <= 2592000。预售时间区间<=15天,
+ * 即presale_end_time - presale_begin_time <= 1296000
+ */
+ @JsonProperty("presale_end_time")
+ private Long presaleEndTime;
+
+ /**
+ * sku发货时效,即付款后/预售结束后{full_payment_presale_delivery_time}天内发货, 该字段仅对stock_type=1时有效。范围是[4, 15]的整数。
+ */
+ @JsonProperty("full_payment_presale_delivery_time")
+ private Integer fullPaymentPresaleDeliveryTime;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SkuInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SkuInfo.java
new file mode 100644
index 0000000000..3b46708039
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SkuInfo.java
@@ -0,0 +1,66 @@
+package me.chanjar.weixin.channel.bean.product;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import me.chanjar.weixin.channel.bean.base.AttrInfo;
+
+/**
+ * SKU信息
+ *
+ * @author Zeyes
+ */
+@Data
+public class SkuInfo implements Serializable {
+
+ private static final long serialVersionUID = -8734396136299597845L;
+
+ /** 商家自定义商品ID */
+ @JsonProperty("out_product_id")
+ private String outProductId;
+
+ /** 商家自定义skuID */
+ @JsonProperty("out_sku_id")
+ private String outSkuId;
+
+ /** sku小图 */
+ @JsonProperty("thumb_img")
+ private String thumbImg;
+
+ /** 售卖价格,以分为单位,数字类型,最大不超过10000000(1000万元) */
+ @JsonProperty("sale_price")
+ private Integer salePrice;
+
+ /** 市场价格,以分为单位,数字类型,最大不超过10000000(1000万元),且必须比sale_price大 */
+ @JsonProperty("market_price")
+ private Integer marketPrice;
+
+ /** 库存,数字类型,最大不超过10000000(1000万) */
+ @JsonProperty("stock_num")
+ private Integer stockNum;
+
+ /** 商品编码,字符类型,最长不超过20 */
+ @JsonProperty("sku_code")
+ private String skuCode;
+
+ /** SKU属性 */
+ @JsonProperty("sku_attrs")
+ private List attrs;
+
+ /** sku发货信息 */
+ @JsonProperty("sku_deliver_info")
+ private SkuDeliverInfo skuDeliverInfo;
+
+ /** skuID */
+ @JsonProperty("sku_id")
+ private Long skuId;
+
+ public SkuInfo() {
+ }
+
+ public SkuInfo(String outProductId, String outSkuId) {
+ this.outProductId = outProductId;
+ this.outSkuId = outSkuId;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SkuStockInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SkuStockInfo.java
new file mode 100644
index 0000000000..a0dccb1329
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SkuStockInfo.java
@@ -0,0 +1,35 @@
+package me.chanjar.weixin.channel.bean.product;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 商品库存
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class SkuStockInfo implements Serializable {
+
+ private static final long serialVersionUID = 4719729125885685958L;
+
+ /** 通用库存数量 */
+ @JsonProperty("normal_stock_num")
+ private Integer normalStockNum;
+
+ /** 限时抢购库存数量 */
+ @JsonProperty("limited_discount_stock_num")
+ private Integer limitedDiscountStockNum;
+
+ /** 区域库存 */
+ @JsonProperty("warehouse_stocks")
+ private List warehouseStocks;
+
+ /** 库存总量:通用库存数量 + 限时抢购库存数量 + 区域库存总量 */
+ @JsonProperty("total_stock_num")
+ private Integer totalStockNum;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SkuStockParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SkuStockParam.java
new file mode 100644
index 0000000000..cf7374e75e
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SkuStockParam.java
@@ -0,0 +1,34 @@
+package me.chanjar.weixin.channel.bean.product;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class SkuStockParam implements Serializable {
+
+ private static final long serialVersionUID = -5542939078361208816L;
+
+ /** 内部商品ID */
+ @JsonProperty("product_id")
+ protected String productId;
+
+ /** 内部sku_id */
+ @JsonProperty("sku_id")
+ protected String skuId;
+
+ /** 修改类型。1: 增加;2:减少;3:设置 */
+ @JsonProperty("diff_type")
+ protected Integer diffType;
+
+ /** 增加、减少或者设置的库存值 */
+ @JsonProperty("num")
+ protected Integer num;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SkuStockResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SkuStockResponse.java
new file mode 100644
index 0000000000..9cbd6f18c0
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SkuStockResponse.java
@@ -0,0 +1,22 @@
+package me.chanjar.weixin.channel.bean.product;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 库存信息响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class SkuStockResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -2156342792354605826L;
+
+ /** 库存信息 */
+ private SkuStockInfo data;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SpuCategory.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SpuCategory.java
new file mode 100644
index 0000000000..8adc311f95
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SpuCategory.java
@@ -0,0 +1,22 @@
+package me.chanjar.weixin.channel.bean.product;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 商品类目id
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class SpuCategory implements Serializable {
+
+ private static final long serialVersionUID = -8500610555473351789L;
+
+ /** 类目id */
+ @JsonProperty("cat_id")
+ private String id;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SpuGetResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SpuGetResponse.java
new file mode 100644
index 0000000000..b01682802f
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SpuGetResponse.java
@@ -0,0 +1,28 @@
+package me.chanjar.weixin.channel.bean.product;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 商品信息 响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class SpuGetResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -8955745006296226140L;
+
+ /** 商品线上数据,入参data_type==2时不返回该字段;入参data_type==3且商品未处于上架状态,不返回该字段 */
+ @JsonProperty("product")
+ private SpuInfo product;
+
+ /** 商品草稿数据,入参data_type==1时不返回该字段 */
+ @JsonProperty("edit_product")
+ private SpuInfo editProduct;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SpuInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SpuInfo.java
new file mode 100644
index 0000000000..7e3834f10e
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SpuInfo.java
@@ -0,0 +1,97 @@
+package me.chanjar.weixin.channel.bean.product;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.AttrInfo;
+
+/**
+ * Spu信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class SpuInfo extends SpuSimpleInfo {
+
+ private static final long serialVersionUID = -1183209029245287297L;
+
+ /** 标题,字符类型,最少不低于3,最长不超过60。商品标题不得仅为数字、字母、字符或上述三种的组合 */
+ @JsonProperty("title")
+ private String title;
+
+ /** 副标题,最多18字符 */
+ @JsonProperty("sub_title")
+ private String subTitle;
+
+ /** 主图,多张,列表,图片类型,最多不超过9张 */
+ @JsonProperty("head_imgs")
+ private List headImgs;
+
+ /** 发货方式,若为无需快递(仅对部分类目开放),则无需填写运费模版id。0:快递发货;1:无需快递;默认0 */
+ @JsonProperty("deliver_method")
+ private Integer deliverMethod;
+
+ /** 商品详情 */
+ @JsonProperty("desc_info")
+ private DescriptionInfo descInfo;
+
+ /** 商品类目,大小恒等于3(一二三级类目) */
+ @JsonProperty("cats")
+ private List cats;
+
+ /** 商品参数 */
+ @JsonProperty("attrs")
+ private List attrs;
+
+ /** 商品编码 */
+ @JsonProperty("spu_code")
+ private String spuCode;
+
+ /** 品牌id,无品牌为2100000000 */
+ @JsonProperty("brand_id")
+ private String brandId;
+
+ /** 商品资质图片(最多5张) */
+ @JsonProperty("qualifications")
+ private List qualifications;
+
+ /** 运费信息 */
+ @JsonProperty("express_info")
+ private ExpressInfo expressInfo;
+
+ /** 售后说明 */
+ @JsonProperty("aftersale_desc")
+ private String afterSaleDesc;
+
+ /** 限购信息 */
+ @JsonProperty("limited_info")
+ @JsonInclude(Include.NON_EMPTY)
+ private LimitInfo limitInfo;
+
+ /** 附加服务 */
+ @JsonProperty("extra_service")
+ private ExtraServiceInfo extraService;
+
+ /** 商品线上状态 {@link me.chanjar.weixin.channel.enums.SpuStatus } */
+ @JsonProperty("status")
+ private Integer status;
+
+ /** 商品草稿状态 */
+ @JsonProperty("edit_status")
+ private Integer editStatus;
+
+ /** 最低价格 */
+ @JsonProperty("min_price")
+ private Integer minPrice;
+
+ /** 创建时间 yyyy-MM-dd HH:mm:ss */
+ @JsonProperty("create_time")
+ private String createTime;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SpuListParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SpuListParam.java
new file mode 100644
index 0000000000..775bdf990d
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SpuListParam.java
@@ -0,0 +1,32 @@
+package me.chanjar.weixin.channel.bean.product;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import me.chanjar.weixin.channel.bean.base.StreamPageParam;
+
+/**
+ * 商品列表查询参数
+ *
+ * @author Zeyes
+ */
+@Data
+@JsonInclude(Include.NON_NULL)
+public class SpuListParam extends StreamPageParam {
+
+ private static final long serialVersionUID = -242932365961748404L;
+
+ /** 商品状态 */
+ @JsonProperty("status")
+ private Integer status;
+
+ public SpuListParam() {
+ }
+
+ public SpuListParam(Integer pageSize, String nextKey, Integer status) {
+ this.pageSize = pageSize;
+ this.nextKey = nextKey;
+ this.status = status;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SpuListResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SpuListResponse.java
new file mode 100644
index 0000000000..421725c04b
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SpuListResponse.java
@@ -0,0 +1,33 @@
+package me.chanjar.weixin.channel.bean.product;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 商品列表信息 响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class SpuListResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -7448819335418389308L;
+
+ /** 总数 */
+ @JsonProperty("total_num")
+ private Integer totalNum;
+
+ /** 本次翻页的上下文,用于请求下一页 */
+ @JsonProperty("next_key")
+ private String nextKey;
+
+ /** 商品 id 列表 */
+ @JsonProperty("product_ids")
+ private List ids;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SpuSimpleInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SpuSimpleInfo.java
new file mode 100644
index 0000000000..b1ab3febe7
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SpuSimpleInfo.java
@@ -0,0 +1,29 @@
+package me.chanjar.weixin.channel.bean.product;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class SpuSimpleInfo implements Serializable {
+
+ private static final long serialVersionUID = 5583726432139404883L;
+
+ /** 交易组件平台内部商品ID */
+ @JsonProperty("product_id")
+ protected String productId;
+
+ /** 商家自定义商品ID */
+ @JsonProperty("out_product_id")
+ protected String outProductId;
+
+ /** sku数组 */
+ @JsonProperty("skus")
+ protected List skus;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SpuUpdateResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SpuUpdateResponse.java
new file mode 100644
index 0000000000..815ee4412c
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/SpuUpdateResponse.java
@@ -0,0 +1,25 @@
+package me.chanjar.weixin.channel.bean.product;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 商品信息 响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class SpuUpdateResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -7072796795527767292L;
+
+ /** 商品信息 */
+ @JsonProperty("data")
+ private SpuInfo data;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/WarehouseStockInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/WarehouseStockInfo.java
new file mode 100644
index 0000000000..bb239c9492
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/WarehouseStockInfo.java
@@ -0,0 +1,24 @@
+package me.chanjar.weixin.channel.bean.product;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class WarehouseStockInfo implements Serializable {
+
+ private static final long serialVersionUID = 3184902895765107425L;
+
+ /** 区域库存外部id */
+ @JsonProperty("out_warehouse_id")
+ private String outWarehouseId;
+
+ /** 区域库存数量 */
+ @JsonProperty("num")
+ private Integer num;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/FinderSceneInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/FinderSceneInfo.java
new file mode 100644
index 0000000000..76d54d90c9
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/FinderSceneInfo.java
@@ -0,0 +1,38 @@
+package me.chanjar.weixin.channel.bean.sharer;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 视频号场景信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class FinderSceneInfo implements Serializable {
+
+ private static final long serialVersionUID = 5298261857489231549L;
+ /** 视频号唯一标识 */
+ @JsonProperty("promoter_id")
+ private String promoterId;
+
+ /** 视频号昵称 */
+ @JsonProperty("finder_nickname")
+ private String finderNickname;
+
+ /** 直播间唯一标识 */
+ @JsonProperty("live_export_id")
+ private String liveExportId;
+
+ /** 短视频唯一标识 */
+ @JsonProperty("video_export_id")
+ private String videoExportId;
+
+ /** 短视频标题 */
+ @JsonProperty("video_title")
+ private String videoTitle;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/SharerBindResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/SharerBindResponse.java
new file mode 100644
index 0000000000..4a0f8f2bb4
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/SharerBindResponse.java
@@ -0,0 +1,31 @@
+package me.chanjar.weixin.channel.bean.sharer;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 分享员绑定响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class SharerBindResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 7078787380791500161L;
+ /** 邀请二维码的图片二进制base64编码,3天有效 */
+ @JsonProperty("qrcode_img_base64")
+ private String qrcodeImgBase64;
+
+ public String getQrcodeImgBase64() {
+ return qrcodeImgBase64;
+ }
+
+ public void setQrcodeImgBase64(String qrcodeImgBase64) {
+ this.qrcodeImgBase64 = qrcodeImgBase64;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/SharerInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/SharerInfo.java
new file mode 100644
index 0000000000..73aaeddbd4
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/SharerInfo.java
@@ -0,0 +1,39 @@
+package me.chanjar.weixin.channel.bean.sharer;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+
+/**
+ * 分享员信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class SharerInfo implements Serializable {
+
+ private static final long serialVersionUID = -4373597470611742887L;
+ /** 分享员openid */
+ @JsonProperty("openid")
+ private String openid;
+
+ /** 分享员unionid */
+ @JsonProperty("unionid")
+ private String unionid;
+
+ /** 分享员openid */
+ @JsonProperty("nickname")
+ private String nickname;
+
+ /** 绑定时间 */
+ @JsonProperty("bind_time")
+ private Long bindTime;
+
+ /** 分享员类型 {@link me.chanjar.weixin.channel.enums.SharerType} */
+ @JsonProperty("sharer_type")
+ private Integer sharerType;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/SharerInfoResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/SharerInfoResponse.java
new file mode 100644
index 0000000000..554109c1a9
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/SharerInfoResponse.java
@@ -0,0 +1,25 @@
+package me.chanjar.weixin.channel.bean.sharer;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 分享员信息响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class SharerInfoResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 1090517907546557929L;
+ /** 分享员信息 */
+ @JsonProperty("sharer_info_list")
+ private List list;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/SharerListParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/SharerListParam.java
new file mode 100644
index 0000000000..97ab2797b8
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/SharerListParam.java
@@ -0,0 +1,30 @@
+package me.chanjar.weixin.channel.bean.sharer;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import me.chanjar.weixin.channel.bean.base.PageParam;
+
+/**
+ * @author Zeyes
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@JsonInclude(Include.NON_NULL)
+public class SharerListParam extends PageParam {
+
+ private static final long serialVersionUID = -2454284952706596246L;
+ /** 分享员类型 {@link me.chanjar.weixin.channel.enums.SharerType} */
+ @JsonProperty("sharer_type")
+ private Integer sharerType;
+
+ public SharerListParam() {
+ }
+
+ public SharerListParam(Integer page, Integer pageSize, Integer sharerType) {
+ super(page, pageSize);
+ this.sharerType = sharerType;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/SharerOrder.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/SharerOrder.java
new file mode 100644
index 0000000000..682753e64f
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/SharerOrder.java
@@ -0,0 +1,70 @@
+package me.chanjar.weixin.channel.bean.sharer;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 分享员订单
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class SharerOrder implements Serializable {
+
+ private static final long serialVersionUID = 1528673402572025670L;
+ /**
+ * 订单号
+ */
+ @JsonProperty("order_id")
+ private String orderId;
+
+ /**
+ * 分享场景 {@link me.chanjar.weixin.channel.enums.ShareScene}
+ */
+ @JsonProperty("share_scene")
+ private Integer sharerScene;
+
+ /**
+ * 分享员openid
+ */
+ @JsonProperty("sharer_openid")
+ private String sharerOpenid;
+
+ /**
+ * 分享员类型 {@link me.chanjar.weixin.channel.enums.SharerType}
+ */
+ @JsonProperty("sharer_type")
+ private Integer sharerType;
+
+ /**
+ * 商品sku_id
+ */
+ @JsonProperty("sku_id")
+ private String skuId;
+
+
+ /**
+ * 商品唯一id
+ */
+ @JsonProperty("product_id")
+ private String productId;
+
+
+ /**
+ * 是否从企微分享
+ */
+ @JsonProperty("from_wecom")
+ private Boolean fromWxWork;
+
+
+ /**
+ * 视频号场景信息
+ */
+ @JsonProperty("finder_scene_info")
+ private FinderSceneInfo sceneInfo;
+
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/SharerOrderParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/SharerOrderParam.java
new file mode 100644
index 0000000000..5ada6e3bcf
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/SharerOrderParam.java
@@ -0,0 +1,36 @@
+package me.chanjar.weixin.channel.bean.sharer;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.PageParam;
+
+/**
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@JsonInclude(Include.NON_NULL)
+public class SharerOrderParam extends PageParam {
+
+ private static final long serialVersionUID = 5240085870008898601L;
+ /** 分享员openid */
+ @JsonProperty("openid")
+ private String openid;
+
+ /** 分享场景 */
+ @JsonProperty("share_scene")
+ private Integer shareScene;
+
+ /** 订单创建开始时间 */
+ @JsonProperty("start_time")
+ private Long startTime;
+
+ /** 订单创建结束时间 */
+ @JsonProperty("end_time")
+ private Long endTime;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/SharerOrderResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/SharerOrderResponse.java
new file mode 100644
index 0000000000..c84da4114b
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/SharerOrderResponse.java
@@ -0,0 +1,24 @@
+package me.chanjar.weixin.channel.bean.sharer;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 分享员订单响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class SharerOrderResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 2807417719466178508L;
+ /** 分享员订单 */
+ @JsonProperty("order_list")
+ private List list;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/SharerSearchParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/SharerSearchParam.java
new file mode 100644
index 0000000000..a2669775cb
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/SharerSearchParam.java
@@ -0,0 +1,32 @@
+package me.chanjar.weixin.channel.bean.sharer;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+
+/**
+ * @author Zeyes
+ */
+@Data
+@JsonInclude(Include.NON_NULL)
+public class SharerSearchParam implements Serializable {
+
+ private static final long serialVersionUID = -6763899740755735718L;
+ /** 分享员openid */
+ @JsonProperty("openid")
+ private String openid;
+
+ /** 微信号 */
+ @JsonProperty("username")
+ private String username;
+
+ public SharerSearchParam() {
+ }
+
+ public SharerSearchParam(String openid, String username) {
+ this.openid = openid;
+ this.username = username;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/SharerSearchResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/SharerSearchResponse.java
new file mode 100644
index 0000000000..52631521df
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/SharerSearchResponse.java
@@ -0,0 +1,40 @@
+package me.chanjar.weixin.channel.bean.sharer;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 分享员绑定响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class SharerSearchResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -5346019069466917659L;
+ /** 分享员openid */
+ @JsonProperty("openid")
+ private String openid;
+
+ /** 分享员unionid */
+ @JsonProperty("unionid")
+ private String unionid;
+
+ /** 分享员openid */
+ @JsonProperty("nickname")
+ private String nickname;
+
+ /** 绑定时间 */
+ @JsonProperty("bind_time")
+ private Long bindTime;
+
+ /** 分享员类型 {@link me.chanjar.weixin.channel.enums.SharerType} */
+ @JsonProperty("sharer_type")
+ private Integer sharerType;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/SharerUnbindParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/SharerUnbindParam.java
new file mode 100644
index 0000000000..cd8f21d409
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/SharerUnbindParam.java
@@ -0,0 +1,25 @@
+package me.chanjar.weixin.channel.bean.sharer;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonInclude(Include.NON_NULL)
+public class SharerUnbindParam implements Serializable {
+
+ private static final long serialVersionUID = -4515654492511136037L;
+ /** openid列表 */
+ @JsonProperty("openid_list")
+ private List openIds;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/SharerUnbindResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/SharerUnbindResponse.java
new file mode 100644
index 0000000000..9166bc0b58
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/sharer/SharerUnbindResponse.java
@@ -0,0 +1,32 @@
+package me.chanjar.weixin.channel.bean.sharer;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 分享员解绑响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class SharerUnbindResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -2395560383862569445L;
+ /** 成功列表 */
+ @JsonProperty("success_openid")
+ private List successList;
+
+ /** 失败列表,可重试 */
+ @JsonProperty("fail_openid")
+ private List failList;
+
+ /** 拒绝列表,不可重试(openid错误,未到解绑时间等) */
+ @JsonProperty("refuse_openid")
+ private List refuseList;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/shop/ShopInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/shop/ShopInfo.java
new file mode 100644
index 0000000000..b2209a4309
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/shop/ShopInfo.java
@@ -0,0 +1,28 @@
+package me.chanjar.weixin.channel.bean.shop;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 店铺信息
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class ShopInfo implements Serializable {
+
+ /** 店铺名称 */
+ @JsonProperty("nickname")
+ private String nickname;
+
+ /** 店铺头像URL */
+ @JsonProperty("headimg_url")
+ private String headImgUrl;
+
+ /** 店铺类型,目前为"企业"或"个体工商户" */
+ @JsonProperty("subject_type")
+ private String subjectType;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/shop/ShopInfoResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/shop/ShopInfoResponse.java
new file mode 100644
index 0000000000..b4317ad3c0
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/shop/ShopInfoResponse.java
@@ -0,0 +1,19 @@
+package me.chanjar.weixin.channel.bean.shop;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 店铺基本信息响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class ShopInfoResponse extends WxChannelBaseResponse {
+
+ @JsonProperty("info")
+ private ShopInfo info;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/LocationPriorityResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/LocationPriorityResponse.java
new file mode 100644
index 0000000000..5959cb746d
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/LocationPriorityResponse.java
@@ -0,0 +1,25 @@
+package me.chanjar.weixin.channel.bean.warehouse;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 仓库优先级响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class LocationPriorityResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = -4037484169497319150L;
+
+ /** 按照out_warehouse_id排序优先级从高到低 */
+ @JsonProperty("priority_sort")
+ private List prioritySort;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/PriorityLocationParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/PriorityLocationParam.java
new file mode 100644
index 0000000000..0b304487a7
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/PriorityLocationParam.java
@@ -0,0 +1,24 @@
+package me.chanjar.weixin.channel.bean.warehouse;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+/**
+ * 带优先级的仓库区域
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class PriorityLocationParam extends WarehouseLocation {
+
+ private static final long serialVersionUID = -3087702364669180903L;
+
+ /** 按照out_warehouse_id排序优先级从高到低 */
+ @JsonProperty("priority_sort")
+ private List prioritySort;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/StockGetParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/StockGetParam.java
new file mode 100644
index 0000000000..99e00a4801
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/StockGetParam.java
@@ -0,0 +1,29 @@
+package me.chanjar.weixin.channel.bean.warehouse;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class StockGetParam implements Serializable {
+
+ private static final long serialVersionUID = -4144913434092446664L;
+ /** 商品ID */
+ @JsonProperty("product_id")
+ private String productId;
+
+ /** skuID */
+ @JsonProperty("sku_id")
+ private String skuId;
+
+ /** 外部仓库ID */
+ @JsonProperty("out_warehouse_id")
+ private String outWarehouseId;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/UpdateLocationParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/UpdateLocationParam.java
new file mode 100644
index 0000000000..5b71c0a4b4
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/UpdateLocationParam.java
@@ -0,0 +1,29 @@
+package me.chanjar.weixin.channel.bean.warehouse;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 仓库区域
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class UpdateLocationParam implements Serializable {
+
+ private static final long serialVersionUID = 6102771485047925091L;
+
+ /** 外部仓库ID */
+ @JsonProperty("out_warehouse_id")
+ private String outWarehouseId;
+
+ /** 覆盖区域 */
+ @JsonProperty("cover_locations")
+ private List coverLocations;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/Warehouse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/Warehouse.java
new file mode 100644
index 0000000000..7ca07e637f
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/Warehouse.java
@@ -0,0 +1,36 @@
+package me.chanjar.weixin.channel.bean.warehouse;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 仓库
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class Warehouse implements Serializable {
+
+ private static final long serialVersionUID = -2322154583471063637L;
+
+ /** 外部仓库ID,一个店铺下,同一个外部ID只能创建一个仓库,最大32字符 */
+ @JsonProperty("out_warehouse_id")
+ private String outWarehouseId;
+
+ /** 仓库名称 */
+ @JsonProperty("name")
+ private String name;
+
+ /** 仓库介绍 */
+ @JsonProperty("intro")
+ private String intro;
+
+ /** 覆盖区域,可以在创建后添加 */
+ @JsonProperty("cover_locations")
+ private List coverLocations;
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/WarehouseIdsResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/WarehouseIdsResponse.java
new file mode 100644
index 0000000000..57c989a56b
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/WarehouseIdsResponse.java
@@ -0,0 +1,48 @@
+package me.chanjar.weixin.channel.bean.warehouse;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import java.util.Map;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 仓库id列表响应
+ *
+ * @author Zeyes
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class WarehouseIdsResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 3974529583232187473L;
+
+ /** 外部仓库ID列表 */
+ @JsonProperty("out_warehouse_ids")
+ private List ids;
+
+ /** 本次翻页的上下文,用于请求下一页,如果是空,则当前是最后一页 */
+ @JsonProperty("next_key")
+ private String nextKey;
+
+ public WarehouseIdsResponse() {
+ }
+
+ @JsonProperty("data")
+ private void unpackNameFromNestedObject(Map map) {
+ if (map == null) {
+ return;
+ }
+ Object obj = map.get("out_warehouse_ids");
+ if (obj != null) {
+ if (obj instanceof List) {
+ this.ids = (List) obj;
+ }
+ }
+ obj = map.get("next_key");
+ if (obj != null) {
+ this.nextKey = (String) obj;
+ }
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/WarehouseLocation.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/WarehouseLocation.java
new file mode 100644
index 0000000000..33309522bb
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/WarehouseLocation.java
@@ -0,0 +1,36 @@
+package me.chanjar.weixin.channel.bean.warehouse;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 仓库区域
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class WarehouseLocation implements Serializable {
+
+ private static final long serialVersionUID = 1626579682640060352L;
+
+ /** 省份地址编码 */
+ @JsonProperty("address_id1")
+ private Integer addressId1;
+
+ /** 市地址编码 */
+ @JsonProperty("address_id2")
+ private Integer addressId2;
+
+ /** 区地址编码 */
+ @JsonProperty("address_id3")
+ private Integer addressId3;
+
+ /** 街道地址编码 */
+ @JsonProperty("address_id4")
+ private Integer addressId4;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/WarehouseLocationParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/WarehouseLocationParam.java
new file mode 100644
index 0000000000..2b64e55dea
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/WarehouseLocationParam.java
@@ -0,0 +1,22 @@
+package me.chanjar.weixin.channel.bean.warehouse;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import lombok.Data;
+
+/**
+ * @author Zeyes
+ */
+@Data
+@JsonInclude(Include.NON_NULL)
+public class WarehouseLocationParam extends WarehouseLocation {
+
+ private static final long serialVersionUID = 3347484433136057123L;
+
+ public WarehouseLocationParam() {
+ }
+
+ public WarehouseLocationParam(Integer addressId1, Integer addressId2, Integer addressId3, Integer addressId4) {
+ super(addressId1, addressId2, addressId3, addressId4);
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/WarehouseParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/WarehouseParam.java
new file mode 100644
index 0000000000..77ac1a8134
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/WarehouseParam.java
@@ -0,0 +1,20 @@
+package me.chanjar.weixin.channel.bean.warehouse;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+/**
+ * 仓库
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class WarehouseParam extends Warehouse {
+
+ private static final long serialVersionUID = -3412047348380785225L;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/WarehouseResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/WarehouseResponse.java
new file mode 100644
index 0000000000..fa96771d67
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/WarehouseResponse.java
@@ -0,0 +1,21 @@
+package me.chanjar.weixin.channel.bean.warehouse;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 仓库响应
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class WarehouseResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 3206095869486573824L;
+ /** 仓库库存 */
+ @JsonProperty("data")
+ private Warehouse data;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/WarehouseStockParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/WarehouseStockParam.java
new file mode 100644
index 0000000000..5a4354504d
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/WarehouseStockParam.java
@@ -0,0 +1,22 @@
+package me.chanjar.weixin.channel.bean.warehouse;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import me.chanjar.weixin.channel.bean.product.SkuStockParam;
+
+/**
+ * 库存参数
+ *
+ * @author Zeyes
+ */
+@Data
+@NoArgsConstructor
+public class WarehouseStockParam extends SkuStockParam {
+
+ private static final long serialVersionUID = -5121207621628542490L;
+
+ /** 外部仓库ID */
+ @JsonProperty("out_warehouse_id")
+ private String outWarehouseId;
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/WarehouseStockResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/WarehouseStockResponse.java
new file mode 100644
index 0000000000..64d0d2b5b0
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/warehouse/WarehouseStockResponse.java
@@ -0,0 +1,34 @@
+package me.chanjar.weixin.channel.bean.warehouse;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.Map;
+import lombok.Data;
+import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
+
+/**
+ * 仓库库存响应
+ *
+ * @author Zeyes
+ */
+@Data
+public class WarehouseStockResponse extends WxChannelBaseResponse {
+
+ private static final long serialVersionUID = 1810645965041317763L;
+ /** 仓库库存 */
+ @JsonProperty("num")
+ private Integer num;
+
+ public WarehouseStockResponse() {
+ }
+
+ @JsonProperty("data")
+ private void unpackNameFromNestedObject(Map map) {
+ if (map == null) {
+ return;
+ }
+ Object obj = map.get("num");
+ if (obj != null) {
+ this.num = (Integer) obj;
+ }
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/common/ChannelWxError.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/common/ChannelWxError.java
new file mode 100644
index 0000000000..eb8cda4996
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/common/ChannelWxError.java
@@ -0,0 +1,25 @@
+package me.chanjar.weixin.channel.common;
+
+import me.chanjar.weixin.channel.enums.WxChannelErrorMsgEnum;
+import me.chanjar.weixin.common.error.WxError;
+
+/**
+ * 微信视频号错误码
+ *
+ * @author Zeyes
+ */
+public class ChannelWxError extends WxError {
+
+ private static final long serialVersionUID = -2638512715814977441L;
+
+ public ChannelWxError() {
+ }
+
+ public ChannelWxError(int errorCode, String errorMsgEn) {
+ super(errorCode, errorMsgEn);
+ if (WxChannelErrorMsgEnum.findMsgByCode(errorCode) != null) {
+ this.setErrorMsg(WxChannelErrorMsgEnum.findMsgByCode(errorCode));
+ }
+ this.setErrorMsgEn(errorMsgEn);
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/config/WxChannelConfig.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/config/WxChannelConfig.java
new file mode 100644
index 0000000000..ad24234fb0
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/config/WxChannelConfig.java
@@ -0,0 +1,185 @@
+package me.chanjar.weixin.channel.config;
+
+import java.util.concurrent.locks.Lock;
+import me.chanjar.weixin.channel.api.BaseWxChannelService;
+import me.chanjar.weixin.common.bean.WxAccessToken;
+import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder;
+
+/**
+ * 视频号小店配置
+ *
+ * @author Zeyes
+ */
+public interface WxChannelConfig {
+
+ /**
+ * Gets access token.
+ *
+ * @return the access token
+ */
+ String getAccessToken();
+
+ /**
+ * Gets access token lock.
+ *
+ * @return the access token lock
+ */
+ Lock getAccessTokenLock();
+
+ /**
+ * Is access token expired boolean.
+ *
+ * @return the boolean
+ */
+ boolean isAccessTokenExpired();
+
+ /**
+ * 强制将access token过期掉
+ */
+ void expireAccessToken();
+
+ /**
+ * 应该是线程安全的
+ *
+ * @param accessToken 要更新的WxAccessToken对象
+ */
+ void updateAccessToken(WxAccessToken accessToken);
+
+ /**
+ * 应该是线程安全的
+ *
+ * @param accessToken 新的accessToken值
+ * @param expiresInSeconds 过期时间,以秒为单位
+ */
+ void updateAccessToken(String accessToken, int expiresInSeconds);
+
+ /**
+ * Gets appid.
+ *
+ * @return the appid
+ */
+ String getAppid();
+
+ /**
+ * Gets secret.
+ *
+ * @return the secret
+ */
+ String getSecret();
+
+ /**
+ * Gets token.
+ *
+ * @return the token
+ */
+ String getToken();
+
+ /**
+ * Gets aes key.
+ *
+ * @return the aes key
+ */
+ String getAesKey();
+
+ /**
+ * Gets msg data format.
+ *
+ * @return the msg data format
+ */
+ String getMsgDataFormat();
+
+ /**
+ * Gets expires time.
+ *
+ * @return the expires time
+ */
+ long getExpiresTime();
+
+ /**
+ * Gets http proxy host.
+ *
+ * @return the http proxy host
+ */
+ String getHttpProxyHost();
+
+ /**
+ * Gets http proxy port.
+ *
+ * @return the http proxy port
+ */
+ int getHttpProxyPort();
+
+ /**
+ * Gets http proxy username.
+ *
+ * @return the http proxy username
+ */
+ String getHttpProxyUsername();
+
+ /**
+ * Gets http proxy password.
+ *
+ * @return the http proxy password
+ */
+ String getHttpProxyPassword();
+
+ /**
+ * http 请求重试间隔
+ *
+ * {@link BaseWxChannelService#setRetrySleepMillis(int)(int)}
+ *
+ */
+ int getRetrySleepMillis();
+
+ /**
+ * http 请求最大重试次数
+ *
+ * {@link BaseWxChannelService#setMaxRetryTimes(int)}
+ *
+ */
+ int getMaxRetryTimes();
+
+ /**
+ * http client builder
+ *
+ * @return ApacheHttpClientBuilder apache http client builder
+ */
+ ApacheHttpClientBuilder getApacheHttpClientBuilder();
+
+ /**
+ * 是否自动刷新token
+ *
+ * @return the boolean
+ */
+ boolean autoRefreshToken();
+
+ /**
+ * 设置自定义的apiHost地址
+ * 具体取值,可以参考https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Interface_field_description.html
+ *
+ * @param apiHostUrl api域名地址
+ */
+ void setApiHostUrl(String apiHostUrl);
+
+ /**
+ * 获取自定义的apiHost地址,用于替换原请求中的https://api.weixin.qq.com
+ * 具体取值,可以参考https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Interface_field_description.html
+ *
+ * @return 自定义的api域名地址
+ */
+ String getApiHostUrl();
+
+ /**
+ * 获取自定义的获取accessToken地址,用于向自定义统一服务获取accessToken
+ *
+ * @return 自定义的获取accessToken地址
+ */
+ String getAccessTokenUrl();
+
+ /**
+ * 设置自定义的获取accessToken地址 可用于设置获取accessToken的自定义服务
+ *
+ * @param accessTokenUrl 自定义的获取accessToken地址
+ */
+ void setAccessTokenUrl(String accessTokenUrl);
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/config/impl/WxChannelDefaultConfigImpl.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/config/impl/WxChannelDefaultConfigImpl.java
new file mode 100644
index 0000000000..e32bcad83e
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/config/impl/WxChannelDefaultConfigImpl.java
@@ -0,0 +1,233 @@
+package me.chanjar.weixin.channel.config.impl;
+
+import java.io.File;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+import lombok.Getter;
+import me.chanjar.weixin.channel.config.WxChannelConfig;
+import me.chanjar.weixin.channel.util.JsonUtils;
+import me.chanjar.weixin.common.bean.WxAccessToken;
+import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder;
+
+/**
+ * 基于内存的微信配置provider,在实际生产环境中应该将这些配置持久化
+ *
+ * @author Zeyes
+ */
+@Getter
+public class WxChannelDefaultConfigImpl implements WxChannelConfig {
+
+ protected volatile String appid;
+ protected volatile String token;
+ protected Lock accessTokenLock = new ReentrantLock();
+ /**
+ * 临时文件目录.
+ */
+ protected volatile File tmpDirFile;
+ private volatile String msgDataFormat;
+ private volatile String secret;
+ private volatile String accessToken;
+ private volatile String aesKey;
+ private volatile long expiresTime;
+ private volatile String httpProxyHost;
+ private volatile int httpProxyPort;
+ private volatile String httpProxyUsername;
+ private volatile String httpProxyPassword;
+
+ private volatile int retrySleepMillis = 1000;
+ private volatile int maxRetryTimes = 5;
+ private volatile ApacheHttpClientBuilder apacheHttpClientBuilder;
+ private String apiHostUrl;
+ private String accessTokenUrl;
+
+ /**
+ * 会过期的数据提前过期时间,默认预留200秒的时间
+ */
+ protected long expiresAheadInMillis(int expiresInSeconds) {
+ return System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L;
+ }
+
+ /**
+ * 判断 expiresTime 是否已经过期
+ */
+ protected boolean isExpired(long expiresTime) {
+ return System.currentTimeMillis() > expiresTime;
+ }
+
+ @Override
+ public String getAccessToken() {
+ return this.accessToken;
+ }
+
+ public void setAccessToken(String accessToken) {
+ this.accessToken = accessToken;
+ }
+
+ @Override
+ public Lock getAccessTokenLock() {
+ return this.accessTokenLock;
+ }
+
+ public void setAccessTokenLock(Lock accessTokenLock) {
+ this.accessTokenLock = accessTokenLock;
+ }
+
+ @Override
+ public boolean isAccessTokenExpired() {
+ return isExpired(this.expiresTime);
+ }
+
+ @Override
+ public synchronized void updateAccessToken(WxAccessToken accessToken) {
+ updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn());
+ }
+
+ @Override
+ public synchronized void updateAccessToken(String accessToken, int expiresInSeconds) {
+ setAccessToken(accessToken);
+ setExpiresTime(expiresAheadInMillis(expiresInSeconds));
+ }
+
+
+ @Override
+ public void expireAccessToken() {
+ this.expiresTime = 0;
+ }
+
+ @Override
+ public String getSecret() {
+ return this.secret;
+ }
+
+ public void setSecret(String secret) {
+ this.secret = secret;
+ }
+
+ @Override
+ public String getToken() {
+ return this.token;
+ }
+
+ public void setToken(String token) {
+ this.token = token;
+ }
+
+ @Override
+ public long getExpiresTime() {
+ return this.expiresTime;
+ }
+
+ public void setExpiresTime(long expiresTime) {
+ this.expiresTime = expiresTime;
+ }
+
+ @Override
+ public String getAesKey() {
+ return this.aesKey;
+ }
+
+ public void setAesKey(String aesKey) {
+ this.aesKey = aesKey;
+ }
+
+ @Override
+ public String getMsgDataFormat() {
+ return this.msgDataFormat;
+ }
+
+ public void setMsgDataFormat(String msgDataFormat) {
+ this.msgDataFormat = msgDataFormat;
+ }
+
+ @Override
+ public String getHttpProxyHost() {
+ return this.httpProxyHost;
+ }
+
+ public void setHttpProxyHost(String httpProxyHost) {
+ this.httpProxyHost = httpProxyHost;
+ }
+
+ @Override
+ public int getHttpProxyPort() {
+ return this.httpProxyPort;
+ }
+
+ public void setHttpProxyPort(int httpProxyPort) {
+ this.httpProxyPort = httpProxyPort;
+ }
+
+ @Override
+ public String getHttpProxyUsername() {
+ return this.httpProxyUsername;
+ }
+
+ public void setHttpProxyUsername(String httpProxyUsername) {
+ this.httpProxyUsername = httpProxyUsername;
+ }
+
+ @Override
+ public String getHttpProxyPassword() {
+ return this.httpProxyPassword;
+ }
+
+ public void setHttpProxyPassword(String httpProxyPassword) {
+ this.httpProxyPassword = httpProxyPassword;
+ }
+
+ @Override
+ public int getRetrySleepMillis() {
+ return this.retrySleepMillis;
+ }
+
+ public void setRetrySleepMillis(int retrySleepMillis) {
+ this.retrySleepMillis = retrySleepMillis;
+ }
+
+ @Override
+ public int getMaxRetryTimes() {
+ return this.maxRetryTimes;
+ }
+
+ public void setMaxRetryTimes(int maxRetryTimes) {
+ this.maxRetryTimes = maxRetryTimes;
+ }
+
+ @Override
+ public String toString() {
+ return JsonUtils.encode(this);
+ }
+
+ @Override
+ public ApacheHttpClientBuilder getApacheHttpClientBuilder() {
+ return this.apacheHttpClientBuilder;
+ }
+
+ public void setApacheHttpClientBuilder(ApacheHttpClientBuilder apacheHttpClientBuilder) {
+ this.apacheHttpClientBuilder = apacheHttpClientBuilder;
+ }
+
+ @Override
+ public boolean autoRefreshToken() {
+ return true;
+ }
+
+ @Override
+ public void setApiHostUrl(String apiHostUrl) {
+ this.apiHostUrl = apiHostUrl;
+ }
+
+ @Override
+ public void setAccessTokenUrl(String accessTokenUrl) {
+ this.accessTokenUrl = accessTokenUrl;
+ }
+
+ @Override
+ public String getAppid() {
+ return appid;
+ }
+
+ public void setAppid(String appid) {
+ this.appid = appid;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/config/impl/WxChannelRedisConfigImpl.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/config/impl/WxChannelRedisConfigImpl.java
new file mode 100644
index 0000000000..cbb289c899
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/config/impl/WxChannelRedisConfigImpl.java
@@ -0,0 +1,73 @@
+package me.chanjar.weixin.channel.config.impl;
+
+import java.util.concurrent.TimeUnit;
+import me.chanjar.weixin.common.redis.WxRedisOps;
+
+/**
+ * 基于redis存储的微信视频号小店配置类
+ *
+ * @author Zeyes
+ */
+public class WxChannelRedisConfigImpl extends WxChannelDefaultConfigImpl {
+
+ private static final String ACCESS_TOKEN_KEY_TPL = "%s:access_token:%s";
+ private static final String LOCK_KEY_TPL = "%s:lock:%s:";
+
+ private final WxRedisOps redisOps;
+ private final String keyPrefix;
+
+ private volatile String accessTokenKey;
+ private volatile String lockKey;
+
+ public WxChannelRedisConfigImpl(WxRedisOps redisOps, String keyPrefix) {
+ this.redisOps = redisOps;
+ this.keyPrefix = keyPrefix;
+ }
+
+ @Override
+ public void setAppid(String appId) {
+ super.setAppid(appId);
+ this.accessTokenKey = String.format(ACCESS_TOKEN_KEY_TPL, this.keyPrefix, appId);
+ this.lockKey = String.format(LOCK_KEY_TPL, this.keyPrefix, appId);
+ super.accessTokenLock = this.redisOps.getLock(lockKey.concat("accessTokenLock"));
+ }
+
+ //------------------------------------------------------------------------
+ // token相关
+ //------------------------------------------------------------------------
+ @Override
+ public String getAccessToken() {
+ return redisOps.getValue(this.accessTokenKey);
+ }
+
+ @Override
+ public boolean isAccessTokenExpired() {
+ Long expire = redisOps.getExpire(this.accessTokenKey);
+ return expire == null || expire < 2;
+ }
+
+ @Override
+ public synchronized void updateAccessToken(String accessToken, int expiresInSeconds) {
+ redisOps.setValue(this.accessTokenKey, accessToken, expiresInSeconds - 200, TimeUnit.SECONDS);
+ }
+
+ @Override
+ public void expireAccessToken() {
+ redisOps.expire(this.accessTokenKey, 0, TimeUnit.SECONDS);
+ }
+
+
+ @Override
+ public String toString() {
+ return "WxChannelRedisConfigImpl{" +
+ "appid='" + appid + '\'' +
+ ", token='" + token + '\'' +
+ ", accessTokenLock=" + accessTokenLock +
+ ", tmpDirFile=" + tmpDirFile +
+ ", redisOps=" + redisOps +
+ ", keyPrefix='" + keyPrefix + '\'' +
+ ", accessTokenKey='" + accessTokenKey + '\'' +
+ ", lockKey='" + lockKey + '\'' +
+ '}';
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/config/impl/WxChannelRedissonConfigImpl.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/config/impl/WxChannelRedissonConfigImpl.java
new file mode 100644
index 0000000000..d5de517163
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/config/impl/WxChannelRedissonConfigImpl.java
@@ -0,0 +1,89 @@
+package me.chanjar.weixin.channel.config.impl;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Lock;
+import lombok.NonNull;
+import me.chanjar.weixin.common.bean.WxAccessToken;
+import me.chanjar.weixin.common.redis.RedissonWxRedisOps;
+import me.chanjar.weixin.common.redis.WxRedisOps;
+import org.apache.commons.lang3.StringUtils;
+import org.redisson.api.RedissonClient;
+
+/**
+ * 基于Redisson的实现
+ *
+ * @author yuanqixun
+ * created on 2020/5/3
+ */
+public class WxChannelRedissonConfigImpl extends WxChannelDefaultConfigImpl {
+
+ protected static final String LOCK_KEY = "wx_channel_lock:";
+ protected static final String MA_ACCESS_TOKEN_KEY = "wx_channel_access_token_key:";
+
+ /**
+ * redis 存储的 key 的前缀,可为空
+ */
+ protected String keyPrefix;
+ protected String accessTokenKey;
+ protected String lockKey;
+
+ private final WxRedisOps redisOps;
+
+ public WxChannelRedissonConfigImpl(@NonNull RedissonClient redissonClient, String keyPrefix) {
+ this(new RedissonWxRedisOps(redissonClient), keyPrefix);
+ }
+
+ public WxChannelRedissonConfigImpl(@NonNull RedissonClient redissonClient) {
+ this(redissonClient, null);
+ }
+
+ private WxChannelRedissonConfigImpl(@NonNull WxRedisOps redisOps, String keyPrefix) {
+ this.redisOps = redisOps;
+ this.keyPrefix = keyPrefix;
+ }
+
+ @Override
+ public void setAppid(String appid) {
+ super.setAppid(appid);
+ String prefix = StringUtils.isBlank(keyPrefix) ? "" :
+ (StringUtils.endsWith(keyPrefix, ":") ? keyPrefix : (keyPrefix + ":"));
+ lockKey = prefix + LOCK_KEY.concat(appid);
+ accessTokenKey = prefix + MA_ACCESS_TOKEN_KEY.concat(appid);
+ }
+
+ protected Lock getLockByKey(String key) {
+ return redisOps.getLock(key);
+ }
+
+ @Override
+ public Lock getAccessTokenLock() {
+ return getLockByKey(this.lockKey.concat(":").concat("accessToken"));
+ }
+
+ @Override
+ public String getAccessToken() {
+ return redisOps.getValue(this.accessTokenKey);
+ }
+
+ @Override
+ public boolean isAccessTokenExpired() {
+ Long expire = redisOps.getExpire(this.accessTokenKey);
+ return expire == null || expire < 2;
+ }
+
+ @Override
+ public void updateAccessToken(WxAccessToken accessToken) {
+ redisOps.setValue(this.accessTokenKey, accessToken.getAccessToken(), accessToken.getExpiresIn(), TimeUnit.SECONDS);
+ }
+
+ @Override
+ public void updateAccessToken(String accessToken, int expiresInSeconds) {
+ redisOps.setValue(this.accessTokenKey, accessToken, expiresInSeconds, TimeUnit.SECONDS);
+ }
+
+ @Override
+ public void expireAccessToken() {
+ redisOps.expire(this.accessTokenKey, 0, TimeUnit.SECONDS);
+ }
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/constant/MessageEventConstants.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/constant/MessageEventConstants.java
new file mode 100644
index 0000000000..e0e419efc6
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/constant/MessageEventConstants.java
@@ -0,0 +1,70 @@
+package me.chanjar.weixin.channel.constant;
+
+/**
+ * 消息回调
+ *
+ * @author Zeyes
+ */
+public interface MessageEventConstants {
+ /** 品牌资质事件回调 */
+ String BRAND = "channels_ec_brand";
+ /** 商品审核结果 */
+ String PRODUCT_SPU_AUDIT = "product_spu_audit";
+ /** 商品上下架 */
+ String PRODUCT_SPU_STATUS_UPDATE = "product_spu_listing";
+ /** 商品更新 */
+ String PRODUCT_SPU_UPDATE = "product_spu_update";
+ /** 类目审核结果 */
+ String PRODUCT_CATEGORY_AUDIT = "product_category_audit";
+ /** 订单下单 */
+ String ORDER_NEW = "channels_ec_order_new";
+ /** 订单取消 */
+ String ORDER_CANCEL = "channels_ec_order_cancel";
+ /** 订单支付成功 */
+ String ORDER_PAY = "channels_ec_order_pay";
+ /** 订单发货 */
+ String ORDER_DELIVER = "channels_ec_order_deliver";
+ /** 订单确认收货 */
+ String ORDER_CONFIRM = "channels_ec_order_confirm";
+ /** 订单结算成功 */
+ String ORDER_SETTLE = "channels_ec_order_settle";
+ /** 订单其他信息更新 */
+ String ORDER_EXT_INFO_UPDATE = "channels_ec_order_ext_info_update";
+ /** 订单状态更新 */
+ String ORDER_STATUS_UPDATE = "product_order_status_update";
+ /** 售后单更新通知 */
+ String AFTER_SALE_UPDATE = "channels_ec_aftersale_update";
+ /** 纠纷更新通知 */
+ String COMPLAINT_NOTIFY = "channels_ec_complaint_update";
+ // 优惠券相关
+ /** 优惠券领取通知 */
+ String RECEIVE_COUPON = "channels_ec_coupon_receive";
+ /** 创建优惠券通知 */
+ String CREATE_COUPON = "channels_ec_coupon_create";
+ /** 优惠券删除通知 */
+ String DELETE_COUPON = "channels_ec_coupon_delete";
+ /** 优惠券过期通知 */
+ String EXPIRE_COUPON = "channels_ec_coupon_expire";
+ /** 更新优惠券信息通知 */
+ String UPDATE_COUPON_INFO = "channels_ec_coupon_info_change";
+ /** 优惠券作废通知 */
+ String INVALID_COUPON = "channels_ec_coupon_invalid";
+ /** 用户优惠券过期通知 */
+ String USER_COUPON_EXPIRE = "channels_ec_user_coupon_expire";
+ /** 优惠券返还通知 */
+ String USER_COUPON_UNUSE = "channels_ec_user_coupon_unuse";
+ /** 优惠券核销通知 */
+ String USER_COUPON_USE = "channels_ec_user_coupon_use";
+ // 资金相关
+ /** 结算账户变更回调 */
+ String ACCOUNT_NOTIFY = "channels_ec_acct_notify";
+ /** 提现回调 */
+ String WITHDRAW_NOTIFY = "channels_ec_withdraw_notify";
+ /** 提现二维码回调 */
+ String QRCODE_STATUS = "qrcode_status";
+ // 团长
+ String SUPPLIER_ITEM_UPDATE = "head_supplier_item_update";
+ // 其他
+ /** 进入会话事件 */
+ String USER_ENTER_TEMP_SESSION = "user_enter_tempsession";
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/constant/WxChannelApiUrlConstants.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/constant/WxChannelApiUrlConstants.java
new file mode 100644
index 0000000000..cb29cfda39
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/constant/WxChannelApiUrlConstants.java
@@ -0,0 +1,354 @@
+package me.chanjar.weixin.channel.constant;
+
+import lombok.experimental.UtilityClass;
+
+/**
+ * 视频号小店接口地址常量
+ *
+ * @author Zeyes
+ */
+@UtilityClass
+public class WxChannelApiUrlConstants {
+
+ /**
+ * 获取access_token.
+ */
+ public static final String GET_ACCESS_TOKEN_URL =
+ "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
+
+ /** 基础接口 */
+ public interface Basics {
+
+ /** 获取店铺基本信息 */
+ String GET_SHOP_INFO = "https://api.weixin.qq.com/channels/ec/basics/info/get";
+ /** 上传图片 */
+ String IMG_UPLOAD_URL = "https://api.weixin.qq.com/channels/ec/basics/img/upload";
+ /** 上传资质图片 */
+ String UPLOAD_QUALIFICATION_FILE = "https://api.weixin.qq.com/channels/ec/basics/qualification/upload";
+ /** 下载图片 */
+ String GET_IMG_URL = "https://api.weixin.qq.com/channels/ec/basics/media/get";
+ /** 获取地址编码 */
+ String GET_ADDRESS_CODE = "https://api.weixin.qq.com/channels/ec/basics/addresscode/get";
+ }
+
+ /** 商品类目相关接口 */
+ public interface Category {
+
+ /** 获取所有的类目 */
+ String LIST_ALL_CATEGORY_URL = "https://api.weixin.qq.com/channels/ec/category/all";
+ /** 获取类目详情 */
+ String GET_CATEGORY_DETAIL_URL = "https://api.weixin.qq.com/channels/ec/category/detail";
+ /** 获取可用的子类目详情 */
+ String AVAILABLE_CATEGORY_URL = "https://api.weixin.qq.com/channels/ec/category/availablesoncategories/get";
+ /** 上传类目资质 */
+ String ADD_CATEGORY_URL = "https://api.weixin.qq.com/channels/ec/category/add";
+ /** 获取类目审核结果 */
+ String GET_CATEGORY_AUDIT_URL = "https://api.weixin.qq.com/channels/ec/category/audit/get";
+ /** 取消类目提审 */
+ String CANCEL_CATEGORY_AUDIT_URL = "https://api.weixin.qq.com/channels/ec/category/audit/cancel";
+ /** 获取账号申请通过的类目和资质信息 */
+ String LIST_PASS_CATEGORY_URL = "https://api.weixin.qq.com/channels/ec/category/list/get";
+ }
+
+ /** 品牌资质相关接口 */
+ public interface Brand {
+
+ /** 获取品牌库列表 */
+ String ALL_BRAND_URL = "https://api.weixin.qq.com/channels/ec/brand/all";
+ /** 新增品牌资质 */
+ String ADD_BRAND_URL = "https://api.weixin.qq.com/channels/ec/brand/add";
+ /** 更新品牌资质 */
+ String UPDATE_BRAND_URL = "https://api.weixin.qq.com/channels/ec/brand/update";
+ /** 撤回品牌资质审核 */
+ String CANCEL_BRAND_AUDIT_URL = "https://api.weixin.qq.com/channels/ec/brand/audit/cancel";
+ /** 删除品牌资质 */
+ String DELETE_BRAND_URL = "https://api.weixin.qq.com/channels/ec/brand/delete";
+ /** 获取品牌资质申请详情 */
+ String GET_BRAND_URL = "https://api.weixin.qq.com/channels/ec/brand/get";
+ /** 获取品牌资质申请列表 */
+ String LIST_BRAND_URL = "https://api.weixin.qq.com/channels/ec/brand/list/get";
+ /** 获取生效中的品牌资质列表 */
+ String LIST_BRAND_VALID_URL = "https://api.weixin.qq.com/channels/ec/brand/valid/list/get";
+ }
+
+ /** 商品操作相关接口 */
+ public interface Spu {
+
+ /** 添加商品 */
+ String SPU_ADD_URL = "https://api.weixin.qq.com/channels/ec/product/add";
+ /** 删除商品 */
+ String SPU_DEL_URL = "https://api.weixin.qq.com/channels/ec/product/delete";
+ /** 获取商品详情 */
+ String SPU_GET_URL = "https://api.weixin.qq.com/channels/ec/product/get";
+ /** 获取商品列表 */
+ String SPU_LIST_URL = "https://api.weixin.qq.com/channels/ec/product/list/get";
+ /** 更新商品 */
+ String SPU_UPDATE_URL = "https://api.weixin.qq.com/channels/ec/product/update";
+ /** 上架商品 */
+ String SPU_LISTING_URL = "https://api.weixin.qq.com/channels/ec/product/listing";
+ /** 下架商品 */
+ String SPU_DELISTING_URL = "https://api.weixin.qq.com/channels/ec/product/delisting";
+ /** 撤回商品审核 */
+ String CANCEL_AUDIT_URL = "https://api.weixin.qq.com/channels/ec/product/audit/cancel";
+ /** 获取实时库存 */
+ String SPU_GET_STOCK_URL = "https://api.weixin.qq.com/channels/ec/product/stock/get";
+ /** 更新商品库存 */
+ String SPU_UPDATE_STOCK_URL = "https://api.weixin.qq.com/channels/ec/product/stock/update";
+ /** 添加限时抢购任务 */
+ String ADD_LIMIT_TASK_URL = "https://api.weixin.qq.com/channels/ec/product/limiteddiscounttask/add";
+ /** 拉取限时抢购任务列表 */
+ String LIST_LIMIT_TASK_URL = "https://api.weixin.qq.com/channels/ec/product/limiteddiscounttask/list/get";
+ /** 停止限时抢购任务 */
+ String STOP_LIMIT_TASK_URL = "https://api.weixin.qq.com/channels/ec/product/limiteddiscounttask/stop";
+ /** 删除限时抢购任务 */
+ String DELETE_LIMIT_TASK_URL = "https://api.weixin.qq.com/channels/ec/product/limiteddiscounttask/delete";
+ }
+
+ /** 区域仓库 */
+ public interface Warehouse {
+
+ /** 添加区域仓库 */
+ String ADD_WAREHOUSE_URL = "https://api.weixin.qq.com/channels/ec/warehouse/create";
+ /** 获取区域仓库列表 */
+ String LIST_WAREHOUSE_URL = "https://api.weixin.qq.com/channels/ec/warehouse/list/get";
+ /** 获取区域仓库详情 */
+ String GET_WAREHOUSE_URL = "https://api.weixin.qq.com/channels/ec/warehouse/get";
+ /** 更新区域仓库详情 */
+ String UPDATE_WAREHOUSE_URL = "https://api.weixin.qq.com/channels/ec/warehouse/detail/update";
+ /** 批量增加覆盖区域 */
+ String ADD_COVER_AREA_URL = "https://api.weixin.qq.com/channels/ec/warehouse/coverlocations/add";
+ /** 批量删除覆盖区域 */
+ String DELETE_COVER_AREA_URL = "https://api.weixin.qq.com/channels/ec/warehouse/coverlocations/del";
+ /** 设置指定地址下的仓的优先级 */
+ String SET_WAREHOUSE_PRIORITY_URL = "https://api.weixin.qq.com/channels/ec/warehouse/address/prioritysort/set";
+ /** 获取指定地址下的仓的优先级 */
+ String GET_WAREHOUSE_PRIORITY_URL = "https://api.weixin.qq.com/channels/ec/warehouse/address/prioritysort/get";
+ /** 更新区域仓库存 */
+ String UPDATE_WAREHOUSE_STOCK_URL = "https://api.weixin.qq.com/channels/ec/warehouse/stock/update";
+ /** 获取区域仓库存 */
+ String GET_WAREHOUSE_STOCK_URL = "https://api.weixin.qq.com/channels/ec/warehouse/stock/get";
+ }
+
+ /** 订单相关接口 */
+ public interface Order {
+
+ /** 获取订单列表 */
+ String ORDER_LIST_URL = "https://api.weixin.qq.com/channels/ec/order/list/get";
+ /** 获取订单详情 */
+ String ORDER_GET_URL = "https://api.weixin.qq.com/channels/ec/order/get";
+ /** 更改订单价格 */
+ String UPDATE_PRICE_URL = "https://api.weixin.qq.com/channels/ec/order/price/update";
+ /** 修改订单备注 */
+ String UPDATE_REMARK_URL = "https://api.weixin.qq.com/channels/ec/order/merchantnotes/update";
+ /** 更修改订单地址 */
+ String UPDATE_ADDRESS_URL = "https://api.weixin.qq.com/channels/ec/order/address/update";
+ /** 修改物流信息 */
+ String UPDATE_EXPRESS_URL = "https://api.weixin.qq.com/channels/ec/order/deliveryinfo/update";
+ /** 同意用户修改收货地址申请 */
+ String ACCEPT_ADDRESS_MODIFY_URL = "https://api.weixin.qq.com/channels/ec/order/addressmodify/accept";
+ /** 拒绝用户修改收货地址申请 */
+ String REJECT_ADDRESS_MODIFY_URL = "https://api.weixin.qq.com/channels/ec/order/addressmodify/reject";
+ /** 订单搜索 */
+ String ORDER_SEARCH_URL = "https://api.weixin.qq.com/channels/ec/order/search";
+ }
+
+ /** 售后相关接口 */
+ public interface AfterSale {
+
+ /** 获取售后列表 */
+ String AFTER_SALE_LIST_URL = "https://api.weixin.qq.com/channels/ec/aftersale/getaftersalelist";
+ /** 获取售后单 */
+ String AFTER_SALE_GET_URL = "https://api.weixin.qq.com/channels/ec/aftersale/getaftersaleorder";
+ /** 同意售后 */
+ String AFTER_SALE_ACCEPT_URL = "https://api.weixin.qq.com/channels/ec/aftersale/acceptapply";
+ /** 拒绝售后 */
+ String AFTER_SALE_REJECT_URL = "https://api.weixin.qq.com/channels/ec/aftersale/rejectapply";
+ /** 上传退款凭证 */
+ String AFTER_SALE_UPLOAD_URL = "https://api.weixin.qq.com/channels/ec/aftersale/uploadrefundcertificate";
+ }
+
+ /** 纠纷相关接口 */
+ public interface Complaint {
+
+ /** 商家补充纠纷单留言 */
+ String ADD_COMPLAINT_MATERIAL_URL = "https://api.weixin.qq.com/channels/ec/aftersale/addcomplaintmaterial";
+ /** 商家举证 */
+ String ADD_COMPLAINT_PROOF_URL = "https://api.weixin.qq.com/channels/ec/aftersale/addcomplaintproof";
+ /** 获取纠纷单 */
+ String GET_COMPLAINT_ORDER_URL = "https://api.weixin.qq.com/channels/ec/aftersale/getcomplaintorder";
+ }
+
+ /** 物流相关接口 */
+ public interface Delivery {
+
+ /** 获取快递公司列表 */
+ String GET_DELIVERY_COMPANY_URL = "https://api.weixin.qq.com/channels/ec/order/deliverycompanylist/get";
+ /** 订单发货 */
+ String DELIVERY_SEND_URL = "https://api.weixin.qq.com/channels/ec/order/delivery/send";
+ }
+
+ /** 运费模板相关接口 */
+ public interface FreightTemplate {
+
+ /** 获取运费模板列表 */
+ String LIST_TEMPLATE_URL = "https://api.weixin.qq.com/channels/ec/merchant/getfreighttemplatelist";
+ /** 查询运费模版 */
+ String GET_TEMPLATE_URL = "https://api.weixin.qq.com/channels/ec/merchant/getfreighttemplatedetail";
+ /** 增加运费模版 */
+ String ADD_TEMPLATE_URL = "https://api.weixin.qq.com/channels/ec/merchant/addfreighttemplate";
+ /** 更新运费模版 */
+ String UPDATE_TEMPLATE_URL = "https://api.weixin.qq.com/channels/ec/merchant/updatefreighttemplate";
+ }
+
+ /** 地址管理相关接口 */
+ public interface Address {
+
+ /** 增加地址 */
+ String ADD_ADDRESS_URL = "https://api.weixin.qq.com/channels/ec/merchant/address/add";
+ /** 获取地址列表 */
+ String LIST_ADDRESS_URL = "https://api.weixin.qq.com/channels/ec/merchant/address/list";
+ /** 获取地址详情 */
+ String GET_ADDRESS_URL = "https://api.weixin.qq.com/channels/ec/merchant/address/get";
+ /** 更新地址 */
+ String UPDATE_ADDRESS_URL = "https://api.weixin.qq.com/channels/ec/merchant/address/update";
+ /** 删除地址 */
+ String DELETE_ADDRESS_URL = "https://api.weixin.qq.com/channels/ec/merchant/address/delete";
+ }
+
+ /** 优惠券相关接口 */
+ public interface Coupon {
+
+ /** 创建优惠券 */
+ String CREATE_COUPON_URL = "https://api.weixin.qq.com/channels/ec/coupon/create";
+ /** 更新优惠券 */
+ String UPDATE_COUPON_URL = "https://api.weixin.qq.com/channels/ec/coupon/update";
+ /** 更新优惠券状态 */
+ String UPDATE_COUPON_STATUS_URL = "https://api.weixin.qq.com/channels/ec/coupon/update_status";
+ /** 获取优惠券详情 */
+ String GET_COUPON_URL = "https://api.weixin.qq.com/channels/ec/coupon/get";
+ /** 获取优惠券ID列表 */
+ String LIST_COUPON_URL = "https://api.weixin.qq.com/channels/ec/coupon/get_list";
+ /** 获取用户优惠券ID列表 */
+ String LIST_USER_COUPON_URL = "https://api.weixin.qq.com/channels/ec/coupon/get_user_coupon_list";
+ /** 获取用户优惠券详情 */
+ String GET_USER_COUPON_URL = "https://api.weixin.qq.com/channels/ec/coupon/get_user_coupon";
+ }
+
+ /** 分享员相关接口 */
+ public interface Share {
+
+ /** 邀请分享员 */
+ String BIND_SHARER_URL = "https://api.weixin.qq.com/channels/ec/sharer/bind";
+ /** 获取绑定的分享员 */
+ String SEARCH_SHARER_URL = "https://api.weixin.qq.com/channels/ec/sharer/search_sharer";
+ /** 获取绑定的分享员列表 */
+ String LIST_SHARER_URL = "https://api.weixin.qq.com/channels/ec/sharer/get_sharer_list";
+ /** 获取分享员订单列表 */
+ String LIST_SHARER_ORDER_URL = "https://api.weixin.qq.com/channels/ec/sharer/get_sharer_order_list";
+ /** 解绑分享员 */
+ String UNBIND_SHARER_URL = "https://api.weixin.qq.com/channels/ec/sharer/unbind";
+ }
+
+ /** 资金相关接口 */
+ public interface Fund {
+
+ /** 获取账户余额 */
+ String GET_BALANCE_URL = "https://api.weixin.qq.com/channels/ec/funds/getbalance";
+ /** 获取结算账户 */
+ String GET_BANK_ACCOUNT_URL = "https://api.weixin.qq.com/channels/ec/funds/getbankacct";
+ /** 获取资金流水详情 */
+ String GET_BALANCE_FLOW_DETAIL_URL = "https://api.weixin.qq.com/channels/ec/league/funds/getfundsflowdetail";
+ /** 获取资金流水列表 */
+ String GET_BALANCE_FLOW_LIST_URL = "https://api.weixin.qq.com/channels/ec/league/funds/getfundsflowlist";
+ /** 获取提现记录 */
+ String GET_WITHDRAW_DETAIL_URL = "https://api.weixin.qq.com/channels/ec/funds/getwithdrawdetail";
+ /** 获取提现记录列表 */
+ String GET_WITHDRAW_LIST_URL = "https://api.weixin.qq.com/channels/ec/funds/getwithdrawlist";
+ /** 修改结算账户 */
+ String SET_BANK_ACCOUNT_URL = "https://api.weixin.qq.com/channels/ec/funds/setbankacct";
+ /** 商户提现 */
+ String WITHDRAW_URL = "https://api.weixin.qq.com/channels/ec/funds/submitwithdraw";
+ /** 根据卡号查银行信息 */
+ String GET_BANK_BY_NUM_URL = "https://api.weixin.qq.com/shop/funds/getbankbynum";
+ /** 搜索银行列表 */
+ String GET_BANK_LIST_URL = "https://api.weixin.qq.com/shop/funds/getbanklist";
+ /** 查询城市列表 */
+ String GET_CITY_URL = "https://api.weixin.qq.com/shop/funds/getcity";
+ /** 查询大陆银行省份列表 */
+ String GET_PROVINCE_URL = "https://api.weixin.qq.com/shop/funds/getprovince";
+ /** 查询支行列表 */
+ String GET_SUB_BANK_URL = "https://api.weixin.qq.com/shop/funds/getsubbranch";
+ /** 获取二维码 */
+ String GET_QRCODE_URL = "https://api.weixin.qq.com/shop/funds/qrcode/get";
+ /** 查询扫码状态 */
+ String CHECK_QRCODE_URL = "https://api.weixin.qq.com/shop/funds/qrcode/check";
+ }
+
+ /** 优选联盟相关接口 */
+ public interface League {
+
+ /** 添加团长商品到橱窗 */
+ String ADD_SUPPLIER_GOODS_URL = "https://api.weixin.qq.com/channels/ec/league/headsupplier/window/add";
+ /** 查询橱窗上团长商品列表 */
+ String LIST_SUPPLIER_GOODS_URL = "https://api.weixin.qq.com/channels/ec/league/headsupplier/window/getall";
+ /** 从橱窗移除团长商品 */
+ String REMOVE_SUPPLIER_GOODS_URL = "https://api.weixin.qq.com/channels/ec/league/headsupplier/window/remove";
+ /** 查询橱窗上团长商品详情 */
+ String GET_SUPPLIER_GOODS_URL = "https://api.weixin.qq.com/channels/ec/league/headsupplier/window/getdetail";
+ /** 获取达人橱窗授权链接 */
+ String GET_SUPPLIER_AUTH_URL = "https://api.weixin.qq.com/channels/ec/league/headsupplier/windowauth/get";
+ /** 获取达人橱窗授权状态 */
+ String GET_SUPPLIER_AUTH_STATUS_URL = "https://api.weixin.qq.com/channels/ec/league/headsupplier/windowauth/status/get";
+ /** 获取团长账户余额 */
+ String GET_SUPPLIER_BALANCE_URL = "https://api.weixin.qq.com/channels/ec/league/headsupplier/funds/balance/get";
+ /** 获取资金流水详情 */
+ String GET_SUPPLIER_BALANCE_FLOW_DETAIL_URL = "https://api.weixin.qq.com/channels/ec/league/headsupplier/funds/flowdetail/get";
+ /** 获取资金流水列表 */
+ String GET_SUPPLIER_BALANCE_FLOW_LIST_URL = "https://api.weixin.qq.com/channels/ec/league/headsupplier/funds/flowlist/get";
+ /** 获取合作商品详情 */
+ String GET_SUPPLIER_ITEM_URL = "https://api.weixin.qq.com/channels/ec/league/headsupplier/item/get";
+ /** 获取合作商品列表 */
+ String GET_SUPPLIER_ITEM_LIST_URL = "https://api.weixin.qq.com/channels/ec/league/headsupplier/item/list/get";
+ /** 获取佣金单详情 */
+ String GET_SUPPLIER_ORDER_URL = "https://api.weixin.qq.com/channels/ec/league/headsupplier/order/get";
+ /** 获取佣金单列表 */
+ String GET_SUPPLIER_ORDER_LIST_URL = "https://api.weixin.qq.com/channels/ec/league/headsupplier/order/list/get";
+ /** 获取合作小店详情 */
+ String GET_SUPPLIER_SHOP_URL = "https://api.weixin.qq.com/channels/ec/league/headsupplier/shop/get";
+ /** 获取合作小店列表 */
+ String GET_SUPPLIER_SHOP_LIST_URL = "https://api.weixin.qq.com/channels/ec/league/headsupplier/shop/list/get";
+ /** 新增达人 */
+ String ADD_PROMOTER_URL = "https://api.weixin.qq.com/channels/ec/league/promoter/add";
+ /** 编辑达人 */
+ String EDIT_PROMOTER_URL = "https://api.weixin.qq.com/channels/ec/league/promoter/upd";
+ /** 删除达人 */
+ String DELETE_PROMOTER_URL = "https://api.weixin.qq.com/channels/ec/league/promoter/delete";
+ /** 获取达人详情信息 */
+ String GET_PROMOTER_URL = "https://api.weixin.qq.com/channels/ec/league/promoter/get";
+ /** 拉取商店达人列表 */
+ String GET_PROMOTER_LIST_URL = "https://api.weixin.qq.com/channels/ec/league/promoter/list/get";
+ /** 批量新增联盟商品 */
+ String BATCH_ADD_LEAGUE_ITEM_URL = "https://api.weixin.qq.com/channels/ec/league/item/batchadd";
+ /** 更新联盟商品信息 */
+ String UPDATE_LEAGUE_ITEM_URL = "https://api.weixin.qq.com/channels/ec/league/item/upd";
+ /** 删除联盟商品 */
+ String DELETE_LEAGUE_ITEM_URL = "https://api.weixin.qq.com/channels/ec/league/item/delete";
+ /** 拉取联盟商品详情 */
+ String GET_LEAGUE_ITEM_URL = "https://api.weixin.qq.com/channels/ec/league/item/get";
+ /** 拉取联盟商品推广列表 */
+ String GET_LEAGUE_ITEM_LIST_URL = "https://api.weixin.qq.com/channels/ec/league/item/list/get";
+ }
+
+ /** 视频号助手开放接口 */
+ public interface Assistant {
+
+ /** 上架商品到橱窗 */
+ String ADD_WINDOW_PRODUCT_URL = "https://api.weixin.qq.com/channels/ec/window/product/add";
+ /** 获取橱窗商品详情 */
+ String GET_WINDOW_PRODUCT_URL = "https://api.weixin.qq.com/channels/ec/window/product/get";
+ /** 获取已添加到橱窗的商品列表 */
+ String LIST_WINDOW_PRODUCT_URL = "https://api.weixin.qq.com/channels/ec/window/product/list/get";
+ /** 下架橱窗商品 */
+ String OFF_WINDOW_PRODUCT_URL = "https://api.weixin.qq.com/channels/ec/window/product/off";
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/AccountType.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/AccountType.java
new file mode 100644
index 0000000000..96cfc43956
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/AccountType.java
@@ -0,0 +1,43 @@
+package me.chanjar.weixin.channel.enums;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 视频号小店 账户类型
+ *
+ * @author Zeyes
+ */
+@JsonFormat(shape = JsonFormat.Shape.OBJECT)
+public enum AccountType {
+ /** 对公银行账户 */
+ ACCOUNT_TYPE_BUSINESS("ACCOUNT_TYPE_BUSINESS", "对公银行账户"),
+ /** 经营者个人银行卡 */
+ ACCOUNT_TYPE_PRIVATE("ACCOUNT_TYPE_PRIVATE", "经营者个人银行卡"),
+
+ ;
+
+ private final String key;
+ private final String value;
+
+ AccountType(String key, String value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ public static AccountType getByKey(String key) {
+ for (AccountType reason : AccountType.values()) {
+ if (reason.getKey().equals(key)) {
+ return reason;
+ }
+ }
+ return ACCOUNT_TYPE_PRIVATE;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/AfterSaleStatus.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/AfterSaleStatus.java
new file mode 100644
index 0000000000..60e77d9e53
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/AfterSaleStatus.java
@@ -0,0 +1,60 @@
+package me.chanjar.weixin.channel.enums;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 视频号小店 售后单状态
+ *
+ * @author Zeyes
+ */
+@JsonFormat(shape = JsonFormat.Shape.OBJECT)
+public enum AfterSaleStatus {
+ /** 用户取消申请 */
+ USER_CANCELD("USER_CANCELD", "用户取消申请"),
+ /** 商家受理中 */
+ MERCHANT_PROCESSING("MERCHANT_PROCESSING", "商家受理中"),
+ /** 商家拒绝退款 */
+ MERCHANT_REJECT_REFUND("MERCHANT_REJECT_REFUND", "商家拒绝退款"),
+ /** 商家拒绝退货退款 */
+ MERCHANT_REJECT_RETURN("MERCHANT_REJECT_RETURN", "商家拒绝退货退款"),
+ /** 待买家退货 */
+ USER_WAIT_RETURN("USER_WAIT_RETURN", "待买家退货"),
+ /** 7 售后单关闭 */
+ RETURN_CLOSED("RETURN_CLOSED", "退货退款关闭"),
+ /** 8 待商家收货 */
+ MERCHANT_WAIT_RECEIPT("MERCHANT_WAIT_RECEIPT", "待商家收货"),
+ /** 商家逾期未退款 */
+ MERCHANT_OVERDUE_REFUND("MERCHANT_OVERDUE_REFUND", "商家逾期未退款"),
+ /** 退款完成 */
+ MERCHANT_REFUND_SUCCESS("MERCHANT_REFUND_SUCCESS", "退款完成"),
+ /** 退货退款完成 */
+ MERCHANT_RETURN_SUCCESS("MERCHANT_RETURN_SUCCESS", "退货退款完成"),
+ /** 11 平台退款中 */
+ PLATFORM_REFUNDING("PLATFORM_REFUNDING", "平台退款中"),
+ /** 25 平台退款失败 */
+ PLATFORM_REFUND_FAIL("PLATFORM_REFUND_FAIL", "平台退款失败"),
+ /** 待用户确认 */
+ USER_WAIT_CONFIRM("USER_WAIT_CONFIRM", "待用户确认"),
+ /** 商家打款失败,客服关闭售后 */
+ MERCHANT_REFUND_RETRY_FAIL("MERCHANT_REFUND_RETRY_FAIL", "商家打款失败,客服关闭售后"),
+ /** 售后关闭 */
+ MERCHANT_FAIL("MERCHANT_FAIL", "售后关闭"),
+ ;
+
+ private final String key;
+ private final String value;
+
+ AfterSaleStatus(String key, String value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/AfterSaleType.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/AfterSaleType.java
new file mode 100644
index 0000000000..8cbdf521f5
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/AfterSaleType.java
@@ -0,0 +1,32 @@
+package me.chanjar.weixin.channel.enums;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 售后类型
+ *
+ * @author Zeyes
+ */
+@JsonFormat(shape = JsonFormat.Shape.OBJECT)
+public enum AfterSaleType {
+ /** 1 仅退款 */
+ REFUND_ONLY("REFUND", "仅退款"),
+ /** 2 退货退款 */
+ REFUND_GOODS("RETURN", "退货退款");
+
+ private final String key;
+ private final String value;
+
+ AfterSaleType(String key, String value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/AfterSalesReason.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/AfterSalesReason.java
new file mode 100644
index 0000000000..c3409a05cd
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/AfterSalesReason.java
@@ -0,0 +1,63 @@
+package me.chanjar.weixin.channel.enums;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 视频号小店 售后原因
+ *
+ * @author Zeyes
+ */
+@JsonFormat(shape = JsonFormat.Shape.OBJECT)
+public enum AfterSalesReason {
+ /** 拍错/多拍 */
+ INCORRECT_SELECTION("INCORRECT_SELECTION", "拍错/多拍"),
+ /** 不想要了 */
+ NO_LONGER_WANT("NO_LONGER_WANT", "不想要了"),
+ /** 无快递信息 */
+ NO_EXPRESS_INFO("NO_EXPRESS_INFO", "无快递信息"),
+ /** 包裹为空 */
+ EMPTY_PACKAGE("EMPTY_PACKAGE", "包裹为空"),
+ /** 已拒签包裹 */
+ REJECT_RECEIVE_PACKAGE("REJECT_RECEIVE_PACKAGE", "已拒签包裹"),
+ /** 快递长时间未送达 */
+ NOT_DELIVERED_TOO_LONG("NOT_DELIVERED_TOO_LONG", "快递长时间未送达了"),
+ /** 与商品描述不符 */
+ NOT_MATCH_PRODUCT_DESC("NOT_MATCH_PRODUCT_DESC", "与商品描述不符"),
+ /** 质量问题 */
+ QUALITY_ISSUE("QUALITY_ISSUE", "质量问题"),
+ /** 卖家发错货 */
+ SEND_WRONG_GOODS("SEND_WRONG_GOODS", "卖家发错货"),
+ /** 三无产品 */
+ THREE_NO_PRODUCT("THREE_NO_PRODUCT", "三无产品"),
+ /** 假冒产品 */
+ FAKE_PRODUCT("FAKE_PRODUCT", "假冒产品"),
+ /** 其它 */
+ OTHERS("OTHERS", "其它"),
+ ;
+
+ private final String key;
+ private final String value;
+
+ AfterSalesReason(String key, String value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ public static AfterSalesReason getByKey(String key) {
+ for (AfterSalesReason reason : AfterSalesReason.values()) {
+ if (reason.getKey().equals(key)) {
+ return reason;
+ }
+ }
+ // 找不到就返回其他了
+ return OTHERS;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/CommissionOrderStatus.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/CommissionOrderStatus.java
new file mode 100644
index 0000000000..bdf29d2765
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/CommissionOrderStatus.java
@@ -0,0 +1,37 @@
+package me.chanjar.weixin.channel.enums;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 佣金订单状态
+ *
+ * @author Zeyes
+ */
+@JsonFormat(shape = JsonFormat.Shape.OBJECT)
+public enum CommissionOrderStatus {
+
+ /** 20 未结算 */
+ NOT_SETTLED(20, "未结算"),
+ /** 100 已结算 */
+ SETTLED(100, "已结算"),
+ /** 200 取消结算 */
+ CANCEL_SETTLED(200, "取消结算"),
+
+ ;
+
+ private final int key;
+ private final String val;
+
+ CommissionOrderStatus(int key, String val) {
+ this.key = key;
+ this.val = val;
+ }
+
+ public int getKey() {
+ return key;
+ }
+
+ public String getVal() {
+ return val;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/ComplaintItemType.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/ComplaintItemType.java
new file mode 100644
index 0000000000..d7f1aae8ec
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/ComplaintItemType.java
@@ -0,0 +1,112 @@
+package me.chanjar.weixin.channel.enums;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 纠纷历史操作类型
+ *
+ * @author Zeyes
+ */
+@JsonFormat(shape = JsonFormat.Shape.OBJECT)
+public enum ComplaintItemType {
+ /** 1 申请平台介入 */
+ APPLY_PLATFORM_INTERVENTION(1, "申请平台介入"),
+ /** 2 用户留言 */
+ USER_MESSAGE(2, "用户留言"),
+ /** 3 商家留言 */
+ MERCHANT_MESSAGE(3, "商家留言"),
+ /** 4 提交投诉成功 */
+ SUBMIT_COMPLAINT_SUCCESS(4, "提交投诉成功"),
+ /** 5 投诉已取消 */
+ COMPLAINT_CANCELLED(5, "投诉已取消"),
+ /** 6 商家已超时 */
+ MERCHANT_TIMEOUT(6, "商家已超时"),
+ /** 7 用户补充凭证 */
+ USER_SUPPLEMENTARY_EVIDENCE(7, "用户补充凭证"),
+ /** 8 商家补充凭证 */
+ MERCHANT_SUPPLEMENTARY_EVIDENCE(8, "商家补充凭证"),
+ /** 10 待商家处理纠纷 */
+ WAIT_MERCHANT_HANDLE_DISPUTE(10, "待商家处理纠纷"),
+ /** 11 待平台处理 */
+ WAIT_PLATFORM_HANDLE(11, "待平台处理"),
+ /** 12 取消平台介入 */
+ CANCEL_PLATFORM_INTERVENTION(12, "取消平台介入"),
+ /** 13 平台处理中 */
+ PLATFORM_PROCESSING(13, "平台处理中"),
+ /** 14 待用户补充凭证 */
+ WAIT_USER_SUPPLEMENTARY_EVIDENCE(14, "待用户补充凭证"),
+ /** 16 待商家补充凭证 */
+ WAIT_MERCHANT_SUPPLEMENTARY_EVIDENCE(16, "待商家补充凭证"),
+ /** 18 待双方补充凭证 */
+ WAIT_BOTH_PARTIES_SUPPLEMENTARY_EVIDENCE(18, "待双方补充凭证"),
+ /** 20 待商家确认 */
+ WAIT_MERCHANT_CONFIRM(20, "待商家确认"),
+ /** 21 商家申诉中 */
+ MERCHANT_APPEALING(21, "商家申诉中"),
+ /** 22 调解完成 */
+ MEDIATION_COMPLETE(22, "调解完成"),
+ /** 23 待平台核实 */
+ WAIT_PLATFORM_VERIFY(23, "待平台核实"),
+ /** 24 重新退款中 */
+ REFUNDING_AGAIN(24, "重新退款中"),
+ /** 26 调解关闭 */
+ MEDIATION_CLOSED(26, "调解关闭"),
+ /** 30 平台判定用户责任 */
+ PLATFORM_JUDGMENT_USER_RESPONSIBILITY(30, "平台判定用户责任"),
+ /** 31 平台判定商家责任 */
+ PLATFORM_JUDGMENT_MERCHANT_RESPONSIBILITY(31, "平台判定商家责任"),
+ /** 32 平台判定双方责任 */
+ PLATFORM_JUDGMENT_BOTH_PARTIES_RESPONSIBILITY(32, "平台判定双方责任"),
+ /** 33 平台判定无责任 */
+ PLATFORM_JUDGMENT_NO_RESPONSIBILITY(33, "平台判定无责任"),
+ /** 34 平台判定申诉无效 */
+ PLATFORM_JUDGMENT_APPEAL_INVALID(34, "平台判定申诉无效"),
+ /** 35 平台判定申诉生效 */
+ PLATFORM_JUDGMENT_APPEAL_EFFECTIVE(35, "平台判定申诉生效"),
+ /** 36 平台判定退款有效 */
+ PLATFORM_JUDGMENT_REFUND_EFFECTIVE(36, "平台判定退款有效"),
+ /** 37 平台判定退款无效 */
+ PLATFORM_JUDGMENT_REFUND_INVALID(37, "平台判定退款无效"),
+ /** 50 用户发起退款 */
+ USER_INITIATE_REFUND(50, "用户发起退款"),
+ /** 51 商家拒绝退款 */
+ MERCHANT_REFUSE_REFUND(51, "商家拒绝退款"),
+ /** 52 用户取消申请 */
+ USER_CANCEL_APPLICATION(52, "用户取消申请"),
+ /** 56 待买家退货 */
+ WAIT_BUYER_RETURN_GOODS(56, "待买家退货"),
+ /** 57 退货退款关闭 */
+ REFUND_CLOSED(57, "退货退款关闭"),
+ /** 58 待商家收货 */
+ WAIT_MERCHANT_RECEIVE_GOODS(58, "待商家收货"),
+ /** 59 商家逾期未退款 */
+ MERCHANT_OVERDUE_REFUND(59, "商家逾期未退款"),
+ /** 60 退款完成 */
+ REFUND_COMPLETE(60, "退款完成"),
+ /** 61 退货退款完成 */
+ REFUND_GOODS_COMPLETE(61, "退货退款完成"),
+ /** 62 平台退款中 */
+ PLATFORM_REFUNDING(62, "平台退款中"),
+ /** 63 平台退款失败 */
+ PLATFORM_REFUND_FAILED(63, "平台退款失败"),
+ /** 64 待用户确认 */
+ WAIT_USER_CONFIRM(64, "待用户确认"),
+
+ ;
+
+ private final int key;
+ private final String value;
+
+ ComplaintItemType(int key, String value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ public int getKey() {
+ return key;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/ComplaintStatus.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/ComplaintStatus.java
new file mode 100644
index 0000000000..c11c5fc432
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/ComplaintStatus.java
@@ -0,0 +1,30 @@
+package me.chanjar.weixin.channel.enums;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 纠纷单状态
+ *
+ * @author Zeyes
+ */
+@JsonFormat(shape = JsonFormat.Shape.OBJECT)
+public enum ComplaintStatus {
+
+ ;
+
+ private final int key;
+ private final String value;
+
+ ComplaintStatus(int key, String value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ public int getKey() {
+ return key;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/CouponType.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/CouponType.java
new file mode 100644
index 0000000000..9001f286ab
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/CouponType.java
@@ -0,0 +1,45 @@
+package me.chanjar.weixin.channel.enums;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 视频号小店 优惠券 推广类型
+ *
+ * @author Zeyes
+ */
+@JsonFormat(shape = JsonFormat.Shape.OBJECT)
+public enum CouponType {
+ /** 1 商品条件折券 */
+ C_1(1, "商品条件折券"),
+ /** 2 商品满减券 */
+ C_2(2, "商品满减券"),
+ /** 3 商品统一折扣券 */
+ C_3(3, "商品统一折扣券"),
+ /** 4 商品直减券 */
+ C_4(4, "商品直减券"),
+ /** 101 店铺条件折扣券 */
+ C_101(101, "店铺条件折扣券"),
+ /** 102 店铺满减券 */
+ C_102(102, "店铺满减券"),
+ /** 103 店铺统一折扣券 */
+ C_103(103, "店铺统一折扣券"),
+ /** 104 店铺直减券 */
+ C_104(104, "店铺直减券"),
+ ;
+
+ private final int key;
+ private final String val;
+
+ CouponType(int key, String val) {
+ this.key = key;
+ this.val = val;
+ }
+
+ public int getKey() {
+ return key;
+ }
+
+ public String getVal() {
+ return val;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/CouponValidType.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/CouponValidType.java
new file mode 100644
index 0000000000..bb037cbbdf
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/CouponValidType.java
@@ -0,0 +1,34 @@
+package me.chanjar.weixin.channel.enums;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 视频号小店 优惠券 推广类型
+ *
+ * @author Zeyes
+ */
+@JsonFormat(shape = JsonFormat.Shape.OBJECT)
+public enum CouponValidType {
+ /** 指定时间范围生效 */
+ COUPON_VALID_TYPE_TIME(1, "指定时间范围生效"),
+ /** 生效天数 */
+ COUPON_VALID_TYPE_DAY(2, "生效天数"),
+
+ ;
+
+ private final int key;
+ private final String val;
+
+ CouponValidType(int key, String val) {
+ this.key = key;
+ this.val = val;
+ }
+
+ public int getKey() {
+ return key;
+ }
+
+ public String getVal() {
+ return val;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/DeliveryType.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/DeliveryType.java
new file mode 100644
index 0000000000..8a024ca6f7
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/DeliveryType.java
@@ -0,0 +1,42 @@
+package me.chanjar.weixin.channel.enums;
+
+/**
+ * 快递类型
+ *
+ * @author Zeyes
+ */
+public enum DeliveryType {
+ /** 1 自寄快递 */
+ SELF_DELIVERY(1, "自寄快递"),
+ /** 2 在线签约快递单 */
+ ONLINE_DELIVERY(2, "在线签约快递单"),
+ /** 3 虚拟商品无需物流发货 */
+ VIRTUAL_DELIVERY(3, "虚拟商品无需物流发货"),
+ /** 4 在线快递散单 */
+ ONLINE_DELIVERY_SCATTER(4, "在线快递散单");
+
+ private final Integer key;
+ private final String value;
+
+ DeliveryType(Integer key, String value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ public static DeliveryType getDeliveryType(Integer key) {
+ for (DeliveryType deliveryType : DeliveryType.values()) {
+ if (deliveryType.getKey().equals(key)) {
+ return deliveryType;
+ }
+ }
+ return null;
+ }
+
+ public Integer getKey() {
+ return key;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/FundsType.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/FundsType.java
new file mode 100644
index 0000000000..ea3f8873ec
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/FundsType.java
@@ -0,0 +1,50 @@
+package me.chanjar.weixin.channel.enums;
+
+/**
+ * 资金类型
+ *
+ * @author Zeyes
+ */
+public enum FundsType {
+
+ /** 1 订单支付收入 */
+ ORDER_PAY_INCOME(1, "订单支付收入"),
+ /** 2 订单手续费 */
+ ORDER_FEE(2, "订单手续费"),
+ /** 3 退款 */
+ REFUND(3, "退款"),
+ /** 4 提现 */
+ WITHDRAW(4, "提现"),
+ /** 5 提现失败退票 */
+ WITHDRAW_FAIL(5, "提现失败退票"),
+ /** 6 导购分账 */
+ GUIDE_SHARE(6, "导购分账"),
+ /** 7 联盟分账 */
+ LEAGUE_SHARE(7, "联盟分账"),
+ /** 8 运费险分账 */
+ FREIGHT_SHARE(8, "运费险分账"),
+ /** 9 联盟平台抽佣 */
+ LEAGUE_COMMISSION(9, "联盟平台抽佣"),
+ /** 10 小店抽佣 */
+ SHOP_COMMISSION(10, "小店抽佣"),
+ /** 99 分账 */
+ SHARE(99, "分账"),
+
+ ;
+
+ private final int key;
+ private final String value;
+
+ FundsType(int key, String value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ public int getKey() {
+ return key;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/MessageType.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/MessageType.java
new file mode 100644
index 0000000000..4406104d9f
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/MessageType.java
@@ -0,0 +1,21 @@
+package me.chanjar.weixin.channel.enums;
+
+/**
+ * 消息类型
+ *
+ * @author Zeyes
+ */
+public enum MessageType {
+ EVENT("event"),
+ ;
+
+ private final String key;
+
+ MessageType(String key) {
+ this.key = key;
+ }
+
+ public String getKey() {
+ return key;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/PromoteType.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/PromoteType.java
new file mode 100644
index 0000000000..fa0bd60913
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/PromoteType.java
@@ -0,0 +1,29 @@
+package me.chanjar.weixin.channel.enums;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 视频号小店 优惠券 推广类型
+ *
+ * @author Zeyes
+ */
+@JsonFormat(shape = JsonFormat.Shape.OBJECT)
+public enum PromoteType {
+ PROMOTE_TYPE_SHOP(1, "小店内推广");
+
+ private final int key;
+ private final String val;
+
+ PromoteType(int key, String val) {
+ this.key = key;
+ this.val = val;
+ }
+
+ public int getKey() {
+ return key;
+ }
+
+ public String getVal() {
+ return val;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/QrCheckStatus.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/QrCheckStatus.java
new file mode 100644
index 0000000000..b0b2d64e31
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/QrCheckStatus.java
@@ -0,0 +1,46 @@
+package me.chanjar.weixin.channel.enums;
+
+/**
+ * 二维码核销状态
+ *
+ * @author Zeyes
+ */
+public enum QrCheckStatus {
+ /** 0 未扫码 */
+ NOT_SCAN(0, "未扫码"),
+ /** 1 已确认 */
+ CONFIRMED(1, "已确认"),
+ /** 2 已取消 */
+ CANCEL(2, "已取消"),
+ /** 3 已失效 */
+ INVALID(3, "已失效"),
+ /** 4 已扫码 */
+ SCAN(4, "已扫码"),
+
+ ;
+
+ private final int key;
+ private final String value;
+
+ QrCheckStatus(int key, String value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ public static QrCheckStatus getByKey(Integer key) {
+ for (QrCheckStatus status : QrCheckStatus.values()) {
+ if (status.getKey() == key) {
+ return status;
+ }
+ }
+ return NOT_SCAN;
+ }
+
+ public int getKey() {
+ return key;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/SendTime.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/SendTime.java
new file mode 100644
index 0000000000..85e4d4f0d6
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/SendTime.java
@@ -0,0 +1,67 @@
+package me.chanjar.weixin.channel.enums;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 视频号小店 发货时间
+ *
+ * @author Zeyes
+ */
+@JsonFormat(shape = JsonFormat.Shape.OBJECT)
+public enum SendTime {
+// /** 4小时内发货 */
+// FOUR_HOUR("SendTime_FOUR_HOUR", "4小时内发货"),
+// /** 8小时内发货 */
+// EIGHT_HOUR("SendTime_EIGHT_HOUR", "8小时内发货"),
+// /** 12小时内发货 */
+// TWELVE_HOUR("SendTime_TWELVE_HOUR", "12小时内发货"),
+// /** 16小时内发货 */
+// SIXTEEN_HOUR("SendTime_SIXTEEN_HOUR", "16小时内发货"),
+// /** 20小时内发货 */
+// TWENTY_HOUR("SendTime_TWENTY_HOUR", "20小时内发货"),
+ /** 24小时内发货 */
+ TWENTYFOUR_HOUR("SendTime_TWENTYFOUR_HOUR", "24小时内发货"),
+ /** 48小时内发货 */
+ FOUTYEIGHT_HOUR("SendTime_FOUTYEIGHT_HOUR", "48小时内发货"),
+ /** 3天内发货 */
+ THREE_DAY("SendTime_THREE_DAY", "3天内发货"),
+// /** 5天内发货 */
+// FIVE_DAY("SendTime_FIVE_DAY", "5天内发货"),
+// /** 7天内发货 */
+// SEVEN_DAY("SendTime_SEVEN_DAY", "7天内发货"),
+// /** 10天内发货 */
+// TEN_DAY("SendTime_TEN_DAY", "10天内发货"),
+// /** 12天内发货 */
+// TWELVE_DAY("SendTime_TWELVE_DAY", "12天内发货"),
+// /** 14天内发货 */
+// FOUTEEN_DAY("SendTime_FOUTEEN_DAY", "14天内发货"),
+// /** 16天内发货 */
+// SIXTEEN_DAY("SendTime_SIXTEEN_DAY", "16天内发货"),
+// /** 20天内发货 */
+// TWENTY_DAY("SendTime_TWENTY_DAY", "20天内发货"),
+// /** 25天内发货 */
+// TWENTYFIVE_DAY("SendTime_TWENTYFIVE_DAY", "25天内发货"),
+// /** 30天内发货 */
+// THIRY_DAY("SendTime_THIRY_DAY", "30天内发货"),
+// /** 35天内发货 */
+// THIRYFIVE_DAY("SendTime_THIRYFIVE_DAY", "35天内发货"),
+// /** 45天内发货 */
+// FOURTYFIVE_DAY("SendTime_FOURTYFIVE_DAY", "45天内发货"),
+ ;
+
+ private final String key;
+ private final String value;
+
+ SendTime(String key, String value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/ShareScene.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/ShareScene.java
new file mode 100644
index 0000000000..b4428dbb24
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/ShareScene.java
@@ -0,0 +1,41 @@
+package me.chanjar.weixin.channel.enums;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 分享场景
+ *
+ * @author Zeyes
+ */
+@JsonFormat(shape = JsonFormat.Shape.OBJECT)
+public enum ShareScene {
+ /** 1 直播间 */
+ LIVE_ROOM(1, "直播间"),
+ /** 2 橱窗 */
+ WINDOW(2, "橱窗"),
+ /** 3 短视频 */
+ SHORT_VIDEO(3, "短视频"),
+ /** 4 视频号主页 */
+ CHANNEL_HOME(4, "视频号主页"),
+ /** 5 商品详情页 */
+ PRODUCT_DETAIL(5, "商品详情页"),
+
+ ;
+
+
+ private final Integer key;
+ private final String value;
+
+ ShareScene(Integer key, String value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ public Integer getKey() {
+ return key;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/SharerType.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/SharerType.java
new file mode 100644
index 0000000000..8f0da3d760
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/SharerType.java
@@ -0,0 +1,35 @@
+package me.chanjar.weixin.channel.enums;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 分享员类型
+ *
+ * @author Zeyes
+ */
+@JsonFormat(shape = JsonFormat.Shape.OBJECT)
+public enum SharerType {
+ /** 0 普通分享员 */
+ NORMAL(0, "普通分享员"),
+ /** 1 企业分享员 */
+ ENTERPRISE(1, "企业分享员"),
+
+ ;
+
+
+ private final Integer key;
+ private final String value;
+
+ SharerType(Integer key, String value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ public Integer getKey() {
+ return key;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/SpuEditStatus.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/SpuEditStatus.java
new file mode 100644
index 0000000000..3d6063b8cf
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/SpuEditStatus.java
@@ -0,0 +1,40 @@
+package me.chanjar.weixin.channel.enums;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 商品编辑状态
+ *
+ * @author Zeyes
+ */
+@JsonFormat(shape = JsonFormat.Shape.OBJECT)
+public enum SpuEditStatus {
+ /** 0 初始值 */
+ INIT(0, "初始值"),
+ /** 1 编辑中 */
+ SUBMIT(1, "编辑中"),
+ /** 2 审核中 */
+ ING(2, "审核中"),
+ /** 3 审核失败 */
+ FAIL(3, "审核失败"),
+ /** 4 审核成功 */
+ SUCCESS(4, "审核成功"),
+ /** 5 商品信息写入中 */
+ WRITING(5, "商品信息写入中");
+
+ private final int status;
+ private final String desc;
+
+ SpuEditStatus(int status, String desc) {
+ this.status = status;
+ this.desc = desc;
+ }
+
+ public int getStatus() {
+ return status;
+ }
+
+ public String getDesc() {
+ return desc;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/SpuStatus.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/SpuStatus.java
new file mode 100644
index 0000000000..a74fee6b07
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/SpuStatus.java
@@ -0,0 +1,39 @@
+package me.chanjar.weixin.channel.enums;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 视频号小店 商品上下架状态
+ *
+ * @author Zeyes
+ */
+@JsonFormat(shape = JsonFormat.Shape.OBJECT)
+public enum SpuStatus {
+
+ /** 0 初始值 */
+ INIT(0, "未上架"),
+ /** 5 上架 */
+ UP(5, "上架"),
+ /** 6 回收站 */
+ TRASH(6, "回收站"),
+ /** 11 自主下架 */
+ DOWN(11, "自主下架"),
+ /** 13 违规下架/风控系统下架 */
+ SYSTEM_DOWN(13, "违规下架");
+
+ private final int status;
+ private final String desc;
+
+ SpuStatus(int status, String desc) {
+ this.status = status;
+ this.desc = desc;
+ }
+
+ public int getStatus() {
+ return status;
+ }
+
+ public String getDesc() {
+ return desc;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/UserCouponStatus.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/UserCouponStatus.java
new file mode 100644
index 0000000000..ce7e97df6c
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/UserCouponStatus.java
@@ -0,0 +1,33 @@
+package me.chanjar.weixin.channel.enums;
+
+/**
+ * 视频号小店 用户优惠券状态
+ *
+ * @author Zeyes
+ */
+public enum UserCouponStatus {
+ /** 100 生效中 */
+ VALID(100, "生效中"),
+ /** 101 已过期 */
+ EXPIRED(101, "已过期"),
+ /** 102 已使用 */
+ USED(102, "已使用"),
+
+ ;
+
+ private final int key;
+ private final String val;
+
+ UserCouponStatus(int key, String val) {
+ this.key = key;
+ this.val = val;
+ }
+
+ public int getKey() {
+ return key;
+ }
+
+ public String getVal() {
+ return val;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/WithdrawStatus.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/WithdrawStatus.java
new file mode 100644
index 0000000000..2d1737cbd0
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/WithdrawStatus.java
@@ -0,0 +1,51 @@
+package me.chanjar.weixin.channel.enums;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 视频号小店 提现状态
+ *
+ * @author Zeyes
+ */
+@JsonFormat(shape = JsonFormat.Shape.OBJECT)
+public enum WithdrawStatus {
+ /** 受理成功 */
+ CREATE_SUCCESS("CREATE_SUCCESS", "受理成功"),
+ /** 提现成功 */
+ SUCCESS("SUCCESS", "提现成功"),
+ /** 提现失败 */
+ FAIL("FAIL", "提现失败"),
+ /** 提现退票 */
+ REFUND("REFUND", "提现退票"),
+ /** 关单 */
+ CLOSE("CLOSE", "关单"),
+ /** 业务单已创建 */
+ INIT("INIT", "业务单已创建"),
+ ;
+
+ private final String key;
+ private final String value;
+
+ WithdrawStatus(String key, String value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ public static WithdrawStatus getByKey(String key) {
+ for (WithdrawStatus reason : WithdrawStatus.values()) {
+ if (reason.getKey().equals(key)) {
+ return reason;
+ }
+ }
+ // 找不到就返回其他了
+ return FAIL;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/WxChannelErrorMsgEnum.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/WxChannelErrorMsgEnum.java
new file mode 100644
index 0000000000..4a699c20d0
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/WxChannelErrorMsgEnum.java
@@ -0,0 +1,63 @@
+package me.chanjar.weixin.channel.enums;
+
+import com.google.common.collect.Maps;
+import java.util.Map;
+import lombok.Getter;
+
+/**
+ * 微信视频号全局返回码
+ *
+ * @author Zeyes
+ */
+@Getter
+public enum WxChannelErrorMsgEnum {
+ /**
+ * 系统繁忙,此时请开发者稍候再试 system error
+ */
+ CODE_1(-1, "系统繁忙,此时请开发者稍候再试"),
+
+ /**
+ * 请求成功 ok
+ */
+ CODE_0(0, "请求成功"),
+
+ /**
+ * AppSecret 错误或者 AppSecret 不属于这个小店,请开发者确认 AppSecret 的正确性
+ */
+ CODE_40001(40001, "AppSecret 错误或者 AppSecret 不属于这个小店,请开发者确认 AppSecret 的正确性"),
+
+ /**
+ * 请确保 grant_type 字段值为 client_credential
+ */
+ CODE_40002(40002, "请确保 grant_type 字段值为 client_credential"),
+
+ /**
+ * 不合法的 AppID,请开发者检查 AppID 的正确性,避免异常字符,注意大小写
+ */
+ CODE_40013(40013, "不合法的 AppID,请开发者检查 AppID 的正确性,避免异常字符,注意大小写"),
+
+ ;
+
+ private final int code;
+ private final String msg;
+
+ WxChannelErrorMsgEnum(int code, String msg) {
+ this.code = code;
+ this.msg = msg;
+ }
+
+ static final Map valueMap = Maps.newHashMap();
+
+ static {
+ for (WxChannelErrorMsgEnum value : WxChannelErrorMsgEnum.values()) {
+ valueMap.put(value.code, value.msg);
+ }
+ }
+
+ /**
+ * 通过错误代码查找其中文含义.
+ */
+ public static String findMsgByCode(int code) {
+ return valueMap.getOrDefault(code, null);
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/WxCouponStatus.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/WxCouponStatus.java
new file mode 100644
index 0000000000..593873fbe4
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/WxCouponStatus.java
@@ -0,0 +1,35 @@
+package me.chanjar.weixin.channel.enums;
+
+/**
+ * 视频号小店 优惠券状态
+ *
+ * @author Zeyes
+ */
+public enum WxCouponStatus {
+ /** 1 初始 */
+ INIT(1, "初始"),
+ /** 2 生效 */
+ VALID(2, "生效"),
+ /** 4 已作废 */
+ INVALID(4, "已作废"),
+ /** 5 删除 */
+ DELETE(5, "删除"),
+
+ ;
+
+ private final int key;
+ private final String val;
+
+ WxCouponStatus(int key, String val) {
+ this.key = key;
+ this.val = val;
+ }
+
+ public int getKey() {
+ return key;
+ }
+
+ public String getVal() {
+ return val;
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/WxOrderStatus.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/WxOrderStatus.java
new file mode 100644
index 0000000000..b064335221
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/enums/WxOrderStatus.java
@@ -0,0 +1,73 @@
+package me.chanjar.weixin.channel.enums;
+
+/**
+ * 视频号小店 订单状态
+ *
+ * @author Zeyes
+ */
+public enum WxOrderStatus {
+ /** 10 待付款 */
+ UNPAID(10, "待付款"),
+ /** 20 待发货(已付款/用户已付尾款) */
+ PAID(20, "待发货"),
+ /** 21 部分发货 */
+ PART_DELIVERY(21, "部分发货"),
+ /** 30 待收货 */
+ DELIVERY(30, "待收货"),
+ /** 100 完成 */
+ COMPLETED(100, "已完成"),
+ /** 190 商品超卖商家取消订单 */
+ UNPAID_CANCEL(190, "已取消"),
+ /** 200 全部商品售后之后,订单取消 */
+ ALL_AFTER_SALE(200, "已取消"),
+ /** 250 用户主动取消/待付款超时取消/商家取消 */
+ CANCEL(250, "已取消");
+
+ private final int key;
+
+ private final String val;
+
+ WxOrderStatus(int key, String val) {
+ this.key = key;
+ this.val = val;
+ }
+
+ public int getKey() {
+ return key;
+ }
+
+ public String getVal() {
+ return val;
+ }
+
+ /**
+ * 获取状态中文
+ *
+ * @param key 状态码
+ * @return 状态
+ */
+ public static String getStatusStr(Integer key) {
+ if (key == null) {
+ return "未知";
+ }
+ for (WxOrderStatus status : WxOrderStatus.values()) {
+ if (key.equals(status.getKey())) {
+ return status.getVal();
+ }
+ }
+ return String.valueOf(key);
+ }
+
+ /**
+ * 判断是否在取消状态
+ *
+ * @param key key
+ * @return boolean
+ */
+ public static boolean isCancel(Integer key) {
+ if (key == null) {
+ return false;
+ }
+ return key.equals(UNPAID_CANCEL.key) || key.equals(ALL_AFTER_SALE.key) || key.equals(CANCEL.key);
+ }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/executor/ChannelFileUploadRequestExecutor.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/executor/ChannelFileUploadRequestExecutor.java
new file mode 100644
index 0000000000..576f1c286a
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/executor/ChannelFileUploadRequestExecutor.java
@@ -0,0 +1,66 @@
+package me.chanjar.weixin.channel.executor;
+
+
+import java.io.File;
+import java.io.IOException;
+import me.chanjar.weixin.common.enums.WxType;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.util.http.RequestExecutor;
+import me.chanjar.weixin.common.util.http.RequestHttp;
+import me.chanjar.weixin.common.util.http.ResponseHandler;
+import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpHost;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.mime.HttpMultipartMode;
+import org.apache.http.entity.mime.MultipartEntityBuilder;
+import org.apache.http.impl.client.CloseableHttpClient;
+
+/**
+ * 视频号小店 图片上传接口 请求的参数是File, 返回的结果是String
+ *
+ * @author Zeyes
+ */
+public class ChannelFileUploadRequestExecutor implements RequestExecutor {
+
+ protected RequestHttp requestHttp;
+
+ public ChannelFileUploadRequestExecutor(RequestHttp requestHttp) {
+ this.requestHttp = requestHttp;
+ }
+
+ @Override
+ public String execute(String uri, File file, WxType wxType) throws WxErrorException, IOException {
+ HttpPost httpPost = new HttpPost(uri);
+ if (requestHttp.getRequestHttpProxy() != null) {
+ RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build();
+ httpPost.setConfig(config);
+ }
+ if (file != null) {
+ HttpEntity entity = MultipartEntityBuilder
+ .create()
+ .addBinaryBody("media", file)
+ .setMode(HttpMultipartMode.RFC6532)
+ .build();
+ httpPost.setEntity(entity);
+ }
+ try (CloseableHttpResponse response = requestHttp.getRequestHttpClient().execute(httpPost)) {
+ return Utf8ResponseHandler.INSTANCE.handleResponse(response);
+ } finally {
+ httpPost.releaseConnection();
+ }
+ }
+
+ @Override
+ public void execute(String uri, File data, ResponseHandler handler, WxType wxType)
+ throws WxErrorException, IOException {
+ handler.handle(this.execute(uri, data, wxType));
+ }
+
+ public static RequestExecutor create(RequestHttp requestHttp) {
+ return new ChannelFileUploadRequestExecutor(requestHttp);
+ }
+
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/executor/ChannelMediaDownloadRequestExecutor.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/executor/ChannelMediaDownloadRequestExecutor.java
new file mode 100644
index 0000000000..1b81dc6d15
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/executor/ChannelMediaDownloadRequestExecutor.java
@@ -0,0 +1,151 @@
+package me.chanjar.weixin.channel.executor;
+
+import static org.apache.commons.io.FileUtils.openOutputStream;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.channel.bean.image.ChannelImageResponse;
+import me.chanjar.weixin.channel.util.JsonUtils;
+import me.chanjar.weixin.common.enums.WxType;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.util.http.RequestExecutor;
+import me.chanjar.weixin.common.util.http.RequestHttp;
+import me.chanjar.weixin.common.util.http.ResponseHandler;
+import me.chanjar.weixin.common.util.http.apache.InputStreamResponseHandler;
+import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.http.Header;
+import org.apache.http.HttpHost;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.entity.ContentType;
+import org.apache.http.impl.client.CloseableHttpClient;
+
+/**
+ * 下载媒体文件请求执行器
+ *
+ * @author Zeyes
+ */
+@Slf4j
+public class ChannelMediaDownloadRequestExecutor implements RequestExecutor {
+
+ protected RequestHttp requestHttp;
+ protected File tmpDirFile;
+
+ private static final Pattern PATTERN = Pattern.compile(".*filename=\"(.*)\"");
+
+ public ChannelMediaDownloadRequestExecutor(RequestHttp requestHttp, File tmpDirFile) {
+ this.requestHttp = requestHttp;
+ this.tmpDirFile = tmpDirFile;
+ }
+
+ @Override
+ public ChannelImageResponse execute(String uri, String data, WxType wxType) throws WxErrorException, IOException {
+ if (data != null) {
+ if (uri.indexOf('?') == -1) {
+ uri += '?';
+ }
+ uri += uri.endsWith("?") ? data : '&' + data;
+ }
+
+ HttpGet httpGet = new HttpGet(uri);
+ if (requestHttp.getRequestHttpProxy() != null) {
+ RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build();
+ httpGet.setConfig(config);
+ }
+
+ try (CloseableHttpResponse response = requestHttp.getRequestHttpClient().execute(httpGet);
+ InputStream inputStream = InputStreamResponseHandler.INSTANCE.handleResponse(response)) {
+ Header[] contentTypeHeader = response.getHeaders("Content-Type");
+ String contentType = null;
+ if (contentTypeHeader != null && contentTypeHeader.length > 0) {
+ contentType = contentTypeHeader[0].getValue();
+ if (contentType.startsWith(ContentType.APPLICATION_JSON.getMimeType())) {
+ // application/json; encoding=utf-8 下载媒体文件出错
+ String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
+ return JsonUtils.decode(responseContent, ChannelImageResponse.class);
+ }
+ }
+
+ String fileName = this.getFileName(response);
+ if (StringUtils.isBlank(fileName)) {
+ fileName = String.valueOf(System.currentTimeMillis());
+ }
+
+ String baseName = FilenameUtils.getBaseName(fileName);
+ if (StringUtils.isBlank(fileName) || baseName.length() < 3) {
+ baseName = String.valueOf(System.currentTimeMillis());
+ }
+ String extension = FilenameUtils.getExtension(fileName);
+ if (StringUtils.isBlank(extension)) {
+ extension = "unknown";
+ }
+ File file = createTmpFile(inputStream, baseName, extension, tmpDirFile);
+ ChannelImageResponse result = new ChannelImageResponse(file, contentType);
+ return result;
+ } finally {
+ httpGet.releaseConnection();
+ }
+ }
+
+ @Override
+ public void execute(String uri, String data, ResponseHandler handler, WxType wxType)
+ throws WxErrorException, IOException {
+ handler.handle(this.execute(uri, data, wxType));
+ }
+
+ public static RequestExecutor