diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index c15adca96..ced7d6de0 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -12,7 +12,7 @@ assignees: '' ## 另外如果确认属于bug,而且已明确如何修复,请参考贡献指南直接提交PR,省的浪费时间在这里描述问题,非常感谢配合 ### 简要描述 -__简单概括描述下你所遇到的问题。__ +__请简单概括描述下你所遇到的问题。__ ### 模块版本情况 * WxJava 模块名: diff --git a/.travis.yml b/.travis.yml index 2b128c8a0..99850df72 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 ba8e495af..c70396482 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 0c8a80022..7783de532 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 df517de76..b55ee50ef 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,8 @@ [![Github](https://img.shields.io/github/stars/Wechat-Group/WxJava?logo=github&style=flat)](https://github.com/Wechat-Group/WxJava) [![GitHub release](https://img.shields.io/github/release/Wechat-Group/WxJava.svg)](https://github.com/Wechat-Group/WxJava/releases) [![Maven Central](https://img.shields.io/maven-central/v/com.github.binarywang/wx-java.svg)](http://mvnrepository.com/artifact/com.github.binarywang/wx-java) -[![Build Status](https://travis-ci.com/Wechat-Group/WxJava.svg?branch=develop)](https://travis-ci.com/Wechat-Group/WxJava) -[![使用IntelliJ IDEA开发维护](https://img.shields.io/badge/IntelliJ%20IDEA-提供支持-blue.svg)](https://www.jetbrains.com/?from=WxJava-weixin-java-tools) +[![Build Status](https://app.travis-ci.com/Wechat-Group/WxJava.svg?branch=develop)](https://app.travis-ci.com/github/Wechat-Group/WxJava) +[![使用IntelliJ IDEA开发维护](https://img.shields.io/badge/IntelliJ%20IDEA-支持-blue.svg)](https://www.jetbrains.com/?from=WxJava-weixin-java-tools) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) #### 微信`Java`开发工具包,支持包括微信支付、开放平台、公众号、企业微信/企业号、小程序等微信功能模块的后端开发。 @@ -17,7 +17,7 @@ - + @@ -31,43 +31,44 @@ - + - diboot低代码开发平台 + diboot低代码开发平台 - + ### 重要信息 -1. 项目合作洽谈,请联系微信`binary0000`(在微信里自行搜索并添加好友即可,请注明来意)。 -2. **2021-11-01 发布 [【4.2.0正式版】](https://mp.weixin.qq.com/s/nIk_xOf6dxkhKfqq830Cuw)**! +1. 项目合作洽谈请联系微信`binary0000`(在微信里自行搜索并添加好友,请注明来意,如有关于SDK问题需讨论请参考下文入群讨论,不要加此微信)。 +2. **2022-4-10 发布 [【4.3.0正式版】](https://mp.weixin.qq.com/s/yCsa7nD4_DLjW1RDcrEk6g)**! 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)** 或本项目中的部分单元测试代码;另外微信开发新手请务必阅读[【开发文档 Wiki 首页】](https://github.com/Wechat-Group/WxJava/wiki)的常见问题部分,可以少走很多弯路,节省不少时间。 -5. 技术交流群:想获得QQ群/微信群/钉钉企业群等信息的同学,请使用微信扫描上面的微信公众号二维码关注 `WxJava` 后点击相关菜单即可获取加入方式,同时也可以在微信中搜索 `weixin-java-tools` 或 `WxJava` 后选择正确的公众号进行关注,该公众号会及时通知SDK相关更新信息,并不定期分享微信Java开发相关技术知识; -6. 钉钉技术交流群:`32206329`(技术交流2群), `30294972`(技术交流1群,目前已满),`35724728`(通知群,实时通知Github项目变更记录)。 -7. 微信开发新手或者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) ,避免浪费大家的宝贵时间; -8. 寻求帮助时需贴代码或大长串异常信息的,请利用 http://paste.ubuntu.com +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 @@ -79,7 +80,7 @@ com.github.binarywang (不同模块参考下文) - 4.2.0 + 4.3.0 ``` @@ -97,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. 目前最新版本号为 [![Maven Central](https://img.shields.io/maven-central/v/com.github.binarywang/wx-java.svg)](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. 目前最新版本号为 [![Maven Central](https://img.shields.io/maven-central/v/com.github.binarywang/wx-java.svg)](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) 分别查看所有最新的版本。 @@ -181,6 +182,7 @@ 1. [007gzs](https://github.com/007gzs) 1. [Silloy](https://github.com/silloy) 1. [mgcnrx11](https://github.com/mgcnrx11) +1. [0katekate0 (Wang_Wong)](https://github.com/0katekate0) 1. [yuanqixun](https://github.com/yuanqixun) 1. [kakotor](https://github.com/kakotor) 1. [aimilin6688 (Jonk)](https://github.com/aimilin6688) diff --git a/demo.md b/demo.md index de5e46209..d6b55b89e 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) [![Build Status](https://travis-ci.org/binarywang/weixin-java-pay-demo.svg?branch=master)](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) [![Build Status](https://travis-ci.org/binarywang/weixin-java-cp-demo.svg?branch=master)](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) [![Build Status](https://travis-ci.org/binarywang/weixin-java-miniapp-demo.svg?branch=master)](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) [![Build Status](https://travis-ci.org/Wechat-Group/weixin-java-open-demo.svg?branch=master)](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) [![Build Status](https://travis-ci.org/binarywang/weixin-java-mp-demo-springmvc.svg?branch=master)](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) [![Build Status](https://travis-ci.org/binarywang/weixin-java-mp-demo.svg?branch=master)](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) [![Build Status](https://travis-ci.org/Wechat-Group/weixin-java-demo-springmvc.svg?branch=master)](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) [![Build Status](https://app.travis-ci.com/binarywang/weixin-java-pay-demo.svg?branch=master)](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) [![Build Status](https://app.travis-ci.com/binarywang/weixin-java-cp-demo.svg?branch=master)](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) [![Build Status](https://app.travis-ci.com/binarywang/weixin-java-miniapp-demo.svg?branch=master)](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) [![Build Status](https://app.travis-ci.com/Wechat-Group/weixin-java-open-demo.svg?branch=master)](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) [![Build Status](https://app.travis-ci.com/binarywang/weixin-java-mp-demo-springmvc.svg?branch=master)](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) [![Build Status](https://app.travis-ci.com/binarywang/weixin-java-mp-demo.svg?branch=master)](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) [![Build Status](https://app.travis-ci.com/Wechat-Group/weixin-java-demo-springmvc.svg?branch=master)](https://app.travis-ci.com/Wechat-Group/weixin-java-demo-springmvc) diff --git a/images/banners/vultr.jpg b/images/banners/vultr.jpg deleted file mode 100644 index 80cf3c2b5..000000000 Binary files a/images/banners/vultr.jpg and /dev/null differ diff --git a/pom.xml b/pom.xml index 899d90d37..20a889005 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.github.binarywang wx-java - 4.3.0 + 4.4.0 pom WxJava - Weixin/Wechat Java SDK 微信开发Java SDK @@ -92,6 +92,16 @@ 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 + @@ -119,7 +129,7 @@ UTF-8 4.5.13 - 9.4.41.v20210516 + 9.4.43.v20210629 @@ -132,7 +142,7 @@ org.jodd jodd-http - 5.2.0 + 6.2.1 provided @@ -155,7 +165,7 @@ commons-codec commons-codec - 1.10 + 1.13 commons-io @@ -185,7 +195,7 @@ com.google.code.gson gson - 2.8.0 + 2.8.9 com.fasterxml.jackson.dataformat @@ -203,7 +213,7 @@ ch.qos.logback logback-classic - 1.2.3 + 1.2.9 test @@ -302,7 +312,7 @@ org.projectlombok lombok - 1.18.8 + 1.18.24 provided @@ -310,6 +320,11 @@ bcpkix-jdk15on 1.68 + + javax.validation + validation-api + 2.0.1.Final + diff --git a/spring-boot-starters/pom.xml b/spring-boot-starters/pom.xml index 36e1ac5d0..652e3af47 100644 --- a/spring-boot-starters/pom.xml +++ b/spring-boot-starters/pom.xml @@ -4,7 +4,7 @@ com.github.binarywang wx-java - 4.3.0 + 4.4.0 pom wx-java-spring-boot-starters 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 index 4d3776171..7a107b94e 100644 --- a/spring-boot-starters/wx-java-cp-spring-boot-starter/pom.xml +++ b/spring-boot-starters/wx-java-cp-spring-boot-starter/pom.xml @@ -4,7 +4,7 @@ wx-java-spring-boot-starters com.github.binarywang - 4.3.0 + 4.4.0 4.0.0 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 index b2cc778ac..030478e53 100644 --- 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 @@ -38,6 +38,10 @@ public class WxCpProperties { * 微信企业号应用 EncodingAESKey */ private String aesKey; + /** + * 微信企业号应用 会话存档私钥 + */ + private String msgAuditPriKey; /** * 微信企业号应用 会话存档类库路径 */ 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 index cfcb16fe0..c4bc30036 100644 --- 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 @@ -18,7 +18,8 @@ protected WxCpDefaultConfigImpl config(WxCpDefaultConfigImpl config, WxCpPropert String token = properties.getToken(); Integer agentId = properties.getAgentId(); String aesKey = properties.getAesKey(); - // 企业微信,会话存档路径 + // 企业微信,私钥,会话存档路径 + String msgAuditPriKey = properties.getMsgAuditPriKey(); String msgAuditLibPath = properties.getMsgAuditLibPath(); config.setCorpId(corpId); @@ -32,6 +33,9 @@ protected WxCpDefaultConfigImpl config(WxCpDefaultConfigImpl config, WxCpPropert if (StringUtils.isNotBlank(aesKey)) { config.setAesKey(aesKey); } + if (StringUtils.isNotBlank(msgAuditPriKey)) { + config.setMsgAuditPriKey(msgAuditPriKey); + } if (StringUtils.isNotBlank(msgAuditLibPath)) { config.setMsgAuditLibPath(msgAuditLibPath); } 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 43d3c7b45..94bc670d2 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,9 @@ - + wx-java-spring-boot-starters com.github.binarywang - 4.3.0 + 4.4.0 4.0.0 @@ -35,6 +33,16 @@ ${spring.boot.version} provided + + org.jodd + jodd-http + provided + + + com.squareup.okhttp3 + okhttp + provided + @@ -60,4 +68,4 @@ - + \ No newline at end of file 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 62f3628c6..dd0da8172 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.3.0 + 4.4.0 4.0.0 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 dd55913b4..433f25611 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.3.0 + 4.4.0 4.0.0 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 a4d91fade..8d96901f2 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,6 +8,7 @@ ``` 2. 添加配置(application.yml) +###### 1)V2版本 ```yml wx: pay: @@ -18,6 +19,17 @@ wx: 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:开头的类路径 +``` 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 bb22aff45..6b51b3a7e 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.3.0 + 4.4.0 4.0.0 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 51f64628b..b199ecc53 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.3.0 + 4.4.0 4.0.0 diff --git a/weixin-graal/pom.xml b/weixin-graal/pom.xml index 1673ba243..8e7fa989b 100644 --- a/weixin-graal/pom.xml +++ b/weixin-graal/pom.xml @@ -6,7 +6,7 @@ com.github.binarywang wx-java - 4.3.0 + 4.4.0 weixin-graal diff --git a/weixin-java-common/pom.xml b/weixin-java-common/pom.xml index fc389d484..1a4a2a5ad 100644 --- a/weixin-java-common/pom.xml +++ b/weixin-java-common/pom.xml @@ -6,7 +6,7 @@ com.github.binarywang wx-java - 4.3.0 + 4.4.0 weixin-java-common @@ -50,7 +50,7 @@ org.slf4j jcl-over-slf4j - 1.7.30 + 1.7.36 @@ -77,6 +77,10 @@ org.projectlombok lombok + + javax.validation + validation-api + ch.qos.logback diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java index 35a201edb..5bef9f28a 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java @@ -10,7 +10,7 @@ /** * 微信开发所使用到的常量类. * - * @author Daniel Qian & binarywang + * @author Daniel Qian & binarywang & Wang_Wong */ public class WxConsts { /** @@ -133,6 +133,54 @@ public static class KefuMsgType { public static final String MP_NEWS_ARTICLE = "mpnewsarticle"; } + /** + * 发送「学校通知」类型 + * https://developer.work.weixin.qq.com/document/path/92321 + */ + public static class SchoolContactMsgType { + + /** + * 文本消息. + */ + public static final String TEXT = "text"; + + /** + * 图片消息. + */ + public static final String IMAGE = "image"; + + /** + * 语音消息. + */ + public static final String VOICE = "voice"; + + /** + * 视频消息. + */ + public static final String VIDEO = "video"; + + /** + * 文件消息 + */ + public static final String FILE = "file"; + + /** + * 图文消息 + */ + public static final String NEWS = "news"; + + /** + * 图文消息(mpnews) + */ + public static final String MPNEWS = "mpnews"; + + /** + * 小程序消息 + */ + public static final String MINIPROGRAM = "miniprogram"; + + } + /** * 企业微信模板卡片消息的卡片类型 */ @@ -287,6 +335,10 @@ public static class EventType { */ public static final String CARD_USER_GIFTING_CARD = "user_gifting_card"; + /** + * 异步安全校验事件 + */ + public static final String WXA_MEDIA_CHECK = "wxa_media_check"; /** * 卡券事件:用户核销卡券 diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxMessageInMemoryDuplicateChecker.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxMessageInMemoryDuplicateChecker.java index 465f35434..88c3aeae6 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxMessageInMemoryDuplicateChecker.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxMessageInMemoryDuplicateChecker.java @@ -8,10 +8,12 @@ *
  * 默认消息重复检查器.
  * 将每个消息id保存在内存里,每隔5秒清理已经过期的消息id,每个消息id的过期时间是15秒
+ * 替换类WxMessageInMemoryDuplicateCheckerSingleton
  * 
* * @author Daniel Qian */ +@Deprecated public class WxMessageInMemoryDuplicateChecker implements WxMessageDuplicateChecker { /** diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxMessageInMemoryDuplicateCheckerSingleton.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxMessageInMemoryDuplicateCheckerSingleton.java new file mode 100644 index 000000000..f275a2bad --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxMessageInMemoryDuplicateCheckerSingleton.java @@ -0,0 +1,91 @@ +package me.chanjar.weixin.common.api; + +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import lombok.extern.slf4j.Slf4j; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/** + * @author jiangby + * @version 1.0 + *

+ * 消息去重,记录消息ID首次出现时的时间戳, + * 15S后定时任务触发时废除该记录消息ID + *

+ * @date 2022/5/26 1:32 + */ +@Slf4j +public class WxMessageInMemoryDuplicateCheckerSingleton implements WxMessageDuplicateChecker { + + /** + * 一个消息ID在内存的过期时间:15秒. + */ + private static final Long TIME_TO_LIVE = 15L; + + /** + * 每隔多少周期检查消息ID是否过期:5秒. + */ + private static final Long CLEAR_PERIOD = 5L; + + /** + * 线程池 + */ + private static final ScheduledThreadPoolExecutor SCHEDULED_THREAD_POOL_EXECUTOR = new ScheduledThreadPoolExecutor(1, + new ThreadFactoryBuilder().setNameFormat("wxMessage-memory-pool-%d").build(), new ThreadPoolExecutor.AbortPolicy()); + + /** + * 消息id->消息时间戳的map. + */ + private static final ConcurrentHashMap MSG_ID_2_TIMESTAMP = new ConcurrentHashMap<>(); + + static { + SCHEDULED_THREAD_POOL_EXECUTOR.scheduleAtFixedRate(() -> { + try { + Long now = System.currentTimeMillis(); + MSG_ID_2_TIMESTAMP.entrySet().removeIf(entry -> now - entry.getValue() > TIME_TO_LIVE * 1000); + } catch (Exception ex) { + log.error("重复消息去重任务出现异常", ex); + } + }, 1, CLEAR_PERIOD, TimeUnit.SECONDS); + } + + /** + * 私有化构造方法,避免外部调用 + */ + private WxMessageInMemoryDuplicateCheckerSingleton() { + } + + /** + * 获取单例 + * + * @return 单例对象 + */ + public static WxMessageInMemoryDuplicateCheckerSingleton getInstance() { + return WxMessageInnerClass.CHECKER_SINGLETON; + } + + /** + * 内部类实现单例 + */ + private static class WxMessageInnerClass { + static final WxMessageInMemoryDuplicateCheckerSingleton CHECKER_SINGLETON = new WxMessageInMemoryDuplicateCheckerSingleton(); + } + + /** + * messageId是否重复 + * + * @param messageId messageId + * @return 是否 + */ + @Override + public boolean isDuplicate(String messageId) { + if (messageId == null) { + return false; + } + Long timestamp = MSG_ID_2_TIMESTAMP.putIfAbsent(messageId, System.currentTimeMillis()); + return timestamp != null; + } +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/WxOAuth2UserInfo.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/WxOAuth2UserInfo.java index e64756002..2880d5932 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/WxOAuth2UserInfo.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/WxOAuth2UserInfo.java @@ -53,12 +53,16 @@ public class WxOAuth2UserInfo implements Serializable { */ @SerializedName("unionid") private String unionId; - /** * privilege 用户特权信息,json数组,如微信沃卡用户为(chinaunicom) */ @SerializedName("privilege") private String[] privileges; + /** + * is_snapshotuser 是否为快照页模式虚拟账号,值为0时是普通用户,1时是虚拟帐号 + */ + @SerializedName("is_snapshotuser") + private Integer snapshotUser; public static WxOAuth2UserInfo fromJson(String json) { return WxGsonBuilder.create().fromJson(json, WxOAuth2UserInfo.class); diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/ocr/WxOcrIdCardResult.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/ocr/WxOcrIdCardResult.java index 0b1e0ff83..93367a445 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/ocr/WxOcrIdCardResult.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/ocr/WxOcrIdCardResult.java @@ -22,6 +22,12 @@ public class WxOcrIdCardResult implements Serializable { private String name; @SerializedName("id") private String id; + @SerializedName("addr") + private String addr; + @SerializedName("gender") + private String gender; + @SerializedName("nationality") + private String nationality; @SerializedName("valid_date") private String validDate; diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/result/WxMinishopImageUploadResult.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/result/WxMinishopImageUploadResult.java index 9aa7a81e2..e476de788 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/result/WxMinishopImageUploadResult.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/result/WxMinishopImageUploadResult.java @@ -1,5 +1,6 @@ package me.chanjar.weixin.common.bean.result; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import lombok.Data; @@ -25,8 +26,12 @@ public static WxMinishopImageUploadResult fromJson(String json) { if (result.getErrcode().equals("0")) { WxMinishopPicFileResult picFileResult = new WxMinishopPicFileResult(); JsonObject picObject = jsonObject.get("pic_file").getAsJsonObject(); - picFileResult.setMediaId(picObject.get("media_id").getAsString()); - picFileResult.setPayMediaId(picObject.get("pay_media_id").getAsString()); + JsonElement mediaId = picObject.get("media_id"); + picFileResult.setMediaId(mediaId==null ? "" : mediaId.getAsString()); + JsonElement payMediaId = picObject.get("pay_media_id"); + picFileResult.setPayMediaId(payMediaId==null ? "" : payMediaId.getAsString()); + JsonElement tempImgUrl = picObject.get("temp_img_url"); + picFileResult.setTempImgUrl(tempImgUrl==null ? "" : tempImgUrl.getAsString()); result.setPicFile(picFileResult); } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/result/WxMinishopPicFileResult.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/result/WxMinishopPicFileResult.java index 1f77a1e6a..2ae2e2320 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/result/WxMinishopPicFileResult.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/result/WxMinishopPicFileResult.java @@ -8,4 +8,5 @@ public class WxMinishopPicFileResult implements Serializable { private String mediaId; private String payMediaId; + private String tempImgUrl; } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxCpErrorMsgEnum.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxCpErrorMsgEnum.java index 61b863bf1..ea1e9e7c6 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxCpErrorMsgEnum.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxCpErrorMsgEnum.java @@ -248,6 +248,10 @@ public enum WxCpErrorMsgEnum { * 不合法的URL;缺少主页URL参数,或者URL不合法(链接需要带上协议头,以 http:// 或者 https:// 开头). */ CODE_40094(40094, "不合法的URL;缺少主页URL参数,或者URL不合法(链接需要带上协议头,以 http:// 或者 https:// 开头)"), + /** + * 不合法的外部联系人userid + */ + CODE_40096(40096,"不合法的外部联系人userid"), /** * 缺少access_token参数. */ @@ -1092,6 +1096,26 @@ public enum WxCpErrorMsgEnum { * 通用错误码,提交审批单内部接口失败 */ CODE_301057(301057, "通用错误码,提交审批单内部接口失败"), + /** + * 输入userid无对应成员 + */ + CODE_301069(301069,"输入userid无对应成员"), + /** + * 系统错误,请稍后再试 + */ + CODE_301070(301070,"系统错误,请稍后再试"), + /** + * 企业内有其他人员有相似人脸,此情况下人脸仍然会录入成功 + */ + CODE_301071(301071,"企业内有其他人员有相似人脸,此情况下人脸仍然会录入成功"), + /** + * 人脸图像数据错误请更换图片 + */ + CODE_301072(301072,"企业内有其他人员有相似人脸,此情况下人脸仍然会录入成功"), + /** + * 输入参数错误 + */ + CODE_301075(301075,"输入参数错误"), /** * 批量导入任务的文件中userid有重复. */ diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/service/WxOAuth2Service.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/service/WxOAuth2Service.java index 5a53de010..e422be06a 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/service/WxOAuth2Service.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/service/WxOAuth2Service.java @@ -14,7 +14,7 @@ public interface WxOAuth2Service { /** *
    * 构造oauth2授权的url连接.
-   * 详情请见: https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html
+   * 详情请见: 网页授权
    * 
* * @param redirectUri 用户授权完成后的重定向链接,无需urlencode, 方法内会进行encode @@ -27,7 +27,7 @@ public interface WxOAuth2Service { /** *
    * 用code换取oauth2的access token.
-   * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=网页授权获取用户基本信息
+   * 详情请见: 网页授权获取用户基本信息
    * 
* * @param code code diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/WxCryptUtil.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/WxCryptUtil.java index d44791eb1..f02d087b7 100755 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/WxCryptUtil.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/WxCryptUtil.java @@ -5,6 +5,7 @@ import lombok.Data; import me.chanjar.weixin.common.error.WxRuntimeException; import org.apache.commons.codec.binary.Base64; +import org.apache.commons.lang3.StringUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.xml.sax.InputSource; @@ -65,7 +66,7 @@ public WxCryptUtil() { public WxCryptUtil(String token, String encodingAesKey, String appidOrCorpid) { this.token = token; this.appidOrCorpid = appidOrCorpid; - this.aesKey = Base64.decodeBase64(CharMatcher.whitespace().removeFrom(encodingAesKey)); + this.aesKey = Base64.decodeBase64(StringUtils.remove(encodingAesKey, " ")); } private static String extractEncryptPart(String xml) { diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddHttpMediaInputStreamUploadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddHttpMediaInputStreamUploadRequestExecutor.java index d0591aee9..479844e42 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddHttpMediaInputStreamUploadRequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddHttpMediaInputStreamUploadRequestExecutor.java @@ -4,7 +4,7 @@ import jodd.http.HttpRequest; import jodd.http.HttpResponse; import jodd.http.ProxyInfo; -import jodd.http.up.ByteArrayUploadable; +import jodd.http.upload.ByteArrayUploadable; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; import me.chanjar.weixin.common.enums.WxType; import me.chanjar.weixin.common.error.WxError; diff --git a/weixin-java-common/src/test/java/me/chanjar/weixin/common/api/WxMessageInMemoryDuplicateCheckerSingletonTest.java b/weixin-java-common/src/test/java/me/chanjar/weixin/common/api/WxMessageInMemoryDuplicateCheckerSingletonTest.java new file mode 100644 index 000000000..d6f4ba2fa --- /dev/null +++ b/weixin-java-common/src/test/java/me/chanjar/weixin/common/api/WxMessageInMemoryDuplicateCheckerSingletonTest.java @@ -0,0 +1,45 @@ +package me.chanjar.weixin.common.api; + +import org.testng.annotations.Test; + +import java.util.concurrent.TimeUnit; + +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +/** + * @author jiangby + * @version 1.0 + * @description: 作用 + * @date 2022/5/26 1:46 + */ +@Test +public class WxMessageInMemoryDuplicateCheckerSingletonTest { + + private static WxMessageInMemoryDuplicateCheckerSingleton checkerSingleton = WxMessageInMemoryDuplicateCheckerSingleton.getInstance(); + + public void test() throws InterruptedException { + Long[] msgIds = new Long[]{1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L}; + + // 第一次检查 + for (Long msgId : msgIds) { + boolean result = checkerSingleton.isDuplicate(String.valueOf(msgId)); + assertFalse(result); + } + + // 初始化后1S进行检查 每五秒检查一次,过期时间为15秒,过15秒再检查 + TimeUnit.SECONDS.sleep(15); + for (Long msgId : msgIds) { + boolean result = checkerSingleton.isDuplicate(String.valueOf(msgId)); + assertTrue(result); + } + + // 过6秒再检查 + TimeUnit.SECONDS.sleep(6); + for (Long msgId : msgIds) { + boolean result = checkerSingleton.isDuplicate(String.valueOf(msgId)); + assertFalse(result); + } + + } +} diff --git a/weixin-java-cp/pom.xml b/weixin-java-cp/pom.xml index 9c8c3f86e..7137a49ff 100644 --- a/weixin-java-cp/pom.xml +++ b/weixin-java-cp/pom.xml @@ -7,7 +7,7 @@ com.github.binarywang wx-java - 4.3.0 + 4.4.0 weixin-java-cp diff --git a/weixin-java-cp/src/main/java/com/tencent/wework/Finance.java b/weixin-java-cp/src/main/java/com/tencent/wework/Finance.java index e653fd0f4..a2bd0175a 100644 --- a/weixin-java-cp/src/main/java/com/tencent/wework/Finance.java +++ b/weixin-java-cp/src/main/java/com/tencent/wework/Finance.java @@ -2,10 +2,12 @@ import lombok.extern.slf4j.Slf4j; +import java.util.List; + /** + * 企业微信会话内容存档Finance类 * 注意: - * 此类必须配置在com.tencent.wework路径底下,否则会报错: - * java.lang.UnsatisfiedLinkError: com.xxx.Finance.NewSdk() + * 此类必须配置在com.tencent.wework路径底下,否则会报错:java.lang.UnsatisfiedLinkError: com.xxx.Finance.NewSdk() *

* Q:JAVA版本的sdk报错UnsatisfiedLinkError? * A:请检查是否修改了sdk的包名。 @@ -13,7 +15,7 @@ * 官方文档: * https://developer.work.weixin.qq.com/document/path/91552 * - * @author Wang_Wong + * @author Wang_Wong * @date 2022-01-17 */ @Slf4j @@ -147,7 +149,7 @@ public static boolean isWindows() { * @param libFiles 类库配置文件 * @param prefixPath 类库文件的前缀路径 */ - public Finance(String[] libFiles, String prefixPath) { + public Finance(List libFiles, String prefixPath) { boolean isWindows = Finance.isWindows(); for (String file : libFiles) { String suffix = file.substring(file.lastIndexOf(".") + 1); @@ -173,7 +175,7 @@ public Finance(String[] libFiles, String prefixPath) { * @param prefixPath * @return */ - public synchronized static Finance loadingLibraries(String[] libFiles, String prefixPath) { + public synchronized static Finance loadingLibraries(List libFiles, String prefixPath) { if (finance != null) { return finance; } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpExportService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpExportService.java new file mode 100644 index 000000000..a28c7fc7d --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpExportService.java @@ -0,0 +1,100 @@ +package me.chanjar.weixin.cp.api; + +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.bean.export.WxCpExportRequest; +import me.chanjar.weixin.cp.bean.export.WxCpExportResult; + +/** + * 异步导出接口 + * + * @author zhongjun + * @date 2022/4/21 + **/ +public interface WxCpExportService { + + /** + *

+   *
+   * 导出成员
+   *
+   * 请求方式:POST(HTTPS)
+   * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/export/simple_user?access_token=ACCESS_TOKEN
+   *
+   * 文档地址:https://developer.work.weixin.qq.com/document/path/94849
+   * 
+ * + * @param params 导出参数 + * @return jobId 异步任务id + * @throws WxErrorException . + */ + String simpleUser(WxCpExportRequest params) throws WxErrorException; + + /** + *
+   *
+   * 导出成员详情
+   *
+   * 请求方式:POST(HTTPS)
+   * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/export/user?access_token=ACCESS_TOKEN
+   *
+   * 文档地址:https://developer.work.weixin.qq.com/document/path/94851
+   * 
+ * + * @param params 导出参数 + * @return jobId 异步任务id + * @throws WxErrorException . + */ + String user(WxCpExportRequest params) throws WxErrorException; + + /** + *
+   *
+   * 导出部门
+   *
+   * 请求方式:POST(HTTPS)
+   * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/export/department?access_token=ACCESS_TOKEN
+   *
+   * 文档地址:https://developer.work.weixin.qq.com/document/path/94852
+   * 
+ * + * @param params 导出参数 + * @return jobId 异步任务id + * @throws WxErrorException . + */ + String department(WxCpExportRequest params) throws WxErrorException; + + /** + *
+   *
+   * 导出标签成员
+   *
+   * 请求方式:POST(HTTPS)
+   * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/export/taguser?access_token=ACCESS_TOKEN
+   *
+   * 文档地址:https://developer.work.weixin.qq.com/document/path/94853
+   * 
+ * + * @param params 导出参数 + * @return jobId 异步任务id + * @throws WxErrorException . + */ + String tagUser(WxCpExportRequest params) throws WxErrorException; + + /** + *
+   *
+   * 获取导出结果
+   *
+   * 请求方式:GET(HTTPS)
+   * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/export/get_result?access_token=ACCESS_TOKEN&jobid=jobid_xxxxxxxxxxxxxxx
+   *
+   * 文档地址:https://developer.work.weixin.qq.com/document/path/94854
+   * 返回的url文件下载解密可参考 CSDN
+   * 
+ * + * @param jobId 异步任务id + * @return 导出结果 + * @throws WxErrorException . + */ + WxCpExportResult getResult(String jobId) throws WxErrorException; +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpExternalContactService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpExternalContactService.java index ae6b59ed6..0335725c7 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpExternalContactService.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpExternalContactService.java @@ -1,17 +1,16 @@ package me.chanjar.weixin.cp.api; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; import lombok.NonNull; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.cp.bean.WxCpBaseResp; import me.chanjar.weixin.cp.bean.external.*; import me.chanjar.weixin.cp.bean.external.contact.*; -import me.chanjar.weixin.cp.bean.oa.WxCpApprovalInfoQueryFilter; import org.jetbrains.annotations.NotNull; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; import java.util.Date; import java.util.List; @@ -57,7 +56,6 @@ public interface WxCpExternalContactService { * @throws WxErrorException the wx error exception */ WxCpContactWayInfo getContactWay(@NonNull String configId) throws WxErrorException; - /** * 更新企业已配置的「联系我」方式 * @@ -172,6 +170,50 @@ public interface WxCpExternalContactService { */ String unionidToExternalUserid(@NotNull String unionid,String openid) throws WxErrorException; + /** + * + * 配置客户群进群方式 + * 企业可以在管理后台-客户联系中配置「加入群聊」的二维码或者小程序按钮,客户通过扫描二维码或点击小程序上的按钮,即可加入特定的客户群。 + * 企业可通过此接口为具有客户联系功能的成员生成专属的二维码或者小程序按钮。 + * 如果配置的是小程序按钮,需要开发者的小程序接入小程序插件。 + * 注意: + * 通过API添加的配置不会在管理端进行展示,每个企业可通过API最多配置50万个「加入群聊」(与「联系我」共用50万的额度)。 + * 文档地址:https://developer.work.weixin.qq.com/document/path/92229 + * @param wxCpGroupJoinWayInfo + * @return {@link WxCpGroupJoinWayResult} + * @throws WxErrorException + */ + WxCpGroupJoinWayResult addJoinWay(@NonNull WxCpGroupJoinWayInfo wxCpGroupJoinWayInfo) throws WxErrorException; + + /** + *更新客户群进群方式配置 + * 更新进群方式配置信息。注意:使用覆盖的方式更新。 + * 文档地址:https://developer.work.weixin.qq.com/document/path/92229 + * @param wxCpGroupJoinWayInfo + * @return + * @throws WxErrorException + */ + WxCpBaseResp updateJoinWay(@NonNull WxCpGroupJoinWayInfo wxCpGroupJoinWayInfo) throws WxErrorException; + + /** + * 获取客户群进群方式配置 + * 获取企业配置的群二维码或小程序按钮。 + * 文档地址:https://developer.work.weixin.qq.com/document/path/92229 + * @param configId + * @return + * @throws WxErrorException + */ + WxCpGroupJoinWayInfo getJoinWay(@NonNull String configId) throws WxErrorException; + + /** + * 删除客户群进群方式配置 + * 文档地址:https://developer.work.weixin.qq.com/document/path/92229 + * @param configId + * @return + * @throws WxErrorException + */ + WxCpBaseResp delJoinWay( @NonNull String configId) throws WxErrorException; + /** * 代开发应用external_userid转换 *
@@ -960,5 +1002,71 @@ WxMediaUploadResult uploadAttachment(String mediaType, String fileType, Integer
   WxMediaUploadResult uploadAttachment(String mediaType, Integer attachmentType, File file)
     throws WxErrorException;
 
+  /**
+   * 
+   * 新建敏感词规则
+   * 企业和第三方应用可以通过此接口新建敏感词规则
+   * 请求方式:POST(HTTPS)
+   * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/externalcontact/add_intercept_rule?access_token=ACCESS_TOKEN
+   * 
+   */
+  WxCpInterceptRuleResultResp addInterceptRule(WxCpInterceptRuleResp ruleResp) throws  WxErrorException;
+  /**
+   * 
+   * 修改敏感词规则
+   * 企业和第三方应用可以通过此接口修改敏感词规则
+   * 请求方式:POST(HTTPS)
+   * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/externalcontact/update_intercept_rule?access_token=ACCESS_TOKEN
+   * 
+   */
+  WxCpInterceptRuleResultResp updateInterceptRule(WxCpInterceptRuleResp ruleResp) throws WxErrorException;
+
+  /**
+   * 
+   * 删除敏感词规则
+   * 企业和第三方应用可以通过此接口修改敏感词规则
+   * 请求方式:POST(HTTPS)
+   * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/externalcontact/del_intercept_rule?access_token=ACCESS_TOKEN
+   * 
+   * @param rule_id 规则id
+   */
+  WxCpBaseResp delInterceptRule(String rule_id) throws WxErrorException;
+
+  /**
+   * 
+   * 创建商品图册
+   * 企业和第三方应用可以通过此接口增加商品
+   * 请求方式:POST(HTTPS)
+   * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/externalcontact/add_product_album?access_token=ACCESS_TOKEN
+   * 文档地址:https://developer.work.weixin.qq.com/document/path/95096#%E5%88%9B%E5%BB%BA%E5%95%86%E5%93%81%E5%9B%BE%E5%86%8C
+   * 
+   * @param wxCpProductAlbumInfo 商品图册信息
+   * @return 商品id
+   */
+  String addProductAlbum(WxCpProductAlbumInfo wxCpProductAlbumInfo) throws WxErrorException;
+
+  /**
+   * 
+   * 编辑商品图册
+   * 企业和第三方应用可以通过此接口修改商品信息
+   * 请求方式:POST(HTTPS)
+   * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/externalcontact/update_product_album?access_token=ACCESS_TOKEN
+   * 文档地址:https://developer.work.weixin.qq.com/document/path/95096#%E7%BC%96%E8%BE%91%E5%95%86%E5%93%81%E5%9B%BE%E5%86%8C
+   * 
+   * @param wxCpProductAlbumInfo 商品图册信息
+   */
+  void updateProductAlbum(WxCpProductAlbumInfo wxCpProductAlbumInfo) throws WxErrorException;
+
+  /**
+   * 
+   * 删除商品图册
+   * 企业和第三方应用可以通过此接口删除商品信息
+   * 请求方式:POST(HTTPS)
+   * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/externalcontact/delete_product_album?access_token=ACCESS_TOKEN
+   * 文档地址:https://developer.work.weixin.qq.com/document/path/95096#%E5%88%A0%E9%99%A4%E5%95%86%E5%93%81%E5%9B%BE%E5%86%8C
+   * 
+   * @param productId 商品id
+   */
+  void deleteProductAlbum(String productId) throws WxErrorException;
 
 }
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpGroupRobotService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpGroupRobotService.java
index b5a9579e0..9839afb9e 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpGroupRobotService.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpGroupRobotService.java
@@ -88,4 +88,13 @@ public interface WxCpGroupRobotService {
    * @throws WxErrorException 异常
    */
   void sendNews(String webhookUrl, List articleList) throws WxErrorException;
+
+  /**
+   * 发送文件类型的消息
+   *
+   * @param webhookUrl  webhook地址
+   * @param mediaId 文件id
+   * @throws WxErrorException 异常
+   */
+  void sendFile(String webhookUrl, String mediaId) throws WxErrorException;
 }
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpKfService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpKfService.java
index 0da548905..b829592e6 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpKfService.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpKfService.java
@@ -1,6 +1,5 @@
 package me.chanjar.weixin.cp.api;
 
-import java.util.List;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.cp.bean.WxCpBaseResp;
 import me.chanjar.weixin.cp.bean.kf.WxCpKfAccountAdd;
@@ -16,8 +15,12 @@
 import me.chanjar.weixin.cp.bean.kf.WxCpKfMsgSendResp;
 import me.chanjar.weixin.cp.bean.kf.WxCpKfServiceStateResp;
 import me.chanjar.weixin.cp.bean.kf.WxCpKfServiceStateTransResp;
+import me.chanjar.weixin.cp.bean.kf.WxCpKfServiceUpgradeConfigResp;
 import me.chanjar.weixin.cp.bean.kf.WxCpKfServicerListResp;
 import me.chanjar.weixin.cp.bean.kf.WxCpKfServicerOpResp;
+import me.chanjar.weixin.cp.bean.kf.*;
+
+import java.util.List;
 
 /**
  * 微信客服接口
@@ -60,11 +63,12 @@ public interface WxCpKfService {
 
   /**
    * 获取客服帐号列表,包括所有的客服帐号的客服ID、名称和头像。
-   *
+   * @param offset 分页,偏移量, 默认为0
+   * @param limit  分页,预期请求的数据量,默认为100,取值范围 1 ~ 100
    * @return 客服帐号列表
    * @throws WxErrorException 异常
    */
-  WxCpKfAccountListResp listAccount() throws WxErrorException;
+  WxCpKfAccountListResp listAccount(Integer offset,Integer limit) throws WxErrorException;
 
   /**
    * 企业可通过此接口获取带有不同参数的客服链接,不同客服帐号对应不同的客服链接。获取后,企业可将链接嵌入到网页等场景中,
@@ -188,4 +192,59 @@ WxCpKfMsgListResp syncMsg(String cursor, String token, Integer limit, Integer vo
    */
   WxCpKfCustomerBatchGetResp customerBatchGet(List externalUserIdList)
     throws WxErrorException;
+
+  /**
+   * 
+   * 获取「客户数据统计」企业汇总数据
+   * 通过此接口,可以获取咨询会话数、咨询客户数等企业汇总统计数据
+   * 请求方式:POST(HTTPS)
+   * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/kf/get_corp_statistic?access_token=ACCESS_TOKEN
+   * 文档地址:https://developer.work.weixin.qq.com/document/path/95489
+   * 
+   * @param request 查询参数
+   * @return 客户数据统计-企业汇总数据
+   */
+  WxCpKfGetCorpStatisticResp getCorpStatistic(WxCpKfGetCorpStatisticRequest request) throws WxErrorException;
+
+  // 「升级服务」配置
+  /**
+   * 获取配置的专员与客户群
+   * @return
+   * @throws WxErrorException
+   */
+  WxCpKfServiceUpgradeConfigResp getUpgradeServiceConfig() throws WxErrorException;
+
+  /**
+   * 升级专员服务
+   * @param openKfid 客服帐号ID
+   * @param externalUserId 微信客户的external_userid
+   * @param userid 服务专员的userid
+   * @param wording 推荐语
+   * @return
+   * @throws WxErrorException
+   */
+  WxCpBaseResp upgradeMemberService(String openKfid, String externalUserId,
+    String userid, String wording) throws WxErrorException;
+
+  /**
+   * 升级客户群服务
+   * @param openKfid 客服帐号ID
+   * @param externalUserId 微信客户的external_userid
+   * @param chatId 客户群id
+   * @param wording 推荐语
+   * @return
+   * @throws WxErrorException
+   */
+  WxCpBaseResp upgradeGroupchatService(String openKfid, String externalUserId,
+    String chatId, String wording) throws WxErrorException;
+
+  /**
+   * 为客户取消推荐
+   * @param openKfid 客服帐号ID
+   * @param externalUserId 微信客户的external_userid
+   * @return
+   * @throws WxErrorException
+   */
+  WxCpBaseResp cancelUpgradeService(String openKfid, String externalUserId)
+    throws WxErrorException;
 }
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java
index 4b417e90f..cb30cea1f 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java
@@ -48,7 +48,7 @@ public interface WxCpLivingService {
    * @return
    * @throws WxErrorException
    */
-  WxCpWatchStat getWatchStat(@NonNull String livingId, Integer nextKey) throws WxErrorException;
+  WxCpWatchStat getWatchStat(@NonNull String livingId, String nextKey) throws WxErrorException;
 
   /**
    * 获取成员直播ID列表
@@ -84,7 +84,7 @@ public interface WxCpLivingService {
    * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/living/create?access_token=ACCESS_TOKEN
    *
    * @param request 创建预约直播请求参数.
-   * @return
+   * @return livingId(直播id)
    * @throws WxErrorException
    */
   String livingCreate(WxCpLivingCreateRequest request) throws WxErrorException;
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMessageService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMessageService.java
index 1b66d00c0..ff71ea0c4 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMessageService.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMessageService.java
@@ -50,4 +50,20 @@ public interface WxCpMessageService {
    * @throws WxErrorException the wx error exception
    */
   WxCpLinkedCorpMessageSendResult sendLinkedCorpMessage(WxCpLinkedCorpMessage message) throws WxErrorException;
+
+  /**
+   * 发送「学校通知」
+   * https://developer.work.weixin.qq.com/document/path/92321
+   * 

+ * 学校可以通过此接口来给家长发送不同类型的学校通知,来满足多种场景下的学校通知需求。目前支持的消息类型为文本、图片、语音、视频、文件、图文。 + *

+ * 请求方式:POST(HTTPS) + * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/externalcontact/message/send?access_token=ACCESS_TOKEN + * + * @param message 要发送的消息对象 + * @return + * @throws WxErrorException + */ + WxCpSchoolContactMessageSendResult sendSchoolContactMessage(WxCpSchoolContactMessage message) throws WxErrorException; + } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMsgAuditService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMsgAuditService.java index 63389aeb8..72f637040 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMsgAuditService.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMsgAuditService.java @@ -33,29 +33,34 @@ public interface WxCpMsgAuditService { /** * 获取解密的聊天数据Model * + * @param sdk getChatDatas()获取到的sdk * @param chatData getChatDatas()获取到的聊天数据 + * @param pkcs1 使用什么方式进行解密,1代表使用PKCS1进行解密,2代表PKCS8进行解密 ... * @return 解密后的聊天数据 * @throws Exception */ - WxCpChatModel getDecryptData(@NonNull WxCpChatDatas.WxCpChatData chatData) throws Exception; + WxCpChatModel getDecryptData(@NonNull long sdk, @NonNull WxCpChatDatas.WxCpChatData chatData, @NonNull Integer pkcs1) throws Exception; /** * 获取解密的聊天数据明文 * + * @param sdk getChatDatas()获取到的sdk * @param chatData getChatDatas()获取到的聊天数据 + * @param pkcs1 使用什么方式进行解密,1代表使用PKCS1进行解密,2代表PKCS8进行解密 ... * @return 解密后的明文 * @throws Exception */ - String getChatPlainText(@NonNull WxCpChatDatas.WxCpChatData chatData) throws Exception; + String getChatPlainText(@NonNull long sdk, @NonNull WxCpChatDatas.WxCpChatData chatData, @NonNull Integer pkcs1) throws Exception; /** * 获取媒体文件 * 针对图片、文件等媒体数据,提供sdk接口拉取数据内容。 - * + *

* 注意: * 根据上面返回的文件类型,拼接好存放文件的绝对路径即可。此时绝对路径写入文件流,来达到获取媒体文件的目的。 * 详情可以看官方文档,亦可阅读此接口源码。 * + * @param sdk getChatDatas()获取到的sdk,注意,每次获取的sdk会不一样 * @param sdkfileid 消息体内容中的sdkfileid信息 * @param proxy 使用代理的请求,需要传入代理的链接。如:socks5://10.0.0.1:8081 或者 http://10.0.0.1:8081,如果没有传null * @param passwd 代理账号密码,需要传入代理的账号密码。如 user_name:passwd_123,如果没有传null @@ -63,7 +68,7 @@ public interface WxCpMsgAuditService { * @param targetFilePath 目标文件绝对路径+实际文件名,比如:/usr/local/file/20220114/474f866b39d10718810d55262af82662.gif * @throws WxErrorException */ - void getMediaFile(@NonNull String sdkfileid, String proxy, String passwd, @NonNull long timeout, @NonNull String targetFilePath) throws WxErrorException; + void getMediaFile(@NonNull long sdk, @NonNull String sdkfileid, String proxy, String passwd, @NonNull long timeout, @NonNull String targetFilePath) throws WxErrorException; /** * 获取会话内容存档开启成员列表 diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOAuth2Service.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOAuth2Service.java index 7c42ea63f..f524ac94b 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOAuth2Service.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOAuth2Service.java @@ -9,6 +9,8 @@ * OAuth2相关管理接口. * Created by BinaryWang on 2017/6/24. *

+ *

+ * 文档1:https://developer.work.weixin.qq.com/document/path/91856 * * @author Binary Wang */ @@ -84,6 +86,19 @@ public interface WxCpOAuth2Service { */ WxCpOauth2UserInfo getUserInfo(Integer agentId, String code) throws WxErrorException; + /** + * 获取家校访问用户身份 + * 该接口用于根据code获取家长或者学生信息 + *

+ * 请求方式:GET(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/getuserinfo?access_token=ACCESS_TOKEN&code=CODE + * + * @param code + * @return + * @throws WxErrorException + */ + WxCpOauth2UserInfo getSchoolUserInfo(String code) throws WxErrorException; + /** *

    * 使用user_ticket获取成员详情.
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOaMeetingRoomService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOaMeetingRoomService.java
new file mode 100644
index 000000000..e69e81766
--- /dev/null
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOaMeetingRoomService.java
@@ -0,0 +1,76 @@
+package me.chanjar.weixin.cp.api;
+
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.cp.bean.oa.meetingroom.WxCpOaMeetingRoom;
+
+import java.util.List;
+
+/**
+ * 企业微信会议室接口.
+ *
+ * @author lm93129
+ * @date 2022年8月12日22:33:36
+ */
+public interface WxCpOaMeetingRoomService {
+  /**
+   * 创建会议室.
+   * 
+   * 该接口用于通过应用在企业内创建一个会议室。
+   * 请求方式: POST(HTTPS)
+   * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/oa/meetingroom/add?access_token=ACCESS_TOKEN
+   *
+   * 文档地址:https://developer.work.weixin.qq.com/document/path/93619
+   * 
+ * + * @param meetingRoom 会议室对象 + * @return 会议室ID + * @throws WxErrorException . + */ + String addMeetingRoom(WxCpOaMeetingRoom meetingRoom) throws WxErrorException; + + /** + * 查询会议室. + *
+   * 该接口用于通过应用在企业内查询会议室列表。
+   * 请求方式: POST(HTTPS)
+   * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/oa/meetingroom/list?access_token=ACCESS_TOKEN
+   *
+   * 文档地址:https://developer.work.weixin.qq.com/document/path/93619
+   * 
+ * + * @param meetingRoomRequest 会议室查询对象 + * @return 会议室ID + * @throws WxErrorException . + */ + List listMeetingRoom(WxCpOaMeetingRoom meetingRoomRequest) throws WxErrorException; + + /** + * 编辑会议室. + *
+   * 该接口用于通过应用在企业内编辑会议室。
+   * 请求方式: POST(HTTPS)
+   * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/oa/meetingroom/edit?access_token=ACCESS_TOKEN
+   *
+   * 文档地址:https://developer.work.weixin.qq.com/document/path/93619
+   * 
+ * + * @param meetingRoom 会议室对象 + * @throws WxErrorException . + */ + void editMeetingRoom(WxCpOaMeetingRoom meetingRoom) throws WxErrorException; + + /** + * 编辑会议室. + *
+   * 该接口用于通过应用在企业内编辑会议室。
+   * 请求方式: POST(HTTPS)
+   * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/oa/meetingroom/del?access_token=ACCESS_TOKEN
+   *
+   * 文档地址:https://developer.work.weixin.qq.com/document/path/93619
+   * 
+ * + * @param meetingRoomId 会议室对象 + * @throws WxErrorException . + */ + void deleteMeetingRoom(Integer meetingRoomId) throws WxErrorException; +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOaService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOaService.java index bbbcb6095..69fabb569 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOaService.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOaService.java @@ -2,6 +2,7 @@ import lombok.NonNull; import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; import me.chanjar.weixin.cp.bean.oa.*; import java.util.Date; @@ -138,6 +139,57 @@ WxCpApprovalInfo getApprovalInfo(@NonNull Date startTime, @NonNull Date endTime, WxCpCorpConfInfo getCorpConf() throws WxErrorException; + /** + * 获取成员假期余额 + * 企业可通过审批应用或自建应用Secret调用本接口,获取可见范围内各个员工的假期余额数据。 + * 第三方应用可获取应用可见范围内各个员工的假期余额数据。 + * + * 请求方式:POST(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/oa/vacation/getuservacationquota?access_token=ACCESS_TOKEN + * + * @param userId 需要获取假期余额的成员的userid + * @return + * @throws WxErrorException + */ + WxCpUserVacationQuota getUserVacationQuota(@NonNull String userId) throws WxErrorException; + + + /** + * 获取审批数据(旧) + * 提示:推荐使用新接口“批量获取审批单号”及“获取审批申请详情”,此接口后续将不再维护、逐步下线。 + * 通过本接口来获取公司一段时间内的审批记录。一次拉取调用最多拉取100个审批记录,可以通过多次拉取的方式来满足需求,但调用频率不可超过600次/分。 + * + * 请求方式:POST(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/corp/getapprovaldata?access_token=ACCESS_TOKEN + * + * @param startTime 获取审批记录的开始时间。Unix时间戳 + * @param endTime 获取审批记录的结束时间。Unix时间戳 + * @param nextSpNum 第一个拉取的审批单号,不填从该时间段的第一个审批单拉取 + * @return + * @throws WxErrorException + */ + WxCpGetApprovalData getApprovalData(@NonNull Long startTime, @NonNull Long endTime, Long nextSpNum) throws WxErrorException; + + + /** + * 修改成员假期余额 + * 企业可通过审批应用或自建应用Secret调用本接口,修改可见范围内员工的“假期余额”。 + * 第三方应用可通过应本接口修改应用可见范围内指定员工的“假期余额”。 + * + * 请求方式:POST(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/oa/vacation/setoneuserquota?access_token=ACCESS_TOKEN + * + * @param userId 需要修改假期余额的成员的userid + * @param vacationId 假期id + * @param leftDuration 设置的假期余额,单位为秒,不能大于1000天或24000小时,当假期时间刻度为按小时请假时,必须为360整倍数,即0.1小时整倍数,按天请假时,必须为8640整倍数,即0.1天整倍数 + * @param timeAttr 假期时间刻度:0-按天请假;1-按小时请假 + * @param remarks 修改备注,用于显示在假期余额的修改记录当中,可对修改行为作说明,不超过200字符 + * @return + * @throws WxErrorException + */ + WxCpBaseResp setOneUserQuota(@NonNull String userId, @NonNull Integer vacationId, @NonNull Integer leftDuration, @NonNull Integer timeAttr, String remarks) throws WxErrorException; + + /** * 获取公费电话拨打记录 * @@ -203,4 +255,17 @@ List getDialRecord(Date startTime, Date endTime, Integer offset, * @throws WxErrorException the wx error exception */ void setCheckinScheduleList(WxCpSetCheckinSchedule wxCpSetCheckinSchedule) throws WxErrorException; + /** + *
+   * 录入打卡人员人脸信息
+   * 企业可通过打卡应用Secret调用本接口,为企业打卡人员录入人脸信息,人脸信息仅用于人脸打卡。
+   * 上传图片大小限制:图片数据不超过1M
+   * 请求方式:POST(HTTPS)
+   * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/checkin/addcheckinuserface?access_token=ACCESS_TOKEN
+   * 文档地址:https://developer.work.weixin.qq.com/document/path/93378
+   * 
+   * @param userId 需要录入的用户id
+   * @param userFace 需要录入的人脸图片数据,需要将图片数据base64处理后填入,对已录入的人脸会进行更新处理
+   */
+  void addCheckInUserFace(String userId, String userFace) throws WxErrorException;
 }
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOaWeDriveService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOaWeDriveService.java
new file mode 100644
index 000000000..fff47ca10
--- /dev/null
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOaWeDriveService.java
@@ -0,0 +1,296 @@
+package me.chanjar.weixin.cp.api;
+
+import lombok.NonNull;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.cp.bean.WxCpBaseResp;
+import me.chanjar.weixin.cp.bean.oa.wedrive.*;
+
+import java.util.List;
+
+/**
+ * 企业微信微盘相关接口.
+ * https://developer.work.weixin.qq.com/document/path/93654
+ *
+ * @author Wang_Wong
+ * @date 2022-04-22
+ */
+public interface WxCpOaWeDriveService {
+
+  /**
+   * 新建空间
+   * 该接口用于在微盘内新建空间,可以指定人创建空间。
+   * 

+ * 请求方式:POST(HTTPS) + * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/wedrive/space_create?access_token=ACCESS_TOKEN + * + * @param request 新建空间对应请求参数 + * @return spaceid(空间id) + * @throws WxErrorException + */ + WxCpSpaceCreateData spaceCreate(@NonNull WxCpSpaceCreateRequest request) throws WxErrorException; + + /** + * 重命名空间 + * 该接口用于重命名已有空间,接收userid参数,以空间管理员身份来重命名。 + *

+ * 请求方式:POST(HTTPS) + * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/wedrive/space_rename?access_token=ACCESS_TOKEN + * + * @param request 重命名空间的请求参数 + * @return + * @throws WxErrorException + */ + WxCpBaseResp spaceRename(@NonNull WxCpSpaceRenameRequest request) throws WxErrorException; + + /** + * 解散空间 + * 该接口用于解散已有空间,需要以空间管理员身份来解散。 + *

+ * 请求方式:POST(HTTPS) + * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/wedrive/space_dismiss?access_token=ACCESS_TOKEN + * + * @param userId + * @param spaceId + * @return + * @throws WxErrorException + */ + WxCpBaseResp spaceDismiss(@NonNull String userId, @NonNull String spaceId) throws WxErrorException; + + /** + * 获取空间信息 + * 该接口用于获取空间成员列表、信息、权限等信息。 + *

+ * 请求方式:POST(HTTPS) + * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/wedrive/space_info?access_token=ACCESS_TOKEN + * + * @param userId + * @param spaceId + * @return + * @throws WxErrorException + */ + WxCpSpaceInfo spaceInfo(@NonNull String userId, @NonNull String spaceId) throws WxErrorException; + + /** + * 添加成员/部门 + * 该接口用于对指定空间添加成员/部门,可一次性添加多个。 + *

+ * 请求方式:POST(HTTPS) + * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/wedrive/space_acl_add?access_token=ACCESS_TOKEN + * + * @param request 添加成员/部门请求参数 + * @return + * @throws WxErrorException + */ + WxCpBaseResp spaceAclAdd(@NonNull WxCpSpaceAclAddRequest request) throws WxErrorException; + + /** + * 移除成员/部门 + * 该接口用于对指定空间移除成员/部门,操作者需要有移除权限。 + *

+ * 请求方式:POST(HTTPS) + * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/wedrive/space_acl_del?access_token=ACCESS_TOKEN + * + * @param request 移除成员/部门请求参数 + * @return + * @throws WxErrorException + */ + WxCpBaseResp spaceAclDel(@NonNull WxCpSpaceAclDelRequest request) throws WxErrorException; + + /** + * 权限管理 + * 该接口用于修改空间权限,需要传入userid,修改权限范围继承传入用户的权限范围。 + *

+ * 请求方式:POST(HTTPS) + * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/wedrive/space_setting?access_token=ACCESS_TOKEN + * + * @param request 权限管理请求参数 + * @return + * @throws WxErrorException + */ + WxCpBaseResp spaceSetting(@NonNull WxCpSpaceSettingRequest request) throws WxErrorException; + + /** + * 获取邀请链接 + * 该接口用于获取空间邀请分享链接。 + *

+ * 请求方式:POST(HTTPS) + * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/wedrive/space_share?access_token=ACCESS_TOKEN + * + * @param userId + * @param spaceId + * @return + * @throws WxErrorException + */ + WxCpSpaceShare spaceShare(@NonNull String userId, @NonNull String spaceId) throws WxErrorException; + + /** + * 获取文件列表 + * 该接口用于获取指定地址下的文件列表。 + *

+ * 请求方式:POST(HTTPS) + * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/wedrive/file_list?access_token=ACCESS_TOKEN + * + * @param request 获取文件列表请求参数 + * @return + * @throws WxErrorException + */ + WxCpFileList fileList(@NonNull WxCpFileListRequest request) throws WxErrorException; + + /** + * 上传文件 + * 该接口用于向微盘中的指定位置上传文件。 + *

+ * 请求方式:POST(HTTPS) + * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/wedrive/file_upload?access_token=ACCESS_TOKEN + * + * @param request 上传文件请求参数 + * @return + * @throws WxErrorException + */ + WxCpFileUpload fileUpload(@NonNull WxCpFileUploadRequest request) throws WxErrorException; + + /** + * 下载文件 + * 该接口用于下载文件,请求的userid需有下载权限。 + *

+ * 请求方式:POST(HTTPS) + * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/wedrive/file_download?access_token=ACCESS_TOKEN + * + * @param userId + * @param fileId + * @return + * @throws WxErrorException + */ + WxCpFileDownload fileDownload(@NonNull String userId, @NonNull String fileId) throws WxErrorException; + + /** + * 重命名文件 + * 该接口用于对指定文件进行重命名。 + *

+ * 请求方式:POST(HTTPS) + * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/wedrive/file_rename?access_token=ACCESS_TOKEN + * + * @param userId + * @param fileId + * @param newName + * @return + * @throws WxErrorException + */ + WxCpFileRename fileRename(@NonNull String userId, @NonNull String fileId, @NonNull String newName) throws WxErrorException; + + /** + * 新建文件/微文档 + * 该接口用于在微盘指定位置新建文件、微文档。 + *

+ * 请求方式:POST(HTTPS) + * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/wedrive/file_create?access_token=ACCESS_TOKEN + * + * @param userId 操作者userid + * @param spaceId 空间spaceid + * @param fatherId 父目录fileid, 在根目录时为空间spaceid + * @param fileType 文件类型, 1:文件夹 3:微文档(文档) 4:微文档(表格) + * @param fileName 文件名字 + * @return + * @throws WxErrorException + */ + WxCpFileCreate fileCreate(@NonNull String userId, @NonNull String spaceId, + @NonNull String fatherId, @NonNull Integer fileType, @NonNull String fileName) throws WxErrorException; + + /** + * 移动文件 + * 该接口用于将文件移动到指定位置。 + *

+ * 请求方式:POST(HTTPS) + * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/wedrive/file_move?access_token=ACCESS_TOKEN + * + * @param request 移动文件的请求参数 + * @return + * @throws WxErrorException + */ + WxCpFileMove fileMove(@NonNull WxCpFileMoveRequest request) throws WxErrorException; + + /** + * 删除文件 + * 该接口用于删除指定文件。 + *

+ * 请求方式:POST(HTTPS) + * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/wedrive/file_delete?access_token=ACCESS_TOKEN + * + * @param userId 操作者userid + * @param fileId 文件fileid列表 + * @return + * @throws WxErrorException + */ + WxCpBaseResp fileDelete(@NonNull String userId, @NonNull List fileId) throws WxErrorException; + + /** + * 新增指定人 + * 该接口用于对指定文件添加指定人/部门。 + *

+ * 请求方式:POST(HTTPS) + * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/wedrive/file_acl_add?access_token=ACCESS_TOKEN + * + * @param request 新增指定人请求参数 + * @return + * @throws WxErrorException + */ + WxCpBaseResp fileAclAdd(@NonNull WxCpFileAclAddRequest request) throws WxErrorException; + + /** + * 删除指定人 + * 该接口用于删除指定文件的指定人/部门。 + *

+ * 请求方式:POST(HTTPS) + * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/wedrive/file_acl_del?access_token=ACCESS_TOKEN + * + * @param request 请求参数 + * @return + * @throws WxErrorException + */ + WxCpBaseResp fileAclDel(@NonNull WxCpFileAclDelRequest request) throws WxErrorException; + + /** + * 分享设置 + * 该接口用于文件的分享设置。 + *

+ * 请求方式:POST(HTTPS) + * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/wedrive/file_setting?access_token=ACCESS_TOKEN + * + * @param userId + * @param fileId + * @param authScope + * @param auth + * @return + * @throws WxErrorException + */ + WxCpBaseResp fileSetting(@NonNull String userId, @NonNull String fileId, @NonNull Integer authScope, Integer auth) throws WxErrorException; + + /** + * 获取分享链接 + * 该接口用于获取文件的分享链接。 + *

+ * 请求方式:POST(HTTPS) + * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/wedrive/file_share?access_token=ACCESS_TOKEN + * + * @param userId + * @param fileId + * @return + * @throws WxErrorException + */ + WxCpFileShare fileShare(@NonNull String userId, @NonNull String fileId) throws WxErrorException; + + /** + * 文件信息 + * 该接口用于获取指定文件的信息。 + *

+ * 请求方式:POST(HTTPS) + * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/wedrive/file_info?access_token=ACCESS_TOKEN + * + * @param userId + * @param fileId + * @return + * @throws WxErrorException + */ + WxCpFileInfo fileInfo(@NonNull String userId, @NonNull String fileId) throws WxErrorException; + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpSchoolHealthService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpSchoolHealthService.java new file mode 100644 index 000000000..76233046d --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpSchoolHealthService.java @@ -0,0 +1,74 @@ +package me.chanjar.weixin.cp.api; + +import lombok.NonNull; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.bean.school.health.WxCpGetHealthReportStat; +import me.chanjar.weixin.cp.bean.school.health.WxCpGetReportAnswer; +import me.chanjar.weixin.cp.bean.school.health.WxCpGetReportJobIds; +import me.chanjar.weixin.cp.bean.school.health.WxCpGetReportJobInfo; + +/** + * 企业微信家校应用 健康上报接口. + * https://developer.work.weixin.qq.com/document/path/93676 + * + * @author Wang_Wong + * @date: 2022/5/31 9:10 + */ +public interface WxCpSchoolHealthService { + + /** + * 获取健康上报使用统计 + * 请求方式:POST(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/health/get_health_report_stat?access_token=ACCESS_TOKEN + * + * @param date 具体某天的使用统计,最长支持获取30天前数据 + * @return + * @throws WxErrorException + */ + WxCpGetHealthReportStat getHealthReportStat(@NonNull String date) throws WxErrorException; + + /** + * 获取健康上报任务ID列表 + * 通过此接口可以获取企业当前正在运行的上报任务ID列表。 + *

+ * 请求方式:POST(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/health/get_report_jobids?access_token=ACCESS_TOKEN + * + * @param offset 否 分页,偏移量, 默认为0 + * @param limit 否 分页,预期请求的数据量,默认为100,取值范围 1 ~ 100 + * @return + * @throws WxErrorException + */ + WxCpGetReportJobIds getReportJobIds(Integer offset, Integer limit) throws WxErrorException; + + /** + * 获取健康上报任务详情 + * 通过此接口可以获取指定的健康上报任务详情。 + *

+ * 请求方式:POST(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/health/get_report_job_info?access_token=ACCESS_TOKEN + * + * @param jobId 是 任务ID + * @param date 是 具体某天任务详情,仅支持获取最近14天数据 + * @return + * @throws WxErrorException + */ + WxCpGetReportJobInfo getReportJobInfo(@NonNull String jobId, @NonNull String date) throws WxErrorException; + + /** + * 获取用户填写答案 + * 通过此接口可以获取指定的健康上报任务详情。 + *

+ * 请求方式:POST(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/health/get_report_answer?access_token=ACCESS_TOKEN + * + * @param jobId + * @param date + * @param offset + * @param limit + * @return + * @throws WxErrorException + */ + WxCpGetReportAnswer getReportAnswer(@NonNull String jobId, @NonNull String date, Integer offset, Integer limit) throws WxErrorException; + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpSchoolService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpSchoolService.java new file mode 100644 index 000000000..5f05ae0c1 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpSchoolService.java @@ -0,0 +1,148 @@ +package me.chanjar.weixin.cp.api; + +import lombok.NonNull; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.bean.living.WxCpLivingResult; +import me.chanjar.weixin.cp.bean.school.*; + +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * 企业微信家校应用 复学码相关接口. + * https://developer.work.weixin.qq.com/document/path/93744 + *

+ * 权限说明: + * 仅复学码应用可以调用 + * + * @author Wang_Wong + * @date: 2022/5/31 9:10 + */ +public interface WxCpSchoolService { + + /** + * 获取老师健康信息 + * 请求方式: POST(HTTPS) + * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/school/user/get_teacher_customize_health_info?access_token=ACCESS_TOKEN + * + * @param date + * @param nextKey + * @param limit + * @return + * @throws WxErrorException + */ + WxCpCustomizeHealthInfo getTeacherCustomizeHealthInfo(@NotNull String date, String nextKey, Integer limit) throws WxErrorException; + + /** + * 获取学生健康信息 + * 请求方式: POST(HTTPS) + * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/school/user/get_student_customize_health_info?access_token=ACCESS_TOKEN + * + * @param date + * @param nextKey + * @param limit + * @return + * @throws WxErrorException + */ + WxCpCustomizeHealthInfo getStudentCustomizeHealthInfo(@NotNull String date, String nextKey, Integer limit) throws WxErrorException; + + /** + * 获取师生健康码 + * 请求方式:POST(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/user/get_health_qrcode?access_token=ACCESS_TOKEN + * + * @param userIds + * @param type + * @return + * @throws WxErrorException + */ + WxCpResultList getHealthQrCode(@NotNull List userIds, @NotNull Integer type) throws WxErrorException; + + /** + * 获取学生付款结果 + * 请求方式: POST(HTTPS) + * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/school/get_payment_result?access_token=ACCESS_TOKEN + * + * @param paymentId + * @return + * @throws WxErrorException + */ + WxCpPaymentResult getPaymentResult(@NotNull String paymentId) throws WxErrorException; + + /** + * 获取订单详情 + * 请求方式: POST(HTTPS) + * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/school/get_trade?access_token=ACCESS_TOKEN + * + * @param paymentId + * @param tradeNo + * @return + * @throws WxErrorException + */ + WxCpTrade getTrade(@NotNull String paymentId, @NotNull String tradeNo) throws WxErrorException; + + /** + * 获取直播详情 + * 请求方式:GET(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/living/get_living_info?access_token=ACCESS_TOKEN&livingid=LIVINGID + * + * @param livingId + * @return + */ + WxCpSchoolLivingInfo getLivingInfo(@NotNull String livingId) throws WxErrorException; + + /** + * 获取老师直播ID列表 + * 通过此接口可以获取指定老师的所有直播ID + *

+ * 请求方式:POST(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/living/get_user_all_livingid?access_token=ACCESS_TOKEN + * + * @param userId + * @param cursor + * @param limit + * @return + * @throws WxErrorException + */ + WxCpLivingResult.LivingIdResult getUserAllLivingId(@NonNull String userId, String cursor, Integer limit) throws WxErrorException; + + /** + * 获取观看直播统计 + * 通过该接口可以获取所有观看直播的人员统计 + *

+ * 请求方式:POST(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/living/get_watch_stat?access_token=ACCESS_TOKEN + * + * @param livingId + * @param nextKey + * @return + * @throws WxErrorException + */ + WxCpSchoolWatchStat getWatchStat(@NonNull String livingId, String nextKey) throws WxErrorException; + + /** + * 获取未观看直播统计 + * 通过该接口可以获取未观看直播的学生统计,学生的家长必须是已经关注「学校通知」才会纳入统计范围。 + *

+ * 请求方式:POST(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/living/get_unwatch_stat?access_token=ACCESS_TOKEN + * + * @param livingId + * @param nextKey + * @return + * @throws WxErrorException + */ + WxCpSchoolUnwatchStat getUnwatchStat(@NonNull String livingId, String nextKey) throws WxErrorException; + + /** + * 删除直播回放 + * 请求方式: POST(HTTPS) + * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/living/delete_replay_data?access_token=ACCESS_TOKEN + * + * @param livingId + * @return + * @throws WxErrorException + */ + WxCpLivingResult deleteReplayData(@NonNull String livingId) throws WxErrorException; + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpSchoolUserService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpSchoolUserService.java new file mode 100644 index 000000000..706c005db --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpSchoolUserService.java @@ -0,0 +1,363 @@ +package me.chanjar.weixin.cp.api; + +import lombok.NonNull; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.bean.WxCpOauth2UserInfo; +import me.chanjar.weixin.cp.bean.school.user.*; + +import java.util.List; + +/** + * 企业微信家校沟通相关接口. + * https://developer.work.weixin.qq.com/document/path/91638 + * + * @author Wang_Wong + * @date: 2022/6/18 9:10 + */ +public interface WxCpSchoolUserService { + + /** + * 获取访问用户身份 + * 该接口用于根据code获取成员信息 + *

+ * 请求方式:GET(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=ACCESS_TOKEN&code=CODE + * + * @param code + * @return + * @throws WxErrorException + */ + WxCpOauth2UserInfo getUserInfo(@NonNull String code) throws WxErrorException; + + /** + * 获取家校访问用户身份 + * 该接口用于根据code获取家长或者学生信息 + *

+ * 请求方式:GET(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/getuserinfo?access_token=ACCESS_TOKEN&code=CODE + * + * @param code + * @return + * @throws WxErrorException + */ + WxCpOauth2UserInfo getSchoolUserInfo(@NonNull String code) throws WxErrorException; + + /** + * 创建学生 + * 请求方式:POST(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/user/create_student?access_token=ACCESS_TOKEN + * + * @param studentUserId + * @param name + * @param departments + * @return + * @throws WxErrorException + */ + WxCpBaseResp createStudent(@NonNull String studentUserId, @NonNull String name, @NonNull List departments) throws WxErrorException; + + /** + * 批量创建学生 + * 请求方式:POST(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/user/batch_create_student?access_token=ACCESS_TOKEN + * + * @param request + * @return + * @throws WxErrorException + */ + WxCpBatchResultList batchCreateStudent(@NonNull WxCpBatchCreateStudentRequest request) throws WxErrorException; + + /** + * 批量删除学生 + * 请求方式:POST(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/user/batch_delete_student?access_token=ACCESS_TOKEN + * + * @param request + * @return + * @throws WxErrorException + */ + WxCpBatchResultList batchDeleteStudent(@NonNull WxCpBatchDeleteStudentRequest request) throws WxErrorException; + + /** + * 批量更新学生 + * 请求方式:POST(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/user/batch_update_student?access_token=ACCESS_TOKEN + * + * @param request + * @return + * @throws WxErrorException + */ + WxCpBatchResultList batchUpdateStudent(@NonNull WxCpBatchUpdateStudentRequest request) throws WxErrorException; + + /** + * 删除学生 + * 请求方式:GET(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/user/delete_student?access_token=ACCESS_TOKEN&userid=USERID + * + * @param studentUserId + * @return + * @throws WxErrorException + */ + WxCpBaseResp deleteStudent(@NonNull String studentUserId) throws WxErrorException; + + /** + * 更新学生 + * 请求方式:POST(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/user/update_student?access_token=ACCESS_TOKEN + * + * @param studentUserId + * @param newStudentUserId + * @param name + * @param departments + * @return + * @throws WxErrorException + */ + WxCpBaseResp updateStudent(@NonNull String studentUserId, String newStudentUserId, String name, List departments) throws WxErrorException; + + /** + * 创建家长 + * 请求方式:POST(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/user/create_parent?access_token=ACCESS_TOKEN + * + * @param request + * @return + * @throws WxErrorException + */ + WxCpBaseResp createParent(@NonNull WxCpCreateParentRequest request) throws WxErrorException; + + /** + * 批量创建家长 + * 请求方式:POST(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/user/batch_create_parent?access_token=ACCESS_TOKEN + * + * @param request + * @return + * @throws WxErrorException + */ + WxCpBatchResultList batchCreateParent(@NonNull WxCpBatchCreateParentRequest request) throws WxErrorException; + + /** + * 批量删除家长 + * 请求方式:POST(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/user/batch_delete_parent?access_token=ACCESS_TOKEN + * + * @param userIdList + * @return + * @throws WxErrorException + */ + WxCpBatchResultList batchDeleteParent(@NonNull String... userIdList) throws WxErrorException; + + /** + * 批量更新家长 + * 请求方式:POST(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/user/batch_update_parent?access_token=ACCESS_TOKEN + * + * @param request + * @return + * @throws WxErrorException + */ + WxCpBatchResultList batchUpdateParent(@NonNull WxCpBatchUpdateParentRequest request) throws WxErrorException; + + /** + * 读取学生或家长 + * 请求方式:GET(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/user/get?access_token=ACCESS_TOKEN&userid=USERID + * + * @param userId + * @return + * @throws WxErrorException + */ + WxCpUserResult getUser(@NonNull String userId) throws WxErrorException; + + /** + * 获取部门成员详情 + * 请求方式:GET(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/user/list?access_token=ACCESS_TOKEN&department_id=DEPARTMENT_ID&fetch_child=FETCH_CHILD + * + * @param departmentId 获取的部门id + * @param fetchChild 1/0:是否递归获取子部门下面的成员 + * @return + * @throws WxErrorException + */ + WxCpUserListResult getUserList(@NonNull Integer departmentId, Integer fetchChild) throws WxErrorException; + + /** + * 获取部门家长详情 + * 请求方式:GET(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/user/list_parent?access_token=ACCESS_TOKEN&department_id=DEPARTMENT_ID + * + * @param departmentId 获取的部门id + * @return + * @throws WxErrorException + */ + WxCpListParentResult getUserListParent(@NonNull Integer departmentId) throws WxErrorException; + + /** + * 更新家长 + * 请求方式:POST(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/user/update_parent?access_token=ACCESS_TOKEN + * + * @param request + * @return + * @throws WxErrorException + */ + WxCpBaseResp updateParent(@NonNull WxCpUpdateParentRequest request) throws WxErrorException; + + /** + * 删除家长 + * 请求方式:GET(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/user/delete_parent?access_token=ACCESS_TOKEN&userid=USERID + * + * @param userId + * @return + * @throws WxErrorException + */ + WxCpBaseResp deleteParent(@NonNull String userId) throws WxErrorException; + + /** + * 设置家校通讯录自动同步模式 + * 企业和第三方可通过此接口修改家校通讯录与班级标签之间的自动同步模式,注意,一旦设置禁止自动同步,将无法再次开启。 + *

+ * 请求方式:POST(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/set_arch_sync_mode?access_token=ACCESS_TOKEN + * + * @param archSyncMode 家校通讯录同步模式:1-禁止将标签同步至家校通讯录,2-禁止将家校通讯录同步至标签,3-禁止家校通讯录和标签相互同步 + * @return + * @throws WxErrorException + */ + WxCpBaseResp setArchSyncMode(@NonNull Integer archSyncMode) throws WxErrorException; + + /** + * 创建部门 + *

+ * 请求方式:POST(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/department/create?access_token=ACCESS_TOKEN + * + * @param request 请求参数对象 + * @return + * @throws WxErrorException + */ + WxCpCreateDepartment createDepartment(@NonNull WxCpCreateDepartmentRequest request) throws WxErrorException; + + /** + * 更新部门 + *

+ * 请求方式:POST(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/department/update?access_token=ACCESS_TOKEN + * + * @param request + * @return + * @throws WxErrorException + */ + WxCpBaseResp updateDepartment(@NonNull WxCpUpdateDepartmentRequest request) throws WxErrorException; + + /** + * 删除部门 + * 请求方式:GET(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/department/delete?access_token=ACCESS_TOKEN&id=ID + * + * @param id + * @return + * @throws WxErrorException + */ + WxCpBaseResp deleteDepartment(Integer id) throws WxErrorException; + + /** + * 设置关注「学校通知」的模式 + * 可通过此接口修改家长关注「学校通知」的模式:“可扫码填写资料加入”或“禁止扫码填写资料加入” + *

+ * 请求方式:POST(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/externalcontact/set_subscribe_mode?access_token=ACCESS_TOKEN + * + * @param subscribeMode 关注模式, 1:可扫码填写资料加入, 2:禁止扫码填写资料加入 + * @return + * @throws WxErrorException + */ + WxCpBaseResp setSubscribeMode(@NonNull Integer subscribeMode) throws WxErrorException; + + /** + * 获取关注「学校通知」的模式 + * 可通过此接口获取家长关注「学校通知」的模式:“可扫码填写资料加入”或“禁止扫码填写资料加入” + *

+ * 请求方式:GET(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get_subscribe_mode?access_token=ACCESS_TOKEN + * + * @return + * @throws WxErrorException + */ + Integer getSubscribeMode() throws WxErrorException; + + /** + * 获取外部联系人详情 + * 学校可通过此接口,根据外部联系人的userid(如何获取?),拉取外部联系人详情。 + *

+ * 请求方式:GET(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get?access_token=ACCESS_TOKEN&external_userid=EXTERNAL_USERID + * + * @param externalUserId 外部联系人的userid,注意不是学校成员的帐号 + * @return + * @throws WxErrorException + */ + WxCpExternalContact getExternalContact(@NonNull String externalUserId) throws WxErrorException; + + /** + * 获取可使用的家长范围 + * 获取可在微信「学校通知-学校应用」使用该应用的家长范围,以学生或部门列表的形式返回。应用只能给该列表下的家长发送「学校通知」。注意该范围只能由学校的系统管理员在「管理端-家校沟通-配置」配置。 + *

+ * 请求方式:GET(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/agent/get_allow_scope?access_token=ACCESS_TOKEN&agentid=AGENTID + * + * @param agentId + * @return + * @throws WxErrorException + */ + WxCpAllowScope getAllowScope(@NonNull Integer agentId) throws WxErrorException; + + /** + * 外部联系人openid转换 + * 企业和服务商可通过此接口,将微信外部联系人的userid(如何获取?)转为微信openid,用于调用支付相关接口。暂不支持企业微信外部联系人(ExternalUserid为wo开头)的userid转openid。 + *

+ * 请求方式:POST(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/externalcontact/convert_to_openid?access_token=ACCESS_TOKEN + * + * @param externalUserId + * @return + * @throws WxErrorException + */ + String convertToOpenId(@NonNull String externalUserId) throws WxErrorException; + + /** + * 获取部门列表 + * 请求方式:GET(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/department/list?access_token=ACCESS_TOKEN&id=ID + * + * @param id + * @return + * @throws WxErrorException + */ + WxCpDepartmentList listDepartment(Integer id) throws WxErrorException; + + /** + * 获取「学校通知」二维码 + * 学校可通过此接口获取「学校通知」二维码,家长可通过扫描此二维码关注「学校通知」并接收学校推送的消息。 + * 请求方式:GET(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get_subscribe_qr_code?access_token=ACCESS_TOKEN + * + * @return + * @throws WxErrorException + */ + WxCpSubscribeQrCode getSubscribeQrCode() throws WxErrorException; + + /** + * 修改自动升年级的配置 + * 请求方式: POST(HTTPS) + * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/school/set_upgrade_info?access_token=ACCESS_TOKEN + * + * @param upgradeTime + * @param upgradeSwitch + * @return + * @throws WxErrorException + */ + WxCpSetUpgradeInfo setUpgradeInfo(Long upgradeTime, Integer upgradeSwitch) throws WxErrorException; + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java index ddb3968c2..44237ba8e 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java @@ -263,6 +263,14 @@ public interface WxCpService extends WxService { */ String replaceParty(String mediaId) throws WxErrorException; + /** + * 上传用户列表,增量更新成员 + * @param mediaId 媒体id + * @return jobId 异步任务id + * @throws WxErrorException the wx error exception + */ + String syncUser(String mediaId) throws WxErrorException; + /** * 上传用户列表覆盖企业号上的用户信息 * @@ -275,11 +283,11 @@ public interface WxCpService extends WxService { /** * 获取异步任务结果 * - * @param joinId the join id + * @param jobId 异步任务id * @return the task result * @throws WxErrorException the wx error exception */ - String getTaskResult(String joinId) throws WxErrorException; + String getTaskResult(String jobId) throws WxErrorException; /** * 初始化http请求对象 @@ -392,6 +400,27 @@ public interface WxCpService extends WxService { */ WxCpOaService getOaService(); + /** + * 获取家校应用复学码相关接口的服务类对象 + * + * @return + */ + WxCpSchoolService getSchoolService(); + + /** + * 获取家校沟通相关接口的服务类对象 + * + * @return + */ + WxCpSchoolUserService getSchoolUserService(); + + /** + * 获取家校应用健康上报的服务类对象 + * + * @return + */ + WxCpSchoolHealthService getSchoolHealthService(); + /** * 获取直播相关接口的服务类对象 * @@ -406,6 +435,13 @@ public interface WxCpService extends WxService { */ WxCpOaAgentService getOaAgentService(); + /** + * 获取OA效率工具 微盘的服务类对象 + * + * @return + */ + WxCpOaWeDriveService getOaWeDriveService(); + /** * 获取会话存档相关接口的服务类对象 * @@ -420,6 +456,13 @@ public interface WxCpService extends WxService { */ WxCpOaCalendarService getOaCalendarService(); + /** + * 获取会议室相关接口的服务类对象 + * + * @return the oa meetingroom service + */ + WxCpOaMeetingRoomService getOaMeetingRoomService(); + /** * 获取日程相关接口的服务类对象 * @@ -503,4 +546,18 @@ public interface WxCpService extends WxService { * @param kfService the kf service */ void setKfService(WxCpKfService kfService); + + /** + * 获取异步导出服务 + * + * @return 异步导出服务 + */ + WxCpExportService getExportService(); + + /** + * 设置异步导出服务 + * + * @param exportService 异步导出服务 + */ + void setExportService(WxCpExportService exportService); } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpTaskCardService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpTaskCardService.java index 3d97cb928..4109c0a03 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpTaskCardService.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpTaskCardService.java @@ -8,6 +8,7 @@ *

  *  任务卡片管理接口.
  *  Created by Jeff on 2019-05-16.
+ *  Updted by HeXiao on 2022-03-09.
  * 
* * @author Jeff @@ -23,9 +24,26 @@ public interface WxCpTaskCardService { * 注意: 这个方法使用WxCpConfigStorage里的agentId *
* - * @param userIds 企业的成员ID列表 - * @param taskId 任务卡片ID + * @param userIds 企业的成员ID列表 + * @param taskId 任务卡片ID * @param replaceName 替换文案 */ void update(List userIds, String taskId, String replaceName) throws WxErrorException; + + + /** + * 更新按钮为不可点击状态 + * 详情请见https://developer.work.weixin.qq.com/document/path/94888#%E6%9B%B4%E6%96%B0%E6%8C%89%E9%92%AE%E4%B8%BA%E4%B8%8D%E5%8F%AF%E7%82%B9%E5%87%BB%E7%8A%B6%E6%80%81 + * @param userIds 企业的成员ID列表 + * @param partyIds 企业的部门ID列表 + * @param tagIds 企业的标签ID列表 + * @param atAll 更新整个任务接收人员 + * @param responseCode 更新卡片所需要消费的code,可通过发消息接口和回调接口返回值获取,一个code只能调用一次该接口,且只能在24小时内调用 + * @param replaceName 需要更新的按钮的文案 + * @throws WxErrorException + */ + void updateTemplateCardButton(List userIds, List partyIds, + List tagIds, Integer atAll, String responseCode, + String replaceName) throws WxErrorException; + } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpUserService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpUserService.java index ede813a0a..d5bd6702c 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpUserService.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpUserService.java @@ -3,8 +3,12 @@ import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.cp.bean.WxCpInviteResult; import me.chanjar.weixin.cp.bean.WxCpUser; +import me.chanjar.weixin.cp.bean.WxCpUseridToOpenUseridResult; import me.chanjar.weixin.cp.bean.external.contact.WxCpExternalContactInfo; +import me.chanjar.weixin.cp.bean.user.WxCpDeptUserResult; +import java.util.ArrayList; +import java.util.Date; import java.util.List; import java.util.Map; @@ -199,4 +203,47 @@ public interface WxCpUserService { * @throws WxErrorException . */ String getJoinQrCode(int sizeType) throws WxErrorException; + + /** + *
+   *
+   * 获取企业活跃成员数。
+   *
+   * 请求方式:POST(HTTPS)
+   * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/user/get_active_stat?access_token=ACCESS_TOKEN
+   *
+   * 文档地址:https://developer.work.weixin.qq.com/document/path/92714
+   * 
+ * + * @param date 具体某天的活跃人数,最长支持获取30天前数据 + * @return join_qrcode 活跃成员数 + * @throws WxErrorException . + */ + Integer getActiveStat(Date date) throws WxErrorException; + + /** + * userid转换为open_userid + * 将自建应用或代开发应用获取的userid转换为第三方应用的userid + * https://developer.work.weixin.qq.com/document/path/95603 + * + * @param useridList + * @return the WxCpUseridToOpenUseridResult + * @throws WxErrorException + */ + WxCpUseridToOpenUseridResult useridToOpenUserid(ArrayList useridList) throws WxErrorException; + + /** + * 获取成员ID列表 + * 获取企业成员的userid与对应的部门ID列表,预计于2022年8月8号发布。若需要获取其他字段,参见「适配建议」。 + *

+ * 请求方式:POST(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/user/list_id?access_token=ACCESS_TOKEN + * + * @param cursor + * @param limit + * @return + * @throws WxErrorException + */ + WxCpDeptUserResult getUserListId(String cursor, Integer limit) throws WxErrorException; + } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/BaseWxCpServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/BaseWxCpServiceImpl.java index 55ddcf9e2..735ccfd85 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/BaseWxCpServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/BaseWxCpServiceImpl.java @@ -49,18 +49,25 @@ public abstract class BaseWxCpServiceImpl implements WxCpService, RequestH private WxCpTagService tagService = new WxCpTagServiceImpl(this); private WxCpAgentService agentService = new WxCpAgentServiceImpl(this); private WxCpOaService oaService = new WxCpOaServiceImpl(this); + private WxCpSchoolService schoolService = new WxCpSchoolServiceImpl(this); + private WxCpSchoolUserService schoolUserService = new WxCpSchoolUserServiceImpl(this); + private WxCpSchoolHealthService schoolHealthService = new WxCpSchoolHealthServiceImpl(this); private WxCpLivingService livingService = new WxCpLivingServiceImpl(this); private WxCpOaAgentService oaAgentService = new WxCpOaAgentServiceImpl(this); + private WxCpOaWeDriveService oaWeDriveService = new WxCpOaWeDriveServiceImpl(this); private WxCpMsgAuditService msgAuditService = new WxCpMsgAuditServiceImpl(this); private WxCpTaskCardService taskCardService = new WxCpTaskCardServiceImpl(this); private WxCpExternalContactService externalContactService = new WxCpExternalContactServiceImpl(this); private WxCpGroupRobotService groupRobotService = new WxCpGroupRobotServiceImpl(this); private WxCpMessageService messageService = new WxCpMessageServiceImpl(this); private WxCpOaCalendarService oaCalendarService = new WxCpOaCalendarServiceImpl(this); + private WxCpOaMeetingRoomService oaMeetingRoomService = new WxCpOaMeetingRoomServiceImpl(this); private WxCpOaScheduleService oaScheduleService = new WxCpOaOaScheduleServiceImpl(this); private WxCpAgentWorkBenchService workBenchService = new WxCpAgentWorkBenchServiceImpl(this); private WxCpKfService kfService = new WxCpKfServiceImpl(this); + private WxCpExportService exportService = new WxCpExportServiceImpl(this); + /** * 全局的是否正在刷新access token的锁. */ @@ -327,12 +334,12 @@ protected T executeInternal(RequestExecutor executor, String uri, E } if (error.getErrorCode() != 0) { - log.error("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", uriWithAccessToken, dataForLog, error); + log.warn("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", uriWithAccessToken, dataForLog, error); throw new WxErrorException(error, e); } return null; } catch (IOException e) { - log.error("\n【请求地址】: {}\n【请求参数】:{}\n【异常信息】:{}", uriWithAccessToken, dataForLog, e.getMessage()); + log.warn("\n【请求地址】: {}\n【请求参数】:{}\n【异常信息】:{}", uriWithAccessToken, dataForLog, e.getMessage()); throw new WxRuntimeException(e); } } @@ -408,6 +415,15 @@ public String replaceParty(String mediaId) throws WxErrorException { return post(this.configStorage.getApiUrl(BATCH_REPLACE_PARTY), jsonObject.toString()); } + @Override + public String syncUser(String mediaId) throws WxErrorException { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("media_id", mediaId); + String responseContent = post(this.configStorage.getApiUrl(BATCH_SYNC_USER), jsonObject.toString()); + JsonObject tmpJson = GsonParser.parse(responseContent); + return tmpJson.get("jobid").getAsString(); + } + @Override public String replaceUser(String mediaId) throws WxErrorException { JsonObject jsonObject = new JsonObject(); @@ -416,8 +432,8 @@ public String replaceUser(String mediaId) throws WxErrorException { } @Override - public String getTaskResult(String joinId) throws WxErrorException { - String url = this.configStorage.getApiUrl(BATCH_GET_RESULT + joinId); + public String getTaskResult(String jobId) throws WxErrorException { + String url = this.configStorage.getApiUrl(BATCH_GET_RESULT + jobId); return get(url, null); } @@ -481,6 +497,21 @@ public WxCpOaService getOaService() { return oaService; } + @Override + public WxCpSchoolService getSchoolService() { + return schoolService; + } + + @Override + public WxCpSchoolUserService getSchoolUserService() { + return schoolUserService; + } + + @Override + public WxCpSchoolHealthService getSchoolHealthService() { + return schoolHealthService; + } + @Override public WxCpLivingService getLivingService() { return livingService; @@ -491,6 +522,11 @@ public WxCpOaAgentService getOaAgentService() { return oaAgentService; } + @Override + public WxCpOaWeDriveService getOaWeDriveService() { + return oaWeDriveService; + } + @Override public WxCpMsgAuditService getMsgAuditService() { return msgAuditService; @@ -501,6 +537,11 @@ public WxCpOaCalendarService getOaCalendarService() { return this.oaCalendarService; } + @Override + public WxCpOaMeetingRoomService getOaMeetingRoomService() { + return this.oaMeetingRoomService; + } + @Override public WxCpGroupRobotService getGroupRobotService() { return groupRobotService; @@ -579,4 +620,15 @@ public WxCpKfService getKfService() { public void setKfService(WxCpKfService kfService) { this.kfService = kfService; } + + + @Override + public WxCpExportService getExportService() { + return exportService; + } + + @Override + public void setExportService(WxCpExportService exportService) { + this.exportService = exportService; + } } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpExportServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpExportServiceImpl.java new file mode 100644 index 000000000..1e9034388 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpExportServiceImpl.java @@ -0,0 +1,59 @@ +package me.chanjar.weixin.cp.api.impl; + +import com.google.gson.JsonObject; +import lombok.RequiredArgsConstructor; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.util.json.GsonParser; +import me.chanjar.weixin.cp.api.WxCpExportService; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.export.WxCpExportRequest; +import me.chanjar.weixin.cp.bean.export.WxCpExportResult; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Export.*; + +/** + * 异步导出接口 + * + * @author zhongjun + * @date 2022/4/21 + **/ +@RequiredArgsConstructor +public class WxCpExportServiceImpl implements WxCpExportService { + + private final WxCpService mainService; + + @Override + public String simpleUser(WxCpExportRequest params) throws WxErrorException { + return export(SIMPLE_USER, params); + } + + @Override + public String user(WxCpExportRequest params) throws WxErrorException { + return export(USER, params); + } + + @Override + public String department(WxCpExportRequest params) throws WxErrorException { + return export(DEPARTMENT, params); + } + + @Override + public String tagUser(WxCpExportRequest params) throws WxErrorException { + return export(TAG_USER, params); + } + + @Override + public WxCpExportResult getResult(String jobId) throws WxErrorException { + String url = String.format(this.mainService.getWxCpConfigStorage().getApiUrl(GET_RESULT), jobId); + String responseContent = this.mainService.get(url, null); + return WxCpGsonBuilder.create().fromJson(responseContent, WxCpExportResult.class); + } + + private String export(String path, WxCpExportRequest params) throws WxErrorException { + String url = this.mainService.getWxCpConfigStorage().getApiUrl(path); + String responseContent = this.mainService.post(url, params.toJson()); + JsonObject tmpJson = GsonParser.parse(responseContent); + return tmpJson.get("jobid").getAsString(); + } +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpExternalContactServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpExternalContactServiceImpl.java index def24cf8b..aa6cc0366 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpExternalContactServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpExternalContactServiceImpl.java @@ -2,10 +2,6 @@ import com.google.gson.Gson; import com.google.gson.JsonObject; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.UUID; import lombok.NonNull; import lombok.RequiredArgsConstructor; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; @@ -25,9 +21,13 @@ import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; import java.util.Collections; import java.util.Date; import java.util.List; +import java.util.UUID; import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.ExternalContact.*; @@ -111,7 +111,7 @@ public WxCpExternalContactInfo getExternalContact(String userId) throws WxErrorE @Override public WxCpExternalContactInfo getContactDetail(String userId, String cursor) throws WxErrorException { String params = userId; - if(StringUtils.isNotEmpty(cursor)){ + if (StringUtils.isNotEmpty(cursor)) { params = params + "&cursor=" + cursor; } final String url = this.mainService.getWxCpConfigStorage().getApiUrl(GET_CONTACT_DETAIL + params); @@ -130,11 +130,11 @@ public String convertToOpenid(@NotNull String externalUserId) throws WxErrorExce } @Override - public String unionidToExternalUserid(@NotNull String unionid,String openid) throws WxErrorException { + public String unionidToExternalUserid(@NotNull String unionid, String openid) throws WxErrorException { JsonObject json = new JsonObject(); json.addProperty("unionid", unionid); - if(StringUtils.isNotEmpty(openid)){ - json.addProperty("openid",openid); + if (StringUtils.isNotEmpty(openid)) { + json.addProperty("openid", openid); } final String url = this.mainService.getWxCpConfigStorage().getApiUrl(UNIONID_TO_EXTERNAL_USERID); String responseContent = this.mainService.post(url, json.toString()); @@ -157,8 +157,8 @@ public WxCpExternalUserIdList unionidToExternalUserid3rd(@NotNull String unionid JsonObject json = new JsonObject(); json.addProperty("unionid", unionid); json.addProperty("openid", openid); - if(StringUtils.isNotEmpty(corpid)){ - json.addProperty("corpid",corpid); + if (StringUtils.isNotEmpty(corpid)) { + json.addProperty("corpid", corpid); } final String url = this.mainService.getWxCpConfigStorage().getApiUrl(UNIONID_TO_EXTERNAL_USERID_3RD); String responseContent = this.mainService.post(url, json.toString()); @@ -188,7 +188,7 @@ public WxCpBaseResp finishExternalUserIdMigration(@NotNull String corpid) throws @Override public String opengidToChatid(@NotNull String opengid) throws WxErrorException { JsonObject json = new JsonObject(); - json.addProperty("opengid",opengid); + json.addProperty("opengid", opengid); final String url = this.mainService.getWxCpConfigStorage().getApiUrl(OPENID_TO_CHATID); String responseContent = this.mainService.post(url, json.toString()); JsonObject tmpJson = GsonParser.parse(responseContent); @@ -247,7 +247,7 @@ public List listFollowers() throws WxErrorException { @Override public WxCpUserExternalUnassignList listUnassignedList(Integer pageIndex, String cursor, Integer pageSize) throws WxErrorException { JsonObject json = new JsonObject(); - if(pageIndex != null){ + if (pageIndex != null) { json.addProperty("page_id", pageIndex); } json.addProperty("cursor", StringUtils.isEmpty(cursor) ? "" : cursor); @@ -518,20 +518,20 @@ public WxCpGetMomentTaskResult getMomentTaskResult(String jobId) throws WxErrorE @Override public WxCpGetMomentList getMomentList(Long startTime, Long endTime, String creator, Integer filterType, - String cursor, Integer limit) throws WxErrorException { + String cursor, Integer limit) throws WxErrorException { JsonObject json = new JsonObject(); json.addProperty("start_time", startTime); json.addProperty("end_time", endTime); if (!StringUtils.isEmpty(creator)) { json.addProperty("creator", creator); } - if (filterType!=null) { + if (filterType != null) { json.addProperty("filter_type", filterType); } if (!StringUtils.isEmpty(cursor)) { json.addProperty("cursor", cursor); } - if (limit!=null) { + if (limit != null) { json.addProperty("limit", limit); } final String url = this.mainService.getWxCpConfigStorage().getApiUrl(GET_MOMENT_LIST); @@ -547,7 +547,7 @@ public WxCpGetMomentTask getMomentTask(String momentId, String cursor, Integer l if (!StringUtils.isEmpty(cursor)) { json.addProperty("cursor", cursor); } - if (limit!=null) { + if (limit != null) { json.addProperty("limit", limit); } final String url = this.mainService.getWxCpConfigStorage().getApiUrl(GET_MOMENT_TASK); @@ -557,14 +557,14 @@ public WxCpGetMomentTask getMomentTask(String momentId, String cursor, Integer l @Override public WxCpGetMomentCustomerList getMomentCustomerList(String momentId, String userId, - String cursor, Integer limit) throws WxErrorException { + String cursor, Integer limit) throws WxErrorException { JsonObject json = new JsonObject(); json.addProperty("moment_id", momentId); json.addProperty("userid", userId); if (!StringUtils.isEmpty(cursor)) { json.addProperty("cursor", cursor); } - if (limit!=null) { + if (limit != null) { json.addProperty("limit", limit); } final String url = this.mainService.getWxCpConfigStorage().getApiUrl(GET_MOMENT_CUSTOMER_LIST); @@ -574,14 +574,14 @@ public WxCpGetMomentCustomerList getMomentCustomerList(String momentId, String u @Override public WxCpGetMomentSendResult getMomentSendResult(String momentId, String userId, - String cursor, Integer limit) throws WxErrorException { + String cursor, Integer limit) throws WxErrorException { JsonObject json = new JsonObject(); json.addProperty("moment_id", momentId); json.addProperty("userid", userId); if (!StringUtils.isEmpty(cursor)) { json.addProperty("cursor", cursor); } - if (limit!=null) { + if (limit != null) { json.addProperty("limit", limit); } final String url = this.mainService.getWxCpConfigStorage().getApiUrl(GET_MOMENT_SEND_RESULT); @@ -790,8 +790,8 @@ public WxCpBaseResp delGroupWelcomeTemplate(@NotNull String templateId, String a * https://work.weixin.qq.com/api/doc/90000/90135/95096#获取商品图册列表 *

* - * @param limit 返回的最大记录数,整型,最大值100,默认值50,超过最大值时取默认值 - * @param cursor 用于分页查询的游标,字符串类型,由上一次调用返回,首次调用可不填 + * @param limit 返回的最大记录数,整型,最大值100,默认值50,超过最大值时取默认值 + * @param cursor 用于分页查询的游标,字符串类型,由上一次调用返回,首次调用可不填 * @return wx cp base resp * @throws WxErrorException the wx error exception */ @@ -811,7 +811,7 @@ public WxCpProductAlbumListResult getProductAlbumList(Integer limit, String curs * https://work.weixin.qq.com/api/doc/90000/90135/95096#获取商品图册 *
* - * @param productId 商品id + * @param productId 商品id * @return wx cp base resp * @throws WxErrorException the wx error exception */ @@ -826,7 +826,7 @@ public WxCpProductAlbumResult getProductAlbum(String productId) throws WxErrorEx @Override public WxMediaUploadResult uploadAttachment(String mediaType, String fileType, Integer attachmentType, - InputStream inputStream) throws WxErrorException, IOException { + InputStream inputStream) throws WxErrorException, IOException { return uploadAttachment(mediaType, attachmentType, FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), fileType)); } @@ -839,4 +839,86 @@ public WxMediaUploadResult uploadAttachment(String mediaType, Integer attachment return this.mainService.execute(MediaUploadRequestExecutor.create( this.mainService.getRequestHttp()), url, file); } + + @Override + public WxCpInterceptRuleResultResp addInterceptRule(WxCpInterceptRuleResp ruleResp) throws WxErrorException { + return WxCpInterceptRuleResultResp + .fromJson(this.mainService.post(this.mainService.getWxCpConfigStorage().getApiUrl(ADD_INTERCEPT_RULE), ruleResp.toJson())); + } + + @Override + public WxCpInterceptRuleResultResp updateInterceptRule(WxCpInterceptRuleResp ruleResp) throws WxErrorException { + return WxCpInterceptRuleResultResp + .fromJson(this.mainService.post(this.mainService.getWxCpConfigStorage().getApiUrl(UPDATE_INTERCEPT_RULE), ruleResp.toJson())); + } + + @Override + public WxCpBaseResp delInterceptRule(String rule_id) throws WxErrorException { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("rule_id", rule_id); + return WxCpBaseResp + .fromJson(this.mainService.post(this.mainService.getWxCpConfigStorage().getApiUrl(DEL_INTERCEPT_RULE), jsonObject)); + } + + @Override + public String addProductAlbum(WxCpProductAlbumInfo wxCpProductAlbumInfo) throws WxErrorException { + String url = this.mainService.getWxCpConfigStorage().getApiUrl(ADD_PRODUCT_ALBUM); + String responseContent = this.mainService.post(url, wxCpProductAlbumInfo.toJson()); + JsonObject tmpJson = GsonParser.parse(responseContent); + return tmpJson.get("product_id").getAsString(); + } + + @Override + public void updateProductAlbum(WxCpProductAlbumInfo wxCpProductAlbumInfo) throws WxErrorException { + String url = this.mainService.getWxCpConfigStorage().getApiUrl(UPDATE_PRODUCT_ALBUM); + this.mainService.post(url, wxCpProductAlbumInfo.toJson()); + } + + @Override + public void deleteProductAlbum(String productId) throws WxErrorException { + JsonObject o = new JsonObject(); + o.addProperty("product_id", productId); + String url = this.mainService.getWxCpConfigStorage().getApiUrl(DELETE_PRODUCT_ALBUM); + this.mainService.post(url, o.toString()); + } + + @Override + public WxCpGroupJoinWayResult addJoinWay(@NonNull WxCpGroupJoinWayInfo wxCpGroupJoinWayInfo) throws WxErrorException { + if (wxCpGroupJoinWayInfo.getJoinWay().getChatIdList() != null && wxCpGroupJoinWayInfo.getJoinWay().getChatIdList().size() > 5) { + throw new WxRuntimeException("使用该配置的客户群ID列表,支持5个"); + } + final String url = this.mainService.getWxCpConfigStorage().getApiUrl(ADD_JOIN_WAY); + String responseContent = this.mainService.post(url, wxCpGroupJoinWayInfo.getJoinWay().toJson()); + + return WxCpGroupJoinWayResult.fromJson(responseContent); + } + + @Override + public WxCpBaseResp updateJoinWay(@NonNull WxCpGroupJoinWayInfo wxCpGroupJoinWayInfo) throws WxErrorException { + if (wxCpGroupJoinWayInfo.getJoinWay().getChatIdList() != null && wxCpGroupJoinWayInfo.getJoinWay().getChatIdList().size() > 5) { + throw new WxRuntimeException("使用该配置的客户群ID列表,支持5个"); + } + final String url = this.mainService.getWxCpConfigStorage().getApiUrl(UPDATE_JOIN_WAY); + String responseContent = this.mainService.post(url, wxCpGroupJoinWayInfo.getJoinWay().toJson()); + return WxCpBaseResp.fromJson(responseContent); + } + + @Override + public WxCpGroupJoinWayInfo getJoinWay(String configId) throws WxErrorException { + JsonObject json = new JsonObject(); + json.addProperty("config_id", configId); + final String url = this.mainService.getWxCpConfigStorage().getApiUrl(GET_JOIN_WAY); + String responseContent = this.mainService.post(url,json); + + return WxCpGroupJoinWayInfo.fromJson(responseContent); + } + + @Override + public WxCpBaseResp delJoinWay(@NonNull String configId) throws WxErrorException { + JsonObject json = new JsonObject(); + json.addProperty("config_id", configId); + final String url = this.mainService.getWxCpConfigStorage().getApiUrl(DEL_JOIN_WAY); + String responseContent = this.mainService.post(url, json); + return WxCpBaseResp.fromJson(responseContent); + } } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpGroupRobotServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpGroupRobotServiceImpl.java index 9661adf47..056a51fdd 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpGroupRobotServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpGroupRobotServiceImpl.java @@ -1,7 +1,6 @@ package me.chanjar.weixin.cp.api.impl; import lombok.RequiredArgsConstructor; -import me.chanjar.weixin.common.error.WxError; import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.cp.api.WxCpGroupRobotService; import me.chanjar.weixin.cp.api.WxCpService; @@ -14,8 +13,6 @@ import java.util.List; import static me.chanjar.weixin.cp.constant.WxCpConsts.GroupRobotMsgType; -import static me.chanjar.weixin.cp.constant.WxCpConsts.GroupRobotMsgType.MARKDOWN; -import static me.chanjar.weixin.cp.constant.WxCpConsts.GroupRobotMsgType.TEXT; /** * 企业微信群机器人消息发送api 实现 @@ -59,7 +56,7 @@ public void sendNews(List articleList) throws WxErrorException { @Override public void sendText(String webhookUrl, String content, List mentionedList, List mobileList) throws WxErrorException { this.cpService.postWithoutToken(webhookUrl, new WxCpGroupRobotMessage() - .setMsgType(TEXT) + .setMsgType(GroupRobotMsgType.TEXT) .setContent(content) .setMentionedList(mentionedList) .setMentionedMobileList(mobileList) @@ -69,7 +66,7 @@ public void sendText(String webhookUrl, String content, List mentionedLi @Override public void sendMarkdown(String webhookUrl, String content) throws WxErrorException { this.cpService.postWithoutToken(webhookUrl, new WxCpGroupRobotMessage() - .setMsgType(MARKDOWN) + .setMsgType(GroupRobotMsgType.MARKDOWN) .setContent(content) .toJson()); } @@ -89,4 +86,11 @@ public void sendNews(String webhookUrl, List articleList) throws WxE .setArticles(articleList).toJson()); } + @Override + public void sendFile(String webhookUrl, String mediaId) throws WxErrorException { + this.cpService.postWithoutToken(webhookUrl, new WxCpGroupRobotMessage() + .setMsgType(GroupRobotMsgType.FILE) + .setMediaId(mediaId).toJson()); + } + } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpKfServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpKfServiceImpl.java index 12f1062b0..238b9c327 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpKfServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpKfServiceImpl.java @@ -4,12 +4,12 @@ import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; import com.google.gson.JsonObject; -import java.util.List; import lombok.RequiredArgsConstructor; import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.cp.api.WxCpKfService; import me.chanjar.weixin.cp.api.WxCpService; import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.bean.kf.*; import me.chanjar.weixin.cp.bean.kf.WxCpKfAccountAdd; import me.chanjar.weixin.cp.bean.kf.WxCpKfAccountAddResp; import me.chanjar.weixin.cp.bean.kf.WxCpKfAccountDel; @@ -23,10 +23,13 @@ import me.chanjar.weixin.cp.bean.kf.WxCpKfMsgSendResp; import me.chanjar.weixin.cp.bean.kf.WxCpKfServiceStateResp; import me.chanjar.weixin.cp.bean.kf.WxCpKfServiceStateTransResp; +import me.chanjar.weixin.cp.bean.kf.WxCpKfServiceUpgradeConfigResp; import me.chanjar.weixin.cp.bean.kf.WxCpKfServicerListResp; import me.chanjar.weixin.cp.bean.kf.WxCpKfServicerOpResp; import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; +import java.util.List; + import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Kf.*; /** @@ -62,9 +65,16 @@ public WxCpBaseResp delAccount(WxCpKfAccountDel del) throws WxErrorException { } @Override - public WxCpKfAccountListResp listAccount() throws WxErrorException { + public WxCpKfAccountListResp listAccount(Integer offset,Integer limit) throws WxErrorException { String url = cpService.getWxCpConfigStorage().getApiUrl(ACCOUNT_LIST); - String responseContent = cpService.post(url, "{}"); + JsonObject json = new JsonObject(); + if (offset != null) { + json.addProperty("offset", offset); + } + if (limit != null) { + json.addProperty("limit", limit); + } + String responseContent = cpService.post(url, json.toString()); return WxCpKfAccountListResp.fromJson(responseContent); } @@ -188,4 +198,68 @@ public WxCpKfCustomerBatchGetResp customerBatchGet(List externalUserIdLi return WxCpKfCustomerBatchGetResp.fromJson(responseContent); } + @Override + public WxCpKfServiceUpgradeConfigResp getUpgradeServiceConfig() throws WxErrorException { + String url = cpService.getWxCpConfigStorage().getApiUrl(CUSTOMER_GET_UPGRADE_SERVICE_CONFIG); + + String response = cpService.get(url, null); + return WxCpKfServiceUpgradeConfigResp.fromJson(response); + } + + @Override + public WxCpBaseResp upgradeMemberService(String openKfid, String externalUserId, + String userid, String wording) throws WxErrorException { + String url = cpService.getWxCpConfigStorage().getApiUrl(CUSTOMER_UPGRADE_SERVICE); + + JsonObject json = new JsonObject(); + json.addProperty("open_kfid", openKfid); + json.addProperty("external_userid", externalUserId); + json.addProperty("type", 1); + + JsonObject memberJson = new JsonObject(); + memberJson.addProperty("userid", userid); + memberJson.addProperty("wording", wording); + json.add("member", memberJson); + + String response = cpService.post(url, json); + return WxCpBaseResp.fromJson(response); + } + + @Override + public WxCpBaseResp upgradeGroupchatService(String openKfid, String externalUserId, + String chatId, String wording) throws WxErrorException { + String url = cpService.getWxCpConfigStorage().getApiUrl(CUSTOMER_UPGRADE_SERVICE); + + JsonObject json = new JsonObject(); + json.addProperty("open_kfid", openKfid); + json.addProperty("external_userid", externalUserId); + json.addProperty("type", 2); + + JsonObject groupchatJson = new JsonObject(); + groupchatJson.addProperty("chat_id", chatId); + groupchatJson.addProperty("wording", wording); + json.add("groupchat", groupchatJson); + + String response = cpService.post(url, json); + return WxCpBaseResp.fromJson(response); + } + + @Override + public WxCpBaseResp cancelUpgradeService(String openKfid, String externalUserId) + throws WxErrorException { + String url = cpService.getWxCpConfigStorage().getApiUrl(CUSTOMER_CANCEL_UPGRADE_SERVICE); + + JsonObject json = new JsonObject(); + json.addProperty("open_kfid", openKfid); + json.addProperty("external_userid", externalUserId); + String response = cpService.post(url, json); + return WxCpBaseResp.fromJson(response); + } + @Override + public WxCpKfGetCorpStatisticResp getCorpStatistic(WxCpKfGetCorpStatisticRequest request) throws WxErrorException { + String url = cpService.getWxCpConfigStorage().getApiUrl(GET_CORP_STATISTIC); + String responseContent = cpService.post(url, GSON.toJson(request)); + return WxCpKfGetCorpStatisticResp.fromJson(responseContent); + } + } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java index 5fdf18cf8..03ad270e6 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java @@ -12,13 +12,15 @@ import me.chanjar.weixin.cp.api.WxCpService; import me.chanjar.weixin.cp.bean.living.*; import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; +import org.apache.commons.lang3.StringUtils; import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Living.*; /** * 企业微信直播接口实现类. + * https://developer.work.weixin.qq.com/document/path/93633 * - * @author Wang_Wong + * @author Wang_Wong * @date 2021-12-21 */ @Slf4j @@ -48,11 +50,11 @@ public WxCpLivingInfo getLivingInfo(String livingId) throws WxErrorException { } @Override - public WxCpWatchStat getWatchStat(String livingId, Integer nextKey) throws WxErrorException { + public WxCpWatchStat getWatchStat(String livingId, String nextKey) throws WxErrorException { String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_WATCH_STAT); JsonObject jsonObject = new JsonObject(); - if (nextKey != null) { - jsonObject.addProperty("next_key", String.valueOf(nextKey)); + if (StringUtils.isNotBlank(nextKey)) { + jsonObject.addProperty("next_key", nextKey); } jsonObject.addProperty("livingid", livingId); String responseContent = this.cpService.post(apiUrl, jsonObject.toString()); diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpMessageServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpMessageServiceImpl.java index 9be2f60df..37b1d1821 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpMessageServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpMessageServiceImpl.java @@ -46,4 +46,15 @@ public WxCpLinkedCorpMessageSendResult sendLinkedCorpMessage(WxCpLinkedCorpMessa return WxCpLinkedCorpMessageSendResult.fromJson(this.cpService.post(this.cpService.getWxCpConfigStorage() .getApiUrl(Message.LINKEDCORP_MESSAGE_SEND), message.toJson())); } + + @Override + public WxCpSchoolContactMessageSendResult sendSchoolContactMessage(WxCpSchoolContactMessage message) throws WxErrorException { + if (null == message.getAgentId()) { + message.setAgentId(this.cpService.getWxCpConfigStorage().getAgentId()); + } + + return WxCpSchoolContactMessageSendResult.fromJson(this.cpService.post(this.cpService.getWxCpConfigStorage() + .getApiUrl(Message.EXTERNAL_CONTACT_MESSAGE_SEND), message.toJson())); + } + } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpMsgAuditServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpMsgAuditServiceImpl.java index 6e47a4648..5f670f483 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpMsgAuditServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpMsgAuditServiceImpl.java @@ -17,6 +17,9 @@ import java.io.File; import java.io.FileOutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; import java.util.List; import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.MsgAudit.*; @@ -39,12 +42,19 @@ public WxCpChatDatas getChatDatas(long seq, @NonNull long limit, String proxy, S throw new WxErrorException("请配置会话存档sdk文件的路径,不要配错了!!"); } + /** + * 完整的文件库路径: + * + * /www/osfile/libcrypto-1_1-x64.dll,libssl-1_1-x64.dll,libcurl-x64.dll,WeWorkFinanceSdk.dll,libWeWorkFinanceSdk_Java.so + */ // 替换斜杠 String replacePath = configPath.replace("\\", "/"); - // 所有的后缀文件 - String suffixFiles = replacePath.substring(replacePath.lastIndexOf("/") + 1); - // 获取的前缀路径 - String prefixPath = replacePath.substring(0, replacePath.lastIndexOf("/") + 1); + // 获取最后一个斜杠的下标,用作分割路径 + int lastIndex = replacePath.lastIndexOf("/") + 1; + // 获取完整路径的前缀路径 + String prefixPath = replacePath.substring(0, lastIndex); + // 获取后缀的所有文件,目的遍历所有文件 + String suffixFiles = replacePath.substring(lastIndex); // 包含so文件 String[] libFiles = suffixFiles.split(","); @@ -52,12 +62,25 @@ public WxCpChatDatas getChatDatas(long seq, @NonNull long limit, String proxy, S throw new WxErrorException("请仔细配置会话存档文件路径!!"); } - Finance.loadingLibraries(libFiles, prefixPath); - long sdk = Finance.SingletonSDK(); + List libList = Arrays.asList(libFiles); + // 判断windows系统会话存档sdk中dll的加载,因为会互相依赖所以是有顺序的,否则会导致无法加载sdk #2598 + List osLib = new LinkedList(); + List fileLib = new ArrayList(); + libList.stream().forEach(s -> { + if (s.contains("lib")) { + osLib.add(s); + } else { + fileLib.add(s); + } + }); + osLib.addAll(fileLib); + + Finance.loadingLibraries(osLib, prefixPath); + long sdk = Finance.NewSdk(); long ret = Finance.Init(sdk, cpService.getWxCpConfigStorage().getCorpId(), cpService.getWxCpConfigStorage().getCorpSecret()); if (ret != 0) { - Finance.DestroySingletonSDK(sdk); + Finance.DestroySdk(sdk); throw new WxErrorException("init sdk err ret " + ret); } @@ -65,7 +88,7 @@ public WxCpChatDatas getChatDatas(long seq, @NonNull long limit, String proxy, S ret = Finance.GetChatData(sdk, seq, limit, proxy, passwd, timeout, slice); if (ret != 0) { Finance.FreeSlice(slice); - Finance.DestroySingletonSDK(sdk); + Finance.DestroySdk(sdk); throw new WxErrorException("getchatdata err ret " + ret); } @@ -74,50 +97,63 @@ public WxCpChatDatas getChatDatas(long seq, @NonNull long limit, String proxy, S Finance.FreeSlice(slice); WxCpChatDatas chatDatas = WxCpChatDatas.fromJson(content); if (chatDatas.getErrCode().intValue() != 0) { + Finance.DestroySdk(sdk); throw new WxErrorException(chatDatas.toJson()); } + chatDatas.setSdk(sdk); return chatDatas; } @Override - public WxCpChatModel getDecryptData(@NonNull WxCpChatDatas.WxCpChatData chatData) throws Exception { - String plainText = this.decryptChatData(chatData); + public WxCpChatModel getDecryptData(@NonNull long sdk, @NonNull WxCpChatDatas.WxCpChatData chatData, @NonNull Integer pkcs1) throws Exception { + String plainText = this.decryptChatData(sdk, chatData, pkcs1); return WxCpChatModel.fromJson(plainText); } - public String decryptChatData(WxCpChatDatas.WxCpChatData chatData) throws Exception { - // 企业获取的会话内容将用公钥加密,企业可用自行保存的私钥解开会话内容数据,aeskey不能为空 - String priKey = cpService.getWxCpConfigStorage().getAesKey(); + public String decryptChatData(long sdk, WxCpChatDatas.WxCpChatData chatData, Integer pkcs1) throws Exception { + /** + * 企业获取的会话内容,使用企业自行配置的消息加密公钥进行加密,企业可用自行保存的私钥解开会话内容数据。 + * msgAuditPriKey 会话存档私钥不能为空 + */ + String priKey = cpService.getWxCpConfigStorage().getMsgAuditPriKey(); if (StringUtils.isEmpty(priKey)) { - throw new WxErrorException("请配置会话存档私钥【aesKey】"); + throw new WxErrorException("请配置会话存档私钥【msgAuditPriKey】"); } - String decryptByPriKey = WxCpCryptUtil.decryptByPriKey(chatData.getEncryptRandomKey(), priKey); - // 每次使用DecryptData解密会话存档前需要调用NewSlice获取一个slice,在使用完slice中数据后,还需要调用FreeSlice释放。 - long sdk = Finance.SingletonSDK(); + String decryptByPriKey = WxCpCryptUtil.decryptPriKey(chatData.getEncryptRandomKey(), priKey, pkcs1); + /** + * 每次使用DecryptData解密会话存档前需要调用NewSlice获取一个slice,在使用完slice中数据后,还需要调用FreeSlice释放。 + */ long msg = Finance.NewSlice(); + /** + * 解密会话存档内容 + * sdk不会要求用户传入rsa私钥,保证用户会话存档数据只有自己能够解密。 + * 此处需要用户先用rsa私钥解密encrypt_random_key后,作为encrypt_key参数传入sdk来解密encrypt_chat_msg获取会话存档明文。 + */ int ret = Finance.DecryptData(sdk, decryptByPriKey, chatData.getEncryptChatMsg(), msg); if (ret != 0) { Finance.FreeSlice(msg); - Finance.DestroySingletonSDK(sdk); + Finance.DestroySdk(sdk); throw new WxErrorException("msg err ret " + ret); } - // 明文 + /** + * 明文 + */ String plainText = Finance.GetContentFromSlice(msg); Finance.FreeSlice(msg); return plainText; } @Override - public String getChatPlainText(WxCpChatDatas.@NonNull WxCpChatData chatData) throws Exception { - return this.decryptChatData(chatData); + public String getChatPlainText(@NonNull long sdk, WxCpChatDatas.@NonNull WxCpChatData chatData, @NonNull Integer pkcs1) throws Exception { + return this.decryptChatData(sdk, chatData, pkcs1); } @Override - public void getMediaFile(@NonNull String sdkfileid, String proxy, String passwd, @NonNull long timeout, @NonNull String targetFilePath) throws WxErrorException { + public void getMediaFile(@NonNull long sdk, @NonNull String sdkfileid, String proxy, String passwd, @NonNull long timeout, @NonNull String targetFilePath) throws WxErrorException { /** * 1、媒体文件每次拉取的最大size为512k,因此超过512k的文件需要分片拉取。 * 2、若该文件未拉取完整,sdk的IsMediaDataFinish接口会返回0,同时通过GetOutIndexBuf接口返回下次拉取需要传入GetMediaData的indexbuf。 @@ -130,13 +166,13 @@ public void getMediaFile(@NonNull String sdkfileid, String proxy, String passwd, String indexbuf = ""; int ret, data_len = 0; + log.debug("正在分片拉取媒体文件 sdkFileId为{}", sdkfileid); while (true) { long mediaData = Finance.NewMediaData(); - long sdk = Finance.SingletonSDK(); ret = Finance.GetMediaData(sdk, indexbuf, sdkfileid, proxy, passwd, timeout, mediaData); if (ret != 0) { Finance.FreeMediaData(mediaData); - Finance.DestroySingletonSDK(sdk); + Finance.DestroySdk(sdk); throw new WxErrorException("getmediadata err ret " + ret); } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOAuth2ServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOAuth2ServiceImpl.java index 8f989f23d..aac6e01a4 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOAuth2ServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOAuth2ServiceImpl.java @@ -77,6 +77,20 @@ public WxCpOauth2UserInfo getUserInfo(Integer agentId, String code) throws WxErr .userTicket(GsonHelper.getString(jo, "user_ticket")) .expiresIn(GsonHelper.getString(jo, "expires_in")) .externalUserId(GsonHelper.getString(jo, "external_userid")) + .parentUserId(GsonHelper.getString(jo, "parent_userid")) + .studentUserId(GsonHelper.getString(jo, "student_userid")) + .build(); + } + + @Override + public WxCpOauth2UserInfo getSchoolUserInfo(String code) throws WxErrorException { + String responseText = this.mainService.get(String.format(this.mainService.getWxCpConfigStorage().getApiUrl(GET_SCHOOL_USER_INFO), code), null); + JsonObject jo = GsonParser.parse(responseText); + + return WxCpOauth2UserInfo.builder() + .deviceId(GsonHelper.getString(jo, "DeviceId")) + .parentUserId(GsonHelper.getString(jo, "parent_userid")) + .studentUserId(GsonHelper.getString(jo, "student_userid")) .build(); } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOaMeetingRoomServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOaMeetingRoomServiceImpl.java new file mode 100644 index 000000000..2bf5b0d57 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOaMeetingRoomServiceImpl.java @@ -0,0 +1,51 @@ +package me.chanjar.weixin.cp.api.impl; + +import com.google.gson.reflect.TypeToken; +import lombok.RequiredArgsConstructor; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.util.json.GsonHelper; +import me.chanjar.weixin.common.util.json.GsonParser; +import me.chanjar.weixin.cp.api.WxCpOaMeetingRoomService; +import me.chanjar.weixin.cp.api.WxCpService; + +import me.chanjar.weixin.cp.bean.oa.meetingroom.WxCpOaMeetingRoom; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.util.List; + +import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Oa.*; + +/** + * @author fcat + * @version 1.0 + * Create by 2022/8/12 23:49 + */ +@RequiredArgsConstructor +public class WxCpOaMeetingRoomServiceImpl implements WxCpOaMeetingRoomService { + private final WxCpService wxCpService; + + @Override + public String addMeetingRoom(WxCpOaMeetingRoom meetingRoom) throws WxErrorException { + return this.wxCpService.post(this.wxCpService.getWxCpConfigStorage().getApiUrl(MEETINGROOM_ADD), meetingRoom); + } + + @Override + public List listMeetingRoom(WxCpOaMeetingRoom meetingRoomRequest) throws WxErrorException { + String response = this.wxCpService.post(this.wxCpService.getWxCpConfigStorage().getApiUrl(MEETINGROOM_LIST), + meetingRoomRequest); + return WxCpGsonBuilder.create().fromJson(GsonParser.parse(response).get("meetingroom_list").getAsJsonArray().toString(), + new TypeToken>() { + }.getType()); + } + + @Override + public void editMeetingRoom(WxCpOaMeetingRoom meetingRoom) throws WxErrorException { + this.wxCpService.post(this.wxCpService.getWxCpConfigStorage().getApiUrl(MEETINGROOM_EDIT), meetingRoom); + } + + @Override + public void deleteMeetingRoom(Integer meetingRoomId) throws WxErrorException { + this.wxCpService.post(this.wxCpService.getWxCpConfigStorage().getApiUrl(MEETINGROOM_DEL), + GsonHelper.buildJsonObject("meetingroom_id", meetingRoomId)); + } +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOaServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOaServiceImpl.java index afee242fe..244bcdef8 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOaServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOaServiceImpl.java @@ -11,8 +11,10 @@ import me.chanjar.weixin.common.util.json.GsonParser; import me.chanjar.weixin.cp.api.WxCpOaService; import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; import me.chanjar.weixin.cp.bean.oa.*; import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; +import org.apache.commons.lang3.StringUtils; import java.util.Date; import java.util.List; @@ -172,6 +174,43 @@ public WxCpCorpConfInfo getCorpConf() throws WxErrorException { return WxCpCorpConfInfo.fromJson(responseContent); } + @Override + public WxCpUserVacationQuota getUserVacationQuota(@NonNull String userId) throws WxErrorException { + final String url = this.mainService.getWxCpConfigStorage().getApiUrl(GET_USER_VACATION_QUOTA); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("userid", userId); + String responseContent = this.mainService.post(url, jsonObject.toString()); + return WxCpUserVacationQuota.fromJson(responseContent); + } + + @Override + public WxCpGetApprovalData getApprovalData(@NonNull Long startTime, @NonNull Long endTime, Long nextSpNum) throws WxErrorException { + final String url = this.mainService.getWxCpConfigStorage().getApiUrl(GET_APPROVAL_DATA); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("starttime", startTime); + jsonObject.addProperty("endtime", endTime); + if (nextSpNum != null) { + jsonObject.addProperty("next_spnum", nextSpNum); + } + String responseContent = this.mainService.post(url, jsonObject.toString()); + return WxCpGetApprovalData.fromJson(responseContent); + } + + @Override + public WxCpBaseResp setOneUserQuota(@NonNull String userId, @NonNull Integer vacationId, @NonNull Integer leftDuration, @NonNull Integer timeAttr, String remarks) throws WxErrorException { + final String url = this.mainService.getWxCpConfigStorage().getApiUrl(SET_ONE_USER_QUOTA); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("userid", userId); + jsonObject.addProperty("vacation_id", vacationId); + jsonObject.addProperty("leftduration", leftDuration); + jsonObject.addProperty("time_attr", timeAttr); + if (StringUtils.isNotEmpty(remarks)) { + jsonObject.addProperty("remarks", remarks); + } + String responseContent = this.mainService.post(url, jsonObject.toString()); + return WxCpBaseResp.fromJson(responseContent); + } + @Override public List getDialRecord(Date startTime, Date endTime, Integer offset, Integer limit) throws WxErrorException { @@ -315,4 +354,13 @@ public void setCheckinScheduleList(WxCpSetCheckinSchedule wxCpSetCheckinSchedule final String url = this.mainService.getWxCpConfigStorage().getApiUrl(SET_CHECKIN_SCHEDULE_DATA); this.mainService.post(url, WxCpGsonBuilder.create().toJson(wxCpSetCheckinSchedule)); } + + @Override + public void addCheckInUserFace(String userId, String userFace) throws WxErrorException { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("userid", userId); + jsonObject.addProperty("userface", userFace); + String url = this.mainService.getWxCpConfigStorage().getApiUrl(ADD_CHECK_IN_USER_FACE); + this.mainService.post(url, jsonObject.toString()); + } } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOaWeDriveServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOaWeDriveServiceImpl.java new file mode 100644 index 000000000..6cac3ec99 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOaWeDriveServiceImpl.java @@ -0,0 +1,204 @@ +package me.chanjar.weixin.cp.api.impl; + +import com.google.gson.JsonObject; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.api.WxCpOaWeDriveService; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.bean.oa.wedrive.*; + +import java.util.List; + +import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Oa.*; + +/** + * 企业微信微盘接口实现类. + * + * @author Wang_Wong + * @date 2022-04-22 + */ +@Slf4j +@RequiredArgsConstructor +public class WxCpOaWeDriveServiceImpl implements WxCpOaWeDriveService { + private final WxCpService cpService; + + @Override + public WxCpSpaceCreateData spaceCreate(@NonNull WxCpSpaceCreateRequest request) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(SPACE_CREATE); + String responseContent = this.cpService.post(apiUrl, request.toJson()); + return WxCpSpaceCreateData.fromJson(responseContent); + } + + @Override + public WxCpBaseResp spaceRename(@NonNull WxCpSpaceRenameRequest request) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(SPACE_RENAME); + String responseContent = this.cpService.post(apiUrl, request.toJson()); + return WxCpBaseResp.fromJson(responseContent); + } + + @Override + public WxCpBaseResp spaceDismiss(@NonNull String userId, @NonNull String spaceId) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(SPACE_DISMISS); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("userid", userId); + jsonObject.addProperty("spaceid", spaceId); + String responseContent = this.cpService.post(apiUrl, jsonObject.toString()); + return WxCpBaseResp.fromJson(responseContent); + } + + @Override + public WxCpSpaceInfo spaceInfo(@NonNull String userId, @NonNull String spaceId) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(SPACE_INFO); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("userid", userId); + jsonObject.addProperty("spaceid", spaceId); + String responseContent = this.cpService.post(apiUrl, jsonObject.toString()); + return WxCpSpaceInfo.fromJson(responseContent); + } + + @Override + public WxCpBaseResp spaceAclAdd(@NonNull WxCpSpaceAclAddRequest request) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(SPACE_ACL_ADD); + String responseContent = this.cpService.post(apiUrl, request.toJson()); + return WxCpBaseResp.fromJson(responseContent); + } + + @Override + public WxCpBaseResp spaceAclDel(@NonNull WxCpSpaceAclDelRequest request) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(SPACE_ACL_DEL); + String responseContent = this.cpService.post(apiUrl, request.toJson()); + return WxCpBaseResp.fromJson(responseContent); + } + + @Override + public WxCpBaseResp spaceSetting(@NonNull WxCpSpaceSettingRequest request) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(SPACE_SETTING); + String responseContent = this.cpService.post(apiUrl, request.toJson()); + return WxCpBaseResp.fromJson(responseContent); + } + + @Override + public WxCpSpaceShare spaceShare(@NonNull String userId, @NonNull String spaceId) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(SPACE_SHARE); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("userid", userId); + jsonObject.addProperty("spaceid", spaceId); + String responseContent = this.cpService.post(apiUrl, jsonObject.toString()); + return WxCpSpaceShare.fromJson(responseContent); + } + + @Override + public WxCpFileList fileList(@NonNull WxCpFileListRequest request) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(FILE_LIST); + String responseContent = this.cpService.post(apiUrl, request.toJson()); + return WxCpFileList.fromJson(responseContent); + } + + @Override + public WxCpFileUpload fileUpload(@NonNull WxCpFileUploadRequest request) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(FILE_UPLOAD); + String responseContent = this.cpService.post(apiUrl, request.toJson()); + return WxCpFileUpload.fromJson(responseContent); + } + + @Override + public WxCpFileDownload fileDownload(@NonNull String userId, @NonNull String fileId) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(FILE_DOWNLOAD); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("userid", userId); + jsonObject.addProperty("fileid", fileId); + String responseContent = this.cpService.post(apiUrl, jsonObject.toString()); + return WxCpFileDownload.fromJson(responseContent); + } + + @Override + public WxCpFileRename fileRename(@NonNull String userId, @NonNull String fileId, @NonNull String newName) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(FILE_RENAME); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("userid", userId); + jsonObject.addProperty("fileid", fileId); + jsonObject.addProperty("new_name", newName); + String responseContent = this.cpService.post(apiUrl, jsonObject.toString()); + return WxCpFileRename.fromJson(responseContent); + } + + @Override + public WxCpFileCreate fileCreate(@NonNull String userId, @NonNull String spaceId, @NonNull String fatherId, @NonNull Integer fileType, @NonNull String fileName) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(FILE_CREATE); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("userid", userId); + jsonObject.addProperty("spaceid", spaceId); + jsonObject.addProperty("fatherid", fatherId); + jsonObject.addProperty("file_type", fileType); + jsonObject.addProperty("file_name", fileName); + String responseContent = this.cpService.post(apiUrl, jsonObject.toString()); + return WxCpFileCreate.fromJson(responseContent); + } + + @Override + public WxCpFileMove fileMove(@NonNull WxCpFileMoveRequest request) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(FILE_MOVE); + String responseContent = this.cpService.post(apiUrl, request.toJson()); + return WxCpFileMove.fromJson(responseContent); + } + + @Override + public WxCpBaseResp fileDelete(@NonNull String userId, @NonNull List fileId) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(FILE_DELETE); + WxCpFileDeleteRequest request = new WxCpFileDeleteRequest(userId, fileId); + String responseContent = this.cpService.post(apiUrl, request.toJson()); + return WxCpBaseResp.fromJson(responseContent); + } + + @Override + public WxCpBaseResp fileAclAdd(@NonNull WxCpFileAclAddRequest request) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(FILE_ACL_ADD); + String responseContent = this.cpService.post(apiUrl, request.toJson()); + return WxCpBaseResp.fromJson(responseContent); + } + + @Override + public WxCpBaseResp fileAclDel(@NonNull WxCpFileAclDelRequest request) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(FILE_ACL_DEL); + String responseContent = this.cpService.post(apiUrl, request.toJson()); + return WxCpBaseResp.fromJson(responseContent); + } + + @Override + public WxCpBaseResp fileSetting(@NonNull String userId, @NonNull String fileId, @NonNull Integer authScope, Integer auth) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(FILE_SETTING); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("userid", userId); + jsonObject.addProperty("fileid", fileId); + jsonObject.addProperty("auth_scope", authScope); + if (auth != null) { + jsonObject.addProperty("auth", auth); + } + String responseContent = this.cpService.post(apiUrl, jsonObject.toString()); + return WxCpBaseResp.fromJson(responseContent); + } + + @Override + public WxCpFileShare fileShare(@NonNull String userId, @NonNull String fileId) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(FILE_SHARE); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("userid", userId); + jsonObject.addProperty("fileid", fileId); + String responseContent = this.cpService.post(apiUrl, jsonObject.toString()); + return WxCpFileShare.fromJson(responseContent); + } + + @Override + public WxCpFileInfo fileInfo(@NonNull String userId, @NonNull String fileId) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(FILE_INFO); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("userid", userId); + jsonObject.addProperty("fileid", fileId); + String responseContent = this.cpService.post(apiUrl, jsonObject.toString()); + return WxCpFileInfo.fromJson(responseContent); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpSchoolHealthServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpSchoolHealthServiceImpl.java new file mode 100644 index 000000000..ff1119cc1 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpSchoolHealthServiceImpl.java @@ -0,0 +1,76 @@ +package me.chanjar.weixin.cp.api.impl; + +import com.google.gson.JsonObject; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.api.WxCpSchoolHealthService; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.school.health.WxCpGetHealthReportStat; +import me.chanjar.weixin.cp.bean.school.health.WxCpGetReportAnswer; +import me.chanjar.weixin.cp.bean.school.health.WxCpGetReportJobIds; +import me.chanjar.weixin.cp.bean.school.health.WxCpGetReportJobInfo; + +import java.util.Optional; + +import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.School.*; + +/** + * 企业微信家校应用 健康上报接口实现类. + * + * @author Wang_Wong + * @date: 2022/5/31 9:16 + */ +@Slf4j +@RequiredArgsConstructor +public class WxCpSchoolHealthServiceImpl implements WxCpSchoolHealthService { + + private final WxCpService cpService; + + @Override + public WxCpGetHealthReportStat getHealthReportStat(@NonNull String date) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_HEALTH_REPORT_STAT); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("date", date); + String responseContent = this.cpService.post(apiUrl, jsonObject.toString()); + return WxCpGetHealthReportStat.fromJson(responseContent); + } + + @Override + public WxCpGetReportJobIds getReportJobIds(Integer offset, Integer limit) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_REPORT_JOBIDS); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("offset", Optional.ofNullable(offset).orElse(0)); + jsonObject.addProperty("limit", Optional.ofNullable(limit).orElse(100)); + String responseContent = this.cpService.post(apiUrl, jsonObject.toString()); + return WxCpGetReportJobIds.fromJson(responseContent); + } + + @Override + public WxCpGetReportJobInfo getReportJobInfo(@NonNull String jobId, @NonNull String date) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_REPORT_JOB_INFO); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("jobid", jobId); + jsonObject.addProperty("date", date); + String responseContent = this.cpService.post(apiUrl, jsonObject.toString()); + return WxCpGetReportJobInfo.fromJson(responseContent); + } + + @Override + public WxCpGetReportAnswer getReportAnswer(@NonNull String jobId, @NonNull String date, Integer offset, Integer limit) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_REPORT_ANSWER); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("jobid", jobId); + jsonObject.addProperty("date", date); + if (offset != null) { + jsonObject.addProperty("offset", offset); + } + if (limit != null) { + jsonObject.addProperty("limit", limit); + } + String responseContent = this.cpService.post(apiUrl, jsonObject.toString()); + return WxCpGetReportAnswer.fromJson(responseContent); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpSchoolServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpSchoolServiceImpl.java new file mode 100644 index 000000000..30500a205 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpSchoolServiceImpl.java @@ -0,0 +1,129 @@ +package me.chanjar.weixin.cp.api.impl; + +import com.google.gson.JsonObject; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.api.WxCpSchoolService; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.living.WxCpLivingResult; +import me.chanjar.weixin.cp.bean.school.*; +import org.apache.commons.lang3.StringUtils; + +import javax.validation.constraints.NotNull; +import java.util.List; +import java.util.Optional; + +import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.School.*; + +/** + * 企业微信家校应用 复学码相关接口实现类. + * https://developer.work.weixin.qq.com/document/path/93744 + * + * @author Wang_Wong + * @date: 2022/6/1 14:05 + */ +@Slf4j +@RequiredArgsConstructor +public class WxCpSchoolServiceImpl implements WxCpSchoolService { + + private final WxCpService cpService; + + @Override + public WxCpCustomizeHealthInfo getTeacherCustomizeHealthInfo(@NotNull String date, String nextKey, Integer limit) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_TEACHER_CUSTOMIZE_HEALTH_INFO); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("date", date); + jsonObject.addProperty("limit", Optional.ofNullable(limit).orElse(100)); + if (nextKey != null) { + jsonObject.addProperty("next_key", nextKey); + } + String responseContent = this.cpService.post(apiUrl, jsonObject.toString()); + return WxCpCustomizeHealthInfo.fromJson(responseContent); + } + + @Override + public WxCpCustomizeHealthInfo getStudentCustomizeHealthInfo(@NotNull String date, String nextKey, Integer limit) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_STUDENT_CUSTOMIZE_HEALTH_INFO); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("date", date); + jsonObject.addProperty("limit", Optional.ofNullable(limit).orElse(100)); + if (nextKey != null) { + jsonObject.addProperty("next_key", nextKey); + } + String responseContent = this.cpService.post(apiUrl, jsonObject.toString()); + return WxCpCustomizeHealthInfo.fromJson(responseContent); + } + + @Override + public WxCpResultList getHealthQrCode(@NotNull List userIds, @NotNull Integer type) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_HEALTH_QRCODE); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("type", type); + jsonObject.addProperty("userids", userIds.toString()); + String responseContent = this.cpService.post(apiUrl, jsonObject.toString()); + return WxCpResultList.fromJson(responseContent); + } + + @Override + public WxCpPaymentResult getPaymentResult(@NotNull String paymentId) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_PAYMENT_RESULT); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("payment_id", paymentId); + String responseContent = this.cpService.post(apiUrl, jsonObject.toString()); + return WxCpPaymentResult.fromJson(responseContent); + } + + @Override + public WxCpTrade getTrade(@NotNull String paymentId, @NotNull String tradeNo) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_TRADE); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("payment_id", paymentId); + jsonObject.addProperty("trade_no", tradeNo); + String responseContent = this.cpService.post(apiUrl, jsonObject.toString()); + return WxCpTrade.fromJson(responseContent); + } + + @Override + public WxCpSchoolLivingInfo getLivingInfo(@NotNull String livingId) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_LIVING_INFO) + livingId; + String responseContent = this.cpService.get(apiUrl, null); + return WxCpSchoolLivingInfo.fromJson(responseContent); + } + + @Override + public WxCpLivingResult.LivingIdResult getUserAllLivingId(@NonNull String userId, String cursor, Integer limit) throws WxErrorException { + return this.cpService.getLivingService().getUserAllLivingId(userId, cursor, limit); + } + + @Override + public WxCpSchoolWatchStat getWatchStat(@NonNull String livingId, String nextKey) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_WATCH_STAT); + JsonObject jsonObject = new JsonObject(); + if (StringUtils.isNotBlank(nextKey)) { + jsonObject.addProperty("next_key", nextKey); + } + jsonObject.addProperty("livingid", livingId); + String responseContent = this.cpService.post(apiUrl, jsonObject.toString()); + return WxCpSchoolWatchStat.fromJson(responseContent); + } + + @Override + public WxCpSchoolUnwatchStat getUnwatchStat(@NonNull String livingId, String nextKey) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_UNWATCH_STAT); + JsonObject jsonObject = new JsonObject(); + if (StringUtils.isNotBlank(nextKey)) { + jsonObject.addProperty("next_key", nextKey); + } + jsonObject.addProperty("livingid", livingId); + String responseContent = this.cpService.post(apiUrl, jsonObject.toString()); + return WxCpSchoolUnwatchStat.fromJson(responseContent); + } + + @Override + public WxCpLivingResult deleteReplayData(@NonNull String livingId) throws WxErrorException { + return cpService.getLivingService().deleteReplayData(livingId); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpSchoolUserServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpSchoolUserServiceImpl.java new file mode 100644 index 000000000..c042d305f --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpSchoolUserServiceImpl.java @@ -0,0 +1,273 @@ +package me.chanjar.weixin.cp.api.impl; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.util.json.GsonParser; +import me.chanjar.weixin.cp.api.WxCpSchoolUserService; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.bean.WxCpOauth2UserInfo; +import me.chanjar.weixin.cp.bean.school.user.*; +import org.apache.commons.lang3.StringUtils; + +import java.util.List; + +import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.ExternalContact.*; +import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.School.*; + +/** + * 企业微信家校沟通相关接口. + * https://developer.work.weixin.qq.com/document/path/91638 + * + * @author Wang_Wong + * @date: 2022/6/18 9:10 + */ +@Slf4j +@RequiredArgsConstructor +public class WxCpSchoolUserServiceImpl implements WxCpSchoolUserService { + + private final WxCpService cpService; + + @Override + public WxCpOauth2UserInfo getUserInfo(@NonNull String code) throws WxErrorException { + return cpService.getOauth2Service().getUserInfo(code); + } + + @Override + public WxCpOauth2UserInfo getSchoolUserInfo(@NonNull String code) throws WxErrorException { + return cpService.getOauth2Service().getSchoolUserInfo(code); + } + + @Override + public WxCpBaseResp createStudent(@NonNull String studentUserId, @NonNull String name, @NonNull List departments) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(CREATE_STUDENT); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("student_userid", studentUserId); + jsonObject.addProperty("name", name); + JsonArray jsonArray = new JsonArray(); + for (Integer depart : departments) { + jsonArray.add(new JsonPrimitive(depart)); + } + jsonObject.add("department", jsonArray); + String responseContent = this.cpService.post(apiUrl, jsonObject.toString()); + return WxCpBaseResp.fromJson(responseContent); + } + + @Override + public WxCpBatchResultList batchCreateStudent(@NonNull WxCpBatchCreateStudentRequest request) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(BATCH_CREATE_STUDENT); + String responseContent = this.cpService.post(apiUrl, request.toJson()); + return WxCpBatchResultList.fromJson(responseContent); + } + + @Override + public WxCpBatchResultList batchDeleteStudent(@NonNull WxCpBatchDeleteStudentRequest request) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(BATCH_DELETE_STUDENT); + String responseContent = this.cpService.post(apiUrl, request.toJson()); + return WxCpBatchResultList.fromJson(responseContent); + } + + @Override + public WxCpBatchResultList batchUpdateStudent(@NonNull WxCpBatchUpdateStudentRequest request) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(BATCH_UPDATE_STUDENT); + String responseContent = this.cpService.post(apiUrl, request.toJson()); + return WxCpBatchResultList.fromJson(responseContent); + } + + @Override + public WxCpBaseResp deleteStudent(@NonNull String studentUserId) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(DELETE_STUDENT) + studentUserId; + String responseContent = this.cpService.get(apiUrl, null); + return WxCpBaseResp.fromJson(responseContent); + } + + @Override + public WxCpBaseResp updateStudent(@NonNull String studentUserId, String newStudentUserId, String name, List departments) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(UPDATE_STUDENT); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("student_userid", studentUserId); + if (StringUtils.isNotEmpty(newStudentUserId)) { + jsonObject.addProperty("new_student_userid", newStudentUserId); + } + if (StringUtils.isNotEmpty(name)) { + jsonObject.addProperty("name", name); + } + if (departments != null && departments.size() > 0) { + JsonArray jsonArray = new JsonArray(); + for (Integer depart : departments) { + jsonArray.add(new JsonPrimitive(depart)); + } + jsonObject.add("department", jsonArray); + } + String responseContent = this.cpService.post(apiUrl, jsonObject.toString()); + return WxCpBaseResp.fromJson(responseContent); + } + + @Override + public WxCpBaseResp createParent(@NonNull WxCpCreateParentRequest request) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(CREATE_PARENT); + String responseContent = this.cpService.post(apiUrl, request.toJson()); + return WxCpBaseResp.fromJson(responseContent); + } + + @Override + public WxCpBatchResultList batchCreateParent(@NonNull WxCpBatchCreateParentRequest request) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(BATCH_CREATE_PARENT); + String responseContent = this.cpService.post(apiUrl, request.toJson()); + return WxCpBatchResultList.fromJson(responseContent); + } + + @Override + public WxCpBatchResultList batchDeleteParent(@NonNull String... userIdList) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(BATCH_DELETE_PARENT); + JsonObject jsonObject = new JsonObject(); + JsonArray jsonArray = new JsonArray(); + for (String userId : userIdList) { + jsonArray.add(new JsonPrimitive(userId)); + } + jsonObject.add("useridlist", jsonArray); + String responseContent = this.cpService.post(apiUrl, jsonObject.toString()); + return WxCpBatchResultList.fromJson(responseContent); + } + + @Override + public WxCpBatchResultList batchUpdateParent(@NonNull WxCpBatchUpdateParentRequest request) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(BATCH_UPDATE_PARENT); + String responseContent = this.cpService.post(apiUrl, request.toJson()); + return WxCpBatchResultList.fromJson(responseContent); + } + + @Override + public WxCpUserResult getUser(@NonNull String userId) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_USER) + userId; + String responseContent = this.cpService.get(apiUrl, null); + return WxCpUserResult.fromJson(responseContent); + } + + @Override + public WxCpUserListResult getUserList(@NonNull Integer departmentId, Integer fetchChild) throws WxErrorException { + String apiUrl = String.format(this.cpService.getWxCpConfigStorage().getApiUrl(GET_USER_LIST), departmentId, fetchChild); + String responseContent = this.cpService.get(apiUrl, null); + return WxCpUserListResult.fromJson(responseContent); + } + + @Override + public WxCpListParentResult getUserListParent(@NonNull Integer departmentId) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_USER_LIST_PARENT) + departmentId; + String responseContent = this.cpService.get(apiUrl, null); + return WxCpListParentResult.fromJson(responseContent); + } + + @Override + public WxCpBaseResp updateParent(@NonNull WxCpUpdateParentRequest request) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(UPDATE_PARENT); + String responseContent = this.cpService.post(apiUrl, request.toJson()); + return WxCpBaseResp.fromJson(responseContent); + } + + @Override + public WxCpBaseResp deleteParent(@NonNull String userId) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(DELETE_PARENT) + userId; + String responseContent = this.cpService.get(apiUrl, null); + return WxCpBaseResp.fromJson(responseContent); + } + + @Override + public WxCpBaseResp setArchSyncMode(@NonNull Integer archSyncMode) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(SET_ARCH_SYNC_MODE); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("arch_sync_mode", archSyncMode); + String responseContent = this.cpService.post(apiUrl, jsonObject.toString()); + return WxCpBaseResp.fromJson(responseContent); + } + + @Override + public WxCpCreateDepartment createDepartment(@NonNull WxCpCreateDepartmentRequest request) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(DEPARTMENT_CREATE); + String responseContent = this.cpService.post(apiUrl, request.toJson()); + return WxCpCreateDepartment.fromJson(responseContent); + } + + @Override + public WxCpBaseResp updateDepartment(@NonNull WxCpUpdateDepartmentRequest request) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(DEPARTMENT_UPDATE); + String responseContent = this.cpService.post(apiUrl, request.toJson()); + return WxCpBaseResp.fromJson(responseContent); + } + + @Override + public WxCpBaseResp deleteDepartment(Integer id) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(DEPARTMENT_DELETE) + id; + String responseContent = this.cpService.get(apiUrl, null); + return WxCpBaseResp.fromJson(responseContent); + } + + @Override + public WxCpBaseResp setSubscribeMode(@NonNull Integer subscribeMode) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(SET_SUBSCRIBE_MODE); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("subscribe_mode", subscribeMode); + String responseContent = this.cpService.post(apiUrl, jsonObject.toString()); + return WxCpBaseResp.fromJson(responseContent); + } + + @Override + public Integer getSubscribeMode() throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_SUBSCRIBE_MODE); + String responseContent = this.cpService.get(apiUrl, null); + return GsonParser.parse(responseContent).get("subscribe_mode").getAsInt(); + } + + @Override + public WxCpExternalContact getExternalContact(@NonNull String externalUserId) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(EXTERNAL_CONTACT_GET) + externalUserId; + String responseContent = this.cpService.get(apiUrl, null); + return WxCpExternalContact.fromJson(responseContent); + } + + @Override + public WxCpAllowScope getAllowScope(@NonNull Integer agentId) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_ALLOW_SCOPE) + agentId; + String responseContent = this.cpService.get(apiUrl, null); + return WxCpAllowScope.fromJson(responseContent); + } + + @Override + public String convertToOpenId(@NonNull String externalUserId) throws WxErrorException { + return cpService.getExternalContactService().convertToOpenid(externalUserId); + } + + @Override + public WxCpDepartmentList listDepartment(Integer id) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(DEPARTMENT_LIST) + id; + String responseContent = this.cpService.get(apiUrl, null); + return WxCpDepartmentList.fromJson(responseContent); + } + + @Override + public WxCpSubscribeQrCode getSubscribeQrCode() throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_SUBSCRIBE_QR_CODE); + String responseContent = this.cpService.get(apiUrl, null); + return WxCpSubscribeQrCode.fromJson(responseContent); + } + + @Override + public WxCpSetUpgradeInfo setUpgradeInfo(Long upgradeTime, Integer upgradeSwitch) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(SET_UPGRADE_INFO); + JsonObject jsonObject = new JsonObject(); + if (upgradeTime != null) { + jsonObject.addProperty("upgrade_time", upgradeTime); + } + if (upgradeSwitch != null) { + jsonObject.addProperty("upgrade_switch", upgradeSwitch); + } + String responseContent = this.cpService.post(apiUrl, jsonObject.toString()); + return WxCpSetUpgradeInfo.fromJson(responseContent); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpTaskCardServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpTaskCardServiceImpl.java index 384a3d30c..9e9e7dea0 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpTaskCardServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpTaskCardServiceImpl.java @@ -38,4 +38,25 @@ public void update(List userIds, String taskId, String replaceName) thro String url = this.mainService.getWxCpConfigStorage().getApiUrl(UPDATE_TASK_CARD); this.mainService.post(url, WxGsonBuilder.create().toJson(data)); } + + @Override + public void updateTemplateCardButton(List userIds, List partyIds, + List tagIds, Integer atAll, + String responseCode, String replaceName) throws WxErrorException { + Integer agentId = this.mainService.getWxCpConfigStorage().getAgentId(); + Map data = new HashMap<>(7); + data.put("userids", userIds); + data.put("partyids", partyIds); + data.put("tagids", tagIds); + data.put("atall", atAll); + data.put("agentid", agentId); + data.put("response_code", responseCode); + Map btnMap = new HashMap<>(); + btnMap.put("replace_name", replaceName); + data.put("button", btnMap); + + String url = this.mainService.getWxCpConfigStorage().getApiUrl(UPDATE_TEMPLATE_CARD); + this.mainService.post(url, WxGsonBuilder.create().toJson(data)); + + } } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImpl.java index d0648b21e..f7ff0f57b 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImpl.java @@ -12,9 +12,15 @@ import me.chanjar.weixin.cp.api.WxCpUserService; import me.chanjar.weixin.cp.bean.WxCpInviteResult; import me.chanjar.weixin.cp.bean.WxCpUser; +import me.chanjar.weixin.cp.bean.WxCpUseridToOpenUseridResult; import me.chanjar.weixin.cp.bean.external.contact.WxCpExternalContactInfo; +import me.chanjar.weixin.cp.bean.user.WxCpDeptUserResult; import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; +import org.apache.commons.lang3.time.FastDateFormat; +import java.text.Format; +import java.util.ArrayList; +import java.util.Date; import java.util.List; import java.util.Map; @@ -29,6 +35,8 @@ */ @RequiredArgsConstructor public class WxCpUserServiceImpl implements WxCpUserService { + private final Format dateFormat = FastDateFormat.getInstance("yyyy-MM-dd"); + private final WxCpService mainService; @Override @@ -208,4 +216,43 @@ public String getJoinQrCode(int sizeType) throws WxErrorException { JsonObject tmpJson = GsonParser.parse(responseContent); return tmpJson.get("join_qrcode").getAsString(); } + + @Override + public Integer getActiveStat(Date date) throws WxErrorException { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("date", this.dateFormat.format(date)); + String url = this.mainService.getWxCpConfigStorage().getApiUrl(GET_ACTIVE_STAT); + String responseContent = this.mainService.post(url, jsonObject.toString()); + JsonObject tmpJson = GsonParser.parse(responseContent); + return tmpJson.get("active_cnt").getAsInt(); + } + + @Override + public WxCpUseridToOpenUseridResult useridToOpenUserid(ArrayList useridList) throws WxErrorException { + JsonObject jsonObject = new JsonObject(); + JsonArray jsonArray = new JsonArray(); + for (String userid : useridList) { + jsonArray.add(userid); + } + jsonObject.add("userid_list", jsonArray); + String url = this.mainService.getWxCpConfigStorage().getApiUrl(USERID_TO_OPEN_USERID); + String responseContent = this.mainService.post(url, jsonObject.toString()); + return WxCpUseridToOpenUseridResult.fromJson(responseContent); + } + + @Override + public WxCpDeptUserResult getUserListId(String cursor, Integer limit) throws WxErrorException { + String apiUrl = this.mainService.getWxCpConfigStorage().getApiUrl(USER_LIST_ID); + JsonObject jsonObject = new JsonObject(); + if (cursor != null) { + jsonObject.addProperty("cursor", cursor); + } + if (limit != null) { + jsonObject.addProperty("limit", limit); + } + String responseContent = this.mainService.post(apiUrl, jsonObject.toString()); + return WxCpDeptUserResult.fromJson(responseContent); + } + + } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpBaseResp.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpBaseResp.java index 254260ea3..07447d68b 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpBaseResp.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpBaseResp.java @@ -8,7 +8,9 @@ import java.io.Serializable; /** - * @author yqx + * 返回结果 + * + * @author yqx & WangWong * @date 2020/3/16 */ @Getter @@ -29,4 +31,9 @@ public boolean success() { public static WxCpBaseResp fromJson(String json) { return WxCpGsonBuilder.create().fromJson(json, WxCpBaseResp.class); } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpOauth2UserInfo.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpOauth2UserInfo.java index 0e10737bf..a35a37c05 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpOauth2UserInfo.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpOauth2UserInfo.java @@ -14,6 +14,8 @@ * Created by BinaryWang on 2019/5/26. *
* + * 文档1:https://developer.work.weixin.qq.com/document/path/91707 + * * @author Binary Wang */ @Data @@ -30,4 +32,7 @@ public class WxCpOauth2UserInfo implements Serializable { private String userTicket; private String expiresIn; private String externalUserId; + private String parentUserId; + private String studentUserId; + } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpTpAdmin.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpTpAdmin.java index a950e0c3f..438ef79fd 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpTpAdmin.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpTpAdmin.java @@ -30,6 +30,9 @@ public static class Admin extends WxCpBaseResp { @SerializedName("userid") private String userId; + + @SerializedName("open_userid") + private String openUserId; @SerializedName("auth_type") private Integer authType; diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpTpAuthInfo.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpTpAuthInfo.java index 9ca497175..1f089e762 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpTpAuthInfo.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpTpAuthInfo.java @@ -36,6 +36,13 @@ public class WxCpTpAuthInfo extends WxCpBaseResp { @SerializedName("auth_info") private AuthInfo authInfo; + + /** + * 企业当前生效的版本信息 + */ + @SerializedName("edition_info") + private EditionInfo editionInfo; + @Getter @Setter public static class DealerCorpInfo extends WxCpBaseResp { @@ -128,6 +135,22 @@ public static class AuthInfo implements Serializable { } + /** + * 企业当前生效的版本信息 + */ + @Getter + @Setter + public static class EditionInfo implements Serializable { + private static final long serialVersionUID = -5028321625140879571L; + + /** + * 授权的应用信息,注意是一个数组,但仅旧的多应用套件授权时会返回多个agent,对新的单应用授权,永远只返回一个agent + */ + @SerializedName("agent") + private List agents; + + } + @Getter @Setter public static class Agent implements Serializable { @@ -170,6 +193,68 @@ public static class Agent implements Serializable { @SerializedName("privilege") private Privilege privilege; + /** + * 版本id + */ + @SerializedName("edition_id") + private String editionId; + + /** + * 版本名称 + */ + @SerializedName("edition_name") + private String editionName; + + /** + * 付费状态 + *
+ *
    + *
  • 0-没有付费;
  • + *
  • 1-限时试用;
  • + *
  • 2-试用过期;
  • + *
  • 3-购买期内;
  • + *
  • 4-购买过期;
  • + *
  • 5-不限时试用;
  • + *
  • 6-购买期内,但是人数超标, 注意,超标后还可以用7天;
  • + *
  • 7-购买期内,但是人数超标, 且已经超标试用7天
  • + *
+ */ + @SerializedName("app_status") + private Integer appStatus; + + /** + * 用户上限。 + *

特别注意, 以下情况该字段无意义,可以忽略:

+ *
    + *
  • 1. 固定总价购买
  • + *
  • 2. app_status = 限时试用/试用过期/不限时试用
  • + *
  • 3. 在第2条“app_status=不限时试用”的情况下,如果该应用的配置为“小企业无使用限制”,user_limit有效,且为限制的人数
  • + *
+ */ + @SerializedName("user_limit") + private Long userLimit; + + /** + * 版本到期时间, 秒级时间戳, 根据需要自行乘以1000(根据购买版本,可能是试用到期时间或付费使用到期时间)。 + *

特别注意,以下情况该字段无意义,可以忽略:

+ *
    + *
  • 1. app_status = 不限时试用
  • + *
+ */ + @SerializedName("expired_time") + private Long expiredTime; + + /** + * 是否虚拟版本 + */ + @SerializedName("is_virtual_version") + private Boolean isVirtualVersion; + + /** + * 是否由互联企业分享安装。详见 企业互联 + */ + @SerializedName("is_shared_from_other_corp") + private Boolean isSharedFromOtherCorp; } /** @@ -216,6 +301,7 @@ public static WxCpTpAuthInfo fromJson(String json) { return WxCpGsonBuilder.create().fromJson(json, WxCpTpAuthInfo.class); } + @Override public String toJson() { return WxCpGsonBuilder.create().toJson(this); } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpTpPermanentCodeInfo.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpTpPermanentCodeInfo.java index 9774f6230..eaf10feae 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpTpPermanentCodeInfo.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpTpPermanentCodeInfo.java @@ -45,7 +45,18 @@ public class WxCpTpPermanentCodeInfo extends WxCpBaseResp { */ @SerializedName("auth_user_info") private AuthUserInfo authUserInfo; + + /** + * 推广二维码安装相关信息 + */ + @SerializedName("register_code_info") + private RegisterCodeInfo registerCodeInfo; + /** + * 企业当前生效的版本信息 + */ + @SerializedName("edition_info") + private EditionInfo editionInfo; @Getter @Setter @@ -127,6 +138,22 @@ public static class AuthInfo implements Serializable { } + /** + * 企业当前生效的版本信息 + */ + @Getter + @Setter + public static class EditionInfo implements Serializable { + private static final long serialVersionUID = -5028321625140879571L; + + /** + * 授权的应用信息,注意是一个数组,但仅旧的多应用套件授权时会返回多个agent,对新的单应用授权,永远只返回一个agent + */ + @SerializedName("agent") + private List agents; + + } + @Getter @Setter public static class Agent implements Serializable { @@ -169,6 +196,69 @@ public static class Agent implements Serializable { @SerializedName("privilege") private Privilege privilege; + /** + * 版本id + */ + @SerializedName("edition_id") + private String editionId; + + /** + * 版本名称 + */ + @SerializedName("edition_name") + private String editionName; + + /** + * 付费状态 + *
+ *
    + *
  • 0-没有付费;
  • + *
  • 1-限时试用;
  • + *
  • 2-试用过期;
  • + *
  • 3-购买期内;
  • + *
  • 4-购买过期;
  • + *
  • 5-不限时试用;
  • + *
  • 6-购买期内,但是人数超标, 注意,超标后还可以用7天;
  • + *
  • 7-购买期内,但是人数超标, 且已经超标试用7天
  • + *
+ */ + @SerializedName("app_status") + private Integer appStatus; + + /** + * 用户上限。 + *

特别注意, 以下情况该字段无意义,可以忽略:

+ *
    + *
  • 1. 固定总价购买
  • + *
  • 2. app_status = 限时试用/试用过期/不限时试用
  • + *
  • 3. 在第2条“app_status=不限时试用”的情况下,如果该应用的配置为“小企业无使用限制”,user_limit有效,且为限制的人数
  • + *
+ */ + @SerializedName("user_limit") + private Long userLimit; + + /** + * 版本到期时间, 秒级时间戳, 根据需要自行乘以1000(根据购买版本,可能是试用到期时间或付费使用到期时间)。 + *

特别注意,以下情况该字段无意义,可以忽略:

+ *
    + *
  • 1. app_status = 不限时试用
  • + *
+ */ + @SerializedName("expired_time") + private Long expiredTime; + + /** + * 是否虚拟版本 + */ + @SerializedName("is_virtual_version") + private Boolean isVirtualVersion; + + /** + * 是否由互联企业分享安装。详见 企业互联 + */ + @SerializedName("is_shared_from_other_corp") + private Boolean isSharedFromOtherCorp; + } /** @@ -187,6 +277,40 @@ public static class AuthUserInfo implements Serializable { @SerializedName("avatar") private String avatar; + + /** + * 授权管理员的open_userid,可能为空 + */ + @SerializedName("open_userid") + private String openUserid; + } + + /** + * 推广二维码安装相关信息 + */ + @Getter + @Setter + public static class RegisterCodeInfo implements Serializable { + private static final long serialVersionUID = -5028321625140879571L; + + /** + * 注册码 + */ + @SerializedName("register_code") + private String registerCode; + + /** + * 推广包ID + */ + @SerializedName("template_id") + private String templateId; + + /** + * 仅当获取注册码指定该字段时才返回 + */ + @SerializedName("state") + private String state; + } /** @@ -233,6 +357,7 @@ public static WxCpTpPermanentCodeInfo fromJson(String json) { return WxCpGsonBuilder.create().fromJson(json, WxCpTpPermanentCodeInfo.class); } + @Override public String toJson() { return WxCpGsonBuilder.create().toJson(this); } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpTpProlongTryResult.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpTpProlongTryResult.java new file mode 100644 index 000000000..1429b8296 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpTpProlongTryResult.java @@ -0,0 +1,49 @@ +package me.chanjar.weixin.cp.bean; + +import com.google.gson.annotations.SerializedName; +import lombok.Getter; +import lombok.Setter; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +/** + * 应用市场延长试用期结果 + * @author leiguoqing + * @date 2022年4月24日 + */ +@Getter +@Setter +public class WxCpTpProlongTryResult extends WxCpBaseResp { + + /** + * The constant serialVersionUID. + */ + private static final long serialVersionUID = -5028321625140879571L; + + /** + * 延长后的试用到期时间(秒级时间戳) + */ + @SerializedName("try_end_time") + private Long tryEndTime; + + + /** + * From json wx cp tp order list get result. + * + * @param json the json + * @return the wx cp tp order list get result + */ + public static WxCpTpProlongTryResult fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpTpProlongTryResult.class); + } + + /** + * To json string. + * + * @return the string + */ + @Override + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUser.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUser.java index 76a8f9330..776e347ce 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUser.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUser.java @@ -31,6 +31,7 @@ public class WxCpUser implements Serializable { private String mobile; private Gender gender; private String email; + private String bizMail; private String avatar; private String thumbAvatar; private String mainDepartment; diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUserDetail.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUserDetail.java index 295acfdbc..5f952acfe 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUserDetail.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUserDetail.java @@ -9,6 +9,7 @@ *
  *  使用user_ticket获取成员详情接口返回类.
  *  Created by BinaryWang on 2018/4/22.
+ *  官方文档:https://developer.work.weixin.qq.com/document/path/91122
  * 
* * @author Binary Wang diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUseridToOpenUserid.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUseridToOpenUserid.java new file mode 100644 index 000000000..2b5cfd435 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUseridToOpenUserid.java @@ -0,0 +1,35 @@ +package me.chanjar.weixin.cp.bean; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; + +/** + * userid转换为open_userid + * 将自建应用或代开发应用获取的userid转换为第三方应用的userid + * 中间对象 + * Created by gxh0797 on 2022.07.26. + * + */ +@Data +public class WxCpUseridToOpenUserid implements Serializable { + private static final long serialVersionUID = 1420065684270213578L; + + @Override + public String toString() { + return WxCpGsonBuilder.create().toJson(this); + } + + public static WxCpUseridToOpenUserid fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpUseridToOpenUserid.class); + } + + @SerializedName("userid") + private String userid; + + @SerializedName("open_userid") + private String openUserid; + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUseridToOpenUseridResult.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUseridToOpenUseridResult.java new file mode 100644 index 000000000..90d002f17 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUseridToOpenUseridResult.java @@ -0,0 +1,42 @@ +package me.chanjar.weixin.cp.bean; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * userid转换为open_userid + * 将自建应用或代开发应用获取的userid转换为第三方应用的userid + * Created by gxh0797 on 2022.07.26. + * + */ +@Data +public class WxCpUseridToOpenUseridResult implements Serializable { + private static final long serialVersionUID = 1420065684270213578L; + + @Override + public String toString() { + return WxCpGsonBuilder.create().toJson(this); + } + + public static WxCpUseridToOpenUseridResult fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpUseridToOpenUseridResult.class); + } + + @SerializedName("errcode") + private Integer errCode; + + @SerializedName("errmsg") + private String errMsg; + + @SerializedName("open_userid_list") + private List openUseridList; + + @SerializedName("invalid_userid_list") + private List invalidUseridList; + + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/article/NewArticle.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/article/NewArticle.java index 854c0ca89..f1e199939 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/article/NewArticle.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/article/NewArticle.java @@ -20,18 +20,22 @@ @NoArgsConstructor public class NewArticle implements Serializable { private static final long serialVersionUID = 4087852055781140659L; + /** * 标题,不超过128个字节,超过会自动截断 */ private String title; + /** * 描述,不超过512个字节,超过会自动截断 */ private String description; + /** * 点击后跳转的链接。 */ private String url; + /** * 图文消息的图片链接,支持JPG、PNG格式,较好的效果为大图1068*455,小图150*150。 */ @@ -41,4 +45,15 @@ public class NewArticle implements Serializable { * 按钮文字,仅在图文数为1条时才生效。 默认为“阅读全文”, 不超过4个文字,超过自动截断。该设置只在企业微信上生效,微工作台(原企业号)上不生效。 */ private String btnText; + + /** + * 小程序appid,必须是与当前应用关联的小程序,appid和pagepath必须同时填写,填写后会忽略url字段 + */ + private String appid; + + /** + * 点击消息卡片后的小程序页面,仅限本小程序内的页面。appid和pagepath必须同时填写,填写后会忽略url字段 + */ + private String pagepath; + } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/export/WxCpExportRequest.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/export/WxCpExportRequest.java new file mode 100644 index 000000000..ef21c19e2 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/export/WxCpExportRequest.java @@ -0,0 +1,41 @@ +package me.chanjar.weixin.cp.bean.export; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; + +/** + * 异步导出参数 + * + * @author zhongjun + * @date 2022/4/21 + **/ +@Data +public class WxCpExportRequest implements Serializable { + private static final long serialVersionUID = -8127528999898984359L; + + /** + * base64encode的加密密钥,长度固定为43,base64decode之后即得到AESKey。加密方式采用AES-256-CBC方式,数据采用PKCS#7填充至32字节的倍数;IV初始向量大小为16字节,取AESKey前16字节,详见:http://tools.ietf.org/html/rfc2315 + */ + @SerializedName("encoding_aeskey") + private String encodingAesKey; + + /** + * 每块数据的部门数,支持范围[104,106],默认值为10^6 + */ + @SerializedName("block_size") + private Integer blockSize; + + /** + * 需要导出的标签 + * 导出标签成员时使用 + */ + @SerializedName("tagid") + private Integer tagId; + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/export/WxCpExportResult.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/export/WxCpExportResult.java new file mode 100644 index 000000000..b291049ae --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/export/WxCpExportResult.java @@ -0,0 +1,48 @@ +package me.chanjar.weixin.cp.bean.export; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; + +import java.util.List; + +/** + * 异步导出响应 + * + * @author zhongjun + * @date 2022/4/21 + **/ +@Data +@EqualsAndHashCode(callSuper = true) +public class WxCpExportResult extends WxCpBaseResp { + private static final long serialVersionUID = -8673839248829238966L; + + /** + * 任务状态:0-未处理,1-处理中,2-完成,3-异常失败 + */ + private Integer status; + + @SerializedName("data_list") + private List dataList; + + + @Data + public static class ExportData { + + /** + * 数据下载链接,支持指定Range头部分段下载。有效期2个小时 + */ + private String url; + + /** + * 密文数据大小 + */ + private Integer size; + + /** + * 密文数据md5 + */ + private String md5; + } +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/WxCpGroupJoinWayInfo.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/WxCpGroupJoinWayInfo.java new file mode 100644 index 000000000..a78aa9098 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/WxCpGroupJoinWayInfo.java @@ -0,0 +1,92 @@ +package me.chanjar.weixin.cp.bean.external; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + *客户群「加入群聊」对象 + * @author Jc + */ +@Data +@NoArgsConstructor +public class WxCpGroupJoinWayInfo implements Serializable { + private static final long serialVersionUID = 5621905029624794129L; + @SerializedName("join_way") + private JoinWay joinWay; + @Getter + @Setter + public static class JoinWay implements Serializable { + private static final long serialVersionUID = 5621905029624794122L; + + /** + * 联系方式的配置id + */ + @SerializedName("config_id") + private String configId; + /** + * 场景。 + * 1 - 群的小程序插件 + * 2 - 群的二维码插件 + */ + @SerializedName("scene") + private Integer scene; + /** + * 联系方式的备注信息,用于助记,超过30个字符将被截断 + */ + @SerializedName("remark") + private String remark; + /** + * 当群满了后,是否自动新建群。0-否;1-是。 默认为1 + */ + @SerializedName("auto_create_room") + private Integer autoCreateRoom; + /** + * 自动建群的群名前缀,当auto_create_room为1时有效。最长40个utf8字符 + */ + @SerializedName("room_base_name") + private String roomBaseName; + /** + * 自动建群的群起始序号,当auto_create_room为1时有效 + */ + @SerializedName("room_base_id") + private Integer roomBaseId; + /** + * 使用该配置的客户群ID列表,支持5个。 + */ + @SerializedName("chat_id_list") + private List chatIdList; + /** + * 联系二维码的URL,仅在配置为群二维码时返回 + */ + @SerializedName("qr_code") + private String qrCode; + /** + 企业自定义的state参数,用于区分不同的入群渠道。不超过30个UTF-8字符 + 如果有设置此参数,在调用获取客户群详情接口时会返回每个群成员对应的该参数值 + */ + @SerializedName("state") + private String state; + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + public static WxCpGroupJoinWayInfo.JoinWay fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpGroupJoinWayInfo.JoinWay.class); + } + } + + public static WxCpGroupJoinWayInfo fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpGroupJoinWayInfo.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/WxCpGroupJoinWayResult.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/WxCpGroupJoinWayResult.java new file mode 100644 index 000000000..f77b6089c --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/WxCpGroupJoinWayResult.java @@ -0,0 +1,23 @@ +package me.chanjar.weixin.cp.bean.external; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +/** + *客户群「加入群聊」配置处理结果 + * @author Jc + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class WxCpGroupJoinWayResult extends WxCpBaseResp { + private static final long serialVersionUID = 5621905029624794129L; + @SerializedName("config_id") + private String configId; + + public static WxCpGroupJoinWayResult fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpGroupJoinWayResult.class); + } +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/WxCpGroupWelcomeTemplateResult.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/WxCpGroupWelcomeTemplateResult.java index 631d6be26..03aadb8db 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/WxCpGroupWelcomeTemplateResult.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/WxCpGroupWelcomeTemplateResult.java @@ -1,5 +1,6 @@ package me.chanjar.weixin.cp.bean.external; +import com.google.gson.annotations.SerializedName; import lombok.*; import me.chanjar.weixin.cp.bean.WxCpBaseResp; import me.chanjar.weixin.cp.bean.external.msg.*; @@ -33,6 +34,18 @@ public class WxCpGroupWelcomeTemplateResult extends WxCpBaseResp implements Seri private Video video; + /** + * 欢迎语素材id + * https://developer.work.weixin.qq.com/document/path/92366 + */ + @SerializedName("template_id") + private String templateId; + + /** + * 是否通知成员将这条入群欢迎语应用到客户群中,0-不通知,1-通知, 不填则通知 + */ + private Integer notify; + public static WxCpGroupWelcomeTemplateResult fromJson(String json) { return WxCpGsonBuilder.create().fromJson(json, WxCpGroupWelcomeTemplateResult.class); } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/WxCpInterceptRuleResp.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/WxCpInterceptRuleResp.java new file mode 100644 index 000000000..0c5f86c3c --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/WxCpInterceptRuleResp.java @@ -0,0 +1,61 @@ +package me.chanjar.weixin.cp.bean.external; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.util.Date; +import java.util.List; + +/** + * 新增敏感词规则请求参数封装实体类 + * + * @author didi + * @date 2022-04-17 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class WxCpInterceptRuleResp { + + @SerializedName("rule_name") + private String ruleName; + @SerializedName("rule_id") + private String ruleId; + @SerializedName("word_list") + private List wordList; + @SerializedName("semantics_list") + private List semanticsList; + @SerializedName("intercept_type") + private int interceptType; + @SerializedName("applicable_range") + private ApplicableRange applicableRange; + + @Data + public static class ApplicableRange { + @SerializedName("user_list") + private List userList; + @SerializedName("department_list") + private List departmentList; + public static ApplicableRange fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, ApplicableRange.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + } + + public static WxCpInterceptRuleResp fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpInterceptRuleResp.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/WxCpInterceptRuleResultResp.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/WxCpInterceptRuleResultResp.java new file mode 100644 index 000000000..2ce6c28f2 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/WxCpInterceptRuleResultResp.java @@ -0,0 +1,30 @@ +package me.chanjar.weixin.cp.bean.external; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; + +/** + * 新建敏感词规则负返回结果 + * @author didi + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class WxCpInterceptRuleResultResp extends WxCpBaseResp implements Serializable { + + @SerializedName("rule_id") + private String ruleId; + + public static WxCpInterceptRuleResultResp fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpInterceptRuleResultResp.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/WxCpProductAlbumInfo.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/WxCpProductAlbumInfo.java index e0ad62ea3..c837d3085 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/WxCpProductAlbumInfo.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/WxCpProductAlbumInfo.java @@ -50,4 +50,8 @@ public static WxCpProductAlbumInfo fromJson(String json) { return WxCpGsonBuilder.create().fromJson(json, WxCpProductAlbumInfo.class); } + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/WxCpUserExternalGroupChatInfo.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/WxCpUserExternalGroupChatInfo.java index 053789f9c..0fa97573c 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/WxCpUserExternalGroupChatInfo.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/WxCpUserExternalGroupChatInfo.java @@ -83,6 +83,12 @@ public static class GroupMember implements Serializable { @SerializedName("join_scene") private int joinScene; + /** + * 该成员入群方式对应的state参数 + */ + @SerializedName("state") + private String state; + /** * 在群里的昵称 */ diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/WxCpUserExternalGroupChatTransferResp.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/WxCpUserExternalGroupChatTransferResp.java index 4f4ee7ef1..ed40f8acf 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/WxCpUserExternalGroupChatTransferResp.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/WxCpUserExternalGroupChatTransferResp.java @@ -39,6 +39,7 @@ public static class GroupChatFailedTransfer extends WxCpBaseResp { /** * 没能成功继承的群ID */ + @SerializedName("chat_id") private String chatId; public static WxCpUserExternalGroupChatTransferResp.GroupChatFailedTransfer fromJson(String json) { diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/WxCpKfGetCorpStatisticRequest.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/WxCpKfGetCorpStatisticRequest.java new file mode 100644 index 000000000..193a6b353 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/WxCpKfGetCorpStatisticRequest.java @@ -0,0 +1,34 @@ +package me.chanjar.weixin.cp.bean.kf; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 获取「客户数据统计」企业汇总数据 + * + * @author zhongjun + * @date 2022/4/25 + **/ +@NoArgsConstructor +@Data +public class WxCpKfGetCorpStatisticRequest { + + /** + * 客服帐号ID。不传入时返回的数据为企业维度汇总的数据 + */ + @SerializedName("open_kfid") + private String openKfId; + + /** + * 起始日期的时间戳,填这一天的0时0分0秒(否则系统自动处理为当天的0分0秒)。取值范围:昨天至前180天 + */ + @SerializedName("start_time") + private Long startTime; + /** + * 结束日期的时间戳,填这一天的0时0分0秒(否则系统自动处理为当天的0分0秒)。取值范围:昨天至前180天 + */ + @SerializedName("end_time") + private Long endTime; + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/WxCpKfGetCorpStatisticResp.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/WxCpKfGetCorpStatisticResp.java new file mode 100644 index 000000000..86d97ab3f --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/WxCpKfGetCorpStatisticResp.java @@ -0,0 +1,96 @@ +package me.chanjar.weixin.cp.bean.kf; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.util.List; + +/** + * 获取「客户数据统计」企业汇总数据 + * + * @author zhongjun + * @date 2022/4/25 + **/ +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@Data +public class WxCpKfGetCorpStatisticResp extends WxCpBaseResp { + private static final long serialVersionUID = -89898989898989898L; + + /** + * 统计数据列表 + */ + @SerializedName("statistic_list") + private List statisticList; + + @NoArgsConstructor + @Data + public static class StatisticList { + /** + * 数据统计日期,为当日0点的时间戳 + */ + @SerializedName("stat_time") + private Long statTime; + + /** + * 一天的统计数据。若当天未产生任何下列统计数据或统计数据还未计算完成则不会返回此项 + */ + @SerializedName("statistic") + private Statistic statistic; + } + + @NoArgsConstructor + @Data + public static class Statistic { + + /** + * 咨询会话数。客户发过消息并分配给接待人员或智能助手的客服会话数,转接不会产生新的会话 + */ + @SerializedName("session_cnt") + private Integer sessionCnt; + + /** + * 咨询客户数。在会话中发送过消息的客户数量,若客户多次咨询只计算一个客户 + */ + @SerializedName("user_cnt") + private Integer customerCnt; + + /** + * 咨询消息总数。客户在会话中发送的消息的数量 + */ + @SerializedName("customer_msg_cnt") + private Integer customerMsgCnt; + + /** + * 升级服务客户数。通过「升级服务」功能成功添加专员或加入客户群的客户数,若同一个客户添加多个专员或客户群,只计算一个客户。在2022年3月10日以后才会有对应统计数据 + */ + @SerializedName("upgrade_service_customer_cnt") + private Integer upgradeServiceCustomerCnt; + + /** + * 智能回复会话数。客户发过消息并分配给智能助手的咨询会话数。通过API发消息或者开启智能回复功能会将客户分配给智能助手 + */ + @SerializedName("ai_transfer_rate") + private Integer aiSessionReplyCnt; + + /** + * 转人工率。一个自然日内,客户给智能助手发消息的会话中,转人工的会话的占比。 + */ + @SerializedName("ai_transfer_rate") + private Integer aiTransferRate; + + /** + * 知识命中率。一个自然日内,客户给智能助手发送的消息中,命中知识库的占比。只有在开启了智能回复原生功能并配置了知识库的情况下,才会产生该项统计数据。当api托管了会话分配,智能回复原生功能失效。若不返回,代表没有向配置知识库的智能接待助手发送消息,该项无法计算 + */ + @SerializedName("ai_knowledge_hit_rate") + private Integer aiKnowledgeHitRate; + } + + public static WxCpKfGetCorpStatisticResp fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpKfGetCorpStatisticResp.class); + } +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/WxCpKfServiceUpgradeConfigResp.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/WxCpKfServiceUpgradeConfigResp.java new file mode 100644 index 000000000..2e9d36d71 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/WxCpKfServiceUpgradeConfigResp.java @@ -0,0 +1,48 @@ +package me.chanjar.weixin.cp.bean.kf; + +import com.google.gson.annotations.SerializedName; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +/** + * @author leiin + * @date 2022/4/26 5:21 下午 + */ +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@Data +public class WxCpKfServiceUpgradeConfigResp extends WxCpBaseResp { + + private static final long serialVersionUID = -3212550906238196617L; + + @SerializedName("member_range") + private MemberRange memberRange; + + @SerializedName("groupchat_range") + private GroupchatRange groupchatRange; + + public static WxCpKfServiceUpgradeConfigResp fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpKfServiceUpgradeConfigResp.class); + } + + @Data + @NoArgsConstructor + public static class MemberRange { + @SerializedName("userid_list") + private List useridList; + + @SerializedName("department_id_list") + private List departmentIdList; + } + + @Data + @NoArgsConstructor + public static class GroupchatRange { + @SerializedName("chat_id_list") + private List chatIdList; + } +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/WxCpTpLicenseAccount.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/WxCpTpLicenseAccount.java new file mode 100644 index 000000000..41d5564ad --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/WxCpTpLicenseAccount.java @@ -0,0 +1,32 @@ +package me.chanjar.weixin.cp.bean.license; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + + +/** + * 订单账号信息 + * @author Totoro + * @date 2022/6/27 14:04 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class WxCpTpLicenseAccount extends WxCpTpLicenseBaseAccount { + private static final long serialVersionUID = 8225061160406054730L; + + /** + * 激活码 + */ + @SerializedName("active_code") + private String activeCode; + + + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/WxCpTpLicenseAccountCount.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/WxCpTpLicenseAccountCount.java new file mode 100644 index 000000000..ba16e4da9 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/WxCpTpLicenseAccountCount.java @@ -0,0 +1,31 @@ +package me.chanjar.weixin.cp.bean.license; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; + +/** + * @author Totoro + * @date 2022/6/27 11:54 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class WxCpTpLicenseAccountCount implements Serializable { + private static final long serialVersionUID = 8521389670723004989L; + + @SerializedName("base_count") + private Integer baseCount; + @SerializedName("external_contact_count") + private Integer externalContactCount; + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/WxCpTpLicenseAccountDuration.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/WxCpTpLicenseAccountDuration.java new file mode 100644 index 000000000..0da8c50d1 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/WxCpTpLicenseAccountDuration.java @@ -0,0 +1,24 @@ +package me.chanjar.weixin.cp.bean.license; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * + * @author Totoro + * @date 2022-6-27 11:22:53 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class WxCpTpLicenseAccountDuration implements Serializable { + private static final long serialVersionUID = 7960912263908286975L; + + private Integer months; + + } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/WxCpTpLicenseActiveAccount.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/WxCpTpLicenseActiveAccount.java new file mode 100644 index 000000000..d65e3473c --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/WxCpTpLicenseActiveAccount.java @@ -0,0 +1,39 @@ +package me.chanjar.weixin.cp.bean.license; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * @author Totoro + * @date 2022-6-27 16:26:35 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class WxCpTpLicenseActiveAccount implements Serializable { + private static final long serialVersionUID = -2382681430861137803L; + + /** + * 用户ID + */ + private String userid; + + /** + * 激活码 + */ + @SerializedName("active_code") + private String activeCode; + + /** + * 激活状态 0为成功 + * 此值在请求激活时无需传入 + */ + @SerializedName("errcode") + private Integer errCode; +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/WxCpTpLicenseActiveCodeInfo.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/WxCpTpLicenseActiveCodeInfo.java new file mode 100644 index 000000000..26e107ccf --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/WxCpTpLicenseActiveCodeInfo.java @@ -0,0 +1,39 @@ +package me.chanjar.weixin.cp.bean.license; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 激活码信息 + * 文档地址:https://developer.work.weixin.qq.com/document/path/95553 + * @author Totoro + * @date 2022/6/27 14:34 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class WxCpTpLicenseActiveCodeInfo extends WxCpTpLicenseBaseAccount { + private static final long serialVersionUID = 7696395903786956694L; + + @SerializedName("active_code") + private String activeCode; + + private Integer status; + + @SerializedName("create_time") + private Long createTime; + + @SerializedName("active_time") + private Long activeTime; + + @SerializedName("expire_time") + private Long expireTime; + + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/WxCpTpLicenseBaseAccount.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/WxCpTpLicenseBaseAccount.java new file mode 100644 index 000000000..4d02f6d32 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/WxCpTpLicenseBaseAccount.java @@ -0,0 +1,38 @@ +package me.chanjar.weixin.cp.bean.license; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; + +/** + * 许可证账号基础类 + * @author Totoro + * @date 2022/6/27 14:39 + */ +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class WxCpTpLicenseBaseAccount implements Serializable { + private static final long serialVersionUID = 7075253491688740047L; + + + /** + * 用户ID + */ + private String userid; + + /** + * 类型 + */ + private Integer type; + + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/WxCpTpLicenseCorpAccount.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/WxCpTpLicenseCorpAccount.java new file mode 100644 index 000000000..246253bdd --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/WxCpTpLicenseCorpAccount.java @@ -0,0 +1,30 @@ +package me.chanjar.weixin.cp.bean.license; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author Totoro + * @date 2022/6/27 15:21 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class WxCpTpLicenseCorpAccount extends WxCpTpLicenseBaseAccount { + + private static final long serialVersionUID = -5856054486686123753L; + + @SerializedName("active_time") + private Long activeTime; + + @SerializedName("expire_time") + private Long expireTime; + + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/WxCpTpLicenseInvalidAccount.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/WxCpTpLicenseInvalidAccount.java new file mode 100644 index 000000000..3fba253bf --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/WxCpTpLicenseInvalidAccount.java @@ -0,0 +1,28 @@ +package me.chanjar.weixin.cp.bean.license; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @author Totoro + * @date 2022-6-27 15:35:30 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class WxCpTpLicenseInvalidAccount extends WxCpTpLicenseBaseAccount { + private static final long serialVersionUID = -3706481243147500720L; + + @SerializedName("errcode") + private Integer errorCode; + @SerializedName("errmsg") + private String errMsg; + + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/WxCpTpLicenseOrder.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/WxCpTpLicenseOrder.java new file mode 100644 index 000000000..a7ac6186f --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/WxCpTpLicenseOrder.java @@ -0,0 +1,52 @@ +package me.chanjar.weixin.cp.bean.license; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; + +/** + * 详细的订单信息 + * 文档地址:https://developer.work.weixin.qq.com/document/path/95648 + * @author Totoro + * @date 2022/6/27 11:38 + */ +@Data +public class WxCpTpLicenseOrder implements Serializable { + + private static final long serialVersionUID = -4094302825442292644L; + + @SerializedName("order_id") + private String orderId; + + @SerializedName("order_type") + private Integer orderType; + + @SerializedName("order_status") + private Integer orderStatus; + + @SerializedName("corpid") + private String corpId; + + @SerializedName("price") + private Long price; + + @SerializedName("account_count") + private WxCpTpLicenseAccountCount accountCount; + + @SerializedName("account_duration") + private WxCpTpLicenseAccountDuration accountDuration; + + @SerializedName("create_time") + private Long createTime; + + @SerializedName("pay_time") + private Long payTime; + + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/WxCpTpLicenseSimpleOrder.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/WxCpTpLicenseSimpleOrder.java new file mode 100644 index 000000000..54e1f0c01 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/WxCpTpLicenseSimpleOrder.java @@ -0,0 +1,33 @@ +package me.chanjar.weixin.cp.bean.license; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; + +/** + * @author Totoro + * @date 2022/6/27 11:38 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class WxCpTpLicenseSimpleOrder implements Serializable { + + private static final long serialVersionUID = -4094302825442292644L; + + @SerializedName("order_id") + private String orderId; + @SerializedName("order_type") + private Integer orderType; + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/WxCpTpLicenseTransfer.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/WxCpTpLicenseTransfer.java new file mode 100644 index 000000000..f50c3cb5f --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/WxCpTpLicenseTransfer.java @@ -0,0 +1,46 @@ +package me.chanjar.weixin.cp.bean.license; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 基础的信息 + * @author Totoro + * @date 2022/6/27 15:50 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class WxCpTpLicenseTransfer implements Serializable { + private static final long serialVersionUID = -5194757640985570778L; + + + /** + * 转移成员加密的userid + */ + @SerializedName("handover_userid") + private String handoverUserId; + + /** + * 接收成员加密的userid + */ + @SerializedName("takeover_userid") + private String takeoverUserId; + + /** + * 基础成功标识符,在请求继承的时候无需传入该参数,参数为企业微信返回 + * 0为成功 + */ + @SerializedName("errcode") + private Integer errCode; + + + + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/account/WxCpTpLicenseActiveInfoByUserResp.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/account/WxCpTpLicenseActiveInfoByUserResp.java new file mode 100644 index 000000000..c9e42650d --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/account/WxCpTpLicenseActiveInfoByUserResp.java @@ -0,0 +1,35 @@ +package me.chanjar.weixin.cp.bean.license.account; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.bean.license.WxCpTpLicenseActiveCodeInfo; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.util.List; + +/** + * 某个企业成员的激活情况 + * 文档地址:https://developer.work.weixin.qq.com/document/path/95555 + * @author Totoro + * @date 2022-6-27 14:51:19 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class WxCpTpLicenseActiveInfoByUserResp extends WxCpBaseResp { + private static final long serialVersionUID = -5172901191911873330L; + + + @SerializedName("active_status") + private Integer activeStatus; + + @SerializedName("active_info_list") + private List activeInfoList; + + + public static WxCpTpLicenseActiveInfoByUserResp fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpTpLicenseActiveInfoByUserResp.class); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/account/WxCpTpLicenseBatchActiveResultResp.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/account/WxCpTpLicenseBatchActiveResultResp.java new file mode 100644 index 000000000..4f394af62 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/account/WxCpTpLicenseBatchActiveResultResp.java @@ -0,0 +1,34 @@ +package me.chanjar.weixin.cp.bean.license.account; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.bean.license.WxCpTpLicenseActiveAccount; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.util.List; + +/** + * 批量激活帐号结果 + * 文档地址:https://developer.work.weixin.qq.com/document/path/95553 + * @author Totoro + * @date 2022-6-27 16:19:21 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class WxCpTpLicenseBatchActiveResultResp extends WxCpBaseResp { + + private static final long serialVersionUID = 8799524570217687659L; + + @SerializedName("active_result") + private List activeResults; + + + + + public static WxCpTpLicenseBatchActiveResultResp fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpTpLicenseBatchActiveResultResp.class); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/account/WxCpTpLicenseBatchCodeInfoResp.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/account/WxCpTpLicenseBatchCodeInfoResp.java new file mode 100644 index 000000000..08a12d178 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/account/WxCpTpLicenseBatchCodeInfoResp.java @@ -0,0 +1,34 @@ +package me.chanjar.weixin.cp.bean.license.account; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.bean.license.WxCpTpLicenseActiveCodeInfo; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.util.List; + +/** + * 批量查询的激活码详情 + * 文档地址:https://developer.work.weixin.qq.com/document/path/95553 + * @author Totoro + * @date 2022-6-27 14:51:19 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class WxCpTpLicenseBatchCodeInfoResp extends WxCpBaseResp { + private static final long serialVersionUID = 1327038464020790843L; + + @SerializedName("active_info_list") + private List activeCodeInfoList; + + @SerializedName("invalid_active_code_list") + private List invalidActiveCodeList; + + + public static WxCpTpLicenseBatchCodeInfoResp fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpTpLicenseBatchCodeInfoResp.class); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/account/WxCpTpLicenseBatchTransferResp.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/account/WxCpTpLicenseBatchTransferResp.java new file mode 100644 index 000000000..737f891e4 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/account/WxCpTpLicenseBatchTransferResp.java @@ -0,0 +1,32 @@ +package me.chanjar.weixin.cp.bean.license.account; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.bean.license.WxCpTpLicenseTransfer; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.util.List; + +/** + * 基础结果返回信息 + * 文档地址:https://developer.work.weixin.qq.com/document/path/95673 + * @author Totoro + * @date 2022/6/27 15:49 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class WxCpTpLicenseBatchTransferResp extends WxCpBaseResp { + private static final long serialVersionUID = 5443977430756597486L; + + @SerializedName("transfer_result") + private List transferResult; + + public static WxCpTpLicenseBatchTransferResp fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpTpLicenseBatchTransferResp.class); + } + + + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/account/WxCpTpLicenseCodeInfoResp.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/account/WxCpTpLicenseCodeInfoResp.java new file mode 100644 index 000000000..9c1c72402 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/account/WxCpTpLicenseCodeInfoResp.java @@ -0,0 +1,29 @@ +package me.chanjar.weixin.cp.bean.license.account; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.bean.license.WxCpTpLicenseActiveCodeInfo; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +/** + * 查询的激活码详情 + * 文档地址:https://developer.work.weixin.qq.com/document/path/95553 + * @author Totoro + * @date 2022/6/27 14:28 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class WxCpTpLicenseCodeInfoResp extends WxCpBaseResp { + private static final long serialVersionUID = 8058798194938243361L; + + @SerializedName("active_info") + private WxCpTpLicenseActiveCodeInfo activeCodeInfo; + + + public static WxCpTpLicenseCodeInfoResp fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpTpLicenseCodeInfoResp.class); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/account/WxCpTpLicenseCorpAccountListResp.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/account/WxCpTpLicenseCorpAccountListResp.java new file mode 100644 index 000000000..623a8e194 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/account/WxCpTpLicenseCorpAccountListResp.java @@ -0,0 +1,37 @@ +package me.chanjar.weixin.cp.bean.license.account; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.bean.license.WxCpTpLicenseCorpAccount; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.util.List; + +/** + * 企业的帐号列表(已激活) + * 文档地址:https://developer.work.weixin.qq.com/document/path/95544 + * @author Totoro + * @date 2022/6/27 15:15 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class WxCpTpLicenseCorpAccountListResp extends WxCpBaseResp { + private static final long serialVersionUID = -7976008813041959375L; + + @SerializedName("next_cursor") + private String nextCursor; + + @SerializedName("has_more") + private Integer hasMore; + + @SerializedName("account_list") + private List orderList; + + + public static WxCpTpLicenseCorpAccountListResp fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpTpLicenseCorpAccountListResp.class); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/order/WxCpTpLicenseCreateOrderResp.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/order/WxCpTpLicenseCreateOrderResp.java new file mode 100644 index 000000000..d5d0d14e0 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/order/WxCpTpLicenseCreateOrderResp.java @@ -0,0 +1,31 @@ +package me.chanjar.weixin.cp.bean.license.order; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +/** + * 订单创建结果 + * 文档地址:https://developer.work.weixin.qq.com/document/path/95644 + * @author Totoro + * @date 2022-6-27 11:26:36 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class WxCpTpLicenseCreateOrderResp extends WxCpBaseResp { + private static final long serialVersionUID = 6644560301282598903L; + + @SerializedName("order_id") + private String orderId; + + + public static WxCpTpLicenseCreateOrderResp fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpTpLicenseCreateOrderResp.class); + } + + + + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/order/WxCpTpLicenseNewOrderRequest.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/order/WxCpTpLicenseNewOrderRequest.java new file mode 100644 index 000000000..447fefd10 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/order/WxCpTpLicenseNewOrderRequest.java @@ -0,0 +1,60 @@ +package me.chanjar.weixin.cp.bean.license.order; +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import me.chanjar.weixin.cp.bean.license.WxCpTpLicenseAccountCount; +import me.chanjar.weixin.cp.bean.license.WxCpTpLicenseAccountDuration; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; + +/** + * 下单购买帐号 + * 文档地址:https://developer.work.weixin.qq.com/document/path/95644 + * @author Totoro + * @date 2022/6/27 10:52 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class WxCpTpLicenseNewOrderRequest implements Serializable { + private static final long serialVersionUID = 6644560301282598903L; + + /** + * 企业ID + */ + @SerializedName("corpid") + private String corpId; + + /** + * 购买者ID + */ + @SerializedName("buyer_userid") + private String buyerUserId; + + /** + * 账号个数 + */ + @SerializedName("account_count") + private WxCpTpLicenseAccountCount accountCount; + + /** + * 购买市场 + */ + @SerializedName("account_duration") + private WxCpTpLicenseAccountDuration accountDuration; + + + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + + + + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/order/WxCpTpLicenseOrderAccountListResp.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/order/WxCpTpLicenseOrderAccountListResp.java new file mode 100644 index 000000000..bab3aeab4 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/order/WxCpTpLicenseOrderAccountListResp.java @@ -0,0 +1,39 @@ +package me.chanjar.weixin.cp.bean.license.order; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.bean.license.WxCpTpLicenseAccount; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.util.List; + +/** + * 获取订单中的帐号列表 + * 文档地址:https://developer.work.weixin.qq.com/document/path/95649 + * @author Totoro + * @date 2022-6-27 14:14:40 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class WxCpTpLicenseOrderAccountListResp extends WxCpBaseResp { + private static final long serialVersionUID = 470154227651487230L; + + @SerializedName("next_cursor") + private String nextCursor; + + @SerializedName("has_more") + private Integer hasMore; + + @SerializedName("account_list") + private List accountList; + + + public static WxCpTpLicenseOrderAccountListResp fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpTpLicenseOrderAccountListResp.class); + } + + + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/order/WxCpTpLicenseOrderInfoResp.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/order/WxCpTpLicenseOrderInfoResp.java new file mode 100644 index 000000000..2d570896f --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/order/WxCpTpLicenseOrderInfoResp.java @@ -0,0 +1,30 @@ +package me.chanjar.weixin.cp.bean.license.order; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.bean.license.WxCpTpLicenseOrder; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +/** + * 订单详情结果 + * 文档:https://developer.work.weixin.qq.com/document/path/95648 + * @author Totoro + * @date 2022/06/27 11:56:03 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class WxCpTpLicenseOrderInfoResp extends WxCpBaseResp { + + private static final long serialVersionUID = 7000171280773370910L; + + private WxCpTpLicenseOrder order; + + + public static WxCpTpLicenseOrderInfoResp fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpTpLicenseOrderInfoResp.class); + } + + + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/order/WxCpTpLicenseOrderListResp.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/order/WxCpTpLicenseOrderListResp.java new file mode 100644 index 000000000..51dc7d8da --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/order/WxCpTpLicenseOrderListResp.java @@ -0,0 +1,39 @@ +package me.chanjar.weixin.cp.bean.license.order; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.bean.license.WxCpTpLicenseSimpleOrder; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.util.List; + +/** + * 获取订单列表详情 + * 文档地址:https://developer.work.weixin.qq.com/document/path/95647 + * @author Totoro + * @date 2022/6/27 11:39 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class WxCpTpLicenseOrderListResp extends WxCpBaseResp { + private static final long serialVersionUID = 1878909432164961275L; + + @SerializedName("next_cursor") + private String nextCursor; + + @SerializedName("has_more") + private Integer hasMore; + + @SerializedName("order_list") + private List orderList; + + + public static WxCpTpLicenseOrderListResp fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpTpLicenseOrderListResp.class); + } + + + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/order/WxCpTpLicenseRenewOrderJobRequest.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/order/WxCpTpLicenseRenewOrderJobRequest.java new file mode 100644 index 000000000..c50c35f77 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/order/WxCpTpLicenseRenewOrderJobRequest.java @@ -0,0 +1,49 @@ +package me.chanjar.weixin.cp.bean.license.order; +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import me.chanjar.weixin.cp.bean.license.WxCpTpLicenseBaseAccount; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 创建下单续期帐号任务 + * 文档地址:https://developer.work.weixin.qq.com/document/path/95646 + * @author Totoro + * @date 2022/6/27 11:12 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class WxCpTpLicenseRenewOrderJobRequest implements Serializable { + + private static final long serialVersionUID = 8074896339359557034L; + /** + * 对应的企业ID + */ + @SerializedName("corpid") + private String corpId; + /** + * 续费的用户UserId + */ + @SerializedName("account_list") + private List accountList; + /** + * 任务id,若不传则默认创建一个新任务。若指定第一次调用后拿到jobid,可以通过该接口将jobid关联多个userid + */ + @SerializedName("jobid") + private String jobId; + + + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/order/WxCpTpLicenseRenewOrderJobResp.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/order/WxCpTpLicenseRenewOrderJobResp.java new file mode 100644 index 000000000..4ec63ec46 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/order/WxCpTpLicenseRenewOrderJobResp.java @@ -0,0 +1,43 @@ +package me.chanjar.weixin.cp.bean.license.order; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.bean.license.WxCpTpLicenseInvalidAccount; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.util.List; + +/** + * 创建下单购买帐号任务返回结果 + * 文档地址:https://developer.work.weixin.qq.com/document/path/95646 + * @author Totoro + * @date 2022-6-27 11:15:20 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class WxCpTpLicenseRenewOrderJobResp extends WxCpBaseResp { + + private static final long serialVersionUID = -4469875729545594102L; + /** + * 任务ID + */ + @SerializedName("jobid") + private String jobId; + /** + * 有效的续费账号列表 + */ + @SerializedName("invalid_account_list") + private List invalidAccountList; + + + + public static WxCpTpLicenseRenewOrderJobResp fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpTpLicenseRenewOrderJobResp.class); + } + + + + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/order/WxCpTpLicenseRenewOrderRequest.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/order/WxCpTpLicenseRenewOrderRequest.java new file mode 100644 index 000000000..a4607f568 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/license/order/WxCpTpLicenseRenewOrderRequest.java @@ -0,0 +1,38 @@ +package me.chanjar.weixin.cp.bean.license.order; +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import me.chanjar.weixin.cp.bean.license.WxCpTpLicenseAccountDuration; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; + +/** + * 续期帐号订单 + * 文档地址:https://developer.work.weixin.qq.com/document/path/95646 + * @author Totoro + * @date 2022-6-27 11:21:51 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class WxCpTpLicenseRenewOrderRequest implements Serializable { + private static final long serialVersionUID = 8709132346969663049L; + + @SerializedName("buyer_userid") + private String buyerUserId; + @SerializedName("jobid") + private String jobId; + @SerializedName("account_duration") + private WxCpTpLicenseAccountDuration accountDuration; + + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingCreateRequest.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingCreateRequest.java index 6da6b81e5..4272a0372 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingCreateRequest.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingCreateRequest.java @@ -1,14 +1,12 @@ package me.chanjar.weixin.cp.bean.living; import com.google.gson.annotations.SerializedName; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; +import lombok.*; import lombok.experimental.Accessors; import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; import java.io.Serializable; +import java.util.List; /** * 创建预约直播请求. @@ -57,10 +55,12 @@ public class WxCpLivingCreateRequest implements Serializable { @SerializedName("activity_detail") private ActivityDetail activityDetail; + @Getter + @Setter public static class ActivityDetail implements Serializable { @SerializedName("image_list") - private String[] imageList; + private List imageList; @SerializedName("description") private String description; diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingInfo.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingInfo.java index b7010e57e..59ba35cd1 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingInfo.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingInfo.java @@ -22,7 +22,7 @@ public class WxCpLivingInfo implements Serializable { private Long livingStart; @SerializedName("living_duration") - private Long livingDurationme; + private Long livingDuration; @SerializedName("status") private Integer status; diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingResult.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingResult.java index 3312eec77..09c912ad8 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingResult.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingResult.java @@ -32,7 +32,7 @@ public static class LivingIdResult implements Serializable { private String nextCursor; @SerializedName("livingid_list") - private String[] livingidList; + private String[] livingIdList; public static LivingIdResult fromJson(String json) { return WxCpGsonBuilder.create().fromJson(json, LivingIdResult.class); diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpGroupRobotMessage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpGroupRobotMessage.java index 387b454cd..bf73d2e6e 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpGroupRobotMessage.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpGroupRobotMessage.java @@ -57,6 +57,11 @@ public class WxCpGroupRobotMessage implements Serializable { */ private List articles; + /** + * 文件id + */ + private String mediaId; + public String toJson() { JsonObject messageJson = new JsonObject(); messageJson.addProperty("msgtype", this.getMsgType()); @@ -112,6 +117,12 @@ public String toJson() { messageJson.add("news", text); break; } + case FILE: { + JsonObject file = new JsonObject(); + file.addProperty("media_id", this.getMediaId()); + messageJson.add("file", file); + break; + } default: } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpLinkedCorpMessage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpLinkedCorpMessage.java index 0e3f67087..042d955bb 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpLinkedCorpMessage.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpLinkedCorpMessage.java @@ -21,6 +21,7 @@ /** * 互联企业消息. + * https://developer.work.weixin.qq.com/document/path/90250 * * @author Binary Wang * @date 2020-08-30 diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpMessage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpMessage.java index 77bc0960a..1ce367d9f 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpMessage.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpMessage.java @@ -92,6 +92,21 @@ public class WxCpMessage implements Serializable { */ private String sourceDesc; + /** + * 来源文字的颜色,目前支持:0(默认) 灰色,1 黑色,2 红色,3 绿色 + */ + private Integer sourceDescColor; + + /** + * 更多操作界面的描述 + */ + private String actionMenuDesc; + + /** + * 操作列表,列表长度取值范围为 [1, 3] + */ + private List actionMenuActionList; + /** * 一级标题,建议不超过36个字 */ @@ -408,6 +423,8 @@ private void handleMsgType(JsonObject messageJson) { articleJson.addProperty("description", article.getDescription()); articleJson.addProperty("url", article.getUrl()); articleJson.addProperty("picurl", article.getPicUrl()); + articleJson.addProperty("appid", article.getAppid()); + articleJson.addProperty("pagepath", article.getPagepath()); articleJsonArray.add(articleJson); } newsJsonObject.add("articles", articleJsonArray); @@ -480,9 +497,22 @@ private void handleMsgType(JsonObject messageJson) { if (StringUtils.isNotBlank(this.getSourceDesc())) { source.addProperty("desc", this.getSourceDesc()); } + source.addProperty("desc_color", this.getSourceDescColor()); template.add("source", source); } + if (StringUtils.isNotBlank(this.getActionMenuDesc())) { + JsonObject action_menu = new JsonObject(); + action_menu.addProperty("desc", this.getActionMenuDesc()); + JsonArray actionList = new JsonArray(); + List actionMenuItemList = this.getActionMenuActionList(); + for (ActionMenuItem actionItemI : actionMenuItemList) { + actionList.add(actionItemI.toJson()); + } + action_menu.add("action_list", actionList); + template.add("action_menu", action_menu); + } + if (StringUtils.isNotBlank(this.getMainTitleTitle()) || StringUtils.isNotBlank(this.getMainTitleDesc())) { JsonObject mainTitle = new JsonObject(); if (StringUtils.isNotBlank(this.getMainTitleTitle())) { diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpMessageSendResult.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpMessageSendResult.java index 6b02941dd..fdb72c7a7 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpMessageSendResult.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpMessageSendResult.java @@ -47,6 +47,12 @@ public static WxCpMessageSendResult fromJson(String json) { @SerializedName("msgid") private String msgId; + /** + * 仅消息类型为“按钮交互型”,“投票选择型”和“多项选择型”的模板卡片消息返回,应用可使用response_code调用更新模版卡片消息接口,24小时内有效,且只能使用一次 + */ + @SerializedName("response_code") + private String responseCode; + public List getInvalidUserList() { return this.content2List(this.invalidUser); } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpSchoolContactMessage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpSchoolContactMessage.java new file mode 100644 index 000000000..77ba45de7 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpSchoolContactMessage.java @@ -0,0 +1,311 @@ +package me.chanjar.weixin.cp.bean.message; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; +import me.chanjar.weixin.common.api.WxConsts.SchoolContactMsgType; +import me.chanjar.weixin.common.util.json.WxGsonBuilder; +import me.chanjar.weixin.cp.bean.article.MpnewsArticle; +import me.chanjar.weixin.cp.bean.article.NewArticle; +import org.apache.commons.lang3.ArrayUtils; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import static me.chanjar.weixin.common.api.WxConsts.SchoolContactMsgType.*; + +/** + * 发送「学校通知」 + * https://developer.work.weixin.qq.com/document/path/92321 + * + * @author Wang_Wong + * @date 2022-06-29 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class WxCpSchoolContactMessage implements Serializable { + private static final long serialVersionUID = 8833792280163704238L; + + /** + * 指定发送对象,0表示发送给家长,1表示发送给学生,2表示发送给家长和学生,默认为0。 + */ + @SerializedName("recv_scope") + private Integer recvScope = 0; + + /** + * 家校通讯录家长列表,recv_scope为0或2表示发送给对应的家长,recv_scope为1忽略,(最多支持1000个) + */ + @SerializedName("to_parent_userid") + private String[] toParentUserId; + + /** + * 家校通讯录学生列表,recv_scope为0表示发送给学生的所有家长,recv_scope为1表示发送给学生,recv_scope为2表示发送给学生和学生的所有家长(最多支持1000个) + */ + @SerializedName("to_student_userid") + private String[] toStudentUserId; + + /** + * 家校通讯录部门列表,recv_scope为0表示发送给班级的所有家长,recv_scope为1表示发送给班级的所有学生,recv_scope为2表示发送给班级的所有学生和家长(最多支持100个) + */ + @SerializedName("to_party") + private String[] toParty; + + /** + * 1表示字段生效,0表示字段无效。recv_scope为0表示发送给学校的所有家长,recv_scope为1表示发送给学校的所有学生,recv_scope为2表示发送给学校的所有学生和家长,默认为0 + */ + @SerializedName("toall") + private Boolean toAll = false; + + /** + * 消息类型 + */ + @SerializedName("msgtype") + private String msgType; + + /** + * 企业应用的id,整型。可在应用的设置页面查看 + */ + @SerializedName("agentid") + private Integer agentId; + + /** + * 消息内容,最长不超过2048个字节(支持id转译) + */ + @SerializedName("content") + private String content; + + /** + * enable_id_trans + * 表示是否开启id转译,0表示否,1表示是,默认0 + */ + @SerializedName("enable_id_trans") + private Boolean enableIdTrans = false; + + /** + * enable_duplicate_check + * 表示是否开启重复消息检查,0表示否,1表示是,默认0 + */ + @SerializedName("enable_duplicate_check") + private Boolean enableDuplicateCheck = false; + + /** + * duplicate_check_interval + * 表示是否重复消息检查的时间间隔,默认1800s,最大不超过4小时 + */ + @SerializedName("duplicate_check_interval") + private Integer duplicateCheckInterval; + + /** + * 图片媒体文件id,可以调用上传临时素材接口获取 + */ + @SerializedName("media_id") + private String mediaId; + + /** + * 视频消息的标题,不超过128个字节,超过会自动截断 + */ + @SerializedName("title") + private String title; + + /** + * 视频消息的描述,不超过512个字节,超过会自动截断 + */ + @SerializedName("description") + private String description; + + /** + * 小程序消息封面的mediaid,封面图建议尺寸为520*416 + */ + @SerializedName("thumb_media_id") + private String thumbMediaId; + + /** + * 小程序appid,必须是关联到企业的小程序应用 + */ + @SerializedName("appid") + private String appId; + + /** + * 点击消息卡片后进入的小程序页面路径 + */ + @SerializedName("pagepath") + private String pagePath; + + /** + * 图文消息 + * https://developer.work.weixin.qq.com/document/path/92321#%E5%9B%BE%E6%96%87%E6%B6%88%E6%81%AF + */ + private List articles = new ArrayList<>(); + + /** + * 图文消息(mpnews) + * https://developer.work.weixin.qq.com/document/path/92321#%E5%9B%BE%E6%96%87%E6%B6%88%E6%81%AF%EF%BC%88mpnews%EF%BC%89 + *

+ * mpnews类型的图文消息,跟普通的图文消息一致,唯一的差异是图文内容存储在企业微信。 + * 多次发送mpnews,会被认为是不同的图文,阅读、点赞的统计会被分开计算。 + */ + private List mpNewsArticles = new ArrayList<>(); + + /** + *

+   * 请使用.
+   * {@link SchoolContactMsgType#TEXT}
+   * {@link SchoolContactMsgType#IMAGE}
+   * {@link SchoolContactMsgType#VOICE}
+   * {@link SchoolContactMsgType#VIDEO}
+   * {@link SchoolContactMsgType#NEWS}
+   * {@link SchoolContactMsgType#MPNEWS}
+   * {@link SchoolContactMsgType#MINIPROGRAM}
+   * 
+ * + * @param msgType 消息类型 + */ + public void setMsgType(String msgType) { + this.msgType = msgType; + } + + public String toJson() { + JsonObject messageJson = new JsonObject(); + + if (this.getRecvScope() != null) { + messageJson.addProperty("recv_scope", this.getRecvScope()); + } + + if (ArrayUtils.isNotEmpty(this.getToParentUserId())) { + messageJson.add("to_parent_userid", WxGsonBuilder.create().toJsonTree(this.getToParentUserId())); + } + + if (ArrayUtils.isNotEmpty(this.getToStudentUserId())) { + messageJson.add("to_student_userid", WxGsonBuilder.create().toJsonTree(this.getToStudentUserId())); + } + + if (ArrayUtils.isNotEmpty(this.getToParty())) { + messageJson.add("to_party", WxGsonBuilder.create().toJsonTree(this.getToParty())); + } + + if (this.getToAll() != null) { + messageJson.addProperty("toall", this.getToAll() ? 1 : 0); + } + + messageJson.addProperty("msgtype", this.getMsgType()); + + if (this.getAgentId() != null) { + messageJson.addProperty("agentid", this.getAgentId()); + } + + if (this.getEnableIdTrans() != null && this.getEnableIdTrans()) { + messageJson.addProperty("enable_id_trans", 1); + } + + if (this.getEnableDuplicateCheck() != null && this.getEnableDuplicateCheck()) { + messageJson.addProperty("enable_duplicate_check", 1); + } + + if (this.getDuplicateCheckInterval() != null) { + messageJson.addProperty("duplicate_check_interval", this.getDuplicateCheckInterval()); + } + + this.handleMsgType(messageJson); + + return messageJson.toString(); + } + + /** + * 封装消息类型 + * + * @param messageJson + */ + private void handleMsgType(JsonObject messageJson) { + switch (this.getMsgType()) { + case TEXT: { + JsonObject text = new JsonObject(); + text.addProperty("content", this.getContent()); + messageJson.add("text", text); + break; + } + case IMAGE: { + JsonObject image = new JsonObject(); + image.addProperty("media_id", this.getMediaId()); + messageJson.add("image", image); + break; + } + case FILE: { + JsonObject image = new JsonObject(); + image.addProperty("media_id", this.getMediaId()); + messageJson.add("file", image); + break; + } + case VOICE: { + JsonObject voice = new JsonObject(); + voice.addProperty("media_id", this.getMediaId()); + messageJson.add("voice", voice); + break; + } + case VIDEO: { + JsonObject video = new JsonObject(); + video.addProperty("media_id", this.getMediaId()); + video.addProperty("title", this.getTitle()); + video.addProperty("description", this.getDescription()); + messageJson.add("video", video); + break; + } + case NEWS: { + JsonObject newsJsonObject = new JsonObject(); + JsonArray articleJsonArray = new JsonArray(); + for (NewArticle article : this.getArticles()) { + JsonObject articleJson = new JsonObject(); + articleJson.addProperty("title", article.getTitle()); + articleJson.addProperty("description", article.getDescription()); + articleJson.addProperty("url", article.getUrl()); + articleJson.addProperty("picurl", article.getPicUrl()); + articleJsonArray.add(articleJson); + } + newsJsonObject.add("articles", articleJsonArray); + messageJson.add("news", newsJsonObject); + break; + } + case MPNEWS: { + JsonObject newsJsonObject = new JsonObject(); + JsonArray articleJsonArray = new JsonArray(); + for (MpnewsArticle article : this.getMpNewsArticles()) { + JsonObject articleJson = new JsonObject(); + articleJson.addProperty("title", article.getTitle()); + articleJson.addProperty("thumb_media_id", article.getThumbMediaId()); + articleJson.addProperty("author", article.getAuthor()); + articleJson.addProperty("content_source_url", article.getContentSourceUrl()); + articleJson.addProperty("content", article.getContent()); + articleJson.addProperty("digest", article.getDigest()); + articleJsonArray.add(articleJson); + } + newsJsonObject.add("articles", articleJsonArray); + messageJson.add("mpnews", newsJsonObject); + break; + } + case MINIPROGRAM: { + JsonObject miniprogram = new JsonObject(); + miniprogram.addProperty("appid", this.getAppId()); + miniprogram.addProperty("pagepath", this.getPagePath()); + miniprogram.addProperty("title", this.getTitle()); + miniprogram.addProperty("thumb_media_id", this.getThumbMediaId()); + + messageJson.add("miniprogram", miniprogram); + break; + } + default: { + // do nothing + } + + } + + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpSchoolContactMessageSendResult.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpSchoolContactMessageSendResult.java new file mode 100644 index 000000000..b65e8352d --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpSchoolContactMessageSendResult.java @@ -0,0 +1,36 @@ +package me.chanjar.weixin.cp.bean.message; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +/** + * 发送「学校通知」返回实体 + * https://developer.work.weixin.qq.com/document/path/92321 + * + * @author Wang_Wong + * @date 2022-06-29 + */ +@Data +public class WxCpSchoolContactMessageSendResult extends WxCpBaseResp { + private static final long serialVersionUID = 3990693822996824333L; + + @SerializedName("invalid_parent_userid") + private String[] invalidParentUserId; + + @SerializedName("invalid_student_userid") + private String[] invalidStudentUserId; + + @SerializedName("invalid_party") + private String[] invalidParty; + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + public static WxCpSchoolContactMessageSendResult fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpSchoolContactMessageSendResult.class); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpTpXmlMessage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpTpXmlMessage.java index 579673594..c2aef9e13 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpTpXmlMessage.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpTpXmlMessage.java @@ -16,6 +16,7 @@ import java.util.Map; /** + * sxh 修改版本,有些参数类型错误,修正版 * 回调推送的message * https://work.weixin.qq.com/api/doc#90001/90143/90612 * @@ -314,6 +315,26 @@ public class WxCpTpXmlMessage implements Serializable { @XStreamConverter(value = XStreamCDataConverter.class) private String taskId; + @XStreamAlias("PaidCorpId") + @XStreamConverter(value = XStreamCDataConverter.class) + private String paidCorpId; + + @XStreamAlias("OrderId") + @XStreamConverter(value = XStreamCDataConverter.class) + private String orderId; + + @XStreamAlias("OperatorId") + @XStreamConverter(value = XStreamCDataConverter.class) + private String operatorId; + + @XStreamAlias("OldOrderId") + @XStreamConverter(value = XStreamCDataConverter.class) + private String oldOrderId; + + @XStreamAlias("NewOrderId") + @XStreamConverter(value = XStreamCDataConverter.class) + private String newOrderId; + @Data @XStreamAlias("ContactSync") public static class ContactSync implements Serializable { @@ -363,13 +384,13 @@ public static class ApprovalInfo implements Serializable { private static final long serialVersionUID = 6031833682211475786L; @XStreamAlias("ThirdNo") - protected Long thirdNo; + protected String thirdNo; @XStreamAlias("OpenSpName") protected String openSpName; @XStreamAlias("OpenTemplateId") - protected Integer openTemplateId; + protected String openTemplateId; @XStreamAlias("OpenSpStatus") protected Integer openSpStatus; @@ -381,7 +402,7 @@ public static class ApprovalInfo implements Serializable { protected String applyUserName; @XStreamAlias("ApplyUserId") - protected Integer applyUserId; + protected String applyUserId; @XStreamAlias("ApplyUserParty") protected String applyUserParty; @@ -427,7 +448,7 @@ public static class Item implements Serializable { @XStreamAlias("ItemName") protected String itemName; @XStreamAlias("ItemUserId") - protected Integer itemUserId; + protected String itemUserId; @XStreamAlias("ItemImage") protected String itemImage; @XStreamAlias("ItemStatus") @@ -447,7 +468,7 @@ public static class NotifyNode implements Serializable { @XStreamAlias("ItemName") protected String itemName; @XStreamAlias("ItemUserId") - protected Integer itemUserId; + protected String itemUserId; @XStreamAlias("ItemImage") protected String itemImage; } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpXmlApprovalInfo.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpXmlApprovalInfo.java new file mode 100644 index 000000000..33d1375b1 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpXmlApprovalInfo.java @@ -0,0 +1,466 @@ +package me.chanjar.weixin.cp.bean.message; + +import com.thoughtworks.xstream.annotations.XStreamAlias; +import com.thoughtworks.xstream.annotations.XStreamConverter; +import com.thoughtworks.xstream.annotations.XStreamImplicit; +import lombok.Data; +import me.chanjar.weixin.common.util.xml.XStreamCDataConverter; + +import java.io.Serializable; +import java.util.List; + +/** + * 审批信息 + * + * 审批申请状态变化回调通知 + * https://developer.work.weixin.qq.com/document/path/91815 + * + * 自建应用审批状态变化通知回调 + * https://developer.work.weixin.qq.com/document/path/90269 + * + * @author Gyv12345 + */ +@XStreamAlias("ApprovalInfo") +@Data +public class WxCpXmlApprovalInfo implements Serializable { + private static final long serialVersionUID = 8136329462880646091L; + + + // 自建应用审批状态变化通知回调 + /** + * 审批单编号,由开发者在发起申请时自定义 + */ + @XStreamAlias("ThirdNo") + @XStreamConverter(value = XStreamCDataConverter.class) + private String thirdNo; + + /** + * 审批模板名称 + */ + @XStreamAlias("OpenSpName") + @XStreamConverter(value = XStreamCDataConverter.class) + private String openSpName; + + /** + * 审批模板id + */ + @XStreamAlias("OpenTemplateId") + @XStreamConverter(value = XStreamCDataConverter.class) + private String openTemplateId; + + /** + * 申请单当前审批状态:1-审批中;2-已通过;3-已驳回;4-已撤销 + */ + @XStreamAlias("OpenSpStatus") + private Integer openSpStatus; + + /** + * 提交者姓名 + */ + @XStreamAlias("ApplyUserName") + @XStreamConverter(value = XStreamCDataConverter.class) + private String applyUserName; + + /** + * 提交者userid + */ + @XStreamAlias("ApplyUserId") + @XStreamConverter(value = XStreamCDataConverter.class) + private String applyUserId; + + /** + * 提交者所在部门 + */ + @XStreamAlias("ApplyUserParty") + @XStreamConverter(value = XStreamCDataConverter.class) + private String applyUserParty; + + /** + * 提交者头像 + */ + @XStreamAlias("ApplyUserImage") + @XStreamConverter(value = XStreamCDataConverter.class) + private String applyUserImage; + + /** + * 当前审批节点:0-第一个审批节点;1-第二个审批节点…以此类推 + */ + @XStreamAlias("ApproverStep") + private Integer approverStep; + + /** + * 审批流程信息 + */ + @XStreamImplicit(itemFieldName = "ApprovalNodes") + private List approvalNodes; + + /** + * 抄送信息,可能有多个抄送人 + */ + @XStreamImplicit(itemFieldName = "NotifyNodes") + private List notifyNodes; + + /** + * 抄送人信息 + */ + @XStreamAlias("NotifyNodes") + @Data + public static class NotifyNode implements Serializable { + private static final long serialVersionUID = -979255011922209018L; + + /** + * 抄送人姓名 + */ + @XStreamAlias("ItemName") + @XStreamConverter(value = XStreamCDataConverter.class) + private String itemName; + + /** + * 抄送人userid + */ + @XStreamAlias("ItemUserid") + @XStreamConverter(value = XStreamCDataConverter.class) + private String itemUserId; + + /** + * 抄送人所在部门 + */ + @XStreamAlias("ItemParty") + @XStreamConverter(value = XStreamCDataConverter.class) + private String itemParty; + + /** + * 抄送人头像 + */ + @XStreamAlias("ItemImage") + @XStreamConverter(value = XStreamCDataConverter.class) + private String itemImage; + + } + + /** + * 审批流程信息,可以有多个审批节点 + */ + @XStreamAlias("ApprovalNodes") + @Data + public static class ApprovalNode implements Serializable { + private static final long serialVersionUID = -979255011922209018L; + + /** + * 节点审批操作状态:1-审批中;2-已同意;3-已驳回;4-已转审 + */ + @XStreamAlias("NodeStatus") + private Integer nodeStatus; + + /** + * 审批节点属性:1-或签;2-会签 + */ + @XStreamAlias("NodeAttr") + private Integer nodeAttr; + + /** + * 审批节点类型:1-固定成员;2-标签;3-上级 + */ + @XStreamAlias("NodeType") + private Integer nodeType; + + /** + * 审批节点信息,当节点为标签或上级时,一个节点可能有多个分支 + */ + @XStreamImplicit(itemFieldName = "Items") + private List items; + + } + + /** + * 审批节点分支,当节点为标签或上级时,一个节点可能有多个分支 + */ + @XStreamAlias("Items") + @Data + public static class Item implements Serializable { + private static final long serialVersionUID = -979255011922209018L; + + /** + * 分支审批人姓名 + */ + @XStreamAlias("ItemName") + @XStreamConverter(value = XStreamCDataConverter.class) + private String itemName; + + /** + * 分支审批人userid + */ + @XStreamAlias("ItemUserid") + @XStreamConverter(value = XStreamCDataConverter.class) + private String itemUserId; + + /** + * 分支审批人所在部门 + */ + @XStreamAlias("ItemParty") + @XStreamConverter(value = XStreamCDataConverter.class) + private String itemParty; + + /** + * 分支审批人头像 + */ + @XStreamAlias("ItemImage") + @XStreamConverter(value = XStreamCDataConverter.class) + private String itemImage; + + /** + * 分支审批人审批意见 + */ + @XStreamAlias("ItemSpeech") + @XStreamConverter(value = XStreamCDataConverter.class) + private String itemSpeech; + + /** + * 分支审批审批操作状态:1-审批中;2-已同意;3-已驳回;4-已转审 + */ + @XStreamAlias("ItemStatus") + private Integer itemStatus; + + /** + * 分支审批人操作时间 + */ + @XStreamAlias("ItemOpTime") + private Long itemOpTime; + + } + + + // 审批申请状态变化回调通知 + /** + * 审批编号 + */ + @XStreamAlias("SpNo") + private String spNo; + + /** + * 审批申请类型名称(审批模板名称) + */ + @XStreamAlias("SpName") + @XStreamConverter(value = XStreamCDataConverter.class) + private String spName; + + /** + * 申请单状态:1-审批中;2-已通过;3-已驳回;4-已撤销;6-通过后撤销;7-已删除;10-已支付 + */ + @XStreamAlias("SpStatus") + private Integer spStatus; + + /** + * 审批模板id。 + */ + @XStreamAlias("TemplateId") + @XStreamConverter(value = XStreamCDataConverter.class) + private String templateId; + + /** + * 审批申请提交时间,Unix时间戳 + */ + @XStreamAlias("ApplyTime") + private Long applyTime; + + /** + * 申请人信息 + */ + @XStreamAlias("Applyer") + private Applier applier; + + /** + * 审批流程信息,可能有多个审批节点。 + */ + @XStreamImplicit(itemFieldName = "SpRecord") + private List spRecords; + + /** + * 抄送信息,可能有多个抄送节点 + * 这回查字典,notifier通知人,Notifyer这不知道是什么 + */ + @XStreamImplicit(itemFieldName = "Notifyer") + private List notifier; + + /** + * 审批申请备注信息,可能有多个备注节点 + */ + @XStreamImplicit(itemFieldName = "Comments") + private List comments; + + /** + * 审批申请单变化类型 + */ + @XStreamAlias("StatuChangeEvent") + private Integer statusChangeEvent; + + /** + * 申请人信息 + */ + @XStreamAlias("Applyer") + @Data + public static class Applier implements Serializable { + private static final long serialVersionUID = -979255011922209018L; + + /** + * 申请人userid + */ + @XStreamAlias("UserId") + private String userId; + + /** + * 申请人所在部门pid + */ + @XStreamAlias("Party") + private String party; + } + + /** + * 审批流程信息 + */ + @XStreamAlias("SpRecord") + @Data + public static class SpRecord implements Serializable { + private static final long serialVersionUID = 1247535623941881764L; + + /** + * 审批节点状态:1-审批中;2-已同意;3-已驳回;4-已转审 + */ + @XStreamAlias("SpStatus") + private String spStatus; + + /** + * 节点审批方式:1-或签;2-会签 + */ + @XStreamAlias("ApproverAttr") + private String approverAttr; + + /** + * 审批节点详情。当节点为标签或上级时,一个节点可能有多个分支 + */ + @XStreamImplicit(itemFieldName = "Details") + private List details; + + } + + /** + * 审批节点详情 + */ + @XStreamAlias("Details") + @Data + public static class Detail implements Serializable { + private static final long serialVersionUID = -8446107461495047603L; + + /** + * 分支审批人 + */ + @XStreamAlias("Approver") + private Approver approver; + + /** + * 审批意见字段 + */ + @XStreamAlias("Speech") + private String speech; + + /** + * 分支审批人审批状态:1-审批中;2-已同意;3-已驳回;4-已转审 + */ + @XStreamAlias("SpStatus") + private String spStatus; + + /** + * 节点分支审批人审批操作时间,0为尚未操作 + */ + @XStreamAlias("SpTime") + private Long spTime; + + /** + * 节点分支审批人审批意见附件,赋值为media_id具体使用请参考:文档-获取临时素材 + */ + @XStreamImplicit(itemFieldName = "Attach") + private List attach; + } + + /** + * 分支审批人 + */ + @Data + @XStreamAlias("Approver") + public static class Approver implements Serializable { + private static final long serialVersionUID = 7360442444186683191L; + + /** + * 分支审批人userid + */ + @XStreamAlias("UserId") + private String userId; + } + + /** + * 抄送信息 + */ + @Data + @XStreamAlias("Notifyer") + public static class Notifier implements Serializable { + private static final long serialVersionUID = -4524071522890013920L; + + /** + * 节点抄送人userid + */ + @XStreamAlias("UserId") + private String userId; + } + + /** + * 审批申请备注信息 + */ + @Data + @XStreamAlias("Comments") + public static class Comment implements Serializable { + private static final long serialVersionUID = 6912156206252719485L; + + /** + * 备注人信息 + */ + @XStreamAlias("CommentUserInfo") + private CommentUserInfo commentUserInfo; + + /** + * 备注提交时间 + */ + @XStreamAlias("CommentTime") + private String commentTime; + + /** + * 备注文本内容 + */ + @XStreamAlias("CommentContent") + private String commentContent; + + /** + * 备注id + */ + @XStreamAlias("CommentId") + private String commentId; + + /** + * 备注意见附件,值是附件media_id + */ + @XStreamImplicit(itemFieldName="Attach") + private List attach; + } + + @Data + @XStreamAlias("CommentUserInfo") + private static class CommentUserInfo implements Serializable { + private static final long serialVersionUID = 5031739716823000947L; + + /** + * 备注人userid + */ + @XStreamAlias("UserId") + private String userId; + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpXmlMessage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpXmlMessage.java index 40d72c3a5..6a81a7b50 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpXmlMessage.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpXmlMessage.java @@ -284,6 +284,15 @@ public class WxCpXmlMessage implements Serializable { @XStreamConverter(value = XStreamCDataConverter.class) private String email; + /** + * 企业邮箱;代开发自建应用不返回该字段。 + * ISSUE#2584 + * @see Link + */ + @XStreamAlias("BizMail") + @XStreamConverter(value = XStreamCDataConverter.class) + private String bizMail; + /** * 头像url。注:如果要获取小图将url最后的”/0”改成”/100”即可. */ @@ -425,11 +434,20 @@ public class WxCpXmlMessage implements Serializable { * 1. 群发的结果. * 2. 通讯录变更事件 * 激活状态:1=已激活 2=已禁用 4=未激活 已激活代表已激活企业微信或已关注微工作台(原企业号). + * 3. 直播回调事件 + * 直播状态 ,0:预约中,1:直播中,2:已结束,4:已取消 (已过期状态目前没有回调) */ @XStreamAlias("Status") @XStreamConverter(value = XStreamCDataConverter.class) private String status; + /** + * 直播ID + */ + @XStreamAlias("LivingId") + @XStreamConverter(value = XStreamCDataConverter.class) + private String livingId; + /** * group_id下粉丝数;或者openid_list中的粉丝数. */ @@ -465,8 +483,17 @@ public class WxCpXmlMessage implements Serializable { private SendLocationInfo sendLocationInfo = new SendLocationInfo(); + /** + * 审批消息 + * + * 审批申请状态变化回调通知 + * https://developer.work.weixin.qq.com/document/path/91815 + * + * 自建应用审批状态变化通知回调 + * https://developer.work.weixin.qq.com/document/path/90269 + */ @XStreamAlias("ApprovalInfo") - private ApprovalInfo approvalInfo = new ApprovalInfo(); + private WxCpXmlApprovalInfo approvalInfo = new WxCpXmlApprovalInfo(); protected static WxCpXmlMessage fromXml(String xml) { @@ -611,246 +638,4 @@ public static class SendLocationInfo implements Serializable { } - /** - * 审批信息 - */ - @XStreamAlias("ApprovalInfo") - @Data - public static class ApprovalInfo implements Serializable { - private static final long serialVersionUID = 8136329462880646091L; - - /** - * 审批编号 - */ - @XStreamAlias("SpNo") - private String spNo; - - /** - * 审批申请类型名称(审批模板名称) - */ - @XStreamAlias("SpName") - @XStreamConverter(value = XStreamCDataConverter.class) - private String spName; - - /** - * 申请单状态:1-审批中;2-已通过;3-已驳回;4-已撤销;6-通过后撤销;7-已删除;10-已支付 - */ - @XStreamAlias("SpStatus") - private Integer spStatus; - - /** - * 审批模板id。 - */ - @XStreamAlias("TemplateId") - @XStreamConverter(value = XStreamCDataConverter.class) - private String templateId; - /** - * 审批申请提交时间,Unix时间戳 - */ - @XStreamAlias("ApplyTime") - private Long applyTime; - - /** - * 申请人信息 - */ - @XStreamAlias("Applyer") - private Applier applier; - - /** - * 审批流程信息,可能有多个审批节点。 - */ - @XStreamImplicit(itemFieldName = "SpRecord") - private List spRecords; - - /** - * 抄送信息,可能有多个抄送节点 - * 这回查字典,notifier通知人,Notifyer这不知道是什么 - */ - @XStreamImplicit(itemFieldName = "Notifyer") - private List notifier; - - /** - * 审批申请备注信息,可能有多个备注节点 - */ - @XStreamImplicit(itemFieldName = "Comments") - private List comments; - - /** - * 审批申请单变化类型 - */ - @XStreamAlias("StatuChangeEvent") - private Integer statusChangeEvent; - - /** - * 申请人信息 - */ - @XStreamAlias("Applyer") - @Data - public static class Applier implements Serializable { - private static final long serialVersionUID = -979255011922209018L; - - /** - * 申请人userid - */ - @XStreamAlias("UserId") - private String userId; - - /** - * 申请人所在部门pid - */ - @XStreamAlias("Party") - private String party; - } - - /** - * 审批流程信息 - */ - @XStreamAlias("SpRecord") - @Data - public static class SpRecord implements Serializable { - - private static final long serialVersionUID = 1247535623941881764L; - - /** - * 审批节点状态:1-审批中;2-已同意;3-已驳回;4-已转审 - */ - @XStreamAlias("SpStatus") - private String spStatus; - - /** - * 节点审批方式:1-或签;2-会签 - */ - @XStreamAlias("ApproverAttr") - private String approverAttr; - - /** - * 审批节点详情。当节点为标签或上级时,一个节点可能有多个分支 - */ - @XStreamImplicit(itemFieldName = "Details") - private List details; - - } - - /** - * 审批节点详情 - */ - @XStreamAlias("Details") - @Data - public static class Detail implements Serializable { - private static final long serialVersionUID = -8446107461495047603L; - - /** - * 分支审批人 - */ - @XStreamAlias("Approver") - private Approver approver; - - /** - * 审批意见字段 - */ - @XStreamAlias("Speech") - private String speech; - - /** - * 分支审批人审批状态:1-审批中;2-已同意;3-已驳回;4-已转审 - */ - @XStreamAlias("SpStatus") - private String spStatus; - - /** - * 节点分支审批人审批操作时间,0为尚未操作 - */ - @XStreamAlias("SpTime") - private Long spTime; - - /** - * 节点分支审批人审批意见附件,赋值为media_id具体使用请参考:文档-获取临时素材 - * TODO 居然可以返回多个,坑爹的,暂时屏蔽注解以免报错,有兴趣挑战的,尽管把代码砸过来吧! - * 请先通过allFieldsMap解析需要的参数! - */ - // @XStreamAlias("Attach") - private String attach; - } - - /** - * 分支审批人 - */ - @Data - @XStreamAlias("Approver") - public static class Approver implements Serializable { - - private static final long serialVersionUID = 7360442444186683191L; - - /** - * 分支审批人userid - */ - @XStreamAlias("UserId") - private String userId; - } - - /** - * 抄送信息 - */ - @Data - @XStreamAlias("Notifyer") - public static class Notifier implements Serializable { - - private static final long serialVersionUID = -4524071522890013920L; - - /** - * 节点抄送人userid - */ - @XStreamAlias("UserId") - private String userId; - } - - /** - * 审批申请备注信息 - */ - @Data - @XStreamAlias("Comments") - public static class Comment implements Serializable { - - private static final long serialVersionUID = 6912156206252719485L; - - /** - * 备注人信息 - */ - @XStreamAlias("CommentUserInfo") - private CommentUserInfo commentUserInfo; - - /** - * 备注提交时间 - */ - @XStreamAlias("CommentTime") - private String commentTime; - - /** - * 备注文本内容 - */ - @XStreamAlias("CommentContent") - private String commentContent; - - /** - * 备注id - */ - @XStreamAlias("CommentId") - private String commentId; - - } - - @Data - @XStreamAlias("CommentUserInfo") - private static class CommentUserInfo implements Serializable { - - private static final long serialVersionUID = 5031739716823000947L; - - /** - * 备注人userid - */ - @XStreamAlias("UserId") - private String userId; - } - } - } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/TemplateCardBuilder.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/TemplateCardBuilder.java index 09a506d8e..866b5b7a0 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/TemplateCardBuilder.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/TemplateCardBuilder.java @@ -36,6 +36,21 @@ public class TemplateCardBuilder extends BaseBuilder { */ private String sourceDesc; + /** + * 来源文字的颜色,目前支持:0(默认) 灰色,1 黑色,2 红色,3 绿色 + */ + private Integer sourceDescColor; + + /** + * 更多操作界面的描述 + */ + private String actionMenuDesc; + + /** + * 操作列表,列表长度取值范围为 [1, 3] + */ + private List actionMenuActionList; + /** * 一级标题,建议不超过36个字 */ @@ -172,6 +187,16 @@ public TemplateCardBuilder cardImageAspectRatio(Float cardImageAspectRatio) { return this; } + public TemplateCardBuilder actionMenuDesc(String actionMenuDesc) { + this.actionMenuDesc = actionMenuDesc; + return this; + } + + public TemplateCardBuilder actionMenuActionList(List actionMenuItemList) { + this.actionMenuActionList = actionMenuItemList; + return this; + } + public TemplateCardBuilder sourceIconUrl(String sourceIconUrl) { this.sourceIconUrl = sourceIconUrl; return this; @@ -182,6 +207,11 @@ public TemplateCardBuilder sourceDesc(String sourceDesc) { return this; } + public TemplateCardBuilder sourceDescColor(Integer sourceDescColor) { + this.sourceDescColor = sourceDescColor; + return this; + } + public TemplateCardBuilder mainTitleTitle(String mainTitleTitle) { this.mainTitleTitle = mainTitleTitle; return this; @@ -294,6 +324,9 @@ public WxCpMessage build() { m.setCardType(this.cardType); m.setSourceIconUrl(this.sourceIconUrl); m.setSourceDesc(this.sourceDesc); + m.setSourceDescColor(this.sourceDescColor); + m.setActionMenuDesc(this.actionMenuDesc); + m.setActionMenuActionList(this.actionMenuActionList); m.setMainTitleTitle(this.mainTitleTitle); m.setMainTitleDesc(this.mainTitleDesc); m.setCardImageUrl(this.cardImageUrl); diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/msgaudit/WxCpChatDatas.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/msgaudit/WxCpChatDatas.java index 8359bc087..212cb8b20 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/msgaudit/WxCpChatDatas.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/msgaudit/WxCpChatDatas.java @@ -12,7 +12,8 @@ /** * 聊天记录数据内容. * - * @author Wang_Wong + * @author Wang_Wong + * @date 2022-01-17 */ @Data public class WxCpChatDatas implements Serializable { @@ -24,6 +25,9 @@ public class WxCpChatDatas implements Serializable { @SerializedName("errmsg") private String errMsg; + @SerializedName("sdk") + private long sdk; + @SerializedName("chatdata") private List chatData; diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/WxCpGetApprovalData.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/WxCpGetApprovalData.java new file mode 100644 index 000000000..8385ab037 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/WxCpGetApprovalData.java @@ -0,0 +1,130 @@ +package me.chanjar.weixin.cp.bean.oa; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 获取审批数据(旧). + * + * @author Wang_Wong + */ +@Data +public class WxCpGetApprovalData extends WxCpBaseResp implements Serializable { + private static final long serialVersionUID = 7387181805254287159L; + + @SerializedName("count") + private Integer count; + + @SerializedName("total") + private Integer total; + + @SerializedName("next_spnum") + private Long nextSpNum; + + @SerializedName("data") + private List data; + + @Getter + @Setter + public static class ApprovalData implements Serializable { + private static final long serialVersionUID = -5696099236344075582L; + + @SerializedName("spname") + private String spName; + + @SerializedName("apply_name") + private String applyName; + + @SerializedName("apply_org") + private String applyOrg; + + @SerializedName("approval_name") + private List approvalName; + + @SerializedName("notify_name") + private List notifyName; + + @SerializedName("mediaids") + private List mediaIds; + + @SerializedName("sp_status") + private Integer spStatus; + + @SerializedName("sp_num") + private Long spNum; + + @SerializedName("apply_time") + private Long applyTime; + + @SerializedName("apply_user_id") + private String applyUserId; + + @SerializedName("expense") + private Expense expense; + + @SerializedName("comm") + private Comm comm; + + } + + @Getter + @Setter + public static class Expense implements Serializable { + private static final long serialVersionUID = -5696099236344075582L; + + @SerializedName("expense_type") + private Integer expenseType; + + @SerializedName("reason") + private String reason; + + @SerializedName("item") + private List item; + + } + + @Getter + @Setter + public static class Comm implements Serializable { + private static final long serialVersionUID = -5696099236344075582L; + + @SerializedName("apply_data") + private String applyData; + + } + + @Getter + @Setter + public static class Item implements Serializable { + private static final long serialVersionUID = -5696099236344075582L; + + @SerializedName("expenseitem_type") + private Integer expenseItemType; + + @SerializedName("time") + private Long time; + + @SerializedName("sums") + private Integer sums; + + @SerializedName("reason") + private String reason; + + } + + public static WxCpGetApprovalData fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpGetApprovalData.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/WxCpRecordSpStatus.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/WxCpRecordSpStatus.java index 055871e23..d6be02d40 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/WxCpRecordSpStatus.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/WxCpRecordSpStatus.java @@ -39,7 +39,17 @@ public enum WxCpRecordSpStatus { * 已退回 */ @SerializedName("11") - WITHDRAWN(11); + WITHDRAWN(11), + /** + * 12-已加签 + */ + @SerializedName("12") + SIGNED(12), + /** + * 13-已同意并加签 + */ + @SerializedName("13") + PASSEDANDSIGNED(13); private final Integer status; diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/WxCpUserVacationQuota.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/WxCpUserVacationQuota.java new file mode 100644 index 000000000..159fcd694 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/WxCpUserVacationQuota.java @@ -0,0 +1,55 @@ +package me.chanjar.weixin.cp.bean.oa; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 成员假期余额信息. + * + * @author Wang_Wong + */ +@Data +public class WxCpUserVacationQuota extends WxCpBaseResp implements Serializable { + private static final long serialVersionUID = 7387181805254287157L; + + @SerializedName("lists") + private List lists; + + @Getter + @Setter + public static class VacationQuota implements Serializable { + private static final long serialVersionUID = -5696099236344075582L; + + @SerializedName("id") + private Integer id; + + @SerializedName("assignduration") + private Integer assignDuration; + + @SerializedName("usedduration") + private Integer usedDuration; + + @SerializedName("leftduration") + private Integer leftDuration; + + @SerializedName("vacationname") + private String vacationName; + + } + + public static WxCpUserVacationQuota fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpUserVacationQuota.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/applydata/ContentValue.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/applydata/ContentValue.java index 6ae69c189..1c97ce90e 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/applydata/ContentValue.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/applydata/ContentValue.java @@ -42,6 +42,12 @@ public class ContentValue implements Serializable { private Vacation vacation; + @SerializedName("date_range") + private Attendance.DataRange dateRange; + + @SerializedName("punch_correction") + private PunchCorrection punchCorrection; + @Data public static class Date implements Serializable { private static final long serialVersionUID = -6181554080062231138L; @@ -166,4 +172,11 @@ public static class TemplateName implements Serializable { private String lang; } + @Data + public static class PunchCorrection implements Serializable { + private static final long serialVersionUID = 2120523160034749170L; + private String state; + private Long time; + } + } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/meetingroom/WxCpOaMeetingRoom.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/meetingroom/WxCpOaMeetingRoom.java new file mode 100644 index 000000000..6333a4eef --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/meetingroom/WxCpOaMeetingRoom.java @@ -0,0 +1,94 @@ +package me.chanjar.weixin.cp.bean.oa.meetingroom; + + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; +import me.chanjar.weixin.common.bean.ToJson; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * @author fcat + * @version 1.0 + * Create by 2022/8/12 22:46 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class WxCpOaMeetingRoom implements Serializable, ToJson { + private static final long serialVersionUID = 2825289798463742532L; + /** + * 会议室Id + */ + @SerializedName("meetingroom_id") + private Integer meetingroomId; + /** + * 会议室名称,最多30个字符 + */ + @SerializedName("name") + private String name; + /** + * 会议室所能容纳的人数 + */ + @SerializedName("capacity") + private Integer capacity; + /** + * 会议室所在城市 + */ + @SerializedName("city") + private String city; + /** + * 会议室所在楼宇 + */ + @SerializedName("building") + private String building; + /** + * 会议室所在楼层 + */ + @SerializedName("floor") + private String floor; + /** + * 会议室支持的设备列表,参数详细1电视2电话3投影4白板5视频 + */ + @SerializedName("equipment") + private List equipment; + /** + * 会议室所在建筑经纬度 + */ + @SerializedName("coordinate") + private Coordinate coordinate; + /** + * 会议室是否需要预定 + */ + @SerializedName("need_approval") + private Integer needApproval; + + @Override + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + @Data + @AllArgsConstructor + public static class Coordinate implements Serializable { + private static final long serialVersionUID = 6626968559923978694L; + /** + * 纬度 + */ + @SerializedName("latitude") + private String latitude; + /** + * 经度 + */ + @SerializedName("longitude") + private String longitude; + } +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileAclAddRequest.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileAclAddRequest.java new file mode 100644 index 000000000..9320cf3c2 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileAclAddRequest.java @@ -0,0 +1,66 @@ +package me.chanjar.weixin.cp.bean.oa.wedrive; + +import com.google.gson.annotations.SerializedName; +import lombok.*; +import lombok.experimental.Accessors; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 新增指定人请求参数. + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class WxCpFileAclAddRequest implements Serializable { + private static final long serialVersionUID = -4960239393895754138L; + + @SerializedName("userid") + private String userId; + + @SerializedName("fileid") + private String fileId; + + @SerializedName("auth_info") + private List authInfo; + + @Getter + @Setter + public static class AuthInfo implements Serializable { + private static final long serialVersionUID = -4960239393895754598L; + + @SerializedName("type") + private Integer type; + + @SerializedName("departmentid") + private Integer departmentId; + + @SerializedName("auth") + private Integer auth; + + @SerializedName("userid") + private String userId; + + public static AuthInfo fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, AuthInfo.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + public static WxCpFileAclAddRequest fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpFileAclAddRequest.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileAclDelRequest.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileAclDelRequest.java new file mode 100644 index 000000000..a86754a1d --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileAclDelRequest.java @@ -0,0 +1,63 @@ +package me.chanjar.weixin.cp.bean.oa.wedrive; + +import com.google.gson.annotations.SerializedName; +import lombok.*; +import lombok.experimental.Accessors; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 删除指定人请求参数. + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class WxCpFileAclDelRequest implements Serializable { + private static final long serialVersionUID = -4960239393895754138L; + + @SerializedName("userid") + private String userId; + + @SerializedName("fileid") + private String fileId; + + @SerializedName("auth_info") + private List authInfo; + + @Getter + @Setter + public static class AuthInfo implements Serializable { + private static final long serialVersionUID = -4960239393895754598L; + + @SerializedName("type") + private Integer type; + + @SerializedName("departmentid") + private Integer departmentId; + + @SerializedName("userid") + private String userId; + + public static AuthInfo fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, AuthInfo.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + public static WxCpFileAclDelRequest fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpFileAclDelRequest.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileCreate.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileCreate.java new file mode 100644 index 000000000..6d7ba3e6f --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileCreate.java @@ -0,0 +1,33 @@ +package me.chanjar.weixin.cp.bean.oa.wedrive; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; + +/** + * 新建文件/微文档 返回信息. + * + * @author Wang_Wong + */ +@Data +public class WxCpFileCreate extends WxCpBaseResp implements Serializable { + private static final long serialVersionUID = -5028321625142879581L; + + @SerializedName("fileid") + private String fileId; + + @SerializedName("url") + private String url; + + public static WxCpFileCreate fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpFileCreate.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileDeleteRequest.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileDeleteRequest.java new file mode 100644 index 000000000..65e19c8a1 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileDeleteRequest.java @@ -0,0 +1,39 @@ +package me.chanjar.weixin.cp.bean.oa.wedrive; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 删除文件请求. + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class WxCpFileDeleteRequest implements Serializable { + private static final long serialVersionUID = -4960239393895754138L; + + @SerializedName("userid") + private String userId; + + @SerializedName("fileid") + private List fileId; + + public static WxCpFileDeleteRequest fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpFileDeleteRequest.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileDownload.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileDownload.java new file mode 100644 index 000000000..638d26e48 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileDownload.java @@ -0,0 +1,36 @@ +package me.chanjar.weixin.cp.bean.oa.wedrive; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; + +/** + * 下载文件返回信息. + * + * @author Wang_Wong + */ +@Data +public class WxCpFileDownload extends WxCpBaseResp implements Serializable { + private static final long serialVersionUID = -5028321625142879581L; + + @SerializedName("download_url") + private String downloadUrl; + + @SerializedName("cookie_name") + private String cookieName; + + @SerializedName("cookie_value") + private String cookieValue; + + public static WxCpFileDownload fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpFileDownload.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileInfo.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileInfo.java new file mode 100644 index 000000000..222105379 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileInfo.java @@ -0,0 +1,89 @@ +package me.chanjar.weixin.cp.bean.oa.wedrive; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; + +/** + * 文件信息. + * + * @author Wang_Wong + */ +@Data +public class WxCpFileInfo extends WxCpBaseResp implements Serializable { + private static final long serialVersionUID = -5028321625142879581L; + + @SerializedName("file_info") + private FileInfo fileInfo; + + @Getter + @Setter + public static class FileInfo implements Serializable { + private static final long serialVersionUID = -4960239393895754598L; + + @SerializedName("fileid") + private String fileId; + + @SerializedName("file_name") + private String fileName; + + @SerializedName("spaceid") + private String spaceId; + + @SerializedName("fatherid") + private String fatherId; + + @SerializedName("file_size") + private Long fileSize; + + @SerializedName("ctime") + private Long cTime; + + @SerializedName("mtime") + private Long mTime; + + @SerializedName("file_type") + private Integer fileType; + + @SerializedName("file_status") + private Integer fileStatus; + + @SerializedName("create_userid") + private String createUserId; + + @SerializedName("update_userid") + private String updateUserId; + + @SerializedName("sha") + private String sha; + + @SerializedName("md5") + private String md5; + + @SerializedName("url") + private String url; + + public static FileInfo fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, FileInfo.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + public static WxCpFileInfo fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpFileInfo.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileList.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileList.java new file mode 100644 index 000000000..b217afdb8 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileList.java @@ -0,0 +1,114 @@ +package me.chanjar.weixin.cp.bean.oa.wedrive; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 获取邀请链接. + * + * @author Wang_Wong + */ +@Data +public class WxCpFileList extends WxCpBaseResp implements Serializable { + private static final long serialVersionUID = -5028321625142879581L; + + @SerializedName("has_more") + private Boolean hasMore; + + @SerializedName("next_start") + private Integer nextStart; + + @SerializedName("file_list") + private FileList fileList; + + @Getter + @Setter + public static class FileList implements Serializable { + private static final long serialVersionUID = -4960239393895754598L; + + @SerializedName("item") + private List item; + + public static FileList fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, FileList.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + @Getter + @Setter + public static class Item implements Serializable { + private static final long serialVersionUID = -4960239393895754598L; + + @SerializedName("fileid") + private String fileId; + + @SerializedName("file_name") + private String fileName; + + @SerializedName("spaceid") + private String spaceId; + + @SerializedName("fatherid") + private String fatherId; + + @SerializedName("file_size") + private Long fileSize; + + @SerializedName("ctime") + private Long cTime; + + @SerializedName("mtime") + private Long mTime; + + @SerializedName("file_type") + private Integer fileType; + + @SerializedName("file_status") + private Integer fileStatus; + + @SerializedName("create_userid") + private String createUserId; + + @SerializedName("update_userid") + private String updateUserId; + + @SerializedName("sha") + private String sha; + + @SerializedName("url") + private String url; + + @SerializedName("md5") + private String md5; + + public static Item fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, Item.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + public static WxCpFileList fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpFileList.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileListRequest.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileListRequest.java new file mode 100644 index 000000000..361a2d4be --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileListRequest.java @@ -0,0 +1,50 @@ +package me.chanjar.weixin.cp.bean.oa.wedrive; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; + +/** + * 获取文件列表请求. + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class WxCpFileListRequest implements Serializable { + private static final long serialVersionUID = -4960239393895754138L; + + @SerializedName("userid") + private String userId; + + @SerializedName("spaceid") + private String spaceId; + + @SerializedName("fatherid") + private String fatherId; + + @SerializedName("sort_type") + private Integer sortType; + + @SerializedName("start") + private Integer start; + + @SerializedName("limit") + private Integer limit; + + public static WxCpFileListRequest fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpFileListRequest.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileMove.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileMove.java new file mode 100644 index 000000000..f9d232df2 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileMove.java @@ -0,0 +1,105 @@ +package me.chanjar.weixin.cp.bean.oa.wedrive; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 移动文件返回信息. + * + * @author Wang_Wong + */ +@Data +public class WxCpFileMove extends WxCpBaseResp implements Serializable { + private static final long serialVersionUID = -5028321625142879581L; + + @SerializedName("file_list") + private FileList fileList; + + @Getter + @Setter + public static class FileList implements Serializable { + private static final long serialVersionUID = -4960239393895754598L; + + @SerializedName("item") + private List item; + + public static FileList fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, FileList.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + @Getter + @Setter + public static class Item implements Serializable { + private static final long serialVersionUID = -4960239393895754598L; + + @SerializedName("fileid") + private String fileId; + + @SerializedName("file_name") + private String fileName; + + @SerializedName("spaceid") + private String spaceId; + + @SerializedName("fatherid") + private String fatherId; + + @SerializedName("file_size") + private Long fileSize; + + @SerializedName("ctime") + private Long cTime; + + @SerializedName("mtime") + private Long mTime; + + @SerializedName("file_type") + private Integer fileType; + + @SerializedName("file_status") + private Integer fileStatus; + + @SerializedName("create_userid") + private String createUserId; + + @SerializedName("update_userid") + private String updateUserId; + + @SerializedName("sha") + private String sha; + + @SerializedName("md5") + private String md5; + + public static Item fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, Item.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + public static WxCpFileMove fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpFileMove.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileMoveRequest.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileMoveRequest.java new file mode 100644 index 000000000..8f8a178aa --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileMoveRequest.java @@ -0,0 +1,58 @@ +package me.chanjar.weixin.cp.bean.oa.wedrive; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; + +/** + * 移动文件请求. + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class WxCpFileMoveRequest implements Serializable { + private static final long serialVersionUID = -4960239393895754138L; + + /** + * 操作者userid + */ + @SerializedName("userid") + private String userId; + + /** + * 如果移动到的目标目录与需要移动的文件重名时,是否覆盖。 + * true:重名文件覆盖 + * false:重名文件进行冲突重命名处理(移动后文件名格式如xxx(1).txt xxx(1).doc等) + */ + @SerializedName("replace") + private Boolean replace; + + /** + * 当前目录的fileid,根目录时为空间spaceid + */ + @SerializedName("fatherid") + private String fatherId; + + /** + * 文件fileid + */ + @SerializedName("fileid") + private String[] fileId; + + public static WxCpFileMoveRequest fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpFileMoveRequest.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileRename.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileRename.java new file mode 100644 index 000000000..26fe21b19 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileRename.java @@ -0,0 +1,89 @@ +package me.chanjar.weixin.cp.bean.oa.wedrive; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; + +/** + * 下载文件返回信息. + * + * @author Wang_Wong + */ +@Data +public class WxCpFileRename extends WxCpBaseResp implements Serializable { + private static final long serialVersionUID = -5028321625142879581L; + + @SerializedName("file") + private File file; + + @Getter + @Setter + public static class File implements Serializable { + private static final long serialVersionUID = -4960239393895754598L; + + @SerializedName("fileid") + private String fileId; + + @SerializedName("file_name") + private String fileName; + + @SerializedName("spaceid") + private String spaceId; + + @SerializedName("fatherid") + private String fatherId; + + @SerializedName("file_size") + private Long fileSize; + + @SerializedName("ctime") + private Long cTime; + + @SerializedName("mtime") + private Long mTime; + + @SerializedName("file_type") + private Integer fileType; + + @SerializedName("file_status") + private Integer fileStatus; + + @SerializedName("create_userid") + private String createUserId; + + @SerializedName("update_userid") + private String updateUserId; + + @SerializedName("sha") + private String sha; + + @SerializedName("url") + private String url; + + @SerializedName("md5") + private String md5; + + public static File fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, File.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + public static WxCpFileRename fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpFileRename.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileShare.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileShare.java new file mode 100644 index 000000000..e3159e0e3 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileShare.java @@ -0,0 +1,30 @@ +package me.chanjar.weixin.cp.bean.oa.wedrive; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; + +/** + * 获取分享链接返回信息. + * + * @author Wang_Wong + */ +@Data +public class WxCpFileShare extends WxCpBaseResp implements Serializable { + private static final long serialVersionUID = -5028321625142879581L; + + @SerializedName("share_url") + private String shareUrl; + + public static WxCpFileShare fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpFileShare.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileUpload.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileUpload.java new file mode 100644 index 000000000..96617dd34 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileUpload.java @@ -0,0 +1,30 @@ +package me.chanjar.weixin.cp.bean.oa.wedrive; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; + +/** + * 上传文件返回信息. + * + * @author Wang_Wong + */ +@Data +public class WxCpFileUpload extends WxCpBaseResp implements Serializable { + private static final long serialVersionUID = -5028321625142879581L; + + @SerializedName("fileid") + private String fileId; + + public static WxCpFileUpload fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpFileUpload.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileUploadRequest.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileUploadRequest.java new file mode 100644 index 000000000..9d2aa7c3f --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpFileUploadRequest.java @@ -0,0 +1,47 @@ +package me.chanjar.weixin.cp.bean.oa.wedrive; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; + +/** + * 上传文件请求. + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class WxCpFileUploadRequest implements Serializable { + private static final long serialVersionUID = -4960239393895754138L; + + @SerializedName("userid") + private String userId; + + @SerializedName("spaceid") + private String spaceId; + + @SerializedName("fatherid") + private String fatherId; + + @SerializedName("file_name") + private String fileName; + + @SerializedName("file_base64_content") + private String fileBase64Content; + + public static WxCpFileUploadRequest fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpFileUploadRequest.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpSpaceAclAddRequest.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpSpaceAclAddRequest.java new file mode 100644 index 000000000..94d65b43f --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpSpaceAclAddRequest.java @@ -0,0 +1,66 @@ +package me.chanjar.weixin.cp.bean.oa.wedrive; + +import com.google.gson.annotations.SerializedName; +import lombok.*; +import lombok.experimental.Accessors; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 添加成员/部门请求. + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class WxCpSpaceAclAddRequest implements Serializable { + private static final long serialVersionUID = -4960239393895754138L; + + @SerializedName("userid") + private String userId; + + @SerializedName("spaceid") + private String spaceId; + + @SerializedName("auth_info") + private List authInfo; + + @Getter + @Setter + public static class AuthInfo implements Serializable { + private static final long serialVersionUID = -4960239393895754598L; + + @SerializedName("type") + private Integer type; + + @SerializedName("departmentid") + private Integer departmentId; + + @SerializedName("auth") + private Integer auth; + + @SerializedName("userid") + private String userId; + + public static AuthInfo fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, AuthInfo.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + public static WxCpSpaceAclAddRequest fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpSpaceAclAddRequest.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpSpaceAclDelRequest.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpSpaceAclDelRequest.java new file mode 100644 index 000000000..272d9a57b --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpSpaceAclDelRequest.java @@ -0,0 +1,63 @@ +package me.chanjar.weixin.cp.bean.oa.wedrive; + +import com.google.gson.annotations.SerializedName; +import lombok.*; +import lombok.experimental.Accessors; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 移除成员/部门请求. + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class WxCpSpaceAclDelRequest implements Serializable { + private static final long serialVersionUID = -4960239393895754138L; + + @SerializedName("userid") + private String userId; + + @SerializedName("spaceid") + private String spaceId; + + @SerializedName("auth_info") + private List authInfo; + + @Getter + @Setter + public static class AuthInfo implements Serializable { + private static final long serialVersionUID = -4960239393895754598L; + + @SerializedName("type") + private Integer type; + + @SerializedName("departmentid") + private Integer departmentId; + + @SerializedName("userid") + private String userId; + + public static AuthInfo fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, AuthInfo.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + public static WxCpSpaceAclDelRequest fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpSpaceAclDelRequest.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpSpaceCreateData.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpSpaceCreateData.java new file mode 100644 index 000000000..121745204 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpSpaceCreateData.java @@ -0,0 +1,30 @@ +package me.chanjar.weixin.cp.bean.oa.wedrive; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; + +/** + * 新建空间信息. + * + * @author Wang_Wong + */ +@Data +public class WxCpSpaceCreateData extends WxCpBaseResp implements Serializable { + private static final long serialVersionUID = -5028321625142879581L; + + @SerializedName("spaceid") + private String spaceId; + + public static WxCpSpaceCreateData fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpSpaceCreateData.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpSpaceCreateRequest.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpSpaceCreateRequest.java new file mode 100644 index 000000000..3b9319e43 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpSpaceCreateRequest.java @@ -0,0 +1,66 @@ +package me.chanjar.weixin.cp.bean.oa.wedrive; + +import com.google.gson.annotations.SerializedName; +import lombok.*; +import lombok.experimental.Accessors; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 新建空间请求. + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class WxCpSpaceCreateRequest implements Serializable { + private static final long serialVersionUID = -4960239393895754138L; + + @SerializedName("userid") + private String userId; + + @SerializedName("space_name") + private String spaceName; + + @SerializedName("auth_info") + private List authInfo; + + @Getter + @Setter + public static class AuthInfo implements Serializable { + private static final long serialVersionUID = -4960239393895754598L; + + @SerializedName("type") + private Integer type; + + @SerializedName("departmentid") + private Integer departmentId; + + @SerializedName("auth") + private Integer auth; + + @SerializedName("userid") + private String userId; + + public static AuthInfo fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, AuthInfo.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + public static WxCpSpaceCreateRequest fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpSpaceCreateRequest.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpSpaceInfo.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpSpaceInfo.java new file mode 100644 index 000000000..821b7ef5e --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpSpaceInfo.java @@ -0,0 +1,105 @@ +package me.chanjar.weixin.cp.bean.oa.wedrive; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 获取空间信息. + * + * @author Wang_Wong + */ +@Data +public class WxCpSpaceInfo extends WxCpBaseResp implements Serializable { + private static final long serialVersionUID = -5028321625142879581L; + + @SerializedName("space_info") + private SpaceInfo spaceInfo; + + @Getter + @Setter + public static class SpaceInfo implements Serializable { + private static final long serialVersionUID = -4960239393895754598L; + + @SerializedName("spaceid") + private String spaceId; + + @SerializedName("space_name") + private String spaceName; + + @SerializedName("auth_list") + private AuthList authList; + + public static SpaceInfo fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, SpaceInfo.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + @Getter + @Setter + public static class AuthList implements Serializable { + private static final long serialVersionUID = -4960239393895754598L; + + @SerializedName("auth_info") + private List authInfo; + + @SerializedName("quit_userid") + private List quitUserId; + + public static AuthList fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, AuthList.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + @Getter + @Setter + public static class AuthInfo implements Serializable { + private static final long serialVersionUID = -4960239393895754598L; + + @SerializedName("type") + private Integer type; + + @SerializedName("departmentid") + private Integer departmentId; + + @SerializedName("auth") + private Integer auth; + + @SerializedName("userid") + private String userId; + + public static AuthInfo fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, AuthInfo.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + public static WxCpSpaceInfo fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpSpaceInfo.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpSpaceRenameRequest.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpSpaceRenameRequest.java new file mode 100644 index 000000000..f7f313326 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpSpaceRenameRequest.java @@ -0,0 +1,41 @@ +package me.chanjar.weixin.cp.bean.oa.wedrive; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; + +/** + * 重命名空间请求. + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class WxCpSpaceRenameRequest implements Serializable { + private static final long serialVersionUID = -4960239393895754138L; + + @SerializedName("userid") + private String userId; + + @SerializedName("spaceid") + private String spaceId; + + @SerializedName("space_name") + private String spaceName; + + public static WxCpSpaceRenameRequest fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpSpaceRenameRequest.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpSpaceSettingRequest.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpSpaceSettingRequest.java new file mode 100644 index 000000000..9239fb73f --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpSpaceSettingRequest.java @@ -0,0 +1,53 @@ +package me.chanjar.weixin.cp.bean.oa.wedrive; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; + +/** + * 权限管理请求. + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class WxCpSpaceSettingRequest implements Serializable { + private static final long serialVersionUID = -4960239393895754138L; + + @SerializedName("userid") + private String userId; + + @SerializedName("spaceid") + private String spaceId; + + @SerializedName("enable_watermark") + private Boolean enableWatermark; + + @SerializedName("add_member_only_admin") + private Boolean addMemberOnlyAdmin; + + @SerializedName("enable_share_url") + private Boolean enableShareUrl; + + @SerializedName("share_url_no_approve") + private Boolean shareUrlNoApprove; + + @SerializedName("share_url_no_approve_default_auth") + private Integer shareUrlNoApproveDefaultAuth; + + public static WxCpSpaceSettingRequest fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpSpaceSettingRequest.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpSpaceShare.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpSpaceShare.java new file mode 100644 index 000000000..929073912 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/wedrive/WxCpSpaceShare.java @@ -0,0 +1,30 @@ +package me.chanjar.weixin.cp.bean.oa.wedrive; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; + +/** + * 获取邀请链接. + * + * @author Wang_Wong + */ +@Data +public class WxCpSpaceShare extends WxCpBaseResp implements Serializable { + private static final long serialVersionUID = -5028321625142879581L; + + @SerializedName("space_share_url") + private String spaceShareUrl; + + public static WxCpSpaceShare fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpSpaceShare.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/order/WxCpTpOrderDetails.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/order/WxCpTpOrderDetails.java new file mode 100644 index 000000000..3b468384b --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/order/WxCpTpOrderDetails.java @@ -0,0 +1,210 @@ +package me.chanjar.weixin.cp.bean.order; + +import com.google.gson.annotations.SerializedName; +import lombok.Getter; +import lombok.Setter; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +/** + * 应用版本付费订单详情 + * + * @author leiguoqing + * @date 2022年4月24日 + */ +@Getter +@Setter +public class WxCpTpOrderDetails extends WxCpBaseResp { + + /** + * The constant serialVersionUID. + */ + private static final long serialVersionUID = -5028321625140879571L; + + /** + * 订单号 + */ + @SerializedName("orderid") + private String orderId; + + /** + * 订单状态。0-未支付,1-已支付,2-已关闭, 3-未支付且已过期, 4-申请退款中, 5-申请退款成功, 6-退款被拒绝 + */ + @SerializedName("order_status") + private Integer orderStatus; + + /** + * 订单类型。0-普通订单,1-扩容订单,2-续期,3-版本变更 + */ + @SerializedName("order_type") + private Integer orderType; + + /** + * 客户企业的corpid + */ + @SerializedName("paid_corpid") + private String paidCorpId; + + /** + * 下单操作人员userid。如果是服务商代下单,没有该字段。 + */ + @SerializedName("operator_id") + private String operatorId; + + + /** + * 应用id + */ + @SerializedName("suiteid") + private String suiteId; + + + /** + * 应用id。(仅旧套件有该字段) + */ + @SerializedName("appid") + private String appId; + + + /** + * 购买版本ID + */ + @SerializedName("edition_id") + private String editionId; + + + /** + * 购买版本名字 + */ + @SerializedName("edition_name") + private String editionName; + + + /** + * 实付款金额,单位分 + */ + @SerializedName("price") + private Long price; + + + /** + * 购买的人数 + */ + @SerializedName("user_count") + private Integer userCount; + + + /** + * 购买的时间,单位天 + */ + @SerializedName("order_period") + private Integer orderPeriod; + + /** + * 下单时间,秒级时间戳 + */ + @SerializedName("order_time") + private Long orderTime; + + /** + * 付款时间,秒级时间戳 + */ + @SerializedName("paid_time") + private Long paidTime; + + + /** + * 购买生效期的开始时间,秒级时间戳 + */ + @SerializedName("begin_time") + private Long beginTime; + + + /** + * 购买生效期的结束时间,秒级时间戳 + */ + @SerializedName("end_time") + private Long endTime; + + /** + * 下单来源。0-客户下单;1-服务商代下单;2-代理商代下单 + */ + @SerializedName("order_from") + private Integer orderFrom; + + + /** + * 下单方corpid + */ + @SerializedName("operator_corpid") + private String operatorCorpId; + + /** + * 服务商分成金额,单位分 + */ + @SerializedName("service_share_amount") + private Long serviceShareAmount; + + + /** + * 平台分成金额,单位分 + */ + @SerializedName("platform_share_amount") + private Long platformShareAmount; + + + /** + * 代理商分成金额,单位分 + */ + @SerializedName("dealer_share_amount") + private Long dealerShareAmount; + + + /** + * 渠道商信息(仅当有渠道商报备后才会有此字段) + */ + @SerializedName("dealer_corp_info") + private DealerCorpInfo dealerCorpInfo; + + + /** + * 渠道商信息(仅当有渠道商报备后才会有此字段) + */ + @Getter + @Setter + public static class DealerCorpInfo { + /** + * 代理商corpid + */ + @SerializedName("corpid") + private String corpId; + + + /** + * 代理商名 + */ + @SerializedName("corp_name") + private String corpName; + } + + /** + * From json wx cp tp order details. + * + * @param json the json + * @return the wx cp tp order details + */ + public static WxCpTpOrderDetails fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpTpOrderDetails.class); + } + + /** + * To json string. + * + * @return the string + */ + @Override + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/order/WxCpTpOrderListGetResult.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/order/WxCpTpOrderListGetResult.java new file mode 100644 index 000000000..341ba9bc9 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/order/WxCpTpOrderListGetResult.java @@ -0,0 +1,53 @@ +package me.chanjar.weixin.cp.bean.order; + +import com.google.gson.annotations.SerializedName; +import lombok.Getter; +import lombok.Setter; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.util.List; + +/** + * 应用版本付费订单列表 + * + * @author leiguoqing + * @date 2022年4月24日 + */ +@Getter +@Setter +public class WxCpTpOrderListGetResult extends WxCpBaseResp { + + /** + * The constant serialVersionUID. + */ + private static final long serialVersionUID = -5028321625140879571L; + + /** + * 订单列表 + */ + @SerializedName("order_list") + private List orderList; + + + /** + * From json wx cp tp order list get result. + * + * @param json the json + * @return the wx cp tp order list get result + */ + public static WxCpTpOrderListGetResult fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpTpOrderListGetResult.class); + } + + /** + * To json string. + * + * @return the string + */ + @Override + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/WxCpCustomizeHealthInfo.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/WxCpCustomizeHealthInfo.java new file mode 100644 index 000000000..a28c3fa35 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/WxCpCustomizeHealthInfo.java @@ -0,0 +1,150 @@ +package me.chanjar.weixin.cp.bean.school; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 获取健康信息. + * + * @author Wang_Wong + */ +@Data +public class WxCpCustomizeHealthInfo extends WxCpBaseResp implements Serializable { + private static final long serialVersionUID = -5028321625142879581L; + + @SerializedName("health_infos") + private List healthInfos; + + @SerializedName("template_id") + private String templateId; + + @SerializedName("next_key") + private String nextKey; + + @SerializedName("ending") + private Integer ending; + + @Getter + @Setter + public static class HealthInfo implements Serializable { + private static final long serialVersionUID = -5696099236344075582L; + + @SerializedName("userid") + private String userId; + + @SerializedName("health_qrcode_status") + private Integer healthQrCodeStatus; + + @SerializedName("self_submit") + private Integer selfSubmit; + + @SerializedName("report_values") + private List reportValues; + + @SerializedName("question_templates") + private List questionTemplates; + + public static HealthInfo fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, HealthInfo.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + @Getter + @Setter + public static class ReportValue implements Serializable { + private static final long serialVersionUID = -5696099236344075582L; + + @SerializedName("question_id") + private Integer questionId; + + @SerializedName("single_chose") + private Integer singleChose; + + @SerializedName("text") + private String text; + + public static ReportValue fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, ReportValue.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + @Getter + @Setter + public static class QuestionTemplate implements Serializable { + private static final long serialVersionUID = -5696099236344075582L; + + @SerializedName("question_id") + private Integer questionId; + + @SerializedName("question_type") + private Integer questionType; + + @SerializedName("title") + private String title; + + @SerializedName("is_must_fill") + private Integer isMustFill; + + @SerializedName("is_not_display") + private Integer isNotDisplay; + + @SerializedName("option_list") + private List optionList; + + public static QuestionTemplate fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, QuestionTemplate.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + @Getter + @Setter + public static class OptionList implements Serializable { + private static final long serialVersionUID = -5696099236344075582L; + + @SerializedName("option_id") + private Integer optionId; + + @SerializedName("option_text") + private String optionText; + + public static OptionList fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, OptionList.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + public static WxCpCustomizeHealthInfo fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpCustomizeHealthInfo.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/WxCpPaymentResult.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/WxCpPaymentResult.java new file mode 100644 index 000000000..e707ba918 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/WxCpPaymentResult.java @@ -0,0 +1,65 @@ +package me.chanjar.weixin.cp.bean.school; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 获取学生付款结果. + * + * @author Wang_Wong + */ +@Data +public class WxCpPaymentResult extends WxCpBaseResp implements Serializable { + private static final long serialVersionUID = -5028321625142879581L; + + @SerializedName("project_name") + private String projectName; + + @SerializedName("amount") + private Integer amount; + + @SerializedName("payment_result") + private List paymentResult; + + @Setter + @Getter + public static class PaymentResult{ + + @SerializedName("student_userid") + private String studentUserId; + + @SerializedName("trade_no") + private String tradeNo; + + @SerializedName("payer_parent_userid") + private String payerParentUserId; + + @SerializedName("trade_state") + private Integer tradeState; + + public static PaymentResult fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, PaymentResult.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + public static WxCpPaymentResult fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpPaymentResult.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/WxCpResultList.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/WxCpResultList.java new file mode 100644 index 000000000..c4305264d --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/WxCpResultList.java @@ -0,0 +1,53 @@ +package me.chanjar.weixin.cp.bean.school; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 获取师生健康码. + * + * @author Wang_Wong + */ +@Data +public class WxCpResultList extends WxCpBaseResp implements Serializable { + private static final long serialVersionUID = -5028321625142879581L; + + @SerializedName("result_list") + private List qrCodeList; + + @Setter + @Getter + public static class QrCodeList extends WxCpBaseResp{ + + @SerializedName("userid") + private String userId; + + @SerializedName("qrcode_data") + private String qrCodeData; + + public static QrCodeList fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, QrCodeList.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + public static WxCpResultList fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpResultList.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/WxCpSchoolLivingInfo.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/WxCpSchoolLivingInfo.java new file mode 100644 index 000000000..2206cfcc2 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/WxCpSchoolLivingInfo.java @@ -0,0 +1,94 @@ +package me.chanjar.weixin.cp.bean.school; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 获取直播详情. + * + * @author Wang_Wong + */ +@Data +public class WxCpSchoolLivingInfo extends WxCpBaseResp implements Serializable { + private static final long serialVersionUID = -5028321625140879571L; + + @SerializedName("living_info") + private LivingInfo livingInfo; + + @Getter + @Setter + public static class LivingInfo implements Serializable { + + @SerializedName("theme") + private String theme; + + @SerializedName("living_start") + private Long livingStart; + + @SerializedName("living_duration") + private Long livingDuration; + + @SerializedName("anchor_userid") + private String anchorUserId; + + @SerializedName("living_range") + private LivingRange livingRange; + + @SerializedName("viewer_num") + private Integer viewerNum; + + @SerializedName("comment_num") + private Integer commentNum; + + @SerializedName("open_replay") + private Integer openReplay; + + @SerializedName("push_stream_url") + private String pushStreamUrl; + + public static LivingInfo fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, LivingInfo.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + @Getter + @Setter + public static class LivingRange implements Serializable { + + @SerializedName("partyids") + private List partyIds; + + @SerializedName("group_names") + private List groupNames; + + public static LivingRange fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, LivingRange.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + public static WxCpSchoolLivingInfo fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpSchoolLivingInfo.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/WxCpSchoolUnwatchStat.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/WxCpSchoolUnwatchStat.java new file mode 100644 index 000000000..964fca869 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/WxCpSchoolUnwatchStat.java @@ -0,0 +1,65 @@ +package me.chanjar.weixin.cp.bean.school; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 获取未观看直播统计 + * + * @author Wang_Wong + */ +@Data +public class WxCpSchoolUnwatchStat extends WxCpBaseResp { + private static final long serialVersionUID = -5028321625140879571L; + + @SerializedName("ending") + private Integer ending; + + @SerializedName("next_key") + private String nextKey; + + @SerializedName("stat_info") + private StatInfo statInfo; + + @Getter + @Setter + public static class StatInfo implements Serializable { + private static final long serialVersionUID = -5696099236344075582L; + + @SerializedName("students") + private List students; + + } + + @Getter + @Setter + public static class Student implements Serializable { + private static final long serialVersionUID = -5696099236344075582L; + + @SerializedName("student_userid") + private String studentUserId; + + @SerializedName("parent_userid") + private String parentUserId; + + @SerializedName("partyids") + private List partyIds; + + } + + public static WxCpSchoolUnwatchStat fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpSchoolUnwatchStat.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/WxCpSchoolWatchStat.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/WxCpSchoolWatchStat.java new file mode 100644 index 000000000..4dd1ebb39 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/WxCpSchoolWatchStat.java @@ -0,0 +1,102 @@ +package me.chanjar.weixin.cp.bean.school; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 获取观看直播统计. + * + * @author Wang_Wong + */ +@Data +public class WxCpSchoolWatchStat extends WxCpBaseResp{ + private static final long serialVersionUID = -5028321625140879571L; + + @SerializedName("ending") + private Integer ending; + + @SerializedName("next_key") + private String nextKey; + + @SerializedName("stat_infoes") + private StatInfo statInfoes; + + @Getter + @Setter + public static class StatInfo implements Serializable { + private static final long serialVersionUID = -5696099236344075582L; + + @SerializedName("students") + private List students; + + @SerializedName("visitors") + private List visitors; + + } + + @Getter + @Setter + public static class Student implements Serializable { + private static final long serialVersionUID = -5696099236344075582L; + + @SerializedName("student_userid") + private String studentUserId; + + @SerializedName("parent_userid") + private String parentUserId; + + @SerializedName("watch_time") + private Integer watchTime; + + @SerializedName("is_comment") + private Integer isComment; + + @SerializedName("enter_time") + private Long enterTime; + + @SerializedName("leave_time") + private Long leaveTime; + + @SerializedName("partyids") + private List partyIds; + + } + + @Getter + @Setter + public static class Visitor implements Serializable { + private static final long serialVersionUID = -5696099236344075582L; + + @SerializedName("nickname") + private String nickname; + + @SerializedName("watch_time") + private Integer watchTime; + + @SerializedName("is_comment") + private Integer isComment; + + @SerializedName("enter_time") + private Long enterTime; + + @SerializedName("leave_time") + private Long leaveTime; + + } + + public static WxCpSchoolWatchStat fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpSchoolWatchStat.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/WxCpTrade.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/WxCpTrade.java new file mode 100644 index 000000000..8283174b2 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/WxCpTrade.java @@ -0,0 +1,39 @@ +package me.chanjar.weixin.cp.bean.school; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; + +/** + * 获取订单详情. + * + * @author Wang_Wong + */ +@Data +public class WxCpTrade extends WxCpBaseResp implements Serializable { + private static final long serialVersionUID = -5028321625142879581L; + + /** + * 微信交易单号 + */ + @SerializedName("transaction_id") + private String transactionId; + + /** + * 交易时间 + */ + @SerializedName("pay_time") + private Long payTime; + + public static WxCpTrade fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpTrade.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/health/WxCpGetHealthReportStat.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/health/WxCpGetHealthReportStat.java new file mode 100644 index 000000000..3bd444832 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/health/WxCpGetHealthReportStat.java @@ -0,0 +1,33 @@ +package me.chanjar.weixin.cp.bean.school.health; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; + +/** + * 获取健康上报使用统计. + * + * @author Wang_Wong + */ +@Data +public class WxCpGetHealthReportStat extends WxCpBaseResp implements Serializable { + private static final long serialVersionUID = -5028321625142879581L; + + @SerializedName("pv") + private Integer pv; + + @SerializedName("uv") + private Integer uv; + + public static WxCpGetHealthReportStat fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpGetHealthReportStat.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/health/WxCpGetReportAnswer.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/health/WxCpGetReportAnswer.java new file mode 100644 index 000000000..a016ad1ef --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/health/WxCpGetReportAnswer.java @@ -0,0 +1,96 @@ +package me.chanjar.weixin.cp.bean.school.health; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 获取用户填写答案. + * + * @author Wang_Wong + */ +@Data +public class WxCpGetReportAnswer extends WxCpBaseResp implements Serializable { + private static final long serialVersionUID = -5028321625142879581L; + + @SerializedName("answers") + private List answers; + + @Getter + @Setter + public static class Answer implements Serializable { + private static final long serialVersionUID = -5696099236344075582L; + + @SerializedName("userid") + private String userId; + + @SerializedName("id_type") + private Integer idType; + + @SerializedName("report_time") + private Long reportTime; + + @SerializedName("student_userid") + private String studentUserId; + + @SerializedName("parent_userid") + private String parentUserId; + + @SerializedName("report_values") + private List reportValues; + + public static Answer fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, Answer.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + @Getter + @Setter + public static class ReportValue implements Serializable { + private static final long serialVersionUID = -5696099236344075582L; + + @SerializedName("question_id") + private Integer questionId; + + @SerializedName("single_chose") + private Integer singleChose; + + @SerializedName("multi_choice") + private List multiChoice; + + @SerializedName("text") + private String text; + + @SerializedName("fileid") + private List fileId; + + public static ReportValue fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, ReportValue.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + public static WxCpGetReportAnswer fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpGetReportAnswer.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/health/WxCpGetReportJobIds.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/health/WxCpGetReportJobIds.java new file mode 100644 index 000000000..768dcec21 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/health/WxCpGetReportJobIds.java @@ -0,0 +1,34 @@ +package me.chanjar.weixin.cp.bean.school.health; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 获取健康上报使用统计. + * + * @author Wang_Wong + */ +@Data +public class WxCpGetReportJobIds extends WxCpBaseResp implements Serializable { + private static final long serialVersionUID = -5028321625142879581L; + + @SerializedName("ending") + private Integer ending; + + @SerializedName("jobids") + private List jobIds; + + public static WxCpGetReportJobIds fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpGetReportJobIds.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/health/WxCpGetReportJobInfo.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/health/WxCpGetReportJobInfo.java new file mode 100644 index 000000000..5ca603101 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/health/WxCpGetReportJobInfo.java @@ -0,0 +1,165 @@ +package me.chanjar.weixin.cp.bean.school.health; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 获取健康上报任务详情. + * + * @author Wang_Wong + */ +@Data +public class WxCpGetReportJobInfo extends WxCpBaseResp implements Serializable { + private static final long serialVersionUID = -5028321625142879581L; + + @SerializedName("job_info") + private JobInfo jobInfo; + + @Getter + @Setter + public static class JobInfo implements Serializable { + private static final long serialVersionUID = -5696099236344075582L; + + @SerializedName("title") + private String title; + + @SerializedName("creator") + private String creator; + + @SerializedName("type") + private Integer type; + + @SerializedName("report_type") + private Integer reportType; + + @SerializedName("skip_weekend") + private Integer skipWeekend; + + @SerializedName("finish_cnt") + private Integer finishCnt; + + @SerializedName("apply_range") + private ApplyRange applyRange; + + @SerializedName("report_to") + private ReportTo reportTo; + + @SerializedName("question_templates") + private List questionTemplates; + + public static JobInfo fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, JobInfo.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + @Getter + @Setter + public static class ApplyRange implements Serializable { + private static final long serialVersionUID = -5696099236344075582L; + + @SerializedName("userids") + private List userIds; + + @SerializedName("partyids") + private List partyIds; + + public static ApplyRange fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, ApplyRange.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + @Getter + @Setter + public static class ReportTo implements Serializable { + private static final long serialVersionUID = -5696099236344075582L; + + @SerializedName("userids") + private List userIds; + + public static ReportTo fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, ReportTo.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + @Getter + @Setter + public static class QuestionTemplate implements Serializable { + private static final long serialVersionUID = -5696099236344075582L; + + @SerializedName("question_id") + private Integer questionId; + + @SerializedName("question_type") + private Integer questionType; + + @SerializedName("is_required") + private Integer isRequired; + + @SerializedName("title") + private String title; + + @SerializedName("option_list") + private List optionList; + + public static QuestionTemplate fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, QuestionTemplate.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + @Getter + @Setter + public static class OptionList implements Serializable { + private static final long serialVersionUID = -5696099236344075582L; + + @SerializedName("option_id") + private Integer optionId; + + @SerializedName("option_text") + private String optionText; + + public static OptionList fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, OptionList.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + public static WxCpGetReportJobInfo fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpGetReportJobInfo.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpAllowScope.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpAllowScope.java new file mode 100644 index 000000000..902cc4adc --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpAllowScope.java @@ -0,0 +1,79 @@ +package me.chanjar.weixin.cp.bean.school.user; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 获取可使用的家长范围 返回结果. + * + * @author Wang_Wong + */ +@Data +public class WxCpAllowScope extends WxCpBaseResp implements Serializable { + private static final long serialVersionUID = -5028321625140879571L; + + @SerializedName("allow_scope") + private AllowScope allowScope; + + @Setter + @Getter + public static class AllowScope implements Serializable { + + @SerializedName("students") + private List students; + + @SerializedName("departments") + private Department departments; + + public static AllowScope fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, AllowScope.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + @Setter + @Getter + public static class Department implements Serializable { + + @SerializedName("partyid") + private List partyId; + + public static Department fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, Department.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + @Setter + @Getter + public static class Student implements Serializable { + + @SerializedName("userid") + private String userId; + + } + + public static WxCpAllowScope fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpAllowScope.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpBatchCreateParentRequest.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpBatchCreateParentRequest.java new file mode 100644 index 000000000..388ce9169 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpBatchCreateParentRequest.java @@ -0,0 +1,88 @@ +package me.chanjar.weixin.cp.bean.school.user; + +import com.google.gson.annotations.SerializedName; +import lombok.*; +import lombok.experimental.Accessors; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 批量创建家长. + * + * @author Wang_Wong + * @date 2022-07-11 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class WxCpBatchCreateParentRequest implements Serializable { + private static final long serialVersionUID = -4960239393895754138L; + + @SerializedName("parents") + private List parents; + + @Setter + @Getter + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class Parent implements Serializable { + + @SerializedName("parent_userid") + private String parentUserId; + + @SerializedName("mobile") + private String mobile; + + @SerializedName("to_invite") + private Boolean toInvite; + + @SerializedName("children") + private List children; + + public static Parent fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, Parent.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + @Setter + @Getter + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class Children implements Serializable { + + @SerializedName("student_userid") + private String studentUserId; + + @SerializedName("relation") + private String relation; + + public static Children fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, Children.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + public static WxCpBatchCreateParentRequest fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpBatchCreateParentRequest.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpBatchCreateStudentRequest.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpBatchCreateStudentRequest.java new file mode 100644 index 000000000..60c208895 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpBatchCreateStudentRequest.java @@ -0,0 +1,59 @@ +package me.chanjar.weixin.cp.bean.school.user; + +import com.google.gson.annotations.SerializedName; +import lombok.*; +import lombok.experimental.Accessors; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 批量创建学生请求. + * + * @author Wang_Wong + * @date 2022-07-01 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class WxCpBatchCreateStudentRequest implements Serializable { + private static final long serialVersionUID = -4960239393895754138L; + + @SerializedName("students") + private List students; + + @Setter + @Getter + public static class Student implements Serializable { + + @SerializedName("student_userid") + private String studentUserId; + + @SerializedName("name") + private String name; + + @SerializedName("department") + private List department; + + public static Student fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, Student.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + public static WxCpBatchCreateStudentRequest fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpBatchCreateStudentRequest.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpBatchDeleteStudentRequest.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpBatchDeleteStudentRequest.java new file mode 100644 index 000000000..801832cb1 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpBatchDeleteStudentRequest.java @@ -0,0 +1,36 @@ +package me.chanjar.weixin.cp.bean.school.user; + +import com.google.gson.annotations.SerializedName; +import lombok.*; +import lombok.experimental.Accessors; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 批量删除学生请求. + * + * @author Wang_Wong + * @date 2022-07-01 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class WxCpBatchDeleteStudentRequest implements Serializable { + private static final long serialVersionUID = -4960239393895754138L; + + @SerializedName("useridlist") + private List userIdList; + + public static WxCpBatchDeleteStudentRequest fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpBatchDeleteStudentRequest.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpBatchResultList.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpBatchResultList.java new file mode 100644 index 000000000..a3cf805db --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpBatchResultList.java @@ -0,0 +1,54 @@ +package me.chanjar.weixin.cp.bean.school.user; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 批量返回结果. + * + * @author Wang_Wong + * @date 2022-07-01 + */ +@Data +public class WxCpBatchResultList extends WxCpBaseResp implements Serializable { + private static final long serialVersionUID = -5028321625140879571L; + + @SerializedName("result_list") + private List resultList; + + @Setter + @Getter + public static class ResultList extends WxCpBaseResp{ + + @SerializedName("parent_userid") + private String parentUserId; + + @SerializedName("student_userid") + private String studentUserId; + + public static ResultList fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, ResultList.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + public static WxCpBatchResultList fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpBatchResultList.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpBatchUpdateParentRequest.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpBatchUpdateParentRequest.java new file mode 100644 index 000000000..18a659d7d --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpBatchUpdateParentRequest.java @@ -0,0 +1,88 @@ +package me.chanjar.weixin.cp.bean.school.user; + +import com.google.gson.annotations.SerializedName; +import lombok.*; +import lombok.experimental.Accessors; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 批量更新家长. + * + * @author Wang_Wong + * @date 2022-07-11 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class WxCpBatchUpdateParentRequest implements Serializable { + private static final long serialVersionUID = -4960239393895754138L; + + @SerializedName("parents") + private List parents; + + @Setter + @Getter + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class Parent implements Serializable { + + @SerializedName("parent_userid") + private String parentUserId; + + @SerializedName("new_parent_userid") + private String newParentUserId; + + @SerializedName("mobile") + private String mobile; + + @SerializedName("children") + private List children; + + public static Parent fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, Parent.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + @Setter + @Getter + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class Children implements Serializable { + + @SerializedName("student_userid") + private String studentUserId; + + @SerializedName("relation") + private String relation; + + public static Children fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, Children.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + public static WxCpBatchUpdateParentRequest fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpBatchUpdateParentRequest.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpBatchUpdateStudentRequest.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpBatchUpdateStudentRequest.java new file mode 100644 index 000000000..106450672 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpBatchUpdateStudentRequest.java @@ -0,0 +1,62 @@ +package me.chanjar.weixin.cp.bean.school.user; + +import com.google.gson.annotations.SerializedName; +import lombok.*; +import lombok.experimental.Accessors; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 批量更新学生请求. + * + * @author Wang_Wong + * @date 2022-07-01 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class WxCpBatchUpdateStudentRequest implements Serializable { + private static final long serialVersionUID = -4960239393895754138L; + + @SerializedName("students") + private List students; + + @Setter + @Getter + public static class Student implements Serializable { + + @SerializedName("student_userid") + private String studentUserId; + + @SerializedName("new_student_userid") + private String newStudentUserId; + + @SerializedName("name") + private String name; + + @SerializedName("department") + private List department; + + public static Student fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, Student.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + public static WxCpBatchUpdateStudentRequest fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpBatchUpdateStudentRequest.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpCreateDepartment.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpCreateDepartment.java new file mode 100644 index 000000000..75d34b2e8 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpCreateDepartment.java @@ -0,0 +1,30 @@ +package me.chanjar.weixin.cp.bean.school.user; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; + +/** + * 创建部门返回结果. + * + * @author Wang_Wong + */ +@Data +public class WxCpCreateDepartment extends WxCpBaseResp implements Serializable { + private static final long serialVersionUID = -5028321625140879571L; + + @SerializedName("id") + private Integer id; + + public static WxCpCreateDepartment fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpCreateDepartment.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpCreateDepartmentRequest.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpCreateDepartmentRequest.java new file mode 100644 index 000000000..a851aacc9 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpCreateDepartmentRequest.java @@ -0,0 +1,80 @@ +package me.chanjar.weixin.cp.bean.school.user; + +import com.google.gson.annotations.SerializedName; +import lombok.*; +import lombok.experimental.Accessors; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 创建部门请求. + * + * @author Wang_Wong + * @date 2022-06-22 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class WxCpCreateDepartmentRequest implements Serializable { + private static final long serialVersionUID = -4960239394895754138L; + + @SerializedName("parentid") + private Integer parentId; + + @SerializedName("name") + private String name; + + @SerializedName("id") + private Integer id; + + @SerializedName("type") + private Integer type; + + @SerializedName("register_year") + private Integer registerYear; + + @SerializedName("standard_grade") + private Integer standardGrade; + + @SerializedName("order") + private Integer order; + + @SerializedName("department_admins") + private List departmentAdmins; + + @Setter + @Getter + public static class DepartmentAdmin implements Serializable { + + @SerializedName("userid") + private String userId; + + @SerializedName("type") + private Integer type; + + @SerializedName("subject") + private String subject; + + public static DepartmentAdmin fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, DepartmentAdmin.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + public static WxCpCreateDepartmentRequest fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpCreateDepartmentRequest.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpCreateParentRequest.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpCreateParentRequest.java new file mode 100644 index 000000000..21de39b8c --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpCreateParentRequest.java @@ -0,0 +1,68 @@ +package me.chanjar.weixin.cp.bean.school.user; + +import com.google.gson.annotations.SerializedName; +import lombok.*; +import lombok.experimental.Accessors; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 创建家长请求. + * + * @author Wang_Wong + * @date 2022-06-20 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class WxCpCreateParentRequest implements Serializable { + private static final long serialVersionUID = -4960239393895754138L; + + @SerializedName("parent_userid") + private String parentUserId; + + @SerializedName("mobile") + private String mobile; + + @SerializedName("to_invite") + private Boolean toInvite; + + @SerializedName("children") + private List children; + + @Setter + @Getter + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class Children implements Serializable { + + @SerializedName("student_userid") + private String studentUserId; + + @SerializedName("relation") + private String relation; + + public static Children fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, Children.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + public static WxCpCreateParentRequest fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpCreateParentRequest.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpDepartmentList.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpDepartmentList.java new file mode 100644 index 000000000..5e1c03184 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpDepartmentList.java @@ -0,0 +1,102 @@ +package me.chanjar.weixin.cp.bean.school.user; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 获取部门列表返回结果. + * + * @author Wang_Wong + */ +@Data +public class WxCpDepartmentList extends WxCpBaseResp implements Serializable { + private static final long serialVersionUID = -5028321625140879571L; + + @SerializedName("departments") + private List departments; + + @Setter + @Getter + public static class Department implements Serializable{ + @SerializedName("parentid") + private Integer parentId; + + @SerializedName("name") + private String name; + + @SerializedName("id") + private Integer id; + + @SerializedName("type") + private Integer type; + + @SerializedName("register_year") + private Integer registerYear; + + @SerializedName("standard_grade") + private Integer standardGrade; + + @SerializedName("order") + private Integer order; + + @SerializedName("is_graduated") + private Integer isGraduated; + + @SerializedName("open_group_chat") + private Integer openGroupChat; + + @SerializedName("group_chat_id") + private String groupChatId; + + @SerializedName("department_admins") + private List departmentAdmins; + + public static Department fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, Department.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + @Setter + @Getter + public static class DepartmentAdmin implements Serializable { + + @SerializedName("userid") + private String userId; + + @SerializedName("type") + private Integer type; + + @SerializedName("subject") + private String subject; + + public static DepartmentAdmin fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, DepartmentAdmin.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + public static WxCpDepartmentList fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpDepartmentList.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpExternalContact.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpExternalContact.java new file mode 100644 index 000000000..d36ba92a3 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpExternalContact.java @@ -0,0 +1,250 @@ +package me.chanjar.weixin.cp.bean.school.user; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 获取外部联系人详情 + * https://developer.work.weixin.qq.com/document/path/91670 + * + * @author Wang_Wong + * @date: 2022/6/27 9:10 + */ +@Data +public class WxCpExternalContact extends WxCpBaseResp implements Serializable { + private static final long serialVersionUID = 4311777322534499260L; + + @SerializedName("external_contact") + private ExternalContact externalContact; + + @SerializedName("follow_user") + private List followedUsers; + + @Getter + @Setter + public static class WxCpFollowUser implements Serializable { + private static final long serialVersionUID = -4301684507150486556L; + + @SerializedName("userid") + private String userId; + + private String remark; + + private String description; + + @SerializedName("createtime") + private Long createTime; + + private String state; + + @SerializedName("remark_mobiles") + private String[] remarkMobiles; + + @SerializedName("remark_corp_name") + private String remarkCorpName; + + private Tag[] tags; + + public static WxCpFollowUser fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpFollowUser.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + @Getter + @Setter + public static class Tag implements Serializable { + private static final long serialVersionUID = -7556237053703295482L; + + /** + * 该成员添加此外部联系人所打标签的分组名称(标签功能需要企业微信升级到2.7.5及以上版本) + */ + @SerializedName("group_name") + private String groupName; + + /** + * 该成员添加此外部联系人所打标签名称 + */ + @SerializedName("tag_name") + private String tagName; + + /** + * 该成员添加此外部联系人所打标签类型, 1-企业设置, 2-用户自定义 + */ + private int type; + + public static Tag fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, Tag.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + @Getter + @Setter + public static class ExternalContact implements Serializable { + private static final long serialVersionUID = -1049085217436072418L; + + @SerializedName("external_userid") + private String externalUserId; + + @SerializedName("position") + private String position; + + @SerializedName("name") + private String name; + + @SerializedName("avatar") + private String avatar; + + @SerializedName("corp_name") + private String corpName; + + @SerializedName("corp_full_name") + private String corpFullName; + + @SerializedName("type") + private Integer type; + + @SerializedName("gender") + private Integer gender; + + @SerializedName("unionid") + private String unionId; + + @SerializedName("is_subscribe") + private Integer isSubscribe; + + @SerializedName("subscriber_info") + private SubscriberInfo subscriberInfo; + + @SerializedName("external_profile") + private ExternalProfile externalProfile; + + public static ExternalContact fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, ExternalContact.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + @Getter + @Setter + public static class SubscriberInfo implements Serializable { + private static final long serialVersionUID = -2899906589789022765L; + + @SerializedName("tag_id") + private List tagId; + + @SerializedName("remark_mobiles") + private List remarkMobiles; + + @SerializedName("remark") + private String remark; + + public static SubscriberInfo fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, SubscriberInfo.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + @Getter + @Setter + public static class ExternalProfile implements Serializable { + private static final long serialVersionUID = -2899906589789022765L; + + @SerializedName("external_attr") + private List externalAttrs; + + } + + @Getter + @Setter + public static class ExternalAttribute implements Serializable { + private static final long serialVersionUID = -1262278808286421085L; + + private int type; + + private String name; + + private Text text; + + private Web web; + + @SerializedName("miniprogram") + private MiniProgram miniProgram; + + public static ExternalAttribute fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, ExternalAttribute.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + @Getter + @Setter + public static class Text implements Serializable { + private static final long serialVersionUID = -8161579335600269094L; + + private String value; + + } + + @Getter + @Setter + public static class Web implements Serializable { + private static final long serialVersionUID = 3664557135411521862L; + + private String title; + + private String url; + + } + + @Getter + @Setter + public static class MiniProgram implements Serializable { + private static final long serialVersionUID = -5329210594501835796L; + + @SerializedName("pagepath") + private String pagePath; + + private String appid; + + private String title; + + } + + public static WxCpExternalContact fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpExternalContact.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpListParentResult.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpListParentResult.java new file mode 100644 index 000000000..1edc3fda8 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpListParentResult.java @@ -0,0 +1,95 @@ +package me.chanjar.weixin.cp.bean.school.user; + +import com.google.gson.annotations.SerializedName; +import lombok.*; +import lombok.experimental.Accessors; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 获取部门家长详情返回结果. + * + * @author Wang_Wong + * @date 2022-07-13 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class WxCpListParentResult extends WxCpBaseResp implements Serializable { + private static final long serialVersionUID = -4960239393895754138L; + + @SerializedName("parents") + private List parents; + + @Setter + @Getter + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class Parent implements Serializable { + + @SerializedName("parent_userid") + private String parentUserId; + + @SerializedName("mobile") + private String mobile; + + @SerializedName("external_userid") + private String externalUserId; + + @SerializedName("is_subscribe") + private Integer isSubscribe; + + @SerializedName("children") + private List children; + + public static Parent fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, Parent.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + @Setter + @Getter + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class Children implements Serializable { + + @SerializedName("student_userid") + private String studentUserId; + + @SerializedName("relation") + private String relation; + + @SerializedName("name") + private String name; + + public static Children fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, Children.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + public static WxCpListParentResult fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpListParentResult.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpSetUpgradeInfo.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpSetUpgradeInfo.java new file mode 100644 index 000000000..7a1b3ee27 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpSetUpgradeInfo.java @@ -0,0 +1,30 @@ +package me.chanjar.weixin.cp.bean.school.user; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; + +/** + * 修改自动升年级的配置 返回结果. + * + * @author Wang_Wong + */ +@Data +public class WxCpSetUpgradeInfo extends WxCpBaseResp implements Serializable { + private static final long serialVersionUID = -5028321625140879571L; + + @SerializedName("next_upgrade_time") + private Long nextUpgradeTime; + + public static WxCpSetUpgradeInfo fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpSetUpgradeInfo.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpSubscribeQrCode.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpSubscribeQrCode.java new file mode 100644 index 000000000..26879266b --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpSubscribeQrCode.java @@ -0,0 +1,36 @@ +package me.chanjar.weixin.cp.bean.school.user; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; + +/** + * 获取「学校通知」二维码 返回结果. + * + * @author Wang_Wong + */ +@Data +public class WxCpSubscribeQrCode extends WxCpBaseResp implements Serializable { + private static final long serialVersionUID = -5028321625140879571L; + + @SerializedName("qrcode_big") + private String qrCodeBig; + + @SerializedName("qrcode_middle") + private String qrCodeMiddle; + + @SerializedName("qrcode_thumb") + private String qrCodeThumb; + + public static WxCpSubscribeQrCode fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpSubscribeQrCode.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpUpdateDepartmentRequest.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpUpdateDepartmentRequest.java new file mode 100644 index 000000000..e1dff520e --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpUpdateDepartmentRequest.java @@ -0,0 +1,86 @@ +package me.chanjar.weixin.cp.bean.school.user; + +import com.google.gson.annotations.SerializedName; +import lombok.*; +import lombok.experimental.Accessors; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 更新部门请求. + * + * @author Wang_Wong + * @date 2022-06-22 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class WxCpUpdateDepartmentRequest implements Serializable { + private static final long serialVersionUID = -4960239394895754138L; + + @SerializedName("parentid") + private Integer parentId; + + @SerializedName("name") + private String name; + + @SerializedName("id") + private Integer id; + + @SerializedName("new_id") + private Integer newId; + + @SerializedName("type") + private Integer type; + + @SerializedName("register_year") + private Integer registerYear; + + @SerializedName("standard_grade") + private Integer standardGrade; + + @SerializedName("order") + private Integer order; + + @SerializedName("department_admins") + private List departmentAdmins; + + @Setter + @Getter + public static class DepartmentAdmin implements Serializable { + + @SerializedName("userid") + private String userId; + + @SerializedName("op") + private Integer op; + + @SerializedName("type") + private Integer type; + + @SerializedName("subject") + private String subject; + + public static DepartmentAdmin fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, DepartmentAdmin.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + public static WxCpUpdateDepartmentRequest fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpUpdateDepartmentRequest.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpUpdateParentRequest.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpUpdateParentRequest.java new file mode 100644 index 000000000..23f404f4d --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpUpdateParentRequest.java @@ -0,0 +1,65 @@ +package me.chanjar.weixin.cp.bean.school.user; + +import com.google.gson.annotations.SerializedName; +import lombok.*; +import lombok.experimental.Accessors; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 更新家长请求. + * + * @author Wang_Wong + * @date 2022-06-20 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class WxCpUpdateParentRequest implements Serializable { + private static final long serialVersionUID = -4960239393895754138L; + + @SerializedName("parent_userid") + private String parentUserId; + + @SerializedName("mobile") + private String mobile; + + @SerializedName("new_parent_userid") + private String newParentUserId; + + @SerializedName("children") + private List children; + + @Setter + @Getter + public static class Children implements Serializable { + + @SerializedName("student_userid") + private String studentUserId; + + @SerializedName("relation") + private String relation; + + public static Children fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, Children.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + public static WxCpUpdateParentRequest fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpUpdateParentRequest.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpUserListResult.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpUserListResult.java new file mode 100644 index 000000000..7913b986e --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpUserListResult.java @@ -0,0 +1,98 @@ +package me.chanjar.weixin.cp.bean.school.user; + +import com.google.gson.annotations.SerializedName; +import lombok.*; +import lombok.experimental.Accessors; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 获取部门成员详情返回结果. + * + * @author Wang_Wong + * @date 2022-07-13 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class WxCpUserListResult extends WxCpBaseResp implements Serializable { + private static final long serialVersionUID = -4960239393895754138L; + + @SerializedName("students") + private List students; + + @Setter + @Getter + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class Parent implements Serializable { + + @SerializedName("parent_userid") + private String parentUserId; + + @SerializedName("relation") + private String relation; + + @SerializedName("mobile") + private String mobile; + + @SerializedName("external_userid") + private String externalUserId; + + @SerializedName("is_subscribe") + private Integer isSubscribe; + + public static Parent fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, Parent.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + @Setter + @Getter + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class Student implements Serializable { + + @SerializedName("student_userid") + private String studentUserId; + + @SerializedName("name") + private String name; + + @SerializedName("department") + private List department; + + @SerializedName("parents") + private List parents; + + public static Student fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, Student.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + public static WxCpUserListResult fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpUserListResult.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpUserResult.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpUserResult.java new file mode 100644 index 000000000..ad0cfb53d --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/school/user/WxCpUserResult.java @@ -0,0 +1,130 @@ +package me.chanjar.weixin.cp.bean.school.user; + +import com.google.gson.annotations.SerializedName; +import lombok.*; +import lombok.experimental.Accessors; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 读取学生或家长返回结果. + * + * @author Wang_Wong + * @date 2022-07-13 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class WxCpUserResult extends WxCpBaseResp implements Serializable { + private static final long serialVersionUID = -4960239393895754138L; + + @SerializedName("student") + private Student student; + + @SerializedName("parent") + private Parent parent; + + @SerializedName("user_type") + private Integer userType; + + @Setter + @Getter + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class Parent implements Serializable { + + @SerializedName("parent_userid") + private String parentUserId; + + @SerializedName("relation") + private String relation; + + @SerializedName("mobile") + private String mobile; + + @SerializedName("external_userid") + private String externalUserId; + + @SerializedName("is_subscribe") + private Integer isSubscribe; + + @SerializedName("children") + private List children; + + public static Parent fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, Parent.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + @Setter + @Getter + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class Student implements Serializable { + + @SerializedName("student_userid") + private String studentUserId; + + @SerializedName("department") + private List department; + + @SerializedName("parents") + private List parents; + + @SerializedName("name") + private String name; + + public static Student fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, Student.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + @Setter + @Getter + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class Children implements Serializable { + + @SerializedName("student_userid") + private String studentUserId; + + @SerializedName("relation") + private String relation; + + public static Children fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, Children.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + public static WxCpUserResult fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpUserResult.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/templatecard/ActionMenuItem.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/templatecard/ActionMenuItem.java new file mode 100644 index 000000000..54950fb82 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/templatecard/ActionMenuItem.java @@ -0,0 +1,40 @@ +package me.chanjar.weixin.cp.bean.templatecard; + +import com.google.gson.JsonObject; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 卡片右上角更多操作按钮点击后出现的操作列表,列表长度取值范围为 [1, 3] + * @author xiaohe + * @date 2022-03-06 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ActionMenuItem implements Serializable { + private static final long serialVersionUID = 400885585614100693L; + + /** + * 操作的描述文案 + */ + private String text; + + /** + * 按钮key值,用户点击后,会产生回调事件将本参数作为EventKey返回,回调事件会带上该key值,最长支持1024字节,不可重复 + */ + private String key; + + public JsonObject toJson() { + JsonObject btnObject = new JsonObject(); + btnObject.addProperty("text", this.getText()); + btnObject.addProperty("key", this.getKey()); + return btnObject; + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/templatecard/HorizontalContent.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/templatecard/HorizontalContent.java index 397420820..393a99dac 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/templatecard/HorizontalContent.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/templatecard/HorizontalContent.java @@ -44,6 +44,11 @@ public class HorizontalContent implements Serializable { */ private String media_id; + /** + * 成员详情的userid,horizontal_content_list.type是3时必填 + */ + private String userid; + public JsonObject toJson() { JsonObject hContentJson = new JsonObject(); @@ -61,6 +66,9 @@ public JsonObject toJson() { if (StringUtils.isNotBlank(this.getMedia_id())) { hContentJson.addProperty("media_id", this.getMedia_id()); } + if (StringUtils.isNotBlank(this.getUserid())) { + hContentJson.addProperty("userid", this.getUserid()); + } return hContentJson; } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/templatecard/TemplateCardButton.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/templatecard/TemplateCardButton.java index 28722c8d7..df7812fd1 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/templatecard/TemplateCardButton.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/templatecard/TemplateCardButton.java @@ -34,6 +34,18 @@ public class TemplateCardButton implements Serializable { */ private String key; + /** + * 按钮点击事件类型,0 或不填代表回调点击事件,1 代表跳转url + */ + private int type; + + /** + * 跳转事件的url,button_list.type是1时必填 + */ + private String url; + + + public JsonObject toJson() { JsonObject btnObject = new JsonObject(); @@ -44,6 +56,10 @@ public JsonObject toJson() { btnObject.addProperty("style", this.getStyle()); } btnObject.addProperty("key", this.getKey()); + btnObject.addProperty("type", this.getType()); + if (null != this.getUrl()) { + btnObject.addProperty("url", this.getUrl()); + } return btnObject; } } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/user/WxCpDeptUserResult.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/user/WxCpDeptUserResult.java new file mode 100644 index 000000000..287476f83 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/user/WxCpDeptUserResult.java @@ -0,0 +1,58 @@ +package me.chanjar.weixin.cp.bean.user; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 获取成员ID列表返回参数 + * + * @author Wang_Wong + * @date 2022/08/09 + */ +@Data +public class WxCpDeptUserResult extends WxCpBaseResp { + private static final long serialVersionUID = 1420065684270213578L; + + @SerializedName("next_cursor") + private String nextCursor; + + @SerializedName("dept_user") + private List deptUser; + + @Getter + @Setter + public static class DeptUserList implements Serializable { + private static final long serialVersionUID = 1420065684270213578L; + + @SerializedName("userid") + private String userId; + + @SerializedName("department") + private Long department; + + public static DeptUserList fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, DeptUserList.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + + } + + public static WxCpDeptUserResult fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpDeptUserResult.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpConfigStorage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpConfigStorage.java index 1d7e9685d..10ae05ead 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpConfigStorage.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpConfigStorage.java @@ -174,6 +174,13 @@ public interface WxCpConfigStorage { */ String getAesKey(); + /** + * 企微会话存档私钥 + * + * @return + */ + String getMsgAuditPriKey(); + /** * 获取企微会话存档系统库 绝对路径 * diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/impl/WxCpDefaultConfigImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/impl/WxCpDefaultConfigImpl.java index c716eb735..442e437cf 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/impl/WxCpDefaultConfigImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/impl/WxCpDefaultConfigImpl.java @@ -43,6 +43,10 @@ public class WxCpDefaultConfigImpl implements WxCpConfigStorage, Serializable { private volatile String token; private volatile String aesKey; private volatile long expiresTime; + /** + * 会话存档私钥以及sdk路径 + */ + private volatile String msgAuditPriKey; private volatile String msgAuditLibPath; private volatile String oauth2redirectUri; private volatile String httpProxyHost; @@ -257,6 +261,11 @@ public String getAesKey() { return this.aesKey; } + @Override + public String getMsgAuditPriKey() { + return this.msgAuditPriKey; + } + @Override public String getMsgAuditLibPath() { return this.msgAuditLibPath; @@ -294,6 +303,15 @@ public void setMsgAuditLibPath(String msgAuditLibPath) { this.msgAuditLibPath = msgAuditLibPath; } + /** + * 设置会话存档私钥 + * + * @param msgAuditPriKey 会话存档私钥 + */ + public void setMsgAuditPriKey(String msgAuditPriKey) { + this.msgAuditPriKey = msgAuditPriKey; + } + @Override public String getOauth2redirectUri() { return this.oauth2redirectUri; diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/impl/WxCpRedisConfigImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/impl/WxCpRedisConfigImpl.java index 89b939e61..662cf226b 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/impl/WxCpRedisConfigImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/impl/WxCpRedisConfigImpl.java @@ -40,6 +40,7 @@ public class WxCpRedisConfigImpl implements WxCpConfigStorage { private volatile String token; private volatile String aesKey; private volatile Integer agentId; + private volatile String msgAuditPriKey; private volatile String msgAuditLibPath; private volatile String oauth2redirectUri; private volatile String httpProxyHost; @@ -321,6 +322,11 @@ public String getAesKey() { return this.aesKey; } + @Override + public String getMsgAuditPriKey() { + return this.msgAuditPriKey; + } + @Override public String getMsgAuditLibPath() { return this.msgAuditLibPath; diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java index b3773eeab..fc5868df6 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java @@ -16,6 +16,7 @@ public interface WxCpApiPathConsts { String GET_AGENT_CONFIG_TICKET = "/cgi-bin/ticket/get?&type=agent_config"; String GET_CALLBACK_IP = "/cgi-bin/getcallbackip"; String BATCH_REPLACE_PARTY = "/cgi-bin/batch/replaceparty"; + String BATCH_SYNC_USER = "/cgi-bin/batch/syncuser"; String BATCH_REPLACE_USER = "/cgi-bin/batch/replaceuser"; String BATCH_GET_RESULT = "/cgi-bin/batch/getresult?jobid="; String JSCODE_TO_SESSION = "/cgi-bin/miniprogram/jscode2session"; @@ -27,6 +28,7 @@ public interface WxCpApiPathConsts { * https://work.weixin.qq.com/api/doc/90000/90135/90235 */ interface Message { + /** * 发送应用消息 */ @@ -39,8 +41,16 @@ interface Message { /** * 互联企业发送应用消息 + * https://developer.work.weixin.qq.com/document/path/90250 */ String LINKEDCORP_MESSAGE_SEND = "/cgi-bin/linkedcorp/message/send"; + + /** + * 发送「学校通知」 + * https://developer.work.weixin.qq.com/document/path/92321 + */ + String EXTERNAL_CONTACT_MESSAGE_SEND = "/cgi-bin/externalcontact/message/send"; + } interface Agent { @@ -57,6 +67,7 @@ interface WorkBench { interface OAuth2 { String GET_USER_INFO = "/cgi-bin/user/getuserinfo?code=%s&agentid=%d"; + String GET_SCHOOL_USER_INFO = "/cgi-bin/school/getuserinfo?code=%s"; String GET_USER_DETAIL = "/cgi-bin/user/getuserdetail"; String URL_OAUTH2_AUTHORIZE = "https://open.weixin.qq.com/connect/oauth2/authorize"; } @@ -102,6 +113,7 @@ interface Oa { String GET_CHECKIN_MONTH_DATA = "/cgi-bin/checkin/getcheckin_monthdata"; String GET_CHECKIN_SCHEDULE_DATA = "/cgi-bin/checkin/getcheckinschedulist"; String SET_CHECKIN_SCHEDULE_DATA = "/cgi-bin/checkin/setcheckinschedulist"; + String ADD_CHECK_IN_USER_FACE = "/cgi-bin/checkin/addcheckinuserface"; /** * 审批 @@ -139,6 +151,40 @@ interface Oa { String SCHEDULE_DEL = "/cgi-bin/oa/schedule/del"; String SCHEDULE_LIST = "/cgi-bin/oa/schedule/get_by_calendar"; + /** + * 会议 + * https://developer.work.weixin.qq.com/document/path/93624 + */ + String MEETINGROOM_ADD = "/cgi-bin/oa/meetingroom/add"; + String MEETINGROOM_LIST = "/cgi-bin/oa/meetingroom/list"; + String MEETINGROOM_EDIT = "/cgi-bin/oa/meetingroom/edit"; + String MEETINGROOM_DEL = "/cgi-bin/oa/meetingroom/del"; + + /** + * 微盘 + * https://developer.work.weixin.qq.com/document/path/93654 + */ + String SPACE_CREATE = "/cgi-bin/wedrive/space_create"; + String SPACE_RENAME = "/cgi-bin/wedrive/space_rename"; + String SPACE_DISMISS = "/cgi-bin/wedrive/space_dismiss"; + String SPACE_INFO = "/cgi-bin/wedrive/space_info"; + String SPACE_ACL_ADD = "/cgi-bin/wedrive/space_acl_add"; + String SPACE_ACL_DEL = "/cgi-bin/wedrive/space_acl_del"; + String SPACE_SETTING = "/cgi-bin/wedrive/space_setting"; + String SPACE_SHARE = "/cgi-bin/wedrive/space_share"; + String FILE_LIST = "/cgi-bin/wedrive/file_list"; + String FILE_UPLOAD = "/cgi-bin/wedrive/file_upload"; + String FILE_DOWNLOAD = "/cgi-bin/wedrive/file_download"; + String FILE_RENAME = "/cgi-bin/wedrive/file_rename"; + String FILE_CREATE = "/cgi-bin/wedrive/file_create"; + String FILE_MOVE = "/cgi-bin/wedrive/file_move"; + String FILE_DELETE = "/cgi-bin/wedrive/file_delete"; + String FILE_INFO = "/cgi-bin/wedrive/file_info"; + String FILE_ACL_ADD = "/cgi-bin/wedrive/file_acl_add"; + String FILE_ACL_DEL = "/cgi-bin/wedrive/file_acl_del"; + String FILE_SETTING = "/cgi-bin/wedrive/file_setting"; + String FILE_SHARE = "/cgi-bin/wedrive/file_share"; + /** * 审批流程引擎 * https://developer.work.weixin.qq.com/document/path/90269 @@ -146,6 +192,52 @@ interface Oa { String GET_OPEN_APPROVAL_DATA = "/cgi-bin/corp/getopenapprovaldata"; } + interface School { + String GET_HEALTH_REPORT_STAT = "/cgi-bin/health/get_health_report_stat"; + String GET_REPORT_JOBIDS = "/cgi-bin/health/get_report_jobids"; + String GET_REPORT_JOB_INFO = "/cgi-bin/health/get_report_job_info"; + String GET_REPORT_ANSWER = "/cgi-bin/health/get_report_answer"; + + String GET_TEACHER_CUSTOMIZE_HEALTH_INFO = "/cgi-bin/school/user/get_teacher_customize_health_info"; + String GET_STUDENT_CUSTOMIZE_HEALTH_INFO = "/cgi-bin/school/user/get_student_customize_health_info"; + String GET_HEALTH_QRCODE = "/cgi-bin/school/user/get_health_qrcode"; + + String BATCH_CREATE_STUDENT = "/cgi-bin/school/user/batch_create_student"; + String BATCH_DELETE_STUDENT = "/cgi-bin/school/user/batch_delete_student"; + String BATCH_UPDATE_STUDENT = "/cgi-bin/school/user/batch_update_student"; + String BATCH_CREATE_PARENT = "/cgi-bin/school/user/batch_create_parent"; + String BATCH_DELETE_PARENT = "/cgi-bin/school/user/batch_delete_parent"; + String BATCH_UPDATE_PARENT = "/cgi-bin/school/user/batch_update_parent"; + + String CREATE_STUDENT = "/cgi-bin/school/user/create_student"; + String DELETE_STUDENT = "/cgi-bin/school/user/delete_student?userid="; + String UPDATE_STUDENT = "/cgi-bin/school/user/update_student"; + String CREATE_PARENT = "/cgi-bin/school/user/create_parent"; + String UPDATE_PARENT = "/cgi-bin/school/user/update_parent"; + String DELETE_PARENT = "/cgi-bin/school/user/delete_parent?userid="; + String GET_USER = "/cgi-bin/school/user/get?userid="; + String GET_USER_LIST = "/cgi-bin/school/user/list?department_id=%s&fetch_child=%d"; + String GET_USER_LIST_PARENT = "/cgi-bin/school/user/list_parent?department_id="; + String SET_ARCH_SYNC_MODE = "/cgi-bin/school/set_arch_sync_mode"; + String SET_UPGRADE_INFO = "/cgi-bin/school/set_upgrade_info"; + + String DEPARTMENT_CREATE = "/cgi-bin/school/department/create"; + String DEPARTMENT_UPDATE = "/cgi-bin/school/department/update"; + String DEPARTMENT_DELETE = "/cgi-bin/school/department/delete?id="; + String DEPARTMENT_LIST = "/cgi-bin/school/department/list?id="; + + String GET_PAYMENT_RESULT = "/cgi-bin/school/get_payment_result"; + String GET_TRADE = "/cgi-bin/school/get_trade"; + String GET_ALLOW_SCOPE = "/cgi-bin/school/agent/get_allow_scope?agentid="; + + /** + * 上课直播 + */ + String GET_LIVING_INFO = "/cgi-bin/school/living/get_living_info?livingid="; + String GET_WATCH_STAT = "/cgi-bin/school/living/get_watch_stat"; + String GET_UNWATCH_STAT = "/cgi-bin/school/living/get_unwatch_stat"; + } + interface Living { String GET_LIVING_CODE = "/cgi-bin/living/get_living_code"; String GET_LIVING_INFO = "/cgi-bin/living/get_living_info?livingid="; @@ -177,6 +269,7 @@ interface Tag { interface TaskCard { String UPDATE_TASK_CARD = "/cgi-bin/message/update_taskcard"; + String UPDATE_TEMPLATE_CARD = "/cgi-bin/message/update_template_card"; } interface Tp { @@ -197,6 +290,31 @@ interface Tp { String CONTACT_SEARCH = "/cgi-bin/service/contact/search"; String GET_ADMIN_LIST = "/cgi-bin/service/get_admin_list"; + // 获取订单详情 + String GET_ORDER = "/cgi-bin/service/get_order"; + + // 获取订单列表 + String GET_ORDER_LIST = "/cgi-bin/service/get_order_list"; + + // 延长试用期 + String PROLONG_TRY = "/cgi-bin/service/prolong_try"; + + } + + interface License { + String CREATE_NEW_ORDER = "/cgi-bin/license/create_new_order"; + String CREATE_RENEW_ORDER_JOB = "/cgi-bin/license/create_renew_order_job"; + String SUBMIT_ORDER_JOB = "/cgi-bin/license/submit_order_job"; + String LIST_ORDER = "/cgi-bin/license/list_order"; + String GET_ORDER = "/cgi-bin/license/get_order"; + String LIST_ORDER_ACCOUNT = "/cgi-bin/license/list_order_account"; + String ACTIVE_ACCOUNT = "/cgi-bin/license/active_account"; + String BATCH_ACTIVE_ACCOUNT = "/cgi-bin/license/batch_active_account"; + String GET_ACTIVE_INFO_BY_CODE = "/cgi-bin/license/get_active_info_by_code"; + String BATCH_GET_ACTIVE_INFO_BY_CODE = "/cgi-bin/license/batch_get_active_info_by_code"; + String LIST_ACTIVED_ACCOUNT = "/cgi-bin/license/list_actived_account"; + String GET_ACTIVE_INFO_BY_USER = "/cgi-bin/license/get_active_info_by_user"; + String BATCH_TRANSFER_LICENSE = "/cgi-bin/license/batch_transfer_license"; } interface User { @@ -214,6 +332,10 @@ interface User { String GET_USER_ID = "/cgi-bin/user/getuserid"; String GET_EXTERNAL_CONTACT = "/cgi-bin/crm/get_external_contact?external_userid="; String GET_JOIN_QR_CODE = "/cgi-bin/corp/get_join_qrcode?size_type="; + String GET_ACTIVE_STAT = "/cgi-bin/user/get_active_stat"; + String USERID_TO_OPEN_USERID = "/cgi-bin/batch/userid_to_openuserid"; + + String USER_LIST_ID = "/cgi-bin/user/list_id"; } interface ExternalContact { @@ -237,6 +359,7 @@ interface ExternalContact { String UPDATE_REMARK = "/cgi-bin/externalcontact/remark"; String LIST_EXTERNAL_CONTACT = "/cgi-bin/externalcontact/list?userid="; String LIST_UNASSIGNED_CONTACT = "/cgi-bin/externalcontact/get_unassigned_list"; + @Deprecated String TRANSFER_UNASSIGNED_CONTACT = "/cgi-bin/externalcontact/transfer"; String TRANSFER_CUSTOMER = "/cgi-bin/externalcontact/transfer_customer"; @@ -249,6 +372,10 @@ interface ExternalContact { String GROUP_CHAT_TRANSFER = "/cgi-bin/externalcontact/groupchat/transfer"; String LIST_USER_BEHAVIOR_DATA = "/cgi-bin/externalcontact/get_user_behavior_data"; String LIST_GROUP_CHAT_DATA = "/cgi-bin/externalcontact/groupchat/statistic"; + String ADD_JOIN_WAY = "/cgi-bin/externalcontact/groupchat/add_join_way"; + String GET_JOIN_WAY = "/cgi-bin/externalcontact/groupchat/get_join_way"; + String UPDATE_JOIN_WAY = "/cgi-bin/externalcontact/groupchat/update_join_way"; + String DEL_JOIN_WAY = "/cgi-bin/externalcontact/groupchat/del_join_way"; String ADD_MSG_TEMPLATE = "/cgi-bin/externalcontact/add_msg_template"; String SEND_WELCOME_MSG = "/cgi-bin/externalcontact/send_welcome_msg"; @@ -271,8 +398,12 @@ interface ExternalContact { String GET_GROUP_MSG_LIST_V2 = "/cgi-bin/externalcontact/get_groupmsg_list_v2"; String GET_GROUP_MSG_RESULT = "/cgi-bin/externalcontact/get_group_msg_result"; + String GET_PRODUCT_ALBUM = "/cgi-bin/externalcontact/get_product_album"; String GET_PRODUCT_ALBUM_LIST = "/cgi-bin/externalcontact/get_product_album_list"; + String ADD_PRODUCT_ALBUM = "/cgi-bin/externalcontact/add_product_album"; + String UPDATE_PRODUCT_ALBUM = "/cgi-bin/externalcontact/update_product_album"; + String DELETE_PRODUCT_ALBUM = "/cgi-bin/externalcontact/delete_product_album"; String GROUP_WELCOME_TEMPLATE_ADD = "/cgi-bin/externalcontact/group_welcome_template/add"; String GROUP_WELCOME_TEMPLATE_EDIT = "/cgi-bin/externalcontact/group_welcome_template/edit"; @@ -281,6 +412,15 @@ interface ExternalContact { String UPLOAD_ATTACHMENT = "/cgi-bin/media/upload_attachment"; + String GET_SUBSCRIBE_QR_CODE = "/cgi-bin/externalcontact/get_subscribe_qr_code"; + String SET_SUBSCRIBE_MODE = "/cgi-bin/externalcontact/set_subscribe_mode"; + String GET_SUBSCRIBE_MODE = "/cgi-bin/externalcontact/get_subscribe_mode"; + String EXTERNAL_CONTACT_GET = "/cgi-bin/externalcontact/get?external_userid="; + + String ADD_INTERCEPT_RULE = "/cgi-bin/externalcontact/add_intercept_rule"; + String UPDATE_INTERCEPT_RULE = "/cgi-bin/externalcontact/update_intercept_rule"; + String DEL_INTERCEPT_RULE = "/cgi-bin/externalcontact/del_intercept_rule"; + } interface Kf { @@ -302,6 +442,18 @@ interface Kf { String SEND_MSG_ON_EVENT = "/cgi-bin/kf/send_msg_on_event"; String CUSTOMER_BATCH_GET = "/cgi-bin/kf/customer/batchget"; + String GET_CORP_STATISTIC = "/cgi-bin/kf/get_corp_statistic"; + String CUSTOMER_GET_UPGRADE_SERVICE_CONFIG = "/cgi-bin/kf/customer/get_upgrade_service_config"; + String CUSTOMER_UPGRADE_SERVICE = "/cgi-bin/kf/customer/upgrade_service"; + String CUSTOMER_CANCEL_UPGRADE_SERVICE = "/cgi-bin/kf/customer/cancel_upgrade_service"; + + } + interface Export { + String SIMPLE_USER = "/cgi-bin/export/simple_user"; + String USER = "/cgi-bin/export/user"; + String DEPARTMENT = "/cgi-bin/export/department"; + String TAG_USER = "/cgi-bin/export/taguser"; + String GET_RESULT = "/cgi-bin/export/get_result?jobid=%s"; } } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpConsts.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpConsts.java index 0c7648a9e..8d8f09271 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpConsts.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpConsts.java @@ -94,7 +94,7 @@ public static class EventType { public static final String TASKCARD_CLICK = "taskcard_click"; /** - * 企业成员添加外部联系人事件推送 + * 企业成员添加外部联系人事件推送 & 会话存档客户同意进行聊天内容存档事件回调事件 */ public static final String CHANGE_EXTERNAL_CONTACT = "change_external_contact"; @@ -110,6 +110,7 @@ public static class EventType { /** * 企业微信审批事件推送(自建应用审批) + * https://developer.work.weixin.qq.com/document/path/90269 */ public static final String OPEN_APPROVAL_CHANGE = "open_approval_change"; @@ -143,6 +144,61 @@ public static class EventType { */ public static final String DELETE_SCHEDULE = "delete_schedule"; + /** + * 家校通讯录事件 + */ + public static final String CHANGE_SCHOOL_CONTACT = "change_school_contact"; + + /** + * 产生会话回调事件 + */ + public static final String MSGAUDIT_NOTIFY = "msgaudit_notify"; + + /** + * 直播回调事件 + */ + public static final String LIVING_STATUS_CHANGE = "living_status_change"; + + } + + /** + * 会话存档事件CHANGE_TYPE + * https://developer.work.weixin.qq.com/document/path/92005 + */ + @UtilityClass + public static class MsgAuditChangeType { + + public static final String MSG_AUDIT_APPROVED = "msg_audit_approved"; + + } + + /** + * 家校通讯录变更事件CHANGE_TYPE + */ + @UtilityClass + public static class SchoolContactChangeType { + + /** + * 部门变更事件 + * https://developer.work.weixin.qq.com/document/path/92052 + */ + public static final String CREATE_DEPARTMENT = "create_department"; + public static final String UPDATE_DEPARTMENT = "update_department"; + public static final String DELETE_DEPARTMENT = "delete_department"; + + /** + * 成员变更事件 + * https://developer.work.weixin.qq.com/document/path/92032 + */ + public static final String CREATE_STUDENT = "create_student"; + public static final String UPDATE_STUDENT = "update_student"; + public static final String DELETE_STUDENT = "delete_student"; + public static final String CREATE_PARENT = "create_parent"; + public static final String UPDATE_PARENT = "update_parent"; + public static final String DELETE_PARENT = "delete_parent"; + public static final String SUBSCRIBE = "subscribe"; + public static final String UNSUBSCRIBE = "unsubscribe"; + } /** @@ -215,7 +271,7 @@ public static class ExternalChatUpdateDetail { */ public static final String DEL_MEMBER = "del_member"; /** - * 成员退群 + * 群主变更 */ public static final String CHANGE_OWNER = "change_owner"; /** @@ -228,8 +284,9 @@ public static class ExternalChatUpdateDetail { public static final String CHANGE_NOTICE = "change_notice"; } } + @UtilityClass - public static class ExternalTagChangeType{ + public static class ExternalTagChangeType { /** * 创建企业客户标签 @@ -250,7 +307,7 @@ public static class ExternalTagChangeType{ } @UtilityClass - public static class TageType{ + public static class TageType { /** * 标签 */ @@ -373,6 +430,12 @@ public static class GroupRobotMsgType { * 图文消息(点击跳转到外链). */ public static final String NEWS = "news"; + + /** + * 文件类型消息. + */ + public static final String FILE = "file"; + } /** diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpTpConsts.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpTpConsts.java index 40270270c..e050c2115 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpTpConsts.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpTpConsts.java @@ -47,6 +47,48 @@ public static class InfoType { */ public static final String CHANGE_EXTERNAL_CONTACT = "change_external_contact"; + /** + * 下单成功通知 + */ + public static final String OPEN_ORDER = "open_order"; + + /** + * 改单通知 + */ + public static final String CHANGE_ORDER = "change_order"; + + /** + * 支付成功通知 + */ + public static final String PAY_FOR_APP_SUCCESS = "pay_for_app_success"; + + /** + * 退款通知 + */ + public static final String REFUND = "refund"; + + /** + * 付费版本变更通知 + */ + public static final String CHANGE_EDITION = "change_editon"; + + + /** + * 接口许可失效通知 + */ + public static final String UNLICENSED_NOTIFY = "unlicensed_notify"; + + /** + * 支付成功通知 + */ + public static final String LICENSE_PAY_SUCCESS = "license_pay_success"; + + /** + * 退款结果通知 + */ + public static final String LICENSE_REFUND = "license_refund"; + + } } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/message/WxCpMessageRouter.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/message/WxCpMessageRouter.java index a0464a725..c027159bc 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/message/WxCpMessageRouter.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/message/WxCpMessageRouter.java @@ -5,6 +5,7 @@ import me.chanjar.weixin.common.api.WxErrorExceptionHandler; import me.chanjar.weixin.common.api.WxMessageDuplicateChecker; import me.chanjar.weixin.common.api.WxMessageInMemoryDuplicateChecker; +import me.chanjar.weixin.common.api.WxMessageInMemoryDuplicateCheckerSingleton; import me.chanjar.weixin.common.session.InternalSession; import me.chanjar.weixin.common.session.InternalSessionManager; import me.chanjar.weixin.common.session.WxSessionManager; @@ -71,11 +72,46 @@ public WxCpMessageRouter(WxCpService wxCpService) { ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("WxCpMessageRouter-pool-%d").build(); this.executorService = new ThreadPoolExecutor(DEFAULT_THREAD_POOL_SIZE, DEFAULT_THREAD_POOL_SIZE, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), namedThreadFactory); - this.messageDuplicateChecker = new WxMessageInMemoryDuplicateChecker(); + this.messageDuplicateChecker = WxMessageInMemoryDuplicateCheckerSingleton.getInstance(); this.sessionManager = wxCpService.getSessionManager(); this.exceptionHandler = new LogExceptionHandler(); } + /** + * 使用自定义的 {@link ExecutorService}. + */ + public WxCpMessageRouter(WxCpService wxMpService, ExecutorService executorService) { + this.wxCpService = wxMpService; + this.executorService = executorService; + this.messageDuplicateChecker = WxMessageInMemoryDuplicateCheckerSingleton.getInstance(); + this.sessionManager = wxCpService.getSessionManager(); + this.exceptionHandler = new LogExceptionHandler(); + } + + /** + * 系统退出前,应该调用该方法 + */ + public void shutDownExecutorService() { + this.executorService.shutdown(); + } + + /** + * 系统退出前,应该调用该方法,增加了超时时间检测 + */ + public void shutDownExecutorService(Integer second) { + this.executorService.shutdown(); + try { + if (!this.executorService.awaitTermination(second, TimeUnit.SECONDS)) { + this.executorService.shutdownNow(); + if (!this.executorService.awaitTermination(second, TimeUnit.SECONDS)) + log.error("线程池未关闭!"); + } + } catch (InterruptedException ie) { + this.executorService.shutdownNow(); + Thread.currentThread().interrupt(); + } + } + /** *
    * 设置自定义的 {@link ExecutorService}
@@ -219,8 +255,8 @@ private boolean isMsgDuplicated(WxCpXmlMessage wxMessage) {
     return this.messageDuplicateChecker.isDuplicate(messageId.toString());
   }
 
-  private void append(StringBuilder sb, String value){
-    if(StringUtils.isNotEmpty(value)){
+  private void append(StringBuilder sb, String value) {
+    if (StringUtils.isNotEmpty(value)) {
       sb.append("-").append(value);
     }
   }
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/message/WxCpTpMessageRouter.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/message/WxCpTpMessageRouter.java
index 5b045082a..848f089c6 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/message/WxCpTpMessageRouter.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/message/WxCpTpMessageRouter.java
@@ -5,6 +5,7 @@
 import me.chanjar.weixin.common.api.WxErrorExceptionHandler;
 import me.chanjar.weixin.common.api.WxMessageDuplicateChecker;
 import me.chanjar.weixin.common.api.WxMessageInMemoryDuplicateChecker;
+import me.chanjar.weixin.common.api.WxMessageInMemoryDuplicateCheckerSingleton;
 import me.chanjar.weixin.common.session.InternalSession;
 import me.chanjar.weixin.common.session.InternalSessionManager;
 import me.chanjar.weixin.common.session.WxSessionManager;
@@ -73,11 +74,46 @@ public WxCpTpMessageRouter(WxCpTpService wxCpTpService) {
     ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("WxCpTpMessageRouter-pool-%d").build();
     this.executorService = new ThreadPoolExecutor(DEFAULT_THREAD_POOL_SIZE, DEFAULT_THREAD_POOL_SIZE,
       0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), namedThreadFactory);
-    this.messageDuplicateChecker = new WxMessageInMemoryDuplicateChecker();
+    this.messageDuplicateChecker = WxMessageInMemoryDuplicateCheckerSingleton.getInstance();
     this.sessionManager = wxCpTpService.getSessionManager();
     this.exceptionHandler = new LogExceptionHandler();
   }
 
+  /**
+   * 使用自定义的 {@link ExecutorService}.
+   */
+  public WxCpTpMessageRouter(WxCpTpService wxCpTpService, ExecutorService executorService) {
+    this.wxCpTpService = wxCpTpService;
+    this.executorService = executorService;
+    this.messageDuplicateChecker = WxMessageInMemoryDuplicateCheckerSingleton.getInstance();
+    this.sessionManager = wxCpTpService.getSessionManager();
+    this.exceptionHandler = new LogExceptionHandler();
+  }
+
+  /**
+   * 系统退出前,应该调用该方法
+   */
+  public void shutDownExecutorService() {
+    this.executorService.shutdown();
+  }
+
+  /**
+   * 系统退出前,应该调用该方法,增加了超时时间检测
+   */
+  public void shutDownExecutorService(Integer second) {
+    this.executorService.shutdown();
+    try {
+      if (!this.executorService.awaitTermination(second, TimeUnit.SECONDS)) {
+        this.executorService.shutdownNow();
+        if (!this.executorService.awaitTermination(second, TimeUnit.SECONDS))
+          log.error("线程池未关闭!");
+      }
+    } catch (InterruptedException ie) {
+      this.executorService.shutdownNow();
+      Thread.currentThread().interrupt();
+    }
+  }
+
   /**
    * 
    * 设置自定义的 {@link ExecutorService}
@@ -200,30 +236,29 @@ public WxCpXmlOutMessage route(final WxCpTpXmlMessage wxMessage) {
 
   private boolean isMsgDuplicated(WxCpTpXmlMessage wxMessage) {
     StringBuilder messageId = new StringBuilder();
-      if (wxMessage.getInfoType() != null) {
-        messageId.append(wxMessage.getInfoType())
-          .append("-").append(StringUtils.trimToEmpty(wxMessage.getSuiteId()))
-          .append("-").append(wxMessage.getTimeStamp())
-          .append("-").append(StringUtils.trimToEmpty(wxMessage.getAuthCorpId()))
-          .append("-").append(StringUtils.trimToEmpty(wxMessage.getUserID()))
-          .append("-").append(StringUtils.trimToEmpty(wxMessage.getChangeType()))
-          .append("-").append(StringUtils.trimToEmpty(wxMessage.getServiceCorpId()));
-      }
+    if (wxMessage.getInfoType() != null) {
+      messageId.append(wxMessage.getInfoType())
+        .append("-").append(StringUtils.trimToEmpty(wxMessage.getSuiteId()))
+        .append("-").append(wxMessage.getTimeStamp())
+        .append("-").append(StringUtils.trimToEmpty(wxMessage.getAuthCorpId()))
+        .append("-").append(StringUtils.trimToEmpty(wxMessage.getUserID()))
+        .append("-").append(StringUtils.trimToEmpty(wxMessage.getChangeType()))
+        .append("-").append(StringUtils.trimToEmpty(wxMessage.getServiceCorpId()));
+    }
 
-      if (wxMessage.getMsgType() != null) {
-        if (wxMessage.getMsgId() != null) {
-          messageId.append(wxMessage.getMsgId())
-            .append("-").append(wxMessage.getCreateTime())
-            .append("-").append(wxMessage.getFromUserName());
-        }
-        else {
-          messageId.append(wxMessage.getMsgType())
-            .append("-").append(wxMessage.getCreateTime())
-            .append("-").append(wxMessage.getFromUserName())
-            .append("-").append(StringUtils.trimToEmpty(wxMessage.getEvent()))
-            .append("-").append(StringUtils.trimToEmpty(wxMessage.getEventKey()));
-        }
+    if (wxMessage.getMsgType() != null) {
+      if (wxMessage.getMsgId() != null) {
+        messageId.append(wxMessage.getMsgId())
+          .append("-").append(wxMessage.getCreateTime())
+          .append("-").append(wxMessage.getFromUserName());
+      } else {
+        messageId.append(wxMessage.getMsgType())
+          .append("-").append(wxMessage.getCreateTime())
+          .append("-").append(wxMessage.getFromUserName())
+          .append("-").append(StringUtils.trimToEmpty(wxMessage.getEvent()))
+          .append("-").append(StringUtils.trimToEmpty(wxMessage.getEventKey()));
       }
+    }
 
     return this.messageDuplicateChecker.isDuplicate(messageId.toString());
   }
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpEditionService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpEditionService.java
new file mode 100644
index 000000000..4f88e9471
--- /dev/null
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpEditionService.java
@@ -0,0 +1,33 @@
+package me.chanjar.weixin.cp.tp.service;
+
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.cp.bean.WxCpTpProlongTryResult;
+
+
+/**
+ * 应用版本付费版本相关接口
+ *
+ * @author leiguoqing
+ * @date 2022年4月24日
+ */
+public interface WxCpTpEditionService {
+
+  /**
+   * 延长试用期
+   * 

+ * 文档地址 + *

+ * 注意: + *

    + *
  • 一个应用可以多次延长试用,但是试用总天数不能超过60天
  • + *
  • 仅限时试用或试用过期状态下的应用可以延长试用期
  • + *
+ * + * @param buyerCorpId 购买方corpId + * @param prolongDays 延长天数 + * @param appId 仅旧套件需要填此参数 + * @return the order + * @throws WxErrorException the wx error exception + */ + WxCpTpProlongTryResult prolongTry(String buyerCorpId, Integer prolongDays, String appId) throws WxErrorException; +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpLicenseService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpLicenseService.java new file mode 100644 index 000000000..8f25e5e5e --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpLicenseService.java @@ -0,0 +1,212 @@ +package me.chanjar.weixin.cp.tp.service; + +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.bean.license.WxCpTpLicenseActiveAccount; +import me.chanjar.weixin.cp.bean.license.WxCpTpLicenseTransfer; +import me.chanjar.weixin.cp.bean.license.account.*; +import me.chanjar.weixin.cp.bean.license.order.*; + +import java.util.Collection; +import java.util.Date; +import java.util.List; + +/** + *
+ * 服务商接口调用许可相关接口
+ * 文档地址:https://developer.work.weixin.qq.com/document/path/95652
+ * 
+ * @author Totoro + * @date 2022/6/27 10:57 + */ +public interface WxCpTpLicenseService { + + + /** + * 下单购买帐号 + * 服务商下单为企业购买新的帐号,可以同时购买基础帐号与互通帐号。 + * 下单之后,需要到服务商管理端发起支付,支付完成之后,订单才能生效。 + * 文档地址:https://developer.work.weixin.qq.com/document/path/95644 + * @param licenseNewOrderRequest 订单信息 + * @return 订单ID + * @throws WxErrorException; + */ + WxCpTpLicenseCreateOrderResp createNewOrder(WxCpTpLicenseNewOrderRequest licenseNewOrderRequest) throws WxErrorException; + + + /** + * 创建下单续期帐号任务 + *
+   *  可以下单为一批已激活帐号的成员续期,续期下单分为两个步骤:
+   * 传入userid列表创建一个任务,创建之后,可以往同一个任务继续追加待续期的userid列表;
+   * 根据步骤1得到的jobid提交订单。
+   * 
+ * @param licenseRenewOrderJobRequest 续费订单信息 + * @return 返回JobId + * @throws WxErrorException; + */ + WxCpTpLicenseRenewOrderJobResp createRenewOrderJob(WxCpTpLicenseRenewOrderJobRequest licenseRenewOrderJobRequest) throws WxErrorException; + + + + /** + * 提交续期订单 + * 创建续期任务之后,需要调用该接口,以提交订单任务。 + * 注意,提交之后,需要到服务商管理端发起支付,支付完成之后,订单才能生效。 + * 文档地址:https://developer.work.weixin.qq.com/document/path/95646 + * @param licenseRenewOrderRequest 订单信息 + * @return 订单ID + * @throws WxErrorException; + */ + WxCpTpLicenseCreateOrderResp submitRenewOrder(WxCpTpLicenseRenewOrderRequest licenseRenewOrderRequest) throws WxErrorException; + + + /** + * 获取订单列表 + * 服务商查询自己某段时间内的平台能力服务订单列表 + * 文档地址:https://developer.work.weixin.qq.com/document/path/95647 + * @param corpId 企业ID + * @param startTime 开始时间,下单时间。可不填。但是不能单独指定该字段,start_time跟end_time必须同时指定。 + * @param endTime 结束时间,下单时间。起始时间跟结束时间不能超过31天。可不填。但是不能单独指定该字段,start_time跟end_time必须同时指定。 + * @param cursor 用于分页查询的游标,字符串类型,由上一次调用返回,首次调用可不填 + * @param limit 返回的最大记录数,整型,最大值1000,默认值500 + * @return 订单列表 + * @throws WxErrorException; + */ + WxCpTpLicenseOrderListResp getOrderList(String corpId, Date startTime, Date endTime, String cursor, int limit) throws WxErrorException; + + + /** + * 获取订单详情 + * 查询某个订单的详情,包括订单的状态、基础帐号个数、互通帐号个数、帐号购买时长等。 + * 注意,该接口不返回订单中的帐号激活码列表或者续期的帐号成员列表,请调用获取订单中的帐号列表接口以获取帐号列表。 + * @param orderId 订单ID + * @return 单条订单信息 + * @throws WxErrorException; + */ + WxCpTpLicenseOrderInfoResp getOrderInfo(String orderId) throws WxErrorException; + + + /** + * 查询指定订单下的平台能力服务帐号列表。 + * 若为购买帐号的订单或者存量企业的版本付费迁移订单,则返回帐号激活码列表; + * 若为续期帐号的订单,则返回续期帐号的成员列表。注意,若是购买帐号的订单, + * 则仅订单支付完成时,系统才会生成帐号,故支付完成之前,该接口不会返回帐号激活码。 + * 文档地址:https://developer.work.weixin.qq.com/document/path/95649 + * @param orderId 订单ID + * @param limit 大小 + * @param cursor 分页游标 + * @return 订单账号列表 + * @throws WxErrorException; + */ + WxCpTpLicenseOrderAccountListResp getOrderAccountList(String orderId, int limit, String cursor) throws WxErrorException; + + + /** + * 激活帐号 + * 下单购买帐号并支付完成之后,先调用获取订单中的帐号列表接口获取到帐号激活码, + * 然后可以调用该接口将激活码绑定到某个企业员工,以对其激活相应的平台服务能力。 + * 文档地址:https://developer.work.weixin.qq.com/document/path/95553 + * @param code 激活码 + * @param corpId 企业ID + * @param userId 用户ID + * @return 激活结果 + * @throws WxErrorException; + */ + WxCpBaseResp activeCode(String code, String corpId, String userId) throws WxErrorException; + + + /** + * 批量激活帐号 + * 可在一次请求里为一个企业的多个成员激活许可帐号,便于服务商批量化处理。 + * 一个userid允许激活一个基础帐号以及一个互通帐号。 + * 单次激活的员工数量不超过1000 + * @param corpId 企业ID + * @param activeAccountList 激活列表 + * @return 激活结果 + * @throws WxErrorException; + */ + WxCpTpLicenseBatchActiveResultResp batchActiveCode(String corpId, List activeAccountList) throws WxErrorException; + + + /** + * 获取激活码详情 + * 查询某个帐号激活码的状态以及激活绑定情况。 + * 文档地址:https://developer.work.weixin.qq.com/document/path/95552 + * @param code 激活码 + * @param corpId 企业ID + * @return 激活码信息 + * @throws WxErrorException; + */ + WxCpTpLicenseCodeInfoResp getActiveInfoByCode(String code, String corpId) throws WxErrorException; + + + /** + * 获取激活码详情 + * 查询某个帐号激活码的状态以及激活绑定情况。 + * 文档地址:https://developer.work.weixin.qq.com/document/path/95552 + * @param codes 激活码 + * @param corpId 企业ID + * @return 激活码信息 + * @throws WxErrorException; + */ + WxCpTpLicenseBatchCodeInfoResp batchGetActiveInfoByCode(Collection codes, String corpId) throws WxErrorException; + + + /** + * 获取企业的帐号列表 + * 查询指定企业下的平台能力服务帐号列表。 + * 文档地址:https://developer.work.weixin.qq.com/document/path/95544 + * @param corpId 企业ID + * @param limit 大小 + * @param cursor 游标 + * @return 已激活列表 + * @throws WxErrorException + */ + WxCpTpLicenseCorpAccountListResp getCorpAccountList(String corpId, int limit, String cursor) throws WxErrorException; + + + /** + * 获取成员的激活详情 + * 查询某个企业成员的激活情况。 + * 文档地址:https://developer.work.weixin.qq.com/document/path/95555 + * @param corpId 企业ID + * @param userId 用户ID + * @return 激活情况 + * @throws WxErrorException; + */ + WxCpTpLicenseActiveInfoByUserResp getActiveInfoByUser(String corpId, String userId) throws WxErrorException; + + + /** + * 帐号继承 + * 在企业员工离职或者工作范围的有变更时,允许将其许可帐号继承给其他员工。 + * @param corpId 企业ID + * @param transferList 转移列表 + * @return 转移结果 + * @throws WxErrorException; + */ + WxCpTpLicenseBatchTransferResp batchTransferLicense(String corpId, List transferList) throws WxErrorException; + + + + + + + + + + + + + + + + + + + + + + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpOrderService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpOrderService.java new file mode 100644 index 000000000..d2288860c --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpOrderService.java @@ -0,0 +1,44 @@ +package me.chanjar.weixin.cp.tp.service; + +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.bean.order.WxCpTpOrderDetails; +import me.chanjar.weixin.cp.bean.order.WxCpTpOrderListGetResult; + +import java.util.Date; + + +/** + * 应用版本付费订单相关接口 + * + * @author leiguoqing + * @date 2022年4月24日 + */ +public interface WxCpTpOrderService { + + /** + * 获取订单详情 + *

+ * 文档地址 + *

+ * + * @param orderId 订单号 + * @return the order + * @throws WxErrorException the wx error exception + */ + WxCpTpOrderDetails getOrder(String orderId) throws WxErrorException; + + + /** + * 获取订单列表 + *

+ * 文档地址 + *

+ * + * @param startTime 起始时间 + * @param endTime 终止时间 + * @param testMode 指定拉取正式或测试模式的订单。默认正式模式。0-正式模式,1-测试模式。 + * @return the order + * @throws WxErrorException the wx error exception + */ + WxCpTpOrderListGetResult getOrderList(Date startTime, Date endTime, Integer testMode) throws WxErrorException; +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpService.java index bd44911fe..8c7615d8d 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpService.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpService.java @@ -474,6 +474,21 @@ public interface WxCpTpService { */ void setWxCpTpUserService(WxCpTpUserService wxCpTpUserService); + /** + * set license service + * + * @param wxCpTpLicenseService the oa service + */ + void setWxCpTpLicenseService(WxCpTpLicenseService wxCpTpLicenseService); + + + /** + * get license service + * + * @return getCpTPLicenseService wx cp tp license service + */ + WxCpTpLicenseService getWxCpTpLicenseService(); + /** * 获取应用的管理员列表 * @@ -530,4 +545,31 @@ public interface WxCpTpService { */ void expireProviderToken(); + /** + * 获取应用版本付费订单相关接口服务 + * + * @return the wx cp tp order service + */ + WxCpTpOrderService getWxCpTpOrderService(); + + /** + * 设置应用版本付费订单相关接口服务 + * + * @param wxCpTpOrderService the wx cp tp order service + */ + void setWxCpTpOrderService(WxCpTpOrderService wxCpTpOrderService); + + /** + * 获取应用版本付费版本相关接口服务 + * + * @return the wx cp tp edition service + */ + WxCpTpEditionService getWxCpTpEditionService(); + + /** + * 设置应用版本付费版本相关接口服务 + * + * @param wxCpTpEditionService the wx cp tp edition service + */ + void setWxCpTpOrderService(WxCpTpEditionService wxCpTpEditionService); } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/BaseWxCpTpServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/BaseWxCpTpServiceImpl.java index 03316b9ae..768164096 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/BaseWxCpTpServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/BaseWxCpTpServiceImpl.java @@ -48,6 +48,9 @@ public abstract class BaseWxCpTpServiceImpl implements WxCpTpService, Requ private WxCpTpMediaService wxCpTpMediaService = new WxCpTpMediaServiceImpl(this); private WxCpTpOAService wxCpTpOAService = new WxCpTpOAServiceImpl(this); private WxCpTpUserService wxCpTpUserService = new WxCpTpUserServiceImpl(this); + private WxCpTpOrderService wxCpTpOrderService = new WxCpTpOrderServiceImpl(this); + private WxCpTpEditionService wxCpTpEditionService = new WxCpTpEditionServiceImpl(this); + private WxCpTpLicenseService wxCpTpLicenseService = new WxCpTpLicenseServiceImpl(this); /** * 全局的是否正在刷新access token的锁. @@ -545,6 +548,18 @@ public void setWxCpTpOAService(WxCpTpOAService wxCpTpOAService) { this.wxCpTpOAService = wxCpTpOAService; } + + @Override + public WxCpTpLicenseService getWxCpTpLicenseService() { + return wxCpTpLicenseService; + } + + + @Override + public void setWxCpTpLicenseService(WxCpTpLicenseService wxCpTpLicenseService) { + this.wxCpTpLicenseService = wxCpTpLicenseService; + } + @Override public void setWxCpTpUserService(WxCpTpUserService wxCpTpUserService) { this.wxCpTpUserService = wxCpTpUserService; @@ -594,6 +609,26 @@ public void expireProviderToken() { this.configStorage.expireProviderToken(); } + @Override + public WxCpTpOrderService getWxCpTpOrderService() { + return wxCpTpOrderService; + } + + @Override + public void setWxCpTpOrderService(WxCpTpOrderService wxCpTpOrderService) { + this.wxCpTpOrderService = wxCpTpOrderService; + } + + @Override + public WxCpTpEditionService getWxCpTpEditionService() { + return wxCpTpEditionService; + } + + @Override + public void setWxCpTpOrderService(WxCpTpEditionService wxCpTpEditionService) { + this.wxCpTpEditionService = wxCpTpEditionService; + } + private WxJsapiSignature doCreateWxJsapiSignature(String url, String authCorpId, String jsapiTicket) { long timestamp = System.currentTimeMillis() / 1000; String noncestr = RandomUtils.getRandomStr(); diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpEditionServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpEditionServiceImpl.java new file mode 100644 index 000000000..8a6a71352 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpEditionServiceImpl.java @@ -0,0 +1,52 @@ +package me.chanjar.weixin.cp.tp.service.impl; + +import com.google.gson.JsonObject; +import lombok.RequiredArgsConstructor; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.bean.WxCpTpProlongTryResult; +import me.chanjar.weixin.cp.tp.service.WxCpTpEditionService; +import me.chanjar.weixin.cp.tp.service.WxCpTpService; + +import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Tp.PROLONG_TRY; + +/** + * 应用版本付费版本相关接口实现 + * + * @author leigouqing + * @date 2022年4月24日 + */ +@RequiredArgsConstructor +public class WxCpTpEditionServiceImpl implements WxCpTpEditionService { + + /** + * The Main service. + */ + private final WxCpTpService mainService; + + /** + * 延长试用期 + *

+ * 文档地址 + *

+ *

    + *
  • 一个应用可以多次延长试用,但是试用总天数不能超过60天
  • + *
  • 仅限时试用或试用过期状态下的应用可以延长试用期
  • + *
+ * + * @param buyerCorpId 购买方corpId + * @param prolongDays 延长天数 + * @param appId 仅旧套件需要填此参数 + * @return the order + * @throws WxErrorException the wx error exception + */ + @Override + public WxCpTpProlongTryResult prolongTry(String buyerCorpId, Integer prolongDays, String appId) throws WxErrorException { + String url = mainService.getWxCpTpConfigStorage().getApiUrl(PROLONG_TRY); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("buyer_corpid", buyerCorpId); + jsonObject.addProperty("prolong_days", prolongDays); + jsonObject.addProperty("appid", appId); + String result = mainService.post(url, jsonObject.toString()); + return WxCpTpProlongTryResult.fromJson(result); + } +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpLicenseServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpLicenseServiceImpl.java new file mode 100644 index 000000000..ea4d3d9c8 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpLicenseServiceImpl.java @@ -0,0 +1,193 @@ +package me.chanjar.weixin.cp.tp.service.impl; + +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import lombok.RequiredArgsConstructor; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.bean.license.WxCpTpLicenseActiveAccount; +import me.chanjar.weixin.cp.bean.license.WxCpTpLicenseTransfer; +import me.chanjar.weixin.cp.bean.license.account.*; +import me.chanjar.weixin.cp.bean.license.order.*; +import me.chanjar.weixin.cp.config.WxCpTpConfigStorage; +import me.chanjar.weixin.cp.tp.service.WxCpTpLicenseService; +import me.chanjar.weixin.cp.tp.service.WxCpTpService; + +import java.util.*; + +import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.License.*; + +/** + * @author Totoro + * @date 2022/6/27 11:03 + */ +@RequiredArgsConstructor +public class WxCpTpLicenseServiceImpl implements WxCpTpLicenseService { + + private final WxCpTpService mainService; + + @Override + public WxCpTpLicenseCreateOrderResp createNewOrder(WxCpTpLicenseNewOrderRequest licenseNewOrderRequest) throws WxErrorException { + String resultText = mainService.post(getWxCpTpConfigStorage().getApiUrl(CREATE_NEW_ORDER) + + getProviderAccessToken(), licenseNewOrderRequest.toJson()); + return WxCpTpLicenseCreateOrderResp.fromJson(resultText); + } + + + @Override + public WxCpTpLicenseRenewOrderJobResp createRenewOrderJob(WxCpTpLicenseRenewOrderJobRequest licenseRenewOrderJobRequest) throws WxErrorException { + String resultText = mainService.post(getWxCpTpConfigStorage().getApiUrl(CREATE_RENEW_ORDER_JOB) + + getProviderAccessToken(), licenseRenewOrderJobRequest.toJson()); + return WxCpTpLicenseRenewOrderJobResp.fromJson(resultText); + } + + + @Override + public WxCpTpLicenseCreateOrderResp submitRenewOrder(WxCpTpLicenseRenewOrderRequest licenseRenewOrderRequest) throws WxErrorException { + String resultText = mainService.post(getWxCpTpConfigStorage().getApiUrl(SUBMIT_ORDER_JOB) + + getProviderAccessToken(), licenseRenewOrderRequest.toJson()); + return WxCpTpLicenseCreateOrderResp.fromJson(resultText); + } + + + @Override + public WxCpTpLicenseOrderListResp getOrderList(String corpId, Date startTime, Date endTime, String cursor, int limit) throws WxErrorException { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("corpid", corpId); + jsonObject.addProperty("cursor", cursor); + jsonObject.addProperty("limit", limit); + if(startTime != null) { + jsonObject.addProperty("start_time", startTime.getTime() / 1000); + } + if(endTime != null) { + jsonObject.addProperty("end_time", endTime.getTime() / 1000); + } + String resultText = mainService.post(getWxCpTpConfigStorage().getApiUrl(LIST_ORDER) + + getProviderAccessToken(), jsonObject.toString()); + return WxCpTpLicenseOrderListResp.fromJson(resultText); + } + + + @Override + public WxCpTpLicenseOrderInfoResp getOrderInfo(String orderId) throws WxErrorException { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("order_id", orderId); + String resultText = mainService.post(getWxCpTpConfigStorage().getApiUrl(GET_ORDER) + + getProviderAccessToken(), jsonObject.toString()); + return WxCpTpLicenseOrderInfoResp.fromJson(resultText); + } + + @Override + public WxCpTpLicenseOrderAccountListResp getOrderAccountList(String orderId, int limit, String cursor) throws WxErrorException { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("order_id", orderId); + jsonObject.addProperty("cursor", cursor); + jsonObject.addProperty("limit", limit); + String resultText = mainService.post(getWxCpTpConfigStorage().getApiUrl(LIST_ORDER_ACCOUNT) + + getProviderAccessToken(), jsonObject.toString()); + return WxCpTpLicenseOrderAccountListResp.fromJson(resultText); + } + + @Override + public WxCpBaseResp activeCode(String code, String corpId, String userId) throws WxErrorException { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("active_code", code); + jsonObject.addProperty("corpid", corpId); + jsonObject.addProperty("userid", userId); + String resultText = mainService.post(getWxCpTpConfigStorage().getApiUrl(ACTIVE_ACCOUNT) + + getProviderAccessToken(), jsonObject.toString()); + return WxCpBaseResp.fromJson(resultText); + } + + @Override + public WxCpTpLicenseBatchActiveResultResp batchActiveCode(String corpId, List activeAccountList) throws WxErrorException { + Map map = new HashMap<>(2); + map.put("corpid", corpId); + map.put("active_list", activeAccountList); + GsonBuilder gsonBuilder = new GsonBuilder(); + String resultText = mainService.post(getWxCpTpConfigStorage().getApiUrl(BATCH_ACTIVE_ACCOUNT) + + getProviderAccessToken(), gsonBuilder.create().toJson(map)); + return WxCpTpLicenseBatchActiveResultResp.fromJson(resultText); + } + + @Override + public WxCpTpLicenseCodeInfoResp getActiveInfoByCode(String code, String corpId) throws WxErrorException { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("active_code", code); + jsonObject.addProperty("corpid", corpId); + String resultText = mainService.post(getWxCpTpConfigStorage().getApiUrl(GET_ACTIVE_INFO_BY_CODE) + + getProviderAccessToken(), jsonObject.toString()); + return WxCpTpLicenseCodeInfoResp.fromJson(resultText); + } + + @Override + public WxCpTpLicenseBatchCodeInfoResp batchGetActiveInfoByCode(Collection codes, String corpId) throws WxErrorException { + JsonObject jsonObject = new JsonObject(); + JsonArray list = new JsonArray(); + for (String code : codes) { + list.add(new JsonPrimitive(code)); + } + jsonObject.add("active_code_list", list); + jsonObject.addProperty("corpid", corpId); + String resultText = mainService.post(getWxCpTpConfigStorage().getApiUrl(BATCH_GET_ACTIVE_INFO_BY_CODE) + + getProviderAccessToken(), jsonObject.toString()); + return WxCpTpLicenseBatchCodeInfoResp.fromJson(resultText); + } + + @Override + public WxCpTpLicenseCorpAccountListResp getCorpAccountList(String corpId, int limit, String cursor) throws WxErrorException { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("corpid", corpId); + jsonObject.addProperty("cursor", cursor); + jsonObject.addProperty("limit", limit); + String resultText = mainService.post(getWxCpTpConfigStorage().getApiUrl(LIST_ACTIVED_ACCOUNT) + + getProviderAccessToken(), jsonObject.toString()); + return WxCpTpLicenseCorpAccountListResp.fromJson(resultText); + } + + @Override + public WxCpTpLicenseActiveInfoByUserResp getActiveInfoByUser(String corpId, String userId) throws WxErrorException { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("corpid", corpId); + jsonObject.addProperty("userid", userId); + String resultText = mainService.post(getWxCpTpConfigStorage().getApiUrl(GET_ACTIVE_INFO_BY_USER) + + getProviderAccessToken(), jsonObject.toString()); + return WxCpTpLicenseActiveInfoByUserResp.fromJson(resultText); + } + + @Override + public WxCpTpLicenseBatchTransferResp batchTransferLicense(String corpId, List transferList) throws WxErrorException { + Map map = new HashMap<>(2); + map.put("corpid", corpId); + map.put("transfer_list", transferList); + GsonBuilder gsonBuilder = new GsonBuilder(); + String resultText = mainService.post(getWxCpTpConfigStorage().getApiUrl(BATCH_TRANSFER_LICENSE) + + getProviderAccessToken(), gsonBuilder.create().toJson(map)); + return WxCpTpLicenseBatchTransferResp.fromJson(resultText); + } + + + /** + * 获取服务商token的拼接参数 + * @return url + * @throws WxErrorException / + */ + private String getProviderAccessToken() throws WxErrorException { + return "?provider_access_token=" + mainService.getWxCpProviderToken(); + } + + + /** + * 获取tp参数配置 + * @return config + */ + private WxCpTpConfigStorage getWxCpTpConfigStorage() { + return mainService.getWxCpTpConfigStorage(); + } + + + + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpOrderServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpOrderServiceImpl.java new file mode 100644 index 000000000..6a598e007 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpOrderServiceImpl.java @@ -0,0 +1,71 @@ +package me.chanjar.weixin.cp.tp.service.impl; + +import com.google.gson.JsonObject; +import lombok.RequiredArgsConstructor; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.bean.order.WxCpTpOrderDetails; +import me.chanjar.weixin.cp.bean.order.WxCpTpOrderListGetResult; +import me.chanjar.weixin.cp.tp.service.WxCpTpOrderService; +import me.chanjar.weixin.cp.tp.service.WxCpTpService; + +import java.util.Date; + +import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Tp.GET_ORDER; +import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Tp.GET_ORDER_LIST; + +/** + * 应用版本付费订单相关接口实现 + * + * @author leigouqing + * @date 2022年4月24日 + */ +@RequiredArgsConstructor +public class WxCpTpOrderServiceImpl implements WxCpTpOrderService { + + /** + * The Main service. + */ + private final WxCpTpService mainService; + + /** + * 获取订单详情 + *

+ * 文档地址 + *

+ * + * @param orderId 订单号 + * @return the order + * @throws WxErrorException the wx error exception + */ + @Override + public WxCpTpOrderDetails getOrder(String orderId) throws WxErrorException { + String url = mainService.getWxCpTpConfigStorage().getApiUrl(GET_ORDER); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("orderid", orderId); + String result = this.mainService.post(url, jsonObject.toString()); + return WxCpTpOrderDetails.fromJson(result); + } + + /** + * 获取订单列表 + *

+ * 文档地址 + *

+ * + * @param startTime 起始时间 + * @param endTime 终止时间 + * @param testMode 指定拉取正式或测试模式的订单。默认正式模式。0-正式模式,1-测试模式。 + * @return the order list + * @throws WxErrorException the wx error exception + */ + @Override + public WxCpTpOrderListGetResult getOrderList(Date startTime, Date endTime, Integer testMode) throws WxErrorException { + String url = mainService.getWxCpTpConfigStorage().getApiUrl(GET_ORDER_LIST); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("start_time", startTime.getTime() / 1000); + jsonObject.addProperty("end_time", endTime.getTime() / 1000); + jsonObject.addProperty("test_mode", testMode); + String result = this.mainService.post(url, jsonObject.toString()); + return WxCpTpOrderListGetResult.fromJson(result); + } +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/crypto/WxCpCryptUtil.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/crypto/WxCpCryptUtil.java index d36a1ce34..8d6a68256 100755 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/crypto/WxCpCryptUtil.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/crypto/WxCpCryptUtil.java @@ -1,15 +1,18 @@ package me.chanjar.weixin.cp.util.crypto; -import com.google.common.base.CharMatcher; -import com.google.common.io.BaseEncoding; +import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.util.crypto.WxCryptUtil; import me.chanjar.weixin.cp.config.WxCpConfigStorage; -import org.apache.commons.codec.binary.Base64; +import org.apache.commons.lang3.StringUtils; +import sun.security.util.DerInputStream; +import sun.security.util.DerValue; import javax.crypto.Cipher; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.RSAPrivateCrtKeySpec; +import java.util.Base64; public class WxCpCryptUtil extends WxCryptUtil { public WxCpCryptUtil(WxCpConfigStorage wxCpConfigStorage) { @@ -24,33 +27,81 @@ public WxCpCryptUtil(WxCpConfigStorage wxCpConfigStorage) { this.token = token; this.appidOrCorpid = corpId; - this.aesKey = BaseEncoding.base64().decode(CharMatcher.whitespace().removeFrom(encodingAesKey)); + this.aesKey = Base64.getDecoder().decode(StringUtils.remove(encodingAesKey, " ")); } /** - * 会话存档接口解密私钥 - * 企业获取的会话内容将用公钥加密,企业用自行保存的私钥解开会话内容数据 + * 判断使用PKCS8或者PKCS1进行解密 + * + * @param encryptRandomKey 使用PUBLICKEY_VER指定版本的公钥进行非对称加密后base64加密的内容 + * @param msgAuditPriKey 会话存档私钥 + * @param pkcs1 使用什么方式进行解密,1代表使用PKCS1进行解密,2代表PKCS8进行解密 ... + * @return + * @throws Exception + */ + public static String decryptPriKey(String encryptRandomKey, String msgAuditPriKey, Integer pkcs1) throws Exception { + if (pkcs1 == null) { + throw new WxErrorException("请配置会话存档解密方式"); + } + + if (pkcs1.intValue() == 1) { + return decryptPriKeyByPKCS1(encryptRandomKey, msgAuditPriKey); + } + + return decryptPriKeyByPKCS8(encryptRandomKey, msgAuditPriKey); + } + + /** + * PKCS8 解密私钥 * * @param encryptRandomKey * @param msgAuditPriKey * @return * @throws Exception */ - public static String decryptByPriKey(String encryptRandomKey, String msgAuditPriKey) throws Exception { - String privateKey = msgAuditPriKey.replaceAll("\\n", "") + public static String decryptPriKeyByPKCS8(String encryptRandomKey, String msgAuditPriKey) throws Exception { + String privateKey = msgAuditPriKey.replaceAll("(\r\n|\r|\n|\n\r)", "") .replace("-----BEGIN PRIVATE KEY-----", "") .replace("-----END PRIVATE KEY-----", "") .replaceAll(" ", ""); - byte[] keyByte = Base64.decodeBase64(privateKey); - PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyByte); + byte[] keyBytes = Base64.getDecoder().decode(privateKey); + PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, priKey); - byte[] utf8 = cipher.doFinal(Base64.decodeBase64(encryptRandomKey)); + byte[] utf8 = cipher.doFinal(Base64.getDecoder().decode(encryptRandomKey)); + return new String(utf8, "UTF-8"); + } + /** + * 会话存档,PKCS1 解密私钥 + * 企业获取的会话内容将用公钥加密,企业用自行保存的私钥解开会话内容数据 + * + * @param encryptRandomKey 使用PUBLICKEY_VER指定版本的公钥进行非对称加密后base64加密的内容,需要业务方先base64 decode处理后,再使用指定版本的私钥进行解密,得出内容。String类型 + * @param msgAuditPriKey 会话存档私钥 + * @return + * @throws Exception + */ + public static String decryptPriKeyByPKCS1(String encryptRandomKey, String msgAuditPriKey) throws Exception { + String privateKey = msgAuditPriKey.replaceAll("(\r\n|\r|\n|\n\r)", "") + .replace("-----BEGIN RSA PRIVATE KEY-----", "") + .replace("-----END RSA PRIVATE KEY-----", "") + .replaceAll(" ", ""); + + byte[] keyBytes = Base64.getDecoder().decode(privateKey); + DerValue[] seq = new DerInputStream(keyBytes).getSequence(0); + RSAPrivateCrtKeySpec keySpec = new RSAPrivateCrtKeySpec(seq[1].getBigInteger(), seq[2].getBigInteger(), + seq[3].getBigInteger(), seq[4].getBigInteger(), + seq[5].getBigInteger(), seq[6].getBigInteger(), + seq[7].getBigInteger(), seq[8].getBigInteger()); + + PrivateKey priKey = KeyFactory.getInstance("RSA").generatePrivate(keySpec); + Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); + cipher.init(Cipher.DECRYPT_MODE, priKey); + byte[] utf8 = cipher.doFinal(Base64.getDecoder().decode(encryptRandomKey)); return new String(utf8, "UTF-8"); } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/crypto/WxCpTpCryptUtil.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/crypto/WxCpTpCryptUtil.java index 900f7ea8a..b9c5f2a6d 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/crypto/WxCpTpCryptUtil.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/crypto/WxCpTpCryptUtil.java @@ -4,6 +4,9 @@ import com.google.common.io.BaseEncoding; import me.chanjar.weixin.common.util.crypto.WxCryptUtil; import me.chanjar.weixin.cp.config.WxCpTpConfigStorage; +import org.apache.commons.lang3.StringUtils; + +import java.util.Base64; /** * @author someone @@ -24,7 +27,7 @@ public WxCpTpCryptUtil(WxCpTpConfigStorage wxCpTpConfigStorage) { this.token = token; this.appidOrCorpid = corpId; - this.aesKey = BaseEncoding.base64().decode(CharMatcher.whitespace().removeFrom(encodingAesKey)); + this.aesKey = Base64.getDecoder().decode(StringUtils.remove(encodingAesKey, " ")); } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/StatisticListAdapter.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/StatisticListAdapter.java new file mode 100644 index 000000000..1dbe15149 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/StatisticListAdapter.java @@ -0,0 +1,32 @@ +package me.chanjar.weixin.cp.util.json; + +import com.google.gson.*; +import me.chanjar.weixin.common.util.json.GsonHelper; +import me.chanjar.weixin.cp.bean.kf.WxCpKfGetCorpStatisticResp; + +import java.lang.reflect.Type; + +/** + * @author zhongjun + * @date 2022/4/25 + **/ +public class StatisticListAdapter implements JsonDeserializer { + + @Override + public WxCpKfGetCorpStatisticResp.StatisticList deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { + WxCpKfGetCorpStatisticResp.StatisticList statisticList = new WxCpKfGetCorpStatisticResp.StatisticList(); + JsonObject asJsonObject = jsonElement.getAsJsonObject(); + statisticList.setStatTime(asJsonObject.get("stat_time").getAsLong()); + JsonElement statistic = asJsonObject.get("statistic"); + if (GsonHelper.isNotNull(statistic)) { + WxCpKfGetCorpStatisticResp.Statistic statisticObj = new WxCpKfGetCorpStatisticResp.Statistic(); + statisticObj.setSessionCnt(statistic.getAsJsonObject().get("session_cnt").getAsInt()); + statisticObj.setCustomerCnt(statistic.getAsJsonObject().get("customer_cnt").getAsInt()); + statisticObj.setCustomerMsgCnt(statistic.getAsJsonObject().get("customer_msg_cnt").getAsInt()); + statisticObj.setUpgradeServiceCustomerCnt(statistic.getAsJsonObject().get("upgrade_service_customer_cnt").getAsInt()); + statisticObj.setAiTransferRate(statistic.getAsJsonObject().get("ai_transfer_rate").getAsInt()); + statisticObj.setAiKnowledgeHitRate(statistic.getAsJsonObject().get("ai_knowledge_hit_rate").getAsInt()); + } + return statisticList; + } +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/WxCpGsonBuilder.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/WxCpGsonBuilder.java index 098935bf0..750d24ed0 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/WxCpGsonBuilder.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/WxCpGsonBuilder.java @@ -9,6 +9,8 @@ import me.chanjar.weixin.cp.bean.WxCpDepart; import me.chanjar.weixin.cp.bean.WxCpTag; import me.chanjar.weixin.cp.bean.WxCpUser; +import me.chanjar.weixin.cp.bean.kf.WxCpKfGetCorpStatisticResp; + import java.util.Objects; /** @@ -27,6 +29,7 @@ public class WxCpGsonBuilder { INSTANCE.registerTypeAdapter(WxError.class, new WxErrorAdapter()); INSTANCE.registerTypeAdapter(WxMenu.class, new WxCpMenuGsonAdapter()); INSTANCE.registerTypeAdapter(WxCpTag.class, new WxCpTagGsonAdapter()); + INSTANCE.registerTypeAdapter(WxCpKfGetCorpStatisticResp.StatisticList.class, new StatisticListAdapter()); } public static Gson create() { diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/WxCpUserGsonAdapter.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/WxCpUserGsonAdapter.java index f75c0ef1e..b91404bf7 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/WxCpUserGsonAdapter.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/WxCpUserGsonAdapter.java @@ -73,6 +73,7 @@ public WxCpUser deserialize(JsonElement json, Type typeOfT, JsonDeserializationC user.setMobile(GsonHelper.getString(o, "mobile")); user.setGender(Gender.fromCode(GsonHelper.getString(o, "gender"))); user.setEmail(GsonHelper.getString(o, "email")); + user.setBizMail(GsonHelper.getString(o, "biz_mail")); user.setAvatar(GsonHelper.getString(o, "avatar")); user.setThumbAvatar(GsonHelper.getString(o, "thumb_avatar")); user.setAddress(GsonHelper.getString(o, "address")); @@ -198,15 +199,9 @@ private void buildExternalAttrs(JsonObject o, WxCpUser user) { @Override public JsonElement serialize(WxCpUser user, Type typeOfSrc, JsonSerializationContext context) { JsonObject o = new JsonObject(); - if (user.getUserId() != null) { - o.addProperty("userid", user.getUserId()); - } - if (user.getNewUserId() != null) { - o.addProperty("new_userid", user.getNewUserId()); - } - if (user.getName() != null) { - o.addProperty("name", user.getName()); - } + this.addProperty(o, "userid", user.getUserId()); + this.addProperty(o, "new_userid", user.getNewUserId()); + this.addProperty(o, "name", user.getName()); if (user.getDepartIds() != null) { JsonArray jsonArray = new JsonArray(); for (Long departId : user.getDepartIds()) { @@ -223,9 +218,7 @@ public JsonElement serialize(WxCpUser user, Type typeOfSrc, JsonSerializationCon o.add("order", jsonArray); } - if (user.getPosition() != null) { - o.addProperty("position", user.getPosition()); - } + this.addProperty(o, "position", user.getPosition()); if (user.getPositions() != null) { JsonArray jsonArray = new JsonArray(); @@ -235,39 +228,20 @@ public JsonElement serialize(WxCpUser user, Type typeOfSrc, JsonSerializationCon o.add("positions", jsonArray); } - if (user.getMobile() != null) { - o.addProperty("mobile", user.getMobile()); - } + this.addProperty(o, "mobile", user.getMobile()); if (user.getGender() != null) { o.addProperty("gender", user.getGender().getCode()); } - if (user.getEmail() != null) { - o.addProperty("email", user.getEmail()); - } - if (user.getAvatar() != null) { - o.addProperty("avatar", user.getAvatar()); - } - if (user.getThumbAvatar() != null) { - o.addProperty("thumb_avatar", user.getThumbAvatar()); - } - if (user.getAddress() != null) { - o.addProperty("address", user.getAddress()); - } - if (user.getAvatarMediaId() != null) { - o.addProperty("avatar_mediaid", user.getAvatarMediaId()); - } - if (user.getStatus() != null) { - o.addProperty("status", user.getStatus()); - } - if (user.getEnable() != null) { - o.addProperty("enable", user.getEnable()); - } - if (user.getAlias() != null) { - o.addProperty("alias", user.getAlias()); - } - if (user.getIsLeader() != null) { - o.addProperty("isleader", user.getIsLeader()); - } + this.addProperty(o, "email", user.getEmail()); + this.addProperty(o, "biz_mail", user.getBizMail()); + this.addProperty(o, "avatar", user.getAvatar()); + this.addProperty(o, "thumb_avatar", user.getThumbAvatar()); + this.addProperty(o, "address", user.getAddress()); + this.addProperty(o, "avatar_mediaid", user.getAvatarMediaId()); + this.addProperty(o, "status", user.getStatus()); + this.addProperty(o, "enable", user.getEnable()); + this.addProperty(o, "alias", user.getAlias()); + this.addProperty(o, "isleader", user.getIsLeader()); if (user.getIsLeaderInDept() != null && user.getIsLeaderInDept().length > 0) { JsonArray ary = new JsonArray(); for (int item : user.getIsLeaderInDept()) { @@ -275,24 +249,14 @@ public JsonElement serialize(WxCpUser user, Type typeOfSrc, JsonSerializationCon } o.add("is_leader_in_dept", ary); } - if (user.getHideMobile() != null) { - o.addProperty("hide_mobile", user.getHideMobile()); - } - if (user.getEnglishName() != null) { - o.addProperty("english_name", user.getEnglishName()); - } - if (user.getTelephone() != null) { - o.addProperty("telephone", user.getTelephone()); - } - if (user.getQrCode() != null) { - o.addProperty("qr_code", user.getQrCode()); - } + this.addProperty(o, "hide_mobile", user.getHideMobile()); + this.addProperty(o, "english_name", user.getEnglishName()); + this.addProperty(o, "telephone", user.getTelephone()); + this.addProperty(o, "qr_code", user.getQrCode()); if (user.getToInvite() != null) { o.addProperty("to_invite", user.getToInvite()); } - if (user.getMainDepartment() != null) { - o.addProperty("main_department", user.getMainDepartment()); - } + this.addProperty(o, "main_department", user.getMainDepartment()); if (!user.getExtAttrs().isEmpty()) { JsonArray attrsJsonArray = new JsonArray(); @@ -322,16 +286,12 @@ public JsonElement serialize(WxCpUser user, Type typeOfSrc, JsonSerializationCon o.add(EXTRA_ATTR, attrsJson); } - if (user.getExternalPosition() != null) { - o.addProperty(EXTERNAL_POSITION, user.getExternalPosition()); - } + this.addProperty(o, EXTERNAL_POSITION, user.getExternalPosition()); JsonObject attrsJson = new JsonObject(); o.add(EXTERNAL_PROFILE, attrsJson); - if (user.getExternalCorpName() != null) { - attrsJson.addProperty(EXTERNAL_CORP_NAME, user.getExternalCorpName()); - } + this.addProperty(attrsJson, EXTERNAL_CORP_NAME, user.getExternalCorpName()); if (user.getWechatChannels() != null) { attrsJson.add(WECHAT_CHANNELS, GsonHelper.buildJsonObject("nickname", user.getWechatChannels().getNickname(), "status", user.getWechatChannels().getStatus())); @@ -370,4 +330,16 @@ public JsonElement serialize(WxCpUser user, Type typeOfSrc, JsonSerializationCon return o; } + private void addProperty(JsonObject object, String property, Integer value) { + if (value != null) { + object.addProperty(property, value); + } + } + + private void addProperty(JsonObject object, String property, String value) { + if (value != null) { + object.addProperty(property, value); + } + } + } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/xml/XStreamTransformer.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/xml/XStreamTransformer.java index 62ea5072e..2fb09ce4c 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/xml/XStreamTransformer.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/xml/XStreamTransformer.java @@ -1,13 +1,13 @@ package me.chanjar.weixin.cp.util.xml; -import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; - import com.thoughtworks.xstream.XStream; import me.chanjar.weixin.common.util.xml.XStreamInitializer; -import me.chanjar.weixin.cp.bean.message.*; import me.chanjar.weixin.cp.bean.WxCpTpXmlPackage; +import me.chanjar.weixin.cp.bean.message.*; + +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; public class XStreamTransformer { diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpLivingTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpLivingTest.java index 295f0497f..43724e5a0 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpLivingTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpLivingTest.java @@ -1,22 +1,29 @@ package me.chanjar.weixin.cp.api; import lombok.extern.slf4j.Slf4j; +import lombok.val; import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.util.XmlUtils; import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl; import me.chanjar.weixin.cp.bean.living.*; +import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage; import me.chanjar.weixin.cp.config.WxCpConfigStorage; +import me.chanjar.weixin.cp.constant.WxCpConsts; import me.chanjar.weixin.cp.demo.WxCpDemoInMemoryConfigStorage; +import me.chanjar.weixin.cp.util.xml.XStreamTransformer; import org.eclipse.jetty.util.ajax.JSON; import org.testng.annotations.Test; import java.io.InputStream; +import java.util.ArrayList; import java.util.Date; /** * 企业微信直播测试类. * 官方文档:https://open.work.weixin.qq.com/api/doc/90000/90135/93632 * - * @author Wang_Wong + * @author Wang_Wong + * @date 2021-12-23 */ @Slf4j public class WxCpLivingTest { @@ -34,6 +41,77 @@ public void test() throws WxErrorException { wxCpService = new WxCpServiceImpl(); wxCpService.setWxCpConfigStorage(config); + + /** + * 直播回调事件 + * 一场完整的直播,会经历 预约直播/开始直播/结束直播 等一系列状态变更。 + * 为了让企业实时获取直播的动态,当直播状态变更后,企业微信会将该变更推送到开发者配置的回调URL。 + * 只有通过接口创建的预约/立即直播才会回调。 + * + * 请注意,只有用企业微信api创建的直播才能收到回调,且调用创建直播接口的应用,要配置好回调url。 + */ + String livingXml = "\n" + + " \n" + + " \n" + + " 1348831860\n" + + " \n" + + " \n" + + " \n" + + " 1\n" + + " 1\n" + + ""; + + final WxCpXmlMessage livingXmlMsg = XStreamTransformer.fromXml(WxCpXmlMessage.class, livingXml); + livingXmlMsg.setAllFieldsMap(XmlUtils.xml2Map(livingXml)); + log.info("livingXmlMsg:{}", JSON.toString(livingXmlMsg)); + + /** + * 直播回调事件常量 + * https://developer.work.weixin.qq.com/document/path/94145 + */ + String livingStatusChange = WxCpConsts.EventType.LIVING_STATUS_CHANGE; + + + /** + * 测试创建直播 + */ + WxCpLivingCreateRequest createRequest = new WxCpLivingCreateRequest(); + createRequest.setAnchorUserid("WangKai"); + createRequest.setTheme("直播1"); + + long currentTimeMillis = System.currentTimeMillis() + 3600000L; + createRequest.setLivingStart(currentTimeMillis); + createRequest.setLivingDuration(3600L); + createRequest.setType(4); + createRequest.setDescription("这是通用直播1"); + + val activityDetail = new WxCpLivingCreateRequest.ActivityDetail(); + activityDetail.setDescription("活动描述,非活动类型的直播不用传"); + +// String[] strings = new String[]{"MEDIA_ID_2", "MEDIA_ID_1"}; + ArrayList imageList = new ArrayList(); + imageList.add("MEDIA_ID_1"); + imageList.add("MEDIA_ID_2"); + + activityDetail.setImageList(imageList); + createRequest.setActivityDetail(activityDetail); + + String livingCreate = wxCpService.getLivingService().livingCreate(createRequest); + log.info("返回的直播id为:{}", livingCreate); + + WxCpLivingCreateRequest thisReq = WxCpLivingCreateRequest.fromJson(createRequest.toJson()); + log.info("返回的数据:{}", thisReq.toJson()); + + // 创建预约直播 + String createJson = "{\"anchor_userid\":\"ChenHu\",\"theme\":\"theme\",\"living_start\":164037820420,\"living_duration\":3600,\"description\":\"test description\",\"type\":4,\"remind_time\":60,\"activity_cover_mediaid\":\"MEDIA_ID\",\"activity_share_mediaid\":\"MEDIA_ID\",\"activity_detail\":{\"description\":\"活动描述,非活动类型的直播不用传\",\"image_list\":[\"xxxx1\",\"xxxx1\"]}}"; + WxCpLivingCreateRequest requestData = WxCpLivingCreateRequest.fromJson(createJson); + String thisLivingId = wxCpService.getLivingService().livingCreate(requestData); + log.info("livingId为:{}", thisLivingId); + + + /** + * other api + */ String livingCode = wxCpService.getLivingService().getLivingCode("o50by5NezHciWnoexJsrI49ILNqI", "lvOQpTDwAAD2MYuOq9y_bmLNMJfbbdGw"); log.info(JSON.toString(livingCode)); @@ -42,7 +120,7 @@ public void test() throws WxErrorException { log.info(livingInfo.toJson()); // 直播观看明细 - WxCpWatchStat watchStat = wxCpService.getLivingService().getWatchStat("lvOQpTDwAAcP9wNOSSxTwpbni-TMPNSg", 0); + WxCpWatchStat watchStat = wxCpService.getLivingService().getWatchStat("lvOQpTDwAAcP9wNOSSxTwpbni-TMPNSg", "0"); log.info(watchStat.toJson()); final String watchStateJson = "{\"errcode\":0,\"errmsg\":\"ok\",\"ending\":1,\"next_key\":\"NEXT_KEY\",\"stat_info\":{\"users\":[{\"userid\":\"userid\",\"watch_time\":30,\"is_comment\":1,\"is_mic\":1}],\"external_users\":[{\"external_userid\":\"external_userid1\",\"type\":1,\"name\":\"user name\",\"watch_time\":30,\"is_comment\":1,\"is_mic\":1},{\"external_userid\":\"external_userid2\",\"type\":2,\"name\":\"user_name\",\"watch_time\":30,\"is_comment\":1,\"is_mic\":1}]}}"; diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpMsgAuditTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpMsgAuditTest.java index 457996a0e..27fd2b215 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpMsgAuditTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpMsgAuditTest.java @@ -1,11 +1,17 @@ package me.chanjar.weixin.cp.api; -import com.google.common.collect.Lists; +import com.google.common.collect.Lists; +import com.tencent.wework.Finance; import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.util.XmlUtils; import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl; +import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage; import me.chanjar.weixin.cp.bean.msgaudit.*; import me.chanjar.weixin.cp.config.WxCpConfigStorage; +import me.chanjar.weixin.cp.constant.WxCpConsts; import me.chanjar.weixin.cp.demo.WxCpDemoInMemoryConfigStorage; +import me.chanjar.weixin.cp.util.xml.XStreamTransformer; +import org.eclipse.jetty.util.ajax.JSON; import org.testng.annotations.Test; import java.io.InputStream; @@ -18,7 +24,7 @@ * 企业微信会话内容存档测试类. * 官方文档:https://developer.work.weixin.qq.com/document/path/91360 * - * @author Wang_Wong + * @author Wang_Wong * @date 2022-01-17 */ @Slf4j @@ -28,6 +34,7 @@ public class WxCpMsgAuditTest { private static WxCpService cpService; // com.binarywang.spring.starter.wxjava.cp.config.WxCpServiceAutoConfiguration + // WxCpServiceImpl.getAccessToken() @Test public void test() throws Exception { @@ -38,22 +45,104 @@ public void test() throws Exception { cpService = new WxCpServiceImpl(); cpService.setWxCpConfigStorage(config); + /** - * 配置: + * 客户同意进行聊天内容存档事件回调 + * 配置了客户联系功能的成员添加外部联系人同意进行聊天内容存档时,回调该事件。 + * + * https://developer.work.weixin.qq.com/document/path/92005 + */ + String msgAuditApprovedXml = "\n" + + "\t\n" + + "\t \n" + + "\t1403610513\n" + + "\t\n" + + "\t\n" + + "\t\n" + + "\t\n" + + "\t\n" + + "\t\n" + + ""; + + final WxCpXmlMessage msgAuditApprovedXmlMsg = XStreamTransformer.fromXml(WxCpXmlMessage.class, msgAuditApprovedXml); + msgAuditApprovedXmlMsg.setAllFieldsMap(XmlUtils.xml2Map(msgAuditApprovedXml)); + log.info("msgAuditApprovedXmlMsg:{}", JSON.toString(msgAuditApprovedXmlMsg)); + + /** + * 产生会话回调事件 + * 为了提升企业会话存档的使用性能,降低无效的轮询次数。 + * 当企业收到或发送新消息时,企业微信可以以事件的形式推送到企业指定的url。回调间隔为15秒,在15秒内若有消息则触发回调,若无消息则不会触发回调。 + * + * https://developer.work.weixin.qq.com/document/path/95039 + */ + String msgAuditNotifyXml = "\n" + + " \n" + + " \n" + + " 1629101687\n" + + " \n" + + " 2000004\n" + + " \n" + + ""; + + final WxCpXmlMessage msgAuditNotifyXmlMsg = XStreamTransformer.fromXml(WxCpXmlMessage.class, msgAuditNotifyXml); + msgAuditNotifyXmlMsg.setAllFieldsMap(XmlUtils.xml2Map(msgAuditNotifyXml)); + log.info("msgAuditNotifyXmlMsg:{}", JSON.toString(msgAuditNotifyXmlMsg)); + + /** + * 增加变更事件类型:产生会话回调事件 + */ + String msgauditNotify = WxCpConsts.EventType.MSGAUDIT_NOTIFY; + + + /** + * 仔细配置: * - * wwa3bexxXXXXXX - * 自定义agentId - * xIpum7Yt4NMXXXXXXX - * 2bSNqXXXXXXXX - * MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDZuPVMyVyMvJkdSCZA893B2pggd1r95T8k2QZgz+VejtaDJCbD60mYoW1Uwwlwuqy8W78M6MmXsskn+5XunyR1WJlJGqgi0OMVGYvSfkNb9kD50fM21CGLcN1y4miL9fVNBIsvJmIUeJCNS8TioAVGFvh2EgzjqTR1gHfDwu8If7rfGmTHkPYL8hQxMg/EQ3451JOIBHSa7EQSx64SIoVWEgSDFQjGEpjUiJRfciyyz+nTSkEDgFa9hpyTS6E0c/3Q5lVDFgIwTArC19XBFKb00PbcFuLriOIsTBX4K9XWBtefVXowAdqUVQDH6BNUIK7/iVPQ4L3p+F5DBOrx8I/7AgMBAAECggEBAK53C/nwEX2lU3ynaB/8SuMga274ta1mmmbIkdfaQA65nyOPQJEWZe8szBN0BoiSzgBR9JI/p+srlQ25CLgiRnDSAmMWPU1I3e72fZi7HPcAKakGmEKDUi4OzyVUUDp3aY3B6lZqB4Yn5o2S/b4sRI2ZspfKdxGncSYHP/Far3i6hzq2C1hbyYM6HkHPcrQ+z6ir6GxjLvHXssVJ+/C0HMsVIQAWPyEGbzWozS+EswmQ+itk+7cewiLWbaCSp6lsjHKGTxJwCxRes0nUt2SfkLnIUkDLxB7c6zDQJCn1K2UckCjNBlCWl+oDWLkLQ7UAJ+4IYYSslR4wXzRg8PplW8ECgYEA9VlEprEoG2oSn3HXIMFg0MANViQe89QJQdwd7D5h4FLxXQLItxqmZj77iktlzlICcK9WT9WHRY1AOilsuMaDmY0VH3Z8r/X9BU712KFJqMYH5CNxrqHOya3BG+CclEKToaOTmo9kiOpFAMNSuuWs6gvILJ0CKEmSUo5G9fJu4fkCgYEA4yypHoRZIP0mDdVDeVtdHHcq5JdWF6xbAFs4P57VHG1KDMWouk3IHSeO279gEIwcBAdaLcMMgFfzyQBwcisxjC76oyoZnbSntB7ZMFdPqALKfxIdleLilbASuRKesVAF+OgOx/yp/aQUeLG2pVBivgn2TyGMwjnxznTh9vh+vpMCgYEAmOva7krdRLkIgnjiLXhab8JEjbxVzoQKgRJBVE5NkxQffGmP0RC7Rl9bSQdVnRNgkfu3QGtGtQMlVRscuM6Cl+JnmASyErqvye89LJja4GcN5BRzdvVDflDeXBHThlU4zza1eVCGyQ+7ko4rsnIVJIvTaHs0LQguO2aStBk3I4ECgYAyBsO3VK3L9fNLWItjThtTCWsIq8rpq6reiTf5yqBjgi2sYlqlrDtFMFDlU190RWZl/Lh/G1TFbpjgypf4jEp89Ft9UugRMpc7sw9g9dk0xmiRUwvw1eXP0NZOqysHIPgvt+qJX7qPgHKBoaD3Bpy3/Lmg82Jr4xa8wECCgnZmwQKBgH7hirPs1/HqBrbxS726IZUf9QTmVkyOYIwzuwFYKb/+4caSah+iaXexVux0xS5tchj/6c1dQSKJmlegV8smIb6EEcko7llA1y1P5QFtXtaaRd07tTsv3BKEg496YLRjbxPzgJn6Fsoz3TTdGwESL8Q3I2h0WmVVhmr/rjr+RkWQ + * ww45xxx88865xxx + * xIpum7Yt4NMXcyxdzcQ2l_46BG4QIQDR57MhA45ebIw // secret + * 200000 // 会话存档的应用id + * // 回调配置的token + * // 回调配置的EncodingAESKey * - * 注意:最好先配置lib开头的系统库,再配置sdk类库,配置绝对路径,最好配置为linux路径 - * windows: - * D:/WorkSpace/libcrypto-1_1-x64.dll,libssl-1_1-x64.dll,libcurl-x64.dll,WeWorkFinanceSdk.dll,libWeWorkFinanceSdk_Java.so - * linux: - * /www/osfile/work_msg_storage/libcrypto-1_1-x64.dll,libssl-1_1-x64.dll,libcurl-x64.dll,WeWorkFinanceSdk.dll,libWeWorkFinanceSdk_Java.so + * // 企业微信会话存档 + * // 1、会话存档私钥,最好去除前缀和换行,如下所示! + * // 2、仔细配置windows以及linux环境sdk路径 + * MIxxx893B2pggd1r95T8k2QxxxxbD6xxxxmXsskn+5XunyR1WJlJGqgi0OMVGYvSfkNb9kD50fM21CGLcN1y4miL9fVNBIsvJmIUeJCNS8TioAVGFvh2EgzjqTR1gH + * /www/osfile/libcrypto-1_1-x64.dll,libssl-1_1-x64.dll,libcurl-x64.dll,WeWorkFinanceSdk.dll,libWeWorkFinanceSdk_Java.so * - */ + * + * 注意:最好先配置lib开头的系统库,再配置sdk类库,配置绝对路径,最好配置为linux路径 + * Windows: + * D:/WorkSpace/libcrypto-1_1-x64.dll,libssl-1_1-x64.dll,libcurl-x64.dll,WeWorkFinanceSdk.dll,libWeWorkFinanceSdk_Java.so + * Linux: + * /www/osfile/work_msg_storage/libcrypto-1_1-x64.dll,libssl-1_1-x64.dll,libcurl-x64.dll,WeWorkFinanceSdk.dll,libWeWorkFinanceSdk_Java.so + * + * + * yml配置(支持多个corpId): + * wx: + * cp: + * appConfigs: + * - agentId: 10001 #客户联系 + * corpId: xxxxxxxxxxx + * secret: T5fTj1n-sBAT4rKNW5c9IYNfPdXZxxxxxxxxxxx + * token: 2bSNqTcLtxxxxxxxxxxx + * aesKey: AXazu2Xyw44SNY1x8go2phn9p9B2xxxxxxxxxxx + * - agentId: 10002 #会话内容存档 + * corpId: xxxxxxxxxxx + * secret: xIpum7Yt4NMXcyxdzcQ2l_46BG4Qxxxxxxxxxxx + * token: + * aesKey: + * msgAuditPriKey: MIxxx893B2pggd1r95T8k2QxxxxbD6xxxxmXsskn+5XunyR1WJlJGqgi0OMVGYvSfkNb9kD50fM21CGLcN1y4miL9fVNBIsvJmIUeJCNS8TioAVGFvh2EgzjqTR1gHxxx + * msgAuditLibPath: /www/osfile/libcrypto-1_1-x64.dll,libssl-1_1-x64.dll,libcurl-x64.dll,WeWorkFinanceSdk.dll,libWeWorkFinanceSdk_Java.so + * + * + * 在线生成非对称加密公钥私钥对: + * http://web.chacuo.net/netrsakeypair + * + * + * 或者可以在linux上使用如下命令生成公钥私钥对: + * openssl genrsa -out private_key.pem 2048 + * openssl rsa -in private_key.pem -pubout -out public_key.pem + * / /** * 建议放到redis,本次请求获取消息记录开始的seq值。首次访问填写0,非首次使用上次企业微信返回的最大seq。允许从任意seq重入拉取。 @@ -84,12 +173,13 @@ public void test() throws Exception { // Integer publickeyVer = chatData.getPublickeyVer(); // 获取明文数据 - final String chatPlainText = cpService.getMsgAuditService().getChatPlainText(chatData); + final String chatPlainText = cpService.getMsgAuditService().getChatPlainText(chatDatas.getSdk(), chatData, 2); final WxCpChatModel wxCpChatModel = WxCpChatModel.fromJson(chatPlainText); log.info("明文数据为:{}", wxCpChatModel.toJson()); // 获取消息数据 - final WxCpChatModel decryptData = cpService.getMsgAuditService().getDecryptData(chatData); + // https://developer.work.weixin.qq.com/document/path/91774 + final WxCpChatModel decryptData = cpService.getMsgAuditService().getDecryptData(chatDatas.getSdk(), chatData, 2); log.info("获取消息数据为:{}", decryptData.toJson()); /** @@ -168,15 +258,24 @@ public void test() throws Exception { return; } - // 拉取媒体文件 + /** + * 拉取媒体文件 + * + * 注意: + * 1、根据上面返回的文件类型,拼接好存放文件的绝对路径即可。此时绝对路径写入文件流,来达到获取媒体文件的目的。 + * 2、拉取完媒体文件之后,此时文件已经存在绝对路径,可以通过mq异步上传到对象存储 + * 3、比如可以上传到阿里云oss或者腾讯云cos + */ String targetPath = path + md5Sum + suffix; - cpService.getMsgAuditService().getMediaFile(sdkFileId, null, null, 1000L, targetPath); + cpService.getMsgAuditService().getMediaFile(chatDatas.getSdk(), sdkFileId, null, null, 1000L, targetPath); } - } - } + // 注意: + // 当此批次数据拉取完毕后,应释放此次sdk + log.info("释放sdk {}", chatDatas.getSdk()); + Finance.DestroySdk(chatDatas.getSdk()); } @@ -428,6 +527,16 @@ public void test() throws Exception { WxCpGroupChat room = cpService.getMsgAuditService().getGroupChat("wrOQpTDwAAyPl84GBJ40W5eWxWtixSCA"); log.info(room.toJson()); + + /** + * 获取access_token + * https://developer.work.weixin.qq.com/document/path/91039 + * https://www.jianshu.com/p/dde171887d63 + */ + String getUrl = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s"; + String data = cpService.get(String.format(getUrl, config.getCorpId(), config.getCorpSecret()), null); + + } } diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpOaAgentTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpOaAgentTest.java index 88d990e4f..94169e416 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpOaAgentTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpOaAgentTest.java @@ -3,12 +3,17 @@ import com.google.gson.reflect.TypeToken; import lombok.extern.slf4j.Slf4j; import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.util.XmlUtils; import me.chanjar.weixin.common.util.json.GsonParser; import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl; +import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage; import me.chanjar.weixin.cp.bean.oa.selfagent.WxCpOpenApprovalData; import me.chanjar.weixin.cp.config.WxCpConfigStorage; +import me.chanjar.weixin.cp.constant.WxCpConsts; import me.chanjar.weixin.cp.demo.WxCpDemoInMemoryConfigStorage; import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; +import me.chanjar.weixin.cp.util.xml.XStreamTransformer; +import org.eclipse.jetty.util.ajax.JSON; import org.testng.annotations.Test; import java.io.InputStream; @@ -16,6 +21,7 @@ /** * 企业微信自建应用接口测试类. * https://developer.work.weixin.qq.com/document/path/90269 + * https://developer.work.weixin.qq.com/document/path/90240#%E5%AE%A1%E6%89%B9%E7%8A%B6%E6%80%81%E9%80%9A%E7%9F%A5%E4%BA%8B%E4%BB%B6 * * @author Wang_Wong * @date 2022-04-06 @@ -37,6 +43,148 @@ public void test() throws WxErrorException { cpService = new WxCpServiceImpl(); cpService.setWxCpConfigStorage(config); + + /** + * 测试 审批状态通知事件 + */ + String testXml2 = "\n" + + " \n" + + " \n" + + " 1527838022\n" + + " \n" + + " \n" + + " 1\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " 1\n" + + " 1527837645\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " 1\n" + + " 1\n" + + " 1\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " 1\n" + + " \n" + + " 0\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " 0\n" + + " \n" + + "\n"; + final WxCpXmlMessage mess2 = XStreamTransformer.fromXml(WxCpXmlMessage.class, testXml2); + mess2.setAllFieldsMap(XmlUtils.xml2Map(testXml2)); + log.info("xmlJson: {}", JSON.toString(mess2)); + + + /** + * 测试 弹出微信相册发图器的事件推送 + * + * https://developer.work.weixin.qq.com/document/path/90240 + */ + String testXml = "\n" + + "\t\n" + + "\t\n" + + "\t1408090816\n" + + "\t\n" + + "\t\n" + + "\t\n" + + "\t1\n" + + "\t\n" + + "\t\n" + + "\t\n" + + "\t\n" + + "\t1\n" + + "\n"; + + final WxCpXmlMessage mess = XStreamTransformer.fromXml(WxCpXmlMessage.class, testXml); + mess.setAllFieldsMap(XmlUtils.xml2Map(testXml)); + log.info("xmlJson: {}", JSON.toString(mess)); + + + /** + * 审批流程引擎 + * 自建应用审批状态变化通知回调 + * + * https://developer.work.weixin.qq.com/document/path/90269 + */ + String approvalInfoXml = "\n" + + " wwd08c8e7c775abaaa \n" + + " sys \n" + + " 1527838022 \n" + + " event \n" + + " open_approval_change\n" + + " 1\n" + + " \n" + + " thirdNoxxx \n" + + " 付款 \n" + + " 1234567111 \n" + + " 1 \n" + + " 1527837645 \n" + + " jackiejjwu \n" + + " WuJunJie \n" + + " 产品部 \n" + + " http://www.qq.com/xxx.png \n" + + " \n" + + " \n" + + " 1 \n" + + " 1 \n" + + " 1 \n" + + " \n" + + " \n" + + " chauvetxiao \n" + + " XiaoWen \n" + + " 产品部 \n" + + " http://www.qq.com/xxx.png \n" + + " 1 \n" + + " \n" + + " 0 \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " jinhuiguo \n" + + " GuoJinHui \n" + + " 行政部 \n" + + " http://www.qq.com/xxx.png \n" + + " \n" + + " \n" + + " 0 \n" + + " \n" + + "\n"; + + final WxCpXmlMessage msg = XStreamTransformer.fromXml(WxCpXmlMessage.class, approvalInfoXml); + msg.setAllFieldsMap(XmlUtils.xml2Map(approvalInfoXml)); + log.info("xmlJson: {}", JSON.toString(msg)); + + /** + * 增加 + * 自建应用审批状态变化通知回调类型 + */ + String openApprovalChange = WxCpConsts.EventType.OPEN_APPROVAL_CHANGE; + + /** * Test */ diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpOaWeDriveServiceTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpOaWeDriveServiceTest.java new file mode 100644 index 000000000..14ecdd2f4 --- /dev/null +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpOaWeDriveServiceTest.java @@ -0,0 +1,284 @@ +package me.chanjar.weixin.cp.api; + +import com.google.common.collect.Lists; +import lombok.extern.slf4j.Slf4j; +import lombok.var; +import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.bean.oa.wedrive.*; +import me.chanjar.weixin.cp.config.WxCpConfigStorage; +import me.chanjar.weixin.cp.demo.WxCpDemoInMemoryConfigStorage; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Base64; +import java.util.List; + +/** + * 微盘测试类. + * 官方文档:https://developer.work.weixin.qq.com/document/path/93654 + * + * @author Wang_Wong + */ +@Slf4j +public class WxCpOaWeDriveServiceTest { + + private static WxCpConfigStorage wxCpConfigStorage; + private static WxCpService cpService; + + @Test + public void test() throws Exception { + + InputStream inputStream = ClassLoader.getSystemResourceAsStream("test-config.xml"); + WxCpDemoInMemoryConfigStorage config = WxCpDemoInMemoryConfigStorage.fromXml(inputStream); + + wxCpConfigStorage = config; + cpService = new WxCpServiceImpl(); + cpService.setWxCpConfigStorage(config); + + String createSpace = "{\"userid\":\"USERID\",\"space_name\":\"SPACE_NAME\",\"auth_info\":[{\"type\":1,\"userid\":\"USERID\",\"auth\":2},{\"type\":2,\"departmentid\":2,\"auth\":1}]}"; + WxCpSpaceCreateRequest wxCpSpaceCreateRequest = WxCpSpaceCreateRequest.fromJson(createSpace); + log.info(wxCpSpaceCreateRequest.toJson()); + + String uId = "WangKai"; + String spId = "s.ww45d3e188865aca30.652091685u4h"; + // 空间的文件id + String fileId = "s.ww45d3e188865aca30.652091685u4h_f.652344507ysDL"; + String fileId2 = "s.ww45d3e188865aca30.652091685u4h_f.652696024TU4P"; + + + /** + * 获取分享链接 + */ + WxCpFileShare fileShare = cpService.getOaWeDriveService().fileShare(uId, fileId2); + log.info("获取分享链接返回结果为:{}", fileShare.toJson()); + + /** + * 分享设置 + */ + WxCpBaseResp fileSetting = cpService.getOaWeDriveService().fileSetting(uId, fileId2, 2, 1); + log.info("分享设置返回结果为:{}", fileSetting.toJson()); + + /** + * 删除指定人 + */ + WxCpFileAclDelRequest aclDelRequest = new WxCpFileAclDelRequest(); + aclDelRequest.setUserId(uId); + aclDelRequest.setFileId(fileId2); + + ArrayList aclDelList = Lists.newArrayList(); + + WxCpFileAclDelRequest.AuthInfo aclDelAuthInfo = new WxCpFileAclDelRequest.AuthInfo(); + aclDelAuthInfo.setType(1); + aclDelAuthInfo.setUserId(uId); + + aclDelList.add(aclDelAuthInfo); + aclDelRequest.setAuthInfo(aclDelList); + + WxCpBaseResp aclDel = cpService.getOaWeDriveService().fileAclDel(aclDelRequest); + log.info("删除指定人返回结果为:{}", aclDel.toJson()); + + /** + * 新增指定人 + */ + WxCpFileAclAddRequest fileAclAdd = new WxCpFileAclAddRequest(); + fileAclAdd.setUserId(uId); + fileAclAdd.setFileId(fileId2); + var authInfoData = new WxCpFileAclAddRequest.AuthInfo(); + authInfoData.setType(1); + authInfoData.setAuth(1); + authInfoData.setUserId(uId); + + ArrayList authList = Lists.newArrayList(); + authList.add(authInfoData); + fileAclAdd.setAuthInfo(authList); + + WxCpBaseResp result = cpService.getOaWeDriveService().fileAclAdd(fileAclAdd); + log.info("返回结果为:{}", result.toJson()); + + /** + * 删除文件 + */ + ArrayList fileIds = Lists.newArrayList(); + fileIds.add(fileId); + WxCpBaseResp fileDelete = cpService.getOaWeDriveService().fileDelete(uId, fileIds); + log.info("删除文件数据为:{}", fileDelete.toJson()); + + /** + * 文件信息 + */ + WxCpFileInfo fileInfo = cpService.getOaWeDriveService().fileInfo(uId, fileId); + log.info("fileInfo数据为:{}", fileInfo.toJson()); + + /** + * 移动文件 + */ + WxCpFileMoveRequest fileMoveRequest = new WxCpFileMoveRequest(); + fileMoveRequest.setUserId(uId); + fileMoveRequest.setFatherId(spId); + fileMoveRequest.setReplace(true); + fileMoveRequest.setFileId(new String[]{fileId}); + + WxCpFileMove fileMove = cpService.getOaWeDriveService().fileMove(fileMoveRequest); + log.info("fileMove数据为:{}", fileMove.toJson()); + + /** + * 新建文件/微文档 + */ + WxCpFileCreate fileCreate = cpService.getOaWeDriveService().fileCreate(uId, spId, spId, 3, "新建微文档1"); + log.info("新建文件/微文档:{}", fileCreate.toJson()); + + /** + * 下载文件 + */ + WxCpFileDownload fileDownload = cpService.getOaWeDriveService().fileDownload(uId, fileId); + log.info("下载文件为:{}", fileDownload.toJson()); + + /** + * 上传文件 + */ + WxCpFileUploadRequest fileUploadRequest = new WxCpFileUploadRequest(); + fileUploadRequest.setUserId(uId); + fileUploadRequest.setSpaceId(spId); + fileUploadRequest.setFatherId(spId); + fileUploadRequest.setFileName("第一个文件"); + + // 将文件转成base64字符串 + File file = new File("D:/info.log.2022-05-07.0.log"); +// File file = new File("D:/16.png"); + FileInputStream inputFile = new FileInputStream(file); + byte[] buffer = new byte[(int)file.length()]; + inputFile.read(buffer); + inputFile.close(); + String encodeBase64Content = Base64.getEncoder().encodeToString(buffer); + fileUploadRequest.setFileBase64Content(encodeBase64Content); + + WxCpFileUpload fileUpload = cpService.getOaWeDriveService().fileUpload(fileUploadRequest); + log.info("上传文件为:{}", fileUpload.toJson()); + + /** + * 重命名文件 + */ + WxCpFileRename fileRename = cpService.getOaWeDriveService().fileRename(uId, fileUpload.getFileId(), "新的名字呢"); + log.info("重命名文件:{}", fileRename.toJson()); + + /** + * 获取文件列表 + */ + WxCpFileListRequest fileListRequest = new WxCpFileListRequest(); + fileListRequest.setUserId(uId); + fileListRequest.setSpaceId(spId); + fileListRequest.setFatherId(spId); + fileListRequest.setSortType(1); + fileListRequest.setStart(0); + fileListRequest.setLimit(100); + + WxCpFileList fileList = cpService.getOaWeDriveService().fileList(fileListRequest); + log.info("获取文件列表为:{}", fileList.toJson()); + + /** + * 权限管理 + */ + WxCpSpaceSettingRequest spaceSettingRequest = new WxCpSpaceSettingRequest(); + spaceSettingRequest.setUserId(uId); + spaceSettingRequest.setSpaceId(spId); +// spaceSettingRequest.setEnableWatermark(false); + spaceSettingRequest.setAddMemberOnlyAdmin(true); + spaceSettingRequest.setEnableShareUrl(false); + spaceSettingRequest.setShareUrlNoApprove(true); + spaceSettingRequest.setShareUrlNoApproveDefaultAuth(2); + + WxCpBaseResp spaceSetting = cpService.getOaWeDriveService().spaceSetting(spaceSettingRequest); + log.info("权限管理信息为:{}", spaceSetting.toJson()); + + /** + * 获取邀请链接 + */ + WxCpSpaceShare spaceShare = cpService.getOaWeDriveService().spaceShare(uId, spId); + log.info("获取邀请链接信息为:{}", spaceShare.toJson()); + + /** + * 获取空间信息 + */ + WxCpSpaceInfo data = cpService.getOaWeDriveService().spaceInfo(uId, spId); + log.info("获取空间信息为:{}", data.toJson()); + + /** + * 移除成员/部门 + */ + WxCpSpaceAclDelRequest spaceAclDelRequest = new WxCpSpaceAclDelRequest(); + spaceAclDelRequest.setUserId(uId); + spaceAclDelRequest.setSpaceId(spId); + + // 被移除的空间成员信息 + WxCpSpaceAclDelRequest.AuthInfo delAuthInfo = new WxCpSpaceAclDelRequest.AuthInfo(); + delAuthInfo.setType(1); + delAuthInfo.setUserId("MiaoMiu99"); + + List delAuthInfoList = new ArrayList<>(); + delAuthInfoList.add(delAuthInfo); + + spaceAclDelRequest.setAuthInfo(delAuthInfoList); + WxCpBaseResp spaceAclDel = cpService.getOaWeDriveService().spaceAclDel(spaceAclDelRequest); + log.info("移除成员/部门,返回数据为:{}", spaceAclDel.toJson()); + + /** + * 添加成员/部门 + * https://developer.work.weixin.qq.com/document/path/93656 + */ + WxCpSpaceAclAddRequest spaceAclAddRequest = new WxCpSpaceAclAddRequest(); + spaceAclAddRequest.setUserId(uId); + spaceAclAddRequest.setSpaceId(spId); + + List authInfoList = new ArrayList<>(); + // 被添加的空间成员信息 + WxCpSpaceAclAddRequest.AuthInfo authInfo = new WxCpSpaceAclAddRequest.AuthInfo(); + authInfo.setAuth(2); + authInfo.setType(1); + authInfo.setUserId("MiaoMiu99"); + + authInfoList.add(authInfo); + spaceAclAddRequest.setAuthInfo(authInfoList); + + WxCpBaseResp wxCpBaseResp = cpService.getOaWeDriveService().spaceAclAdd(spaceAclAddRequest); + log.info("添加成员/部门,返回数据为:{}", wxCpBaseResp.toJson()); + + /** + * 获取空间信息 + */ + WxCpSpaceInfo spaceInfo = cpService.getOaWeDriveService().spaceInfo("WangKai", "s.ww45d3e188865aca30.652091685u4h"); + log.info("获取空间信息,spaceInfo信息为:{}", spaceInfo.toJson()); + + /** + * 新建空间 + */ + WxCpSpaceCreateRequest request = new WxCpSpaceCreateRequest(); + request.setUserId("WangKai"); + request.setSpaceName("测试云盘Three"); + + WxCpSpaceCreateData spaceCreateData = cpService.getOaWeDriveService().spaceCreate(request); + log.info("空间id为:{}", spaceCreateData.getSpaceId()); // + log.info(spaceCreateData.toJson()); + + /** + * 重命名空间 + */ + WxCpSpaceRenameRequest wxCpSpaceRenameRequest = new WxCpSpaceRenameRequest(); + wxCpSpaceRenameRequest.setUserId("WangKai"); + wxCpSpaceRenameRequest.setSpaceId(spaceCreateData.getSpaceId()); + wxCpSpaceRenameRequest.setSpaceName("测试云盘Four"); + WxCpBaseResp baseResp = cpService.getOaWeDriveService().spaceRename(wxCpSpaceRenameRequest); + log.info("重命名成功:{}", baseResp.toJson()); + + /** + * 解散空间 + */ + WxCpBaseResp thisResp = cpService.getOaWeDriveService().spaceDismiss("WangKai", spaceCreateData.getSpaceId()); + log.info("解散成功:{}", thisResp.toJson()); + + } + +} diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpSchoolHealthTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpSchoolHealthTest.java new file mode 100644 index 000000000..5e7469ddf --- /dev/null +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpSchoolHealthTest.java @@ -0,0 +1,79 @@ +package me.chanjar.weixin.cp.api; + +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl; +import me.chanjar.weixin.cp.bean.school.health.WxCpGetHealthReportStat; +import me.chanjar.weixin.cp.bean.school.health.WxCpGetReportAnswer; +import me.chanjar.weixin.cp.bean.school.health.WxCpGetReportJobIds; +import me.chanjar.weixin.cp.bean.school.health.WxCpGetReportJobInfo; +import me.chanjar.weixin.cp.config.WxCpConfigStorage; +import me.chanjar.weixin.cp.demo.WxCpDemoInMemoryConfigStorage; +import org.testng.annotations.Test; + +import java.io.InputStream; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * 企业微信家校应用 健康上报接口. + * https://developer.work.weixin.qq.com/document/path/93676 + * + * @author Wang_Wong + * @date: 2022/5/31 9:10 + */ +@Slf4j +public class WxCpSchoolHealthTest { + + private static WxCpConfigStorage wxCpConfigStorage; + private static WxCpService cpService; + + @Test + public void test() throws WxErrorException { + + InputStream inputStream = ClassLoader.getSystemResourceAsStream("test-config.xml"); + WxCpDemoInMemoryConfigStorage config = WxCpDemoInMemoryConfigStorage.fromXml(inputStream); + + wxCpConfigStorage = config; + cpService = new WxCpServiceImpl(); + cpService.setWxCpConfigStorage(config); + String currDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); + + + // Test + String reportAnswerStr = "{\"errcode\":0,\"errmsg\":\"ok\",\"answers\":[{\"id_type\":1,\"userid\":\"userid2\",\"report_time\":123456789,\"report_values\":[{\"question_id\":1,\"single_choice\":2},{\"question_id\":2,\"text\":\"广东省广州市\"},{\"question_id\":3,\"multi_choice\":[1,3]},{\"question_id\":4,\"fileid\":[\"XXXXXXX\"]}]},{\"id_type\":2,\"student_userid\":\"student_userid1\",\"parent_userid\":\"parent_userid1\",\"report_time\":123456789,\"report_values\":[{\"question_id\":1,\"single_choice\":1},{\"question_id\":2,\"text\":\"广东省深圳市\"},{\"question_id\":3,\"multi_choice\":[1,2,3]},{\"question_id\":4,\"fileid\":[\"XXXXXXX\"]}]}]}"; + WxCpGetReportAnswer getReportAnswer = WxCpGetReportAnswer.fromJson(reportAnswerStr); + log.info("获取对应的getReportAnswer:{}", getReportAnswer.toJson()); + + /** + * 获取用户填写答案 + * https://developer.work.weixin.qq.com/document/path/93679 + */ + WxCpGetReportAnswer reportAnswer = cpService.getSchoolHealthService().getReportAnswer("xxxx", currDate, null, null); + log.info("返回的reportAnswer为:{}", reportAnswer.toJson()); + + /** + * 获取健康上报任务ID列表 + * https://developer.work.weixin.qq.com/document/path/93677 + */ + WxCpGetReportJobIds reportJobids = cpService.getSchoolHealthService().getReportJobIds(null, null); + log.info("返回的reportJobids为:{}", reportJobids.toJson()); + + /** + * 获取健康上报任务详情 + * https://developer.work.weixin.qq.com/document/path/93678 + */ + WxCpGetReportJobInfo reportJobInfo = cpService.getSchoolHealthService().getReportJobInfo(null, currDate); + log.info("返回的reportJobInfo为:{}", reportJobInfo.toJson()); + + /** + * 获取健康上报使用统计 + * https://developer.work.weixin.qq.com/document/path/93676 + */ + String date = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); + WxCpGetHealthReportStat healthReportStat = cpService.getSchoolHealthService().getHealthReportStat(date); + log.info("返回的healthReportStat为:{}", healthReportStat.toJson()); + + } + +} diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpSchoolTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpSchoolTest.java new file mode 100644 index 000000000..c042a55a6 --- /dev/null +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpSchoolTest.java @@ -0,0 +1,154 @@ +package me.chanjar.weixin.cp.api; + +import com.google.common.collect.Lists; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl; +import me.chanjar.weixin.cp.bean.living.WxCpLivingResult; +import me.chanjar.weixin.cp.bean.school.*; +import me.chanjar.weixin.cp.config.WxCpConfigStorage; +import me.chanjar.weixin.cp.demo.WxCpDemoInMemoryConfigStorage; +import org.testng.annotations.Test; + +import java.io.InputStream; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; + +/** + * 企业微信家校应用 复学码相关接口. + * https://developer.work.weixin.qq.com/document/path/93744 + * + * @author Wang_Wong + * @date: 2022/5/31 9:10 + */ +@Slf4j +public class WxCpSchoolTest { + + private static WxCpConfigStorage wxCpConfigStorage; + private static WxCpService cpService; + + @Test + public void test() throws WxErrorException { + + /** + * 注意: + * 权限说明:仅复学码应用可以调用 + */ + InputStream inputStream = ClassLoader.getSystemResourceAsStream("test-config.xml"); + WxCpDemoInMemoryConfigStorage config = WxCpDemoInMemoryConfigStorage.fromXml(inputStream); + + wxCpConfigStorage = config; + cpService = new WxCpServiceImpl(); + cpService.setWxCpConfigStorage(config); + String date = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); + + + /** + * 上课直播 + */ + String livingId = "lvOQpTDwAAh0hxHsSeSwTQcmH0nWUC_Q"; + + + /** + * 获取老师直播ID列表 + * https://developer.work.weixin.qq.com/document/path/93739 + */ + WxCpLivingResult.LivingIdResult result = cpService.getSchoolService().getUserAllLivingId("WangKai", null, 20); + log.info("result:{}", result.toJson()); + + /** + * 删除直播回放 + * https://developer.work.weixin.qq.com/document/path/93743 + */ + WxCpLivingResult livingResult = cpService.getSchoolService().deleteReplayData(livingId); + log.info("livingResult:{}", livingResult.toJson()); + + /** + * 获取未观看直播统计 + * https://developer.work.weixin.qq.com/document/path/93742 + */ + String str3 = "{\"errcode\":0,\"errmsg\":\"ok\",\"ending\":1,\"next_key\":\"NEXT_KEY\",\"stat_info\":{\"students\":[{\"student_userid\":\"zhansan_child\",\"parent_userid\":\"zhangsan\",\"partyids\":[10,11]},{\"student_userid\":\"lisi_child\",\"parent_userid\":\"lisi\",\"partyids\":[5]}]}}"; + WxCpSchoolUnwatchStat schoolUnwatchStat = WxCpSchoolUnwatchStat.fromJson(str3); + log.info("unwatchStat:{}", schoolUnwatchStat.toJson()); + + WxCpSchoolUnwatchStat unwatchStat = cpService.getSchoolService().getUnwatchStat(livingId, "0"); + log.info("unwatchStat:{}", unwatchStat.toJson()); + + /** + * 获取观看直播统计 + * https://developer.work.weixin.qq.com/document/path/93741 + */ + String str2 = "{\"errcode\":0,\"errmsg\":\"ok\",\"ending\":1,\"next_key\":\"NEXT_KEY\",\"stat_infoes\":{\"students\":[{\"student_userid\":\"zhansan_child\",\"parent_userid\":\"zhangsan\",\"partyids\":[10,11],\"watch_time\":30,\"enter_time\":1586433904,\"leave_time\":1586434000,\"is_comment\":1},{\"student_userid\":\"lisi_child\",\"parent_userid\":\"lisi\",\"partyids\":[10,11],\"watch_time\":30,\"enter_time\":1586433904,\"leave_time\":1586434000,\"is_comment\":0}],\"visitors\":[{\"nickname\":\"wx_nickname1\",\"watch_time\":30,\"enter_time\":1586433904,\"leave_time\":1586434000,\"is_comment\":1},{\"nickname\":\"wx_nickname2\",\"watch_time\":30,\"enter_time\":1586433904,\"leave_time\":1586434000,\"is_comment\":0}]}}"; + WxCpSchoolWatchStat wxCpSchoolWatchStat = WxCpSchoolWatchStat.fromJson(str2); + log.info("wxCpSchoolWatchStat:{}", wxCpSchoolWatchStat.toJson()); + + WxCpSchoolWatchStat watchStat = cpService.getSchoolService().getWatchStat(livingId, "0"); + log.info("watchStat:{}", watchStat.toJson()); + + String str1 = "{\"errcode\":0,\"errmsg\":\"ok\",\"living_info\":{\"theme\":\"直角三角形讲解\",\"living_start\":1586405229,\"living_duration\":1800,\"anchor_userid\":\"zhangsan\",\"living_range\":{\"partyids\":[1,4,9],\"group_names\":[\"group_name1\",\"group_name2\"]},\"viewer_num\":100,\"comment_num\":110,\"open_replay\":1,\"push_stream_url\":\"https://www.qq.test.com\"}}"; + WxCpSchoolLivingInfo wxCpSchoolLivingInfo = WxCpSchoolLivingInfo.fromJson(str1); + log.info("str1:{}", wxCpSchoolLivingInfo.toJson()); + + /** + * 获取直播详情 + * https://developer.work.weixin.qq.com/document/path/93740 + */ + WxCpSchoolLivingInfo schoolLivingInfo = cpService.getSchoolService().getLivingInfo(livingId); + log.info("schoolLivingInfo:{}", schoolLivingInfo.toJson()); + + + /** + * 获取学生付款结果 + * https://developer.work.weixin.qq.com/document/path/94553 + */ + String paymentResultStr = "{\"errcode\":0,\"errmsg\":\"ok\",\"project_name\":\"学费\",\"amount\":998,\"payment_result\":[{\"student_userid\":\"xxxx\",\"trade_state\":1,\"trade_no\":\"xxxxx\",\"payer_parent_userid\":\"zhangshan\"}]}"; + WxCpPaymentResult cpPaymentResult = WxCpPaymentResult.fromJson(paymentResultStr); + log.info("cpPaymentResult:{}", cpPaymentResult.toJson()); + + WxCpPaymentResult paymentResult = cpService.getSchoolService().getPaymentResult(""); + log.info("paymentResult:{}", paymentResult.toJson()); + + /** + * 获取订单详情 + * https://developer.work.weixin.qq.com/document/path/94554 + */ + String tradeStr = "{\n" + + "\t\"errcode\":0,\n" + + "\t\"errmsg\":\"ok\",\n" + + "\t\"transaction_id\":\"xxxxx\", \t \n" + + "\t\"pay_time\":12345\n" + + "}"; + WxCpTrade wxCpTrade = WxCpTrade.fromJson(tradeStr); + log.info("wxCpTrade:{}", wxCpTrade.toJson()); + + WxCpTrade trade = cpService.getSchoolService().getTrade("", ""); + log.info("trade:{}", trade.toJson()); + + + /** + * 获取老师健康信息 + * https://developer.work.weixin.qq.com/document/path/93744 + */ + WxCpCustomizeHealthInfo teacherCustomizeHealthInfo = cpService.getSchoolService().getTeacherCustomizeHealthInfo(date, null, null); + log.info("teacherCustomizeHealthInfo为:{}", teacherCustomizeHealthInfo.toJson()); + + /** + * 获取学生健康信息 + * https://developer.work.weixin.qq.com/document/path/93745 + */ + WxCpCustomizeHealthInfo studentCustomizeHealthInfo = cpService.getSchoolService().getStudentCustomizeHealthInfo(date, null, null); + log.info("studentCustomizeHealthInfo为:{}", studentCustomizeHealthInfo.toJson()); + + /** + * 获取师生健康码 + * https://developer.work.weixin.qq.com/document/path/93746 + */ + ArrayList userIds = Lists.newArrayList(); + userIds.add("Wangkai"); + WxCpResultList healthQrCode = cpService.getSchoolService().getHealthQrCode(userIds, 1); + log.info("healthQrCode为:{}", healthQrCode.toJson()); + + } + +} diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpSchoolUserTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpSchoolUserTest.java new file mode 100644 index 000000000..670f2c719 --- /dev/null +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpSchoolUserTest.java @@ -0,0 +1,759 @@ +package me.chanjar.weixin.cp.api; + +import com.google.common.collect.Lists; +import lombok.extern.slf4j.Slf4j; +import lombok.var; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.util.XmlUtils; +import me.chanjar.weixin.common.util.json.GsonParser; +import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.bean.WxCpOauth2UserInfo; +import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage; +import me.chanjar.weixin.cp.bean.school.user.*; +import me.chanjar.weixin.cp.config.WxCpConfigStorage; +import me.chanjar.weixin.cp.demo.WxCpDemoInMemoryConfigStorage; +import me.chanjar.weixin.cp.util.xml.XStreamTransformer; +import org.eclipse.jetty.util.ajax.JSON; +import org.testng.annotations.Test; + +import java.io.InputStream; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * 企业微信家校沟通相关接口. + * https://developer.work.weixin.qq.com/document/path/91638 + * + * @author Wang_Wong + * @date: 2022/6/18 9:10 + */ +@Slf4j +public class WxCpSchoolUserTest { + + private static WxCpConfigStorage wxCpConfigStorage; + private static WxCpService cpService; + + @Test + public void test() throws WxErrorException { + + InputStream inputStream = ClassLoader.getSystemResourceAsStream("test-config.xml"); + WxCpDemoInMemoryConfigStorage config = WxCpDemoInMemoryConfigStorage.fromXml(inputStream); + + wxCpConfigStorage = config; + cpService = new WxCpServiceImpl(); + cpService.setWxCpConfigStorage(config); + + List list = Lists.newArrayList(); + list.add(1); + list.add(2); + list.add(3); + log.info("list:{}", list.toString()); + + final String userId = "WangKai"; + final String exUserId = "wmOQpTDwAAJFHrryZ8I8ALLEZuLHIUKA"; + + + /** + * 获取部门家长详情 + * + * https://developer.work.weixin.qq.com/document/path/92446 + */ + WxCpListParentResult userListParent = cpService.getSchoolUserService().getUserListParent(1); + + String jsonUserListParentResult = "{\n" + + " \"errcode\": 0,\n" + + " \"errmsg\": \"ok\",\n" + + " \"parents\": [\n" + + " {\n" + + " \"parent_userid\": \"zhangsan_parent\",\n" + + " \"mobile\": \"18900000000\",\n" + + " \"is_subscribe\": 1,\n" + + "\t\t\t\"external_userid\":\"xxx\",\n" + + " \"children\": [\n" + + " {\n" + + " \"student_userid\": \"zhangsan\",\n" + + " \"relation\": \"爸爸\",\n" + + " \"name\": \"张三\"\n" + + " }\n" + + " ]\n" + + " },\n" + + "\t\t{\n" + + " \"parent_userid\": \"lisi_parent\",\n" + + " \"mobile\": \"18900000001\",\n" + + " \"is_subscribe\": 0,\n" + + " \"children\": [\n" + + " {\n" + + " \"student_userid\": \"lisi\",\n" + + " \"relation\": \"妈妈\",\n" + + " \"name\": \"李四\"\n" + + " }\n" + + " ]\n" + + " }\n" + + " ]\n" + + "}"; + + WxCpListParentResult wxCpListParentResult = WxCpListParentResult.fromJson(jsonUserListParentResult); + assertThat(wxCpListParentResult.toJson()).isEqualTo(GsonParser.parse(jsonUserListParentResult).toString()); + + + /** + * 获取部门成员详情 + * + * https://developer.work.weixin.qq.com/document/path/92043 + */ + WxCpUserListResult userList = cpService.getSchoolUserService().getUserList(1, 0); + + String jsonUserListResult = "{\n" + + "\t\"errcode\": 0,\n" + + "\t\"errmsg\": \"ok\",\n" + + "\t\"students\":[\n" + + "\t\t{\n" + + "\t\t\t\"student_userid\": \"zhangsan\",\n" + + "\t\t\t\"name\": \"张三\",\n" + + "\t\t\t\"department\": [1, 2],\n" + + "\t\t\t\"parents\": [\n" + + "\t\t\t\t{\n" + + "\t\t\t\t\t\"parent_userid\": \"zhangsan_parent1\",\n" + + "\t\t\t\t\t\"relation\": \"爸爸\",\n" + + "\t\t\t\t\t\"mobile\": \"18000000001\",\n" + + "\t\t\t\t\t\"is_subscribe\": 1,\n" + + "\t\t\t\t\t\"external_userid\":\"xxx\"\n" + + "\t\t\t\t},\n" + + "\t\t\t\t{\n" + + "\t\t\t\t\t\"parent_userid\": \"zhangsan_parent2\",\n" + + "\t\t\t\t\t\"relation\": \"妈妈\",\n" + + "\t\t\t\t\t\"mobile\": \"18000000002\",\n" + + "\t\t\t\t\t\"is_subscribe\": 0\n" + + "\t\t\t\t}\n" + + "\t\t\t]\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"student_userid\": \"lisi\",\n" + + "\t\t\t\"name\": \"李四\",\n" + + "\t\t\t\"department\": [4, 5],\n" + + "\t\t\t\"parents\": [\n" + + "\t\t\t\t{\n" + + "\t\t\t\t\t\"parent_userid\": \"lisi_parent1\",\n" + + "\t\t\t\t\t\"relation\": \"爷爷\",\n" + + "\t\t\t\t\t\"mobile\": \"18000000003\",\n" + + "\t\t\t\t\t\"is_subscribe\": 1,\n" + + "\t\t\t\t\t\"external_userid\":\"xxx\"\n" + + "\t\t\t\t},\n" + + "\t\t\t\t{\n" + + "\t\t\t\t\t\"parent_userid\": \"lisi_parent2\",\n" + + "\t\t\t\t\t\"relation\": \"妈妈\",\n" + + "\t\t\t\t\t\"mobile\": \"18000000004\",\n" + + "\t\t\t\t\t\"is_subscribe\": 1,\n" + + "\t\t\t\t\t\"external_userid\":\"xxx\"\n" + + "\t\t\t\t}\n" + + "\t\t\t]\n" + + "\t\t}\n" + + "\t]\n" + + "}"; + + WxCpUserListResult wxCpUserListResult = WxCpUserListResult.fromJson(jsonUserListResult); + assertThat(wxCpUserListResult.toJson()).isEqualTo(GsonParser.parse(jsonUserListResult).toString()); + + /** + * 读取学生或家长 + * + * https://developer.work.weixin.qq.com/document/path/92337 + */ + WxCpUserResult userResult = cpService.getSchoolUserService().getUser(userId); + + String jsonUserResult = "{\n" + + "\t\"errcode\": 0,\n" + + "\t\"errmsg\": \"ok\",\n" + + "\t\"user_type\": 1,\n" + + "\t\"student\":{\n" + + "\t\t\"student_userid\": \"zhangsan\",\n" + + "\t\t\"name\": \"张三\",\n" + + "\t\t\"department\": [1, 2],\n" + + "\t\t\"parents\":[\n" + + "\t\t\t{\n" + + "\t\t\t\t\"parent_userid\": \"zhangsan_parent1\",\n" + + "\t\t\t\t\"relation\": \"爸爸\",\n" + + "\t\t\t\t\"mobile\":\"18000000000\",\n" + + "\t\t\t\t\"is_subscribe\": 1,\n" + + "\t\t\t\t\"external_userid\":\"xxxxx\"\n" + + "\t\t\t},\n" + + "\t\t\t{\n" + + "\t\t\t\t\"parent_userid\": \"zhangsan_parent2\",\n" + + "\t\t\t\t\"relation\": \"妈妈\",\n" + + "\t\t\t\t\"mobile\": \"18000000001\",\n" + + "\t\t\t\t\"is_subscribe\": 0\n" + + "\t\t\t}\n" + + "\t\t]\n" + + " },\n" + + "\t\"parent\":{\n" + + "\t\t\"parent_userid\": \"zhangsan_parent2\",\n" + + "\t\t\"mobile\": \"18000000003\",\n" + + "\t\t\"is_subscribe\": 1,\n" + + "\t\t\"external_userid\":\"xxxxx\",\n" + + "\t\t\"children\":[\n" + + "\t\t\t{\n" + + "\t\t\t\t\"student_userid\": \"zhangsan\",\n" + + "\t\t\t\t\"relation\": \"妈妈\"\n" + + "\t\t\t},\n" + + "\t\t\t{\n" + + "\t\t\t\t\"student_userid\": \"lisi\",\n" + + "\t\t\t\t\"relation\": \"伯母\"\n" + + "\t\t\t}\n" + + "\t\t]\n" + + "\t}\n" + + "}"; + + WxCpUserResult wxCpUserResult = WxCpUserResult.fromJson(jsonUserResult); + assertThat(wxCpUserResult.toJson()).isEqualTo(GsonParser.parse(jsonUserResult).toString()); + + + /** + * 批量更新家长 + * + * https://developer.work.weixin.qq.com/document/path/92336 + */ + String batchUpdateParentRequestParam = "{\n" + + " \"parents\":[\n" + + " { \n" + + " \"parent_userid\": \"zhangsan_baba\",\n" + + "\t\t\t\"new_parent_userid\":\"zhangsan_baba_new\",\n" + + " \"mobile\": \"10000000000\",\n" + + " \"children\":[\n" + + " { \n" + + " \"student_userid\": \"zhangsan\",\n" + + " \"relation\": \"爸爸\"\n" + + " } \n" + + " ] \n" + + " }, \n" + + " { \n" + + " \"parent_userid\": \"lisi_mama\",\n" + + " \"mobile\": \"10000000001\",\n" + + " \"children\":[\n" + + " {\n" + + " \"student_userid\": \"lisi\",\n" + + " \"relation\": \"妈妈\"\n" + + " } \n" + + " ] \n" + + " } \n" + + " ] \n" + + "}"; + WxCpBatchUpdateParentRequest batchUpdateParentRequest = WxCpBatchUpdateParentRequest.fromJson(batchUpdateParentRequestParam); + WxCpBatchResultList batchUpdateParentResult = cpService.getSchoolUserService().batchUpdateParent(batchUpdateParentRequest); + + + /** + * 批量删除家长 + * + * https://developer.work.weixin.qq.com/document/path/92335 + */ + WxCpBatchResultList batchDeleteParentResult = cpService.getSchoolUserService().batchDeleteParent(new String[]{"abc", userId}); + + + /** + * 批量创建家长 封装请求参数 + * + * https://developer.work.weixin.qq.com/document/path/92334 + */ + var child1 = WxCpBatchCreateParentRequest.Children.builder() + .relation("爸爸") + .studentUserId("zhangsan") + .build(); + var child2 = WxCpBatchCreateParentRequest.Children.builder() + .relation("伯父") + .studentUserId("lisi") + .build(); + var child3 = WxCpBatchCreateParentRequest.Children.builder() + .relation("爸爸") + .studentUserId("lisi") + .build(); + var child4 = WxCpBatchCreateParentRequest.Children.builder() + .relation("伯父") + .studentUserId("zhangsan") + .build(); + + List childrenList1 = Lists.newArrayList(); + childrenList1.add(child1); + childrenList1.add(child2); + + List childrenList2 = Lists.newArrayList(); + childrenList2.add(child3); + childrenList2.add(child4); + + var zhangsanParent = WxCpBatchCreateParentRequest.Parent.builder() + .parentUserId("zhangsan_parent_userid") + .mobile("18000000000") + .toInvite(false) + .children(childrenList1) + .build(); + var lisiParent = WxCpBatchCreateParentRequest.Parent.builder() + .parentUserId("lisi_parent_userid") + .mobile("18000000001") + .children(childrenList2) + .build(); + + List batchCreateParent = Lists.newArrayList(); + batchCreateParent.add(zhangsanParent); + batchCreateParent.add(lisiParent); + WxCpBatchCreateParentRequest wxCpBatchCreateParentRequest = WxCpBatchCreateParentRequest.builder() + .parents(batchCreateParent) + .build(); + + // 请求参数json + String batchCreateParentRequestParam = "{\n" + + "\t\"parents\":[\n" + + "\t\t{\n" + + "\t\t\t\"parent_userid\": \"zhangsan_parent_userid\",\n" + + " \t\t\"mobile\": \"18000000000\",\n" + + "\t\t\t\"to_invite\": false,\n" + + "\t\t\t\"children\":[\n" + + "\t\t\t\t{\n" + + "\t\t\t\t\t\"student_userid\": \"zhangsan\",\n" + + " \t\t \"relation\": \"爸爸\"\n" + + " \t\t },\n" + + " \t\t {\n" + + "\t\t\t\t\t\"student_userid\": \"lisi\",\n" + + " \t\t \"relation\": \"伯父\"\n" + + " \t\t }\n" + + " \t\t]\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"parent_userid\": \"lisi_parent_userid\",\n" + + " \t\t\"mobile\": \"18000000001\",\n" + + "\t\t\t\"children\":[\n" + + "\t\t\t\t{\n" + + "\t\t\t\t\t\"student_userid\": \"lisi\",\n" + + " \t\t \"relation\": \"爸爸\"\n" + + " \t\t },\n" + + " \t\t {\n" + + "\t\t\t\t\t\"student_userid\": \"zhangsan\",\n" + + " \t\t \"relation\": \"伯父\"\n" + + " \t\t }\n" + + " \t\t]\n" + + "\t\t}\n" + + "\t]\n" + + "}"; + assertThat(wxCpBatchCreateParentRequest.toJson()).isEqualTo(GsonParser.parse(batchCreateParentRequestParam).toString()); + + WxCpBatchResultList batchCreateParentResult = cpService.getSchoolUserService().batchCreateParent(wxCpBatchCreateParentRequest); + + // 返回结果 + String batchResultStr = "{\n" + + "\t\"errcode\": 1,\n" + + "\t\"errmsg\": \"invalid parent_userid: lisi_parent_userid\",\n" + + "\t\"result_list\": [\n" + + "\t\t{\n" + + "\t\t\t\"parent_userid\": \"lisi_parent_userid\",\n" + + "\t\t\t\"errcode\": 1,\n" + + "\t\t\t\"errmsg\": \"invalid parent_userid: lisi_parent_userid\",\n" + + "\t\t}\n" + + "\t]\n" + + "}"; + assertThat(batchCreateParentResult.toJson()).isEqualTo(GsonParser.parse(batchResultStr).toString()); + + + /** + * 获取家校访问用户身份 + * + * https://developer.work.weixin.qq.com/document/path/95791 + */ + WxCpOauth2UserInfo schoolUserInfo = cpService.getSchoolUserService().getSchoolUserInfo("abc"); + assertThat(schoolUserInfo).isNotNull(); + + WxCpOauth2UserInfo oauth2UserInfo = cpService.getSchoolUserService().getUserInfo("abc"); + assertThat(oauth2UserInfo).isNotNull(); + + WxCpOauth2UserInfo userInfo = cpService.getOauth2Service().getUserInfo("abc"); + assertThat(userInfo).isNotNull(); + + + // 返回值 + String batchResult = "{\n" + + "\t\"errcode\": 1,\n" + + "\t\"errmsg\": \"invalid student_userid: zhangsan\",\n" + + "\t\"result_list\": [\n" + + "\t\t{\n" + + "\t\t\t\"student_userid\": \"zhangsan\",\n" + + "\t\t\t\"errcode\": 1,\n" + + "\t\t\t\"errmsg\": \"invalid student_userid: zhangsan\"\n" + + "\t\t}\n" + + "\t]\n" + + "}"; + + WxCpBatchResultList batchResultList = WxCpBatchResultList.fromJson(batchResult); + log.info("batchResultList: {}", batchResultList.toJson()); + + + /** + * 批量更新学生 + * https://developer.work.weixin.qq.com/document/path/92330 + * + * 请求方式:POST(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/user/batch_update_student?access_token=ACCESS_TOKEN + */ + String batchUpdateStudent = "{\n" + + "\t\"students\":[\n" + + " {\n" + + "\t\t\t\"student_userid\": \"zhangsan\",\n" + + "\t\t\t\"new_student_userid\":\"zhangsan_new\",\n" + + "\t\t\t\"name\": \"张三\",\n" + + "\t\t\t\"department\": [1, 2]\n" + + "\t\t},\n" + + " {\n" + + "\t\t\t\"student_userid\": \"lisi\",\n" + + "\t\t\t\"name\": \"李四\",\n" + + "\t\t\t\"department\": [3, 4]\n" + + "\t\t}\n" + + " ]\n" + + "}"; + WxCpBatchUpdateStudentRequest batchUpdateStudentRequest = WxCpBatchUpdateStudentRequest.fromJson(batchUpdateStudent); + WxCpBatchResultList list3 = cpService.getSchoolUserService().batchUpdateStudent(batchUpdateStudentRequest); + log.info("list3: {}", list3.toJson()); + + /** + * 批量删除学生 + * https://developer.work.weixin.qq.com/document/path/92329 + * + * 请求方式:POST(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/user/batch_delete_student?access_token=ACCESS_TOKEN + */ + String batchDeleteStudent = "{\n" + + "\t\"useridlist\": [\"zhangsan\", \"lisi\"]\n" + + "}\n"; + WxCpBatchDeleteStudentRequest batchDeleteStudentRequest = WxCpBatchDeleteStudentRequest.fromJson(batchDeleteStudent); + WxCpBatchResultList list2 = cpService.getSchoolUserService().batchDeleteStudent(batchDeleteStudentRequest); + log.info("list2: {}", list2.toJson()); + + /** + * 批量创建学生 + * https://developer.work.weixin.qq.com/document/path/92328 + */ + String batchCreateStudent = "{\n" + + "\t\"students\":[\n" + + " {\n" + + "\t\t\t\"student_userid\": \"zhangsan\",\n" + + "\t\t\t\"name\": \"张三\",\n" + + "\t\t\t\"department\": [1, 2]\n" + + "\t\t},\n" + + " {\n" + + "\t\t\t\"student_userid\": \"lisi\",\n" + + "\t\t\t\"name\": \"李四\",\n" + + "\t\t\t\"department\": [3, 4]\n" + + "\t\t}\n" + + " ]\n" + + "}"; + WxCpBatchCreateStudentRequest batchCreateStudentRequest = WxCpBatchCreateStudentRequest.fromJson(batchCreateStudent); + WxCpBatchResultList list1 = cpService.getSchoolUserService().batchCreateStudent(batchCreateStudentRequest); + log.info("list1: {}", list1.toJson()); + + +// String changeContact = WxCpConsts.EventType.CHANGE_CONTACT; + /** + * 增加变更事件类型: + */ +// WxCpConsts.EventType.CHANGE_SCHOOL_CONTACT; +// WxCpConsts.SchoolContactChangeType.DELETE_STUDENT; +// WxCpConsts.SchoolContactChangeType.CREATE_DEPARTMENT; + + /** + * 测试家校通讯录变更回调 + * https://developer.work.weixin.qq.com/document/path/92052 + * + * 新增学生事件 + * 当学校在家校通讯录中新增学生时,回调此事件。 + */ + String createStudentXml = "\n" + + "\t\n" + + "\t \n" + + "\t1403610513\n" + + "\t\n" + + "\t\n" + + "\t\n" + + "\t\n" + + ""; + + /** + * 家长取消关注事件 + * 当家长取消关注家校通知时,回调此事件。 + */ + String unSubscribeXml = "\n" + + "\t\n" + + "\t \n" + + "\t1403610513\n" + + "\t\n" + + "\t\n" + + "\t\n" + + "\t\n" + + ""; + + /** + * 创建部门事件 + * 当学校在家校通讯录中创建部门时,回调此事件。 + */ + String createDepartmentXml = "\n" + + "\t\n" + + "\t \n" + + "\t1403610513\n" + + "\t\n" + + "\t\n" + + "\t\n" + + "\t\n" + + ""; + + /** + * 删除部门事件 + * 当学校删除家校通讯录部门时,回调此事件。 + */ + String deleteDepartmentXml = "\n" + + "\t\n" + + "\t \n" + + "\t1403610513\n" + + "\t\n" + + "\t\n" + + "\t\n" + + "\t\n" + + ""; + +// WxCpXmlMessage.fromXml(createStudentXml); + final WxCpXmlMessage createStudentMsg = XStreamTransformer.fromXml(WxCpXmlMessage.class, createStudentXml); + Map map1 = XmlUtils.xml2Map(createStudentXml); + createStudentMsg.setAllFieldsMap(map1); + log.info("createStudentMsg:{}", JSON.toString(createStudentMsg)); + + final WxCpXmlMessage unSubscribeMsg = XStreamTransformer.fromXml(WxCpXmlMessage.class, unSubscribeXml); + Map map2 = XmlUtils.xml2Map(unSubscribeXml); + unSubscribeMsg.setAllFieldsMap(map2); + log.info("unSubscribeMsg:{}", JSON.toString(unSubscribeMsg)); + + final WxCpXmlMessage createDepartmentMsg = XStreamTransformer.fromXml(WxCpXmlMessage.class, createDepartmentXml); + createDepartmentMsg.setAllFieldsMap(XmlUtils.xml2Map(createDepartmentXml)); + log.info("createDepartmentMsg:{}", JSON.toString(createDepartmentMsg)); + + final WxCpXmlMessage deleteDepartmentMsg = XStreamTransformer.fromXml(WxCpXmlMessage.class, deleteDepartmentXml); + deleteDepartmentMsg.setAllFieldsMap(XmlUtils.xml2Map(deleteDepartmentXml)); + log.info("deleteDepartmentMsg:{}", JSON.toString(deleteDepartmentMsg)); + + + /** + * 获取可使用的家长范围 + * https://developer.work.weixin.qq.com/document/path/94895 + */ + String str8 = "{\n" + + " \"errcode\": 0,\n" + + " \"errmsg\": \"ok\",\n" + + " \"allow_scope\": {\n" + + " \"students\": [\n" + + " {\"userid\": \"student1\"},\n" + + " {\"userid\": \"student2\"}\n" + + " ],\n" + + "\t \"departments\": [1, 2]\n" + + " }\n" + + "}"; + WxCpAllowScope cpAllowScope = WxCpAllowScope.fromJson(str8); + log.info("cpAllowScope:{}", cpAllowScope.toJson()); + + WxCpAllowScope allowScope = cpService.getSchoolUserService().getAllowScope(100000); + log.info("allowScope:{}", allowScope); + + /** + * 外部联系人openid转换 + * https://developer.work.weixin.qq.com/document/path/92323 + */ + String openId = cpService.getSchoolUserService().convertToOpenId("wmOQpTDwAAh_sKvmJBJ4FQ0iYAcbppFA"); + log.info("openId:{}", openId); + + /** + * 家校沟通 获取外部联系人详情 + * https://developer.work.weixin.qq.com/document/path/92322 + */ + String str7 = "{\"errcode\":0,\"errmsg\":\"ok\",\"external_contact\":{\"external_userid\":\"woAAAA\",\"name\":\"李四\",\"position\":\"Mangaer\",\"avatar\":\"http://p.qlogo.cn/bizmail/IcsdgagqefergqerhewSdage/0\",\"corp_name\":\"腾讯\",\"corp_full_name\":\"腾讯科技有限公司\",\"type\":2,\"gender\":1,\"unionid\":\"unAAAAA\",\"is_subscribe\":1,\"subscriber_info\":{\"tag_id\":[\"TAG_ID1\",\"TAG_ID2\"],\"remark_mobiles\":[\"10000000000\",\"10000000001\"],\"remark\":\"李小明-爸爸\"},\"external_profile\":{\"external_attr\":[{\"type\":0,\"name\":\"文本名称\",\"text\":{\"value\":\"文本\"}},{\"type\":1,\"name\":\"网页名称\",\"web\":{\"url\":\"http://www.test.com\",\"title\":\"标题\"}},{\"type\":2,\"name\":\"测试app\",\"miniprogram\":{\"appid\":\"wxAAAAA\",\"pagepath\":\"/index\",\"title\":\"my miniprogram\"}}]}},\"follow_user\":[{\"userid\":\"rocky\",\"remark\":\"李部长\",\"description\":\"对接采购事物\",\"createtime\":1525779812,\"tags\":[{\"group_name\":\"标签分组名称\",\"tag_name\":\"标签名称\",\"type\":1}],\"remark_corp_name\":\"腾讯科技\",\"remark_mobiles\":[10000000003,10000000004]},{\"userid\":\"tommy\",\"remark\":\"李总\",\"description\":\"采购问题咨询\",\"createtime\":1525881637,\"state\":\"外联二维码1\"}]}"; + WxCpExternalContact wxCpExternalContact = WxCpExternalContact.fromJson(str7); + log.info("wxCpExternalContact:{}", wxCpExternalContact.toJson()); + +// cpService.getExternalContactService().getExternalContact(); + WxCpExternalContact externalContact = cpService.getSchoolUserService().getExternalContact(exUserId); + log.info("externalContact:{}", externalContact.toJson()); + + /** + * 获取关注「学校通知」的模式 + * 可通过此接口获取家长关注「学校通知」的模式:“可扫码填写资料加入”或“禁止扫码填写资料加入” + * https://developer.work.weixin.qq.com/document/path/92290 + */ + Integer subscribeMode = cpService.getSchoolUserService().getSubscribeMode(); + log.info("subscribeMode:{}", subscribeMode); + + /** + * 管理「学校通知」的关注模式 + * 设置关注「学校通知」的模式 + * https://developer.work.weixin.qq.com/document/path/92290 + */ + WxCpBaseResp setSubscribeMode = cpService.getSchoolUserService().setSubscribeMode(1); + log.info("setSubscribeMode:{}", setSubscribeMode.toJson()); + + /** + * 获取「学校通知」二维码 + * https://developer.work.weixin.qq.com/document/path/92320 + */ + String str6 = "{\n" + + " \"errcode\": 0,\n" + + " \"errmsg\": \"ok\",\n" + + " \"qrcode_big\":\"http://p.qpic.cn/wwhead/XXXX\",\n" + + " \"qrcode_middle\":\"http://p.qpic.cn/wwhead/XXXX\",\n" + + " \"qrcode_thumb\":\"http://p.qpic.cn/wwhead/XXXX\"\n" + + "}"; + + WxCpSubscribeQrCode cpSubscribeQrCode = WxCpSubscribeQrCode.fromJson(str6); + log.info("cpSubscribeQrCode:{}", cpSubscribeQrCode.toJson()); + + WxCpSubscribeQrCode subscribeQrCode = cpService.getSchoolUserService().getSubscribeQrCode(); + log.info("subscribeQrCode:{}", subscribeQrCode.toJson()); + + /** + * 修改自动升年级的配置 + * https://developer.work.weixin.qq.com/document/path/92949 + */ + WxCpSetUpgradeInfo wxCpSetUpgradeInfo = cpService.getSchoolUserService().setUpgradeInfo(1594090969L, 2); + log.info("wxCpSetUpgradeInfo:{}", wxCpSetUpgradeInfo.toJson()); + + /** + * 获取部门列表 + * https://developer.work.weixin.qq.com/document/path/92343 + */ + String str5 = "{\"errcode\":0,\"errmsg\":\"ok\",\"departments\":[{\"name\":\"一年级\",\"parentid\":1,\"id\":2,\"type\":2,\"register_year\":2018,\"standard_grade\":1,\"order\":1,\"department_admins\":[{\"userid\":\"zhangsan\",\"type\":1},{\"userid\":\"lisi\",\"type\":2}],\"is_graduated\":0},{\"name\":\"一年级一班\",\"parentid\":1,\"id\":3,\"type\":1,\"department_admins\":[{\"userid\":\"zhangsan\",\"type\":3,\"subject\":\"语文\"},{\"userid\":\"lisi\",\"type\":4,\"subject\":\"数学\"}],\"open_group_chat\":1,\"group_chat_id\":\"group_chat_id\"}]}"; + WxCpDepartmentList wxCpDepartmentList = WxCpDepartmentList.fromJson(str5); + log.info("wxCpDepartmentList:{}", wxCpDepartmentList.toJson()); + + WxCpDepartmentList departmentList = cpService.getSchoolUserService().listDepartment(7); + log.info("departmentList:{}", departmentList.toJson()); + + /** + * 删除部门 + * https://developer.work.weixin.qq.com/document/path/92342 + */ + WxCpBaseResp deleteDepartment = cpService.getSchoolUserService().deleteDepartment(7); + log.info("deleteDepartment:{}", deleteDepartment.toJson()); + + /** + * 更新部门 + * https://developer.work.weixin.qq.com/document/path/92341 + */ + String str4 = "{\"name\":\"一年级\",\"parentid\":5,\"id\":2,\"register_year\":2018,\"standard_grade\":1,\"order\":1,\"new_id\":100,\"department_admins\":[{\"op\":0,\"userid\":\"zhangsan\",\"type\":3,\"subject\":\"语文\"},{\"op\":1,\"userid\":\"lisi\",\"type\":4,\"subject\":\"数学\"}]}"; + WxCpUpdateDepartmentRequest wxCpUpdateDepartmentRequest = WxCpUpdateDepartmentRequest.fromJson(str4); + log.info("wxCpUpdateParentRequest:{}", wxCpUpdateDepartmentRequest.toJson()); + + WxCpBaseResp updateDepartment = cpService.getSchoolUserService().updateDepartment(wxCpUpdateDepartmentRequest); + log.info("updateDepartment:{}", updateDepartment.toJson()); + + /** + * 创建部门 + * https://developer.work.weixin.qq.com/document/path/92340 + */ + String str3 = "{\"name\":\"一年级\",\"parentid\":5,\"id\":2,\"type\":1,\"register_year\":2018,\"standard_grade\":1,\"order\":1,\"department_admins\":[{\"userid\":\"zhangsan\",\"type\":4,\"subject\":\"语文\"},{\"userid\":\"lisi\",\"type\":3,\"subject\":\"数学\"}]}"; + WxCpCreateDepartmentRequest wxCpCreateDepartmentRequest = WxCpCreateDepartmentRequest.fromJson(str3); + log.info("wxCpCreateDepartmentRequest:{}", wxCpCreateDepartmentRequest.toJson()); + + WxCpCreateDepartmentRequest createDepartmentRequest = new WxCpCreateDepartmentRequest(); + createDepartmentRequest.setParentId(5); + createDepartmentRequest.setName("一年级"); + createDepartmentRequest.setId(2); + createDepartmentRequest.setType(1); + createDepartmentRequest.setRegisterYear(2018); + createDepartmentRequest.setStandardGrade(1); + createDepartmentRequest.setOrder(1); + + var departmentAdmin = new WxCpCreateDepartmentRequest.DepartmentAdmin(); + departmentAdmin.setUserId(userId); + departmentAdmin.setType(4); + departmentAdmin.setSubject("英语"); + List createDepartList = Lists.newArrayList(); + createDepartList.add(departmentAdmin); + + createDepartmentRequest.setDepartmentAdmins(createDepartList); + WxCpCreateDepartment createDepartment = cpService.getSchoolUserService().createDepartment(createDepartmentRequest); + log.info("createDepartment:{}", createDepartment.toJson()); + + /** + * 更新家长 + * https://developer.work.weixin.qq.com/document/path/92333 + */ + String str2 = "{\"parent_userid\":\"zhangsan_parent_userid\",\"new_parent_userid\":\"NEW_ID\",\"mobile\":\"18000000000\",\"children\":[{\"student_userid\":\"zhangsan\",\"relation\":\"爸爸\"},{\"student_userid\":\"lisi\",\"relation\":\"伯父\"}]}"; + WxCpUpdateParentRequest updateParentRequest1 = WxCpUpdateParentRequest.fromJson(str2); + log.info("updateParentRequest1:{}", updateParentRequest1.toJson()); + + WxCpUpdateParentRequest updateParentRequest = new WxCpUpdateParentRequest(); + updateParentRequest.setParentUserId("zhangsan"); + updateParentRequest.setMobile("17324399999"); + updateParentRequest.setNewParentUserId("wangkai"); + + var child = new WxCpUpdateParentRequest.Children(); + child.setStudentUserId("zhangguiyuan"); + child.setRelation("伯父"); + + List childList = Lists.newArrayList(); + childList.add(child); + updateParentRequest.setChildren(childList); + + WxCpBaseResp updateParent = cpService.getSchoolUserService().updateParent(updateParentRequest); + log.info("updateParent:{}", updateParent.toJson()); + + /** + * 删除家长 + * https://developer.work.weixin.qq.com/document/path/92332 + */ + WxCpBaseResp deleteParent = cpService.getSchoolUserService().deleteParent("zhangsan"); + log.info("deleteParent:{}", deleteParent.toJson()); + + /** + * 创建家长 + * https://developer.work.weixin.qq.com/document/path/92331 + */ + String str1 = "{\"parent_userid\":\"zhangsan_parent_userid\",\"mobile\":\"10000000000\",\"to_invite\":false,\"children\":[{\"student_userid\":\"zhangsan\",\"relation\":\"爸爸\"},{\"student_userid\":\"lisi\",\"relation\":\"伯父\"}]}"; + WxCpCreateParentRequest createParentRequest1 = WxCpCreateParentRequest.fromJson(str1); + log.info("createParentRequest1:{}", createParentRequest1.toJson()); + + WxCpCreateParentRequest createParentRequest = new WxCpCreateParentRequest(); + createParentRequest.setParentUserId("wangkai"); + createParentRequest.setMobile("17324398888"); + createParentRequest.setToInvite(false); + + var children1 = new WxCpCreateParentRequest.Children(); + children1.setStudentUserId("zhangguiyuan"); + children1.setRelation("伯父"); + + List children = Lists.newArrayList(); + children.add(children1); + createParentRequest.setChildren(children); + + WxCpBaseResp createParent = cpService.getSchoolUserService().createParent(createParentRequest); + log.info("createParent:{}", createParent.toJson()); + + /** + * 设置家校通讯录自动同步模式 + * 企业和第三方可通过此接口修改家校通讯录与班级标签之间的自动同步模式,注意,一旦设置禁止自动同步,将无法再次开启。 + */ + WxCpBaseResp setArchSyncMode = cpService.getSchoolUserService().setArchSyncMode(2); + log.info("setArchSyncMode:{}", setArchSyncMode.toJson()); + + /** + * 更新学生 + */ + WxCpBaseResp updateStudent = cpService.getSchoolUserService().updateStudent("WangKai", "wangkai", "王", list); + log.info("updateStudent:{}", updateStudent.toJson()); + + /** + * 删除学生 + */ + WxCpBaseResp deleteStudent = cpService.getSchoolUserService().deleteStudent("WangKai"); + log.info("deleteStudent:{}", deleteStudent.toJson()); + + /** + * 创建学生 + */ + WxCpBaseResp student = cpService.getSchoolUserService().createStudent("WangKai", "王", list); + log.info("student:{}", student.toJson()); + + } + +} diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpDepartmentServiceImplTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpDepartmentServiceImplTest.java index 7417f8055..d08dee498 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpDepartmentServiceImplTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpDepartmentServiceImplTest.java @@ -72,6 +72,13 @@ public void testDelete() throws Exception { this.wxCpService.getDepartmentService().delete(this.depart.getId()); } + /** + * 获取子部门ID列表 + * https://developer.work.weixin.qq.com/document/path/95350 + * + * @param id + * @throws WxErrorException + */ @Test(dataProvider = "departIds") public void testSimpleList(Long id) throws WxErrorException { System.out.println("=================获取子部门ID列表"); diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpExternalContactServiceImplTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpExternalContactServiceImplTest.java index 3f7cc0b3b..9aa64d662 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpExternalContactServiceImplTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpExternalContactServiceImplTest.java @@ -12,14 +12,13 @@ import me.chanjar.weixin.cp.bean.external.msg.Attachment; import me.chanjar.weixin.cp.bean.external.msg.Image; import me.chanjar.weixin.cp.bean.external.msg.Video; +import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.time.DateFormatUtils; import org.testng.annotations.Guice; import org.testng.annotations.Test; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.List; +import java.util.*; + import org.testng.collections.CollectionUtils; import static org.testng.Assert.assertNotNull; @@ -337,4 +336,51 @@ public void testGetMomentList() throws WxErrorException { assertNotNull(result); } + @Test + public void testAddJoinWay() throws WxErrorException { + + + WxCpGroupJoinWayInfo.JoinWay joinWay = new WxCpGroupJoinWayInfo.JoinWay(); + joinWay.setChatIdList(Arrays.asList("wrfpBaCwAAxR-iIqIUa5vvbpZQcAexJA")); + joinWay.setScene(2); + joinWay.setAutoCreateRoom(1); + joinWay.setRemark("CreateDate:" + DateFormatUtils.ISO_8601_EXTENDED_DATETIME_FORMAT.format(new Date())); + + WxCpGroupJoinWayInfo info = new WxCpGroupJoinWayInfo(); + info.setJoinWay(joinWay); + this.wxCpService.getExternalContactService().addJoinWay(info); + } + + @Test + public void testUpdateJoinWay() throws WxErrorException { + + final String configId = ""; + + WxCpGroupJoinWayInfo.JoinWay joinWay = new WxCpGroupJoinWayInfo.JoinWay(); + joinWay.setConfigId(configId); + joinWay.setChatIdList(Arrays.asList("wrfpBaCwAAxR-iIqIUa5vvbpZQcAexJA")); + joinWay.setScene(2); + joinWay.setAutoCreateRoom(1); + joinWay.setRemark("CreateDate:" + DateFormatUtils.ISO_8601_EXTENDED_DATETIME_FORMAT.format(new Date())); + + WxCpGroupJoinWayInfo info = new WxCpGroupJoinWayInfo(); + info.setJoinWay(joinWay); + this.wxCpService.getExternalContactService().updateJoinWay(info); + } + + @Test + public void testDelJoinWay() throws WxErrorException { + + final String configId = ""; + + this.wxCpService.getExternalContactService().delJoinWay(configId); + } + + @Test + public void testGetJoinWay() throws WxErrorException { + + final String configId = ""; + + this.wxCpService.getExternalContactService().getJoinWay(configId); + } } diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpGroupRobotServiceImplTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpGroupRobotServiceImplTest.java index 57bd9b750..c1a09f359 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpGroupRobotServiceImplTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpGroupRobotServiceImplTest.java @@ -61,7 +61,7 @@ public void testSendImage() throws WxErrorException { @Test public void testSendNews() throws WxErrorException { NewArticle article = new NewArticle("图文消息测试", "hello world", "http://www.baidu.com", - "http://res.mail.qq.com/node/ww/wwopenmng/images/independent/doc/test_pic_msg1.png", null); + "http://res.mail.qq.com/node/ww/wwopenmng/images/independent/doc/test_pic_msg1.png", null, null, null); robotService.sendNews(Stream.of(article).collect(Collectors.toList())); } } diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpKfServiceImplTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpKfServiceImplTest.java index 09a4f568c..d45fba83f 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpKfServiceImplTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpKfServiceImplTest.java @@ -58,7 +58,7 @@ public void testAccountUpd() throws Exception { @Test(priority = 3) public void testAccountList() throws Exception { - WxCpKfAccountListResp resp = this.wxService.getKfService().listAccount(); + WxCpKfAccountListResp resp = this.wxService.getKfService().listAccount(0,10); System.out.println(resp); } diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpMessageServiceImplTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpMessageServiceImplTest.java index 3a1e5460f..d8ba80d99 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpMessageServiceImplTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpMessageServiceImplTest.java @@ -7,7 +7,6 @@ import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.cp.api.ApiTestModule; -import me.chanjar.weixin.cp.api.ApiTestModuleWithMockServer; import me.chanjar.weixin.cp.api.WxCpService; import me.chanjar.weixin.cp.bean.message.WxCpLinkedCorpMessage; import me.chanjar.weixin.cp.bean.message.WxCpMessage; diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpOaMeetingRoomServiceImplTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpOaMeetingRoomServiceImplTest.java new file mode 100644 index 000000000..c97974ab6 --- /dev/null +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpOaMeetingRoomServiceImplTest.java @@ -0,0 +1,71 @@ +package me.chanjar.weixin.cp.api.impl; + +import com.google.inject.Inject; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.api.ApiTestModule; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.oa.meetingroom.WxCpOaMeetingRoom; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import java.util.Arrays; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * 单元测试. + * + * @author Binary Wang + * @date 2020-09-20 + */ + +@Test +@Guice(modules = ApiTestModule.class) +public class WxCpOaMeetingRoomServiceImplTest { + @Inject + protected WxCpService wxService; + + @Test + public void testAdd() throws WxErrorException { + this.wxService.getOaMeetingRoomService().addMeetingRoom(WxCpOaMeetingRoom.builder() + .building("腾讯大厦") + .capacity(10) + .city("深圳") + .name("18F-会议室") + .floor("18F") + .equipment(Arrays.asList(1, 2)) +// .coordinate() + .build()); + + } + + @Test + public void testUpdate() throws WxErrorException { + this.wxService.getOaMeetingRoomService().editMeetingRoom(WxCpOaMeetingRoom.builder() + .building("腾讯大厦") + .capacity(10) + .city("深圳") + .name("16F-会议室") + .floor("16F") + .equipment(Arrays.asList(1, 2, 3)) + .meetingroomId(1) + .build()); + } + + @Test + public void testGet() throws WxErrorException { + final List meetingRooms = this.wxService.getOaMeetingRoomService().listMeetingRoom(WxCpOaMeetingRoom.builder() + .building("腾讯大厦") + .city("深圳") + .equipment(Arrays.asList(1, 2)) + .build()); + assertThat(meetingRooms).isNotEmpty(); + } + + @Test + public void testDelete() throws WxErrorException { + Integer calId = 1; + this.wxService.getOaMeetingRoomService().deleteMeetingRoom(calId); + } +} diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpOaServiceImplTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpOaServiceImplTest.java index d3f52561a..16f53893f 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpOaServiceImplTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpOaServiceImplTest.java @@ -6,6 +6,7 @@ import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.cp.api.ApiTestModule; import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; import me.chanjar.weixin.cp.bean.oa.*; import org.apache.commons.lang3.time.DateFormatUtils; import org.testng.annotations.Guice; @@ -161,8 +162,23 @@ public void testApply() throws WxErrorException { this.wxService.getOaService().apply(new WxCpOaApplyEventRequest().setCreatorUserId("123")); } + /** + * 获取审批数据(旧) + * https://developer.work.weixin.qq.com/document/path/91530 + * + * @throws WxErrorException + */ @Test - public void testGetApprovalData() { + public void testGetApprovalData() throws WxErrorException { + + // 提示:推荐使用新接口“批量获取审批单号”及“获取审批申请详情”,此接口后续将不再维护、逐步下线。 +// WxCpGetApprovalData approvalData = this.wxService.getOaService().getApprovalData(System.currentTimeMillis(), System.currentTimeMillis() + 3600L, null); +// log.info("返回数据:{}", approvalData.toJson()); + + String text = "{\"errcode\":0,\"errmsg\":\"ok\",\"count\":3,\"total\":5,\"next_spnum\":201704240001,\"data\":[{\"spname\":\"报销\",\"apply_name\":\"报销测试\",\"apply_org\":\"报销测试企业\",\"approval_name\":[\"审批人测试\"],\"notify_name\":[\"抄送人测试\"],\"sp_status\":1,\"sp_num\":201704200001,\"mediaids\":[\"WWCISP_G8PYgRaOVHjXWUWFqchpBqqqUpGj0OyR9z6WTwhnMZGCPHxyviVstiv_2fTG8YOJq8L8zJT2T2OvTebANV-2MQ\"],\"apply_time\":1499153693,\"apply_user_id\":\"testuser\",\"expense\":{\"expense_type\":1,\"reason\":\"\",\"item\":[{\"expenseitem_type\":6,\"time\":1492617600,\"sums\":9900,\"reason\":\"\"}]},\"comm\":{\"apply_data\":\"{\\\"item-1492610773696\\\":{\\\"title\\\":\\\"abc\\\",\\\"type\\\":\\\"text\\\",\\\"value\\\":\\\"\\\"}}\"}},{\"spname\":\"请假\",\"apply_name\":\"请假测试\",\"apply_org\":\"请假测试企业\",\"approval_name\":[\"审批人测试\"],\"notify_name\":[\"抄送人测试\"],\"sp_status\":1,\"sp_num\":201704200004,\"apply_time\":1499153693,\"apply_user_id\":\"testuser\",\"leave\":{\"timeunit\":0,\"leave_type\":4,\"start_time\":1492099200,\"end_time\":1492790400,\"duration\":144,\"reason\":\"\"},\"comm\":{\"apply_data\":\"{\\\"item-1492610773696\\\":{\\\"title\\\":\\\"abc\\\",\\\"type\\\":\\\"text\\\",\\\"value\\\":\\\"\\\"}}\"}},{\"spname\":\"自定义审批\",\"apply_name\":\"自定义\",\"apply_org\":\"自定义测试企业\",\"approval_name\":[\"自定义审批人\"],\"notify_name\":[\"自定义抄送人\"],\"sp_status\":1,\"sp_num\":201704240001,\"apply_time\":1499153693,\"apply_user_id\":\"testuser\",\"comm\":{\"apply_data\":\"{\\\"item-1492610773696\\\":{\\\"title\\\":\\\"abc\\\",\\\"type\\\":\\\"text\\\",\\\"value\\\":\\\"\\\"}}\"}}]}"; + WxCpGetApprovalData wxCpGetApprovalData = WxCpGetApprovalData.fromJson(text); + log.info("返回数据2:{}", wxCpGetApprovalData.toJson()); + } @Test @@ -170,13 +186,49 @@ public void testGetDialRecord() { } /** + * 获取企业假期管理配置 * https://developer.work.weixin.qq.com/document/path/93375 + * * @throws WxErrorException */ @Test - public void testGetCorpConf() throws WxErrorException{ + public void testGetCorpConf() throws WxErrorException { WxCpCorpConfInfo corpConf = this.wxService.getOaService().getCorpConf(); log.info(corpConf.toJson()); } + /** + * 获取成员假期余额 + * https://developer.work.weixin.qq.com/document/path/93376 + * + * @throws WxErrorException + */ + @Test + public void testGetUserVacationQuota() throws WxErrorException { + WxCpUserVacationQuota vacationQuota = this.wxService.getOaService().getUserVacationQuota("WangKai"); + log.info(vacationQuota.toJson()); + + String text = "{\"errcode\":0,\"errmsg\":\"ok\",\"lists\":[{\"id\":1,\"assignduration\":0,\"usedduration\":0,\"leftduration\":604800,\"vacationname\":\"年假\"},{\"id\":2,\"assignduration\":0,\"usedduration\":0,\"leftduration\":1296000,\"vacationname\":\"事假\"},{\"id\":3,\"assignduration\":0,\"usedduration\":0,\"leftduration\":0,\"vacationname\":\"病假\"}]}"; + WxCpUserVacationQuota json = WxCpUserVacationQuota.fromJson(text); + log.info("数据为:{}", json.toJson()); + + } + + /** + * 修改成员假期余额 + * https://developer.work.weixin.qq.com/document/path/93377 + * + * @throws WxErrorException + */ + @Test + public void testSetOneUserQuota() throws WxErrorException { + + String text = "{\"errcode\":0,\"errmsg\":\"ok\"}"; + WxCpBaseResp resp = WxCpBaseResp.fromJson(text); + log.info("返回结果为:{}", resp.toJson()); + +// WxCpBaseResp wxCpBaseResp = this.wxService.getOaService().setOneUserQuota(, , , , ); + + } + } diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImplTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImplTest.java index 9c4448830..a09bf6f70 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImplTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImplTest.java @@ -1,22 +1,26 @@ package me.chanjar.weixin.cp.api.impl; -import java.util.List; -import java.util.Map; - -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; -import org.testng.annotations.*; - import com.google.common.collect.Lists; import com.google.inject.Inject; +import lombok.extern.slf4j.Slf4j; import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.cp.api.ApiTestModule; import me.chanjar.weixin.cp.api.WxCpService; import me.chanjar.weixin.cp.bean.Gender; import me.chanjar.weixin.cp.bean.WxCpInviteResult; import me.chanjar.weixin.cp.bean.WxCpUser; +import me.chanjar.weixin.cp.bean.user.WxCpDeptUserResult; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; -import static org.testng.Assert.*; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import static org.testng.Assert.assertNotEquals; +import static org.testng.Assert.assertNotNull; /** *

@@ -25,6 +29,7 @@
  *
  * @author Binary Wang
  */
+@Slf4j
 @Guice(modules = ApiTestModule.class)
 public class WxCpUserServiceImplTest {
   @Inject
@@ -121,4 +126,27 @@ public void testGetUserId() throws WxErrorException {
   @Test
   public void testGetExternalContact() {
   }
+
+  @Test
+  public void testGetActiveStat() throws WxErrorException {
+    Integer activeStat = this.wxCpService.getUserService().getActiveStat(new Date());
+    System.out.printf("active stat: %d", activeStat);
+    assertNotNull(activeStat);
+  }
+
+  /**
+   * 获取成员ID列表
+   * 获取企业成员的userid与对应的部门ID列表,预计于2022年8月8号发布。若需要获取其他字段,参见「适配建议」。
+   * 

+ * https://developer.work.weixin.qq.com/document/40856 + * + * @throws WxErrorException + */ + @Test + public void testGetUserListId() throws WxErrorException { + WxCpDeptUserResult result = this.wxCpService.getUserService().getUserListId(null, 10); + log.info("返回结果为:{}", result.toJson()); + assertNotNull(result); + } + } diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/message/WxCpMessageTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/message/WxCpMessageTest.java index c8a367614..06c895d25 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/message/WxCpMessageTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/message/WxCpMessageTest.java @@ -166,6 +166,12 @@ public void TestTemplateCardBuilder_text_notice() { .value("企业微信.apk") .media_id("文件的media_id") .build(); + HorizontalContent hContent4 = HorizontalContent.builder() + .type(3) + .keyname("员工信息") + .value("点击查看") + .userid("zhangsan") + .build(); TemplateCardJump jump1 = TemplateCardJump.builder() .type(1) @@ -178,7 +184,7 @@ public void TestTemplateCardBuilder_text_notice() { .appid("小程序的appid") .pagepath("/index.html") .build(); - QuoteArea quoteArea=QuoteArea.builder() + QuoteArea quoteArea = QuoteArea.builder() .type(1) .title("引用文献标题") .appid("小程序的appid") @@ -186,17 +192,31 @@ public void TestTemplateCardBuilder_text_notice() { .url("https://work.weixin.qq.com") .quoteText("引用文献样式的引用文案") .build(); + ActionMenuItem action1 = ActionMenuItem.builder() + .text("接受推送") + .key("A") + .build(); + ActionMenuItem action2 = ActionMenuItem.builder() + .text("不再推送") + .key("B") + .build(); WxCpMessage reply = WxCpMessage.TEMPLATECARD().toUser("OPENID") + .toParty("PartyID1 | PartyID2") + .toTag("TagID1 | TagID2") .agentId(1000002) .cardType(WxConsts.TemplateCardType.TEXT_NOTICE) + .taskId("task_id") .sourceIconUrl("图片的url") .sourceDesc("企业微信") + .sourceDescColor(1) + .actionMenuDesc("卡片副交互辅助文本说明") + .actionMenuActionList(Arrays.asList(action1, action2)) .mainTitleTitle("欢迎使用企业微信") .mainTitleDesc("您的好友正在邀请您加入企业微信") .emphasisContentTitle("100") .emphasisContentDesc("核心数据") .subTitleText("下载企业微信还能抢红包!") - .horizontalContents(Arrays.asList(hContent1,hContent2,hContent3)) + .horizontalContents(Arrays.asList(hContent1, hContent2, hContent3, hContent4)) .jumps(Arrays.asList(jump1,jump2)) .cardActionType(2) .cardActionAppid("小程序的appid") @@ -209,8 +229,7 @@ public void TestTemplateCardBuilder_text_notice() { reply.setDuplicateCheckInterval(1800); // System.out.println(reply.toJson()); assertThat(reply.toJson()) - .isEqualTo("{\"agentid\":1000002,\"touser\":\"OPENID\",\"msgtype\":\"template_card\",\"duplicate_check_interval\":1800,\"template_card\":{\"card_type\":\"text_notice\",\"source\":{\"icon_url\":\"图片的url\",\"desc\":\"企业微信\"},\"main_title\":{\"title\":\"欢迎使用企业微信\",\"desc\":\"您的好友正在邀请您加入企业微信\"},\"emphasis_content\":{\"title\":\"100\",\"desc\":\"核心数据\"},\"sub_title_text\":\"下载企业微信还能抢红包!\",\"horizontal_content_list\":[{\"keyname\":\"邀请人\",\"value\":\"张三\"},{\"type\":1,\"keyname\":\"企业微信官网\",\"value\":\"点击访问\",\"url\":\"https://work.weixin.qq.com\"},{\"type\":2,\"keyname\":\"企业微信下载\",\"value\":\"企业微信.apk\",\"media_id\":\"文件的media_id\"}],\"jump_list\":[{\"type\":1,\"title\":\"企业微信官网\",\"url\":\"https://work.weixin.qq.com\"},{\"type\":2,\"title\":\"跳转小程序\",\"appid\":\"小程序的appid\",\"pagepath\":\"/index.html\"}],\"card_action\":{\"type\":2,\"url\":\"https://work.weixin.qq.com\",\"appid\":\"小程序的appid\",\"pagepath\":\"/index.html\"},\"quote_area\":{\"type\":1,\"url\":\"https://work.weixin.qq.com\",\"appid\":\"小程序的appid\",\"pagepath\":\"/index.html\",\"title\":\"引用文献标题\",\"quote_text\":\"引用文献样式的引用文案\"}}}"); - + .isEqualTo("{\"agentid\":1000002,\"touser\":\"OPENID\",\"msgtype\":\"template_card\",\"toparty\":\"PartyID1 | PartyID2\",\"totag\":\"TagID1 | TagID2\",\"duplicate_check_interval\":1800,\"template_card\":{\"card_type\":\"text_notice\",\"source\":{\"icon_url\":\"图片的url\",\"desc\":\"企业微信\",\"desc_color\":1},\"action_menu\":{\"desc\":\"卡片副交互辅助文本说明\",\"action_list\":[{\"text\":\"接受推送\",\"key\":\"A\"},{\"text\":\"不再推送\",\"key\":\"B\"}]},\"main_title\":{\"title\":\"欢迎使用企业微信\",\"desc\":\"您的好友正在邀请您加入企业微信\"},\"emphasis_content\":{\"title\":\"100\",\"desc\":\"核心数据\"},\"sub_title_text\":\"下载企业微信还能抢红包!\",\"task_id\":\"task_id\",\"horizontal_content_list\":[{\"keyname\":\"邀请人\",\"value\":\"张三\"},{\"type\":1,\"keyname\":\"企业微信官网\",\"value\":\"点击访问\",\"url\":\"https://work.weixin.qq.com\"},{\"type\":2,\"keyname\":\"企业微信下载\",\"value\":\"企业微信.apk\",\"media_id\":\"文件的media_id\"},{\"type\":3,\"keyname\":\"员工信息\",\"value\":\"点击查看\",\"userid\":\"zhangsan\"}],\"jump_list\":[{\"type\":1,\"title\":\"企业微信官网\",\"url\":\"https://work.weixin.qq.com\"},{\"type\":2,\"title\":\"跳转小程序\",\"appid\":\"小程序的appid\",\"pagepath\":\"/index.html\"}],\"card_action\":{\"type\":2,\"url\":\"https://work.weixin.qq.com\",\"appid\":\"小程序的appid\",\"pagepath\":\"/index.html\"},\"quote_area\":{\"type\":1,\"url\":\"https://work.weixin.qq.com\",\"appid\":\"小程序的appid\",\"pagepath\":\"/index.html\",\"title\":\"引用文献标题\",\"quote_text\":\"引用文献样式的引用文案\"}}}"); } /** @@ -404,13 +423,13 @@ public void TestTemplateCardBuilder_multiple_interaction() { .question_key("question_key1") .title("选择器标签1") .selected_id("selection_id1") - .options(Arrays.asList(option1,option2)) + .options(Arrays.asList(option1, option2)) .build(); MultipleSelect mSelect2 = MultipleSelect.builder() .question_key("question_key2") .title("选择器标签2") .selected_id("selection_id3") - .options(Arrays.asList(option3,option4)) + .options(Arrays.asList(option3, option4)) .build(); diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/message/WxCpSchoolContactMessageTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/message/WxCpSchoolContactMessageTest.java new file mode 100644 index 000000000..85b734034 --- /dev/null +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/message/WxCpSchoolContactMessageTest.java @@ -0,0 +1,416 @@ +package me.chanjar.weixin.cp.bean.message; + +import com.google.common.collect.Lists; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.api.WxConsts; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.util.json.GsonParser; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl; +import me.chanjar.weixin.cp.bean.article.MpnewsArticle; +import me.chanjar.weixin.cp.bean.article.NewArticle; +import me.chanjar.weixin.cp.bean.school.user.WxCpAllowScope; +import me.chanjar.weixin.cp.bean.school.user.WxCpListParentResult; +import me.chanjar.weixin.cp.bean.school.user.WxCpUserListResult; +import me.chanjar.weixin.cp.config.WxCpConfigStorage; +import me.chanjar.weixin.cp.demo.WxCpDemoInMemoryConfigStorage; +import org.testng.annotations.Test; + +import java.io.InputStream; +import java.util.List; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * 发送「学校通知」消息测试类 + * https://developer.work.weixin.qq.com/document/path/92321 + * + * @author Wang_Wong + * @date 2022-06-29 + */ +@Slf4j +public class WxCpSchoolContactMessageTest { + + private static WxCpConfigStorage wxCpConfigStorage; + private static WxCpService cpService; + + + /** + * 发送「学校通知」 + * 学校可以通过此接口来给家长发送不同类型的学校通知,来满足多种场景下的学校通知需求。目前支持的消息类型为文本、图片、语音、视频、文件、图文。 + * + * https://developer.work.weixin.qq.com/document/path/92321 + * + * 消息体类型请参考测试类 + * WxCpSchoolContactMessageTest + * {@link WxCpSchoolContactMessageTest} + * @throws WxErrorException + */ + @Test + public void testSendSchoolContactMessage() throws WxErrorException { + + InputStream inputStream = ClassLoader.getSystemResourceAsStream("test-config.xml"); + WxCpDemoInMemoryConfigStorage config = WxCpDemoInMemoryConfigStorage.fromXml(inputStream); + + wxCpConfigStorage = config; + cpService = new WxCpServiceImpl(); + cpService.setWxCpConfigStorage(config); + + // 获取可使用的家长范围 返回的数据 + WxCpAllowScope allowScope = cpService.getSchoolUserService().getAllowScope(1000002); + + WxCpUserListResult userList = cpService.getSchoolUserService().getUserList(1, 1); + + // 测试发送给家长 [学校通知] + WxCpListParentResult userListParent = cpService.getSchoolUserService().getUserListParent(1); + List collect = userListParent.getParents() + .stream() + .filter(parent -> parent.getMobile().equals("13079226621")) + .collect(Collectors.toList()); + + String[] parentsId = {"ab0b1691d0204d4900f6b7a7e5a6aa8f", collect.get(0).getParentUserId()}; + + WxCpSchoolContactMessageSendResult sendResult = this.cpService.getMessageService().sendSchoolContactMessage( + + WxCpSchoolContactMessage.builder() + .recvScope(0) + .msgType(WxConsts.SchoolContactMsgType.NEWS) + .toParentUserId(parentsId) +// .toStudentUserId(new String[]{"student_userid1", "student_userid2"}) +// .toParty(new String[]{"partyid1", "partyid2"}) + .toAll(false) + .agentId(cpService.getWxCpConfigStorage().getAgentId()) + .articles(Lists.newArrayList(NewArticle.builder() + .title("这是接口测试标题") + .description("今年中秋节公司有豪礼相送哦") + .url("https://www.baidu.com/") + .picUrl("http://res.mail.qq.com/node/ww/wwopenmng/images/independent/doc/test_pic_msg1.png") + .build())) + .build() + + ); + + log.info("sendResult: {}", sendResult.toJson()); + + } + + // WxCpConsts.SchoolContactChangeType + @Test + public void testToJson_text() { + + WxCpSchoolContactMessage message = WxCpSchoolContactMessage.builder() + .recvScope(0) + .msgType(WxConsts.SchoolContactMsgType.TEXT) + .toParentUserId(new String[]{"parent_userid1", "parent_userid2"}) + .toStudentUserId(new String[]{"student_userid1", "student_userid2"}) + .toParty(new String[]{"partyid1", "partyid2"}) + .toAll(false) + .agentId(1) + .content("你的快递已到,请携带工卡前往邮件中心领取。\n出发前可查看邮件中心视频实况,聪明避开排队。") + .enableIdTrans(false) + .enableDuplicateCheck(false) + .duplicateCheckInterval(1800) + .build(); + + WxCpSchoolContactMessage schoolContactMessage1 = new WxCpSchoolContactMessage(); + schoolContactMessage1.setMsgType(WxConsts.SchoolContactMsgType.TEXT); + schoolContactMessage1.setRecvScope(0); + schoolContactMessage1.setToParentUserId(new String[]{"parent_userid1", "parent_userid2"}); + schoolContactMessage1.setToStudentUserId(new String[]{"student_userid1", "student_userid2"}); + schoolContactMessage1.setToParty(new String[]{"partyid1", "partyid2"}); + schoolContactMessage1.setToAll(false); + schoolContactMessage1.setAgentId(1); + schoolContactMessage1.setContent("你的快递已到,请携带工卡前往邮件中心领取"); + schoolContactMessage1.setEnableIdTrans(false); + schoolContactMessage1.setEnableDuplicateCheck(false); + schoolContactMessage1.setDuplicateCheckInterval(1800); + final String jsonMsg = schoolContactMessage1.toJson(); + + final String json = message.toJson(); + String expectedJson = "{\n" + + "\t\"recv_scope\" : 0,\n" + + "\t\"to_parent_userid\": [\"parent_userid1\", \"parent_userid2\"],\n" + + "\t\"to_student_userid\": [\"student_userid1\", \"student_userid2\"],\n" + + "\t\"to_party\": [\"partyid1\", \"partyid2\"],\n" + + "\t\"toall\" : 0,\n" + + "\t\"msgtype\" : \"text\",\n" + + "\t\"agentid\" : 1,\n" + + "\t\"text\" : {\n" + + "\t\t\"content\" : \"你的快递已到,请携带工卡前往邮件中心领取。\\n出发前可查看邮件中心视频实况,聪明避开排队。\"\n" + + "\t},\n" + + "\t\"enable_id_trans\": 0,\n" + + "\t\"enable_duplicate_check\": 0,\n" + + "\t\"duplicate_check_interval\": 1800\n" + + "}"; + + assertThat(json).isEqualTo(GsonParser.parse(expectedJson).toString()); + } + + @Test + public void testToJson_image() { + WxCpSchoolContactMessage message = WxCpSchoolContactMessage.builder() + .recvScope(0) + .msgType(WxConsts.SchoolContactMsgType.IMAGE) + .toParentUserId(new String[]{"parent_userid1", "parent_userid2"}) + .toStudentUserId(new String[]{"student_userid1", "student_userid2"}) + .toParty(new String[]{"partyid1", "partyid2"}) + .toAll(false) + .agentId(1) + .mediaId("MEDIA_ID") + .build(); + + final String json = message.toJson(); + String expectedJson = "{\n" + + "\t\"recv_scope\" : 0,\n" + + "\t\"to_parent_userid\": [\"parent_userid1\", \"parent_userid2\"],\n" + + "\t\"to_student_userid\": [\"student_userid1\", \"student_userid2\"],\n" + + "\t\"to_party\": [\"partyid1\", \"partyid2\"],\n" + + "\t\"toall\" : 0,\n" + + "\t\"msgtype\" : \"image\",\n" + + "\t\"agentid\" : 1,\n" + + "\t\"image\" : {\n" + + "\t\t\"media_id\" : \"MEDIA_ID\"\n" + + "\t},\n" + + "\t\"enable_duplicate_check\": 0,\n" + + "\t\"duplicate_check_interval\": 1800\n" + + "}"; + + assertThat(json).isEqualTo(GsonParser.parse(expectedJson).toString()); + } + + @Test + public void testToJson_voice() { + WxCpSchoolContactMessage message = WxCpSchoolContactMessage.builder() + .recvScope(0) + .msgType(WxConsts.SchoolContactMsgType.VOICE) + .toParentUserId(new String[]{"parent_userid1", "parent_userid2"}) + .toStudentUserId(new String[]{"student_userid1", "student_userid2"}) + .toParty(new String[]{"partyid1", "partyid2"}) + .toAll(false) + .agentId(1) + .mediaId("MEDIA_ID") + .build(); + + final String json = message.toJson(); + String expectedJson = "{\n" + + "\t\"recv_scope\" : 0,\n" + + "\t\"to_parent_userid\": [\"parent_userid1\", \"parent_userid2\"],\n" + + "\t\"to_student_userid\": [\"student_userid1\", \"student_userid2\"],\n" + + "\t\"to_party\": [\"partyid1\", \"partyid2\"],\n" + + "\t\"toall\" : 0,\n" + + "\t\"msgtype\" : \"voice\",\n" + + "\t\"agentid\" : 1,\n" + + "\t\"voice\" : {\n" + + "\t\t\"media_id\" : \"MEDIA_ID\"\n" + + "\t},\n" + + "\t\"enable_duplicate_check\": 0,\n" + + "\t\"duplicate_check_interval\": 1800\n" + + "}"; + + assertThat(json).isEqualTo(GsonParser.parse(expectedJson).toString()); + } + + @Test + public void testToJson_video() { + WxCpSchoolContactMessage message = WxCpSchoolContactMessage.builder() + .recvScope(0) + .msgType(WxConsts.SchoolContactMsgType.VIDEO) + .toParentUserId(new String[]{"parent_userid1", "parent_userid2"}) + .toStudentUserId(new String[]{"student_userid1", "student_userid2"}) + .toParty(new String[]{"partyid1", "partyid2"}) + .toAll(false) + .agentId(1) + .mediaId("MEDIA_ID") + .title("Title") + .description("Description") + .build(); + + final String json = message.toJson(); + String expectedJson = "{\n" + + "\t\"recv_scope\" : 0,\n" + + "\t\"to_parent_userid\": [\"parent_userid1\", \"parent_userid2\"],\n" + + "\t\"to_student_userid\": [\"student_userid1\", \"student_userid2\"],\n" + + "\t\"to_party\": [\"partyid1\", \"partyid2\"],\n" + + "\t\"toall\" : 0,\n" + + "\t\"msgtype\" : \"video\",\n" + + "\t\"agentid\" : 1,\n" + + "\t\"video\" : {\n" + + " \"media_id\" : \"MEDIA_ID\",\n" + + " \"title\" : \"Title\",\n" + + " \"description\" : \"Description\"\n" + + "\t},\n" + + "\t\"enable_duplicate_check\": 0,\n" + + "\t\"duplicate_check_interval\": 1800\n" + + "}"; + + assertThat(json).isEqualTo(GsonParser.parse(expectedJson).toString()); + } + + @Test + public void testToJson_file() { + WxCpSchoolContactMessage message = WxCpSchoolContactMessage.builder() + .recvScope(0) + .msgType(WxConsts.SchoolContactMsgType.FILE) + .toParentUserId(new String[]{"parent_userid1", "parent_userid2"}) + .toStudentUserId(new String[]{"student_userid1", "student_userid2"}) + .toParty(new String[]{"partyid1", "partyid2"}) + .toAll(false) + .agentId(1) + .mediaId("1Yv-zXfHjSjU-7LH-GwtYqDGS-zz6w22KmWAT5COgP7o") + .build(); + + final String json = message.toJson(); + String expectedJson = "{\n" + + "\t\"recv_scope\" : 0,\n" + + "\t\"to_parent_userid\": [\"parent_userid1\", \"parent_userid2\"],\n" + + "\t\"to_student_userid\": [\"student_userid1\", \"student_userid2\"],\n" + + "\t\"to_party\": [\"partyid1\", \"partyid2\"],\n" + + "\t\"toall\" : 0,\n" + + "\t\"msgtype\" : \"file\",\n" + + "\t\"agentid\" : 1,\n" + + "\t\"file\" : {\n" + + " \"media_id\" : \"1Yv-zXfHjSjU-7LH-GwtYqDGS-zz6w22KmWAT5COgP7o\"\n" + + "\t},\n" + + "\t\"enable_duplicate_check\": 0,\n" + + "\t\"duplicate_check_interval\": 1800\n" + + "}"; + + assertThat(json).isEqualTo(GsonParser.parse(expectedJson).toString()); + } + + @Test + public void testToJson_news() { + WxCpSchoolContactMessage message = WxCpSchoolContactMessage.builder() + .recvScope(0) + .msgType(WxConsts.SchoolContactMsgType.NEWS) + .toParentUserId(new String[]{"parent_userid1", "parent_userid2"}) + .toStudentUserId(new String[]{"student_userid1", "student_userid2"}) + .toParty(new String[]{"partyid1", "partyid2"}) + .toAll(false) + .agentId(1) + .articles(Lists.newArrayList(NewArticle.builder() + .title("中秋节礼品领取") + .description("今年中秋节公司有豪礼相送") + .url("URL") + .picUrl("http://res.mail.qq.com/node/ww/wwopenmng/images/independent/doc/test_pic_msg1.png") + .build())) + .build(); + + final String json = message.toJson(); + String expectedJson = "{\n" + + " \"recv_scope\" : 0,\n" + + " \"to_parent_userid\": [\"parent_userid1\", \"parent_userid2\"],\n" + + " \"to_student_userid\": [\"student_userid1\", \"student_userid2\"],\n" + + " \"to_party\": [\"partyid1\", \"partyid2\"],\n" + + " \"toall\" : 0,\n" + + " \"msgtype\" : \"news\",\n" + + " \"agentid\" : 1,\n" + + " \"news\" : {\n" + + " \"articles\" : [\n" + + " {\n" + + " \"title\" : \"中秋节礼品领取\",\n" + + " \"description\" : \"今年中秋节公司有豪礼相送\",\n" + + " \"url\" : \"URL\",\n" + + " \"picurl\" : \"http://res.mail.qq.com/node/ww/wwopenmng/images/independent/doc/test_pic_msg1.png\"\n" + + " }\n" + + "\t\t]\n" + + " },\n" + + " \"enable_id_trans\": 0,\n" + + " \"enable_duplicate_check\": 0,\n" + + " \"duplicate_check_interval\": 1800\n" + + "}"; + + assertThat(json).isEqualTo(GsonParser.parse(expectedJson).toString()); + } + + + @Test + public void testToJson_mpnews() { + WxCpSchoolContactMessage message = WxCpSchoolContactMessage.builder() + .recvScope(0) + .msgType(WxConsts.SchoolContactMsgType.MPNEWS) + .toParentUserId(new String[]{"parent_userid1", "parent_userid2"}) + .toStudentUserId(new String[]{"student_userid1", "student_userid2"}) + .toParty(new String[]{"partyid1", "partyid2"}) + .toAll(false) + .agentId(1) + .mpNewsArticles(Lists.newArrayList(MpnewsArticle.newBuilder() + .title("Title") + .thumbMediaId("MEDIA_ID") + .author("Author") + .contentSourceUrl("URL") + .content("Content") + .digest("Digest description") + .build())) + .build(); + + final String json = message.toJson(); + String expectedJson = "{\n" + + " \"recv_scope\" : 0,\n" + + " \"to_parent_userid\": [\"parent_userid1\", \"parent_userid2\"],\n" + + " \"to_student_userid\": [\"student_userid1\", \"student_userid2\"],\n" + + " \"to_party\": [\"partyid1\", \"partyid2\"],\n" + + " \"toall\" : 0,\n" + + " \"msgtype\" : \"mpnews\",\n" + + " \"agentid\" : 1,\n" + + " \"mpnews\" : {\n" + + " \"articles\":[\n" + + " {\n" + + " \"title\": \"Title\", \n" + + " \"thumb_media_id\": \"MEDIA_ID\",\n" + + " \"author\": \"Author\",\n" + + " \"content_source_url\": \"URL\",\n" + + " \"content\": \"Content\",\n" + + " \"digest\": \"Digest description\"\n" + + " }\n" + + " ]\n" + + " },\n" + + " \"enable_id_trans\": 0,\n" + + " \"enable_duplicate_check\": 0,\n" + + " \"duplicate_check_interval\": 1800\n" + + "}\n"; + + assertThat(json).isEqualTo(GsonParser.parse(expectedJson).toString()); + } + + @Test + public void testToJson_miniProgram() { + WxCpSchoolContactMessage message = WxCpSchoolContactMessage.builder() + .recvScope(0) + .msgType(WxConsts.SchoolContactMsgType.MINIPROGRAM) + .toParentUserId(new String[]{"parent_userid1", "parent_userid2"}) + .toStudentUserId(new String[]{"student_userid1", "student_userid2"}) + .toParty(new String[]{"partyid1", "partyid2"}) + .toAll(false) + .agentId(1) + .appId("APPID") + .title("欢迎报名夏令营") + .thumbMediaId("MEDIA_ID") + .pagePath("PAGE_PATH") + .build(); + + final String json = message.toJson(); + String expectedJson = "{\n" + + " \"recv_scope\" : 0,\n" + + " \"to_parent_userid\": [\"parent_userid1\", \"parent_userid2\"],\n" + + " \"to_student_userid\": [\"student_userid1\", \"student_userid2\"],\n" + + " \"to_party\": [\"partyid1\", \"partyid2\"],\n" + + " \"toall\" : 0,\n" + + " \"agentid\" : 1,\n" + + " \"msgtype\" : \"miniprogram\",\n" + + " \"miniprogram\" : {\n" + + " \"appid\": \"APPID\",\n" + + " \"title\": \"欢迎报名夏令营\",\n" + + " \"thumb_media_id\": \"MEDIA_ID\",\n" + + " \"pagepath\": \"PAGE_PATH\"\n" + + " },\n" + + " \"enable_id_trans\": 0,\n" + + " \"enable_duplicate_check\": 0,\n" + + " \"duplicate_check_interval\": 1800\n" + + "}\n"; + + assertThat(json).isEqualTo(GsonParser.parse(expectedJson).toString()); + } + +} diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/tp/service/impl/BaseWxCpTpServiceImplTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/tp/service/impl/BaseWxCpTpServiceImplTest.java index 26ca567c1..8a29a1130 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/tp/service/impl/BaseWxCpTpServiceImplTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/tp/service/impl/BaseWxCpTpServiceImplTest.java @@ -12,6 +12,9 @@ import org.testng.Assert; import org.testng.annotations.Test; +import java.util.List; +import java.util.Objects; + import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Tp.GET_AUTH_INFO; import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Tp.GET_PERMANENT_CODE; import static org.assertj.core.api.Assertions.assertThat; @@ -179,6 +182,30 @@ public void testGetPermanentCodeInfo() throws WxErrorException { " \"userid\": \"yuanqixun\", \n" + " \"name\": \"袁启勋\", \n" + " \"avatar\": \"http://wework.qpic.cn/bizmail/ZYqy8EswiaFyPnk7gy7eiafoicz3TL35f4bAvCf2eSe6RVYSK7aPDFxcw/0\"\n" + + " },\n" + + " \"edition_info\":\n" + + " {\n" + + " \"agent\" :\n" + + " [\n" + + " {\n" + + " \"agentid\":1,\n" + + " \"edition_id\":\"RLS65535\",\n" + + " \"edition_name\":\"协同版\",\n" + + " \"app_status\":3,\n" + + " \"user_limit\":200,\n" + + " \"expired_time\":1541990791\n" + + " },\n" + + " {\n" + + " \"agentid\":1,\n" + + " \"edition_id\":\"RLS65535\",\n" + + " \"edition_name\":\"协同版\",\n" + + " \"app_status\":3,\n" + + " \"user_limit\":200,\n" + + " \"expired_time\":1541990791,\n" + + " \"is_virtual_version\":false,\n" + + " \"is_shared_from_other_corp\":true\n" + + " }\n" + + " ]\n" + " }\n" + "}"; @@ -192,6 +219,15 @@ public void testGetPermanentCodeInfo() throws WxErrorException { assertThat(tpPermanentCodeInfo.getAuthInfo().getAgents().get(0).getAgentId()).isEqualTo(1000012); Assert.assertNotNull(tpPermanentCodeInfo.getAuthInfo().getAgents().get(0).getSquareLogoUrl()); Assert.assertNotNull(tpPermanentCodeInfo.getAuthCorpInfo().getCorpSquareLogoUrl()); + + final WxCpTpPermanentCodeInfo.EditionInfo editionInfo = tpPermanentCodeInfo.getEditionInfo(); + Assert.assertNotNull(editionInfo); + + final List editionInfoAgents = editionInfo.getAgents(); + Assert.assertTrue(Objects.nonNull(editionInfoAgents) && !editionInfoAgents.isEmpty()); + + Assert.assertNotNull(editionInfoAgents.get(0).getExpiredTime()); + } @Test @@ -250,6 +286,32 @@ public void testGetAuthInfo() throws WxErrorException { " \"appid\":5\n" + " }\n" + " ]\n" + + " },\n" + + " \"edition_info\":\n" + + " {\n" + + " \"agent\" :\n" + + " [\n" + + " {\n" + + " \"agentid\":1,\n" + + " \"edition_id\":\"RLS65535\",\n" + + " \"edition_name\":\"协同版\",\n" + + " \"app_status\":3,\n" + + " \"user_limit\":200,\n" + + " \"expired_time\":1541990791,\n" + + " \"is_virtual_version\":false,\n" + + " \"is_shared_from_other_corp\":true\n" + + " },\n" + + " {\n" + + " \"agentid\":1,\n" + + " \"edition_id\":\"RLS65535\",\n" + + " \"edition_name\":\"协同版\",\n" + + " \"app_status\":3,\n" + + " \"user_limit\":200,\n" + + " \"expired_time\":1541990791,\n" + + " \"is_virtual_version\":false,\n" + + " \"is_shared_from_other_corp\":true\n" + + " }\n" + + " ]\n" + " }\n" + "}\n"; @@ -263,6 +325,14 @@ public void testGetAuthInfo() throws WxErrorException { Mockito.doReturn(returnJson).when(tpService).post(configStorage.getApiUrl(GET_AUTH_INFO), jsonObject.toString()); WxCpTpAuthInfo authInfo = tpService.getAuthInfo(authCorpId, permanentCode); Assert.assertNotNull(authInfo.getAuthCorpInfo().getCorpId()); + + final WxCpTpAuthInfo.EditionInfo editionInfo = authInfo.getEditionInfo(); + Assert.assertNotNull(editionInfo); + + final List editionInfoAgents = editionInfo.getAgents(); + Assert.assertTrue(Objects.nonNull(editionInfoAgents) && !editionInfoAgents.isEmpty()); + + Assert.assertNotNull(editionInfoAgents.get(0).getExpiredTime()); } @Test diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpEditionServiceImplTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpEditionServiceImplTest.java new file mode 100644 index 000000000..b3561a3ae --- /dev/null +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpEditionServiceImplTest.java @@ -0,0 +1,70 @@ +package me.chanjar.weixin.cp.tp.service.impl; + +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.bean.WxCpTpProlongTryResult; +import me.chanjar.weixin.cp.config.WxCpTpConfigStorage; +import me.chanjar.weixin.cp.config.impl.WxCpTpDefaultConfigImpl; +import me.chanjar.weixin.cp.tp.service.WxCpTpEditionService; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Tp.PROLONG_TRY; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.when; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; + +/** + * 应用版本付费版本相关接口测试 + */ +public class WxCpTpEditionServiceImplTest { + + @Mock + private WxCpTpServiceApacheHttpClientImpl wxCpTpService; + + private WxCpTpConfigStorage configStorage; + + private WxCpTpEditionService wxCpTpEditionService; + + @BeforeClass + public void setUp() { + MockitoAnnotations.initMocks(this); + configStorage = new WxCpTpDefaultConfigImpl(); + when(wxCpTpService.getWxCpTpConfigStorage()).thenReturn(configStorage); + wxCpTpEditionService = new WxCpTpEditionServiceImpl(wxCpTpService); + } + + + /** + * 延长试用期 + */ + @Test + public void testProlongTry() throws WxErrorException { + + String buyerCorpId = "wx7da9abf8ac62baaa"; + Integer prolongDays = 7; + String appId = "1"; + + Long tryEndTime = 1565152189L; + + String result = "" + + " {\n" + + " \"errcode\" : 0,\n" + + " \"errmsg\" : \"ok\",\n" + + " \"try_end_time\" : 1565152189\n" + + " }"; + + String url = configStorage.getApiUrl(PROLONG_TRY); + when(wxCpTpService.post(eq(url), any(String.class))).thenReturn(result); + + final WxCpTpProlongTryResult prolongTryResult = wxCpTpEditionService.prolongTry(buyerCorpId, prolongDays, appId); + + assertNotNull(prolongTryResult); + + assertEquals(prolongTryResult.getTryEndTime(), tryEndTime); + + } +} diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpLicenseServiceImplTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpLicenseServiceImplTest.java new file mode 100644 index 000000000..00772ad6b --- /dev/null +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpLicenseServiceImplTest.java @@ -0,0 +1,457 @@ +package me.chanjar.weixin.cp.tp.service.impl; + +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.bean.license.*; +import me.chanjar.weixin.cp.bean.license.account.*; +import me.chanjar.weixin.cp.bean.license.order.*; +import me.chanjar.weixin.cp.config.WxCpTpConfigStorage; +import me.chanjar.weixin.cp.config.impl.WxCpTpDefaultConfigImpl; +import me.chanjar.weixin.cp.tp.service.WxCpTpLicenseService; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import java.util.*; + +import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.License.*; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.when; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; + +/** + * 许可证账号服务测试 + * @author Totoro + * @date 2022/6/27 16:34 + */ +public class WxCpTpLicenseServiceImplTest { + + @Mock + private WxCpTpServiceApacheHttpClientImpl wxCpTpService; + + private WxCpTpConfigStorage configStorage; + + private WxCpTpLicenseService wxCpTpLicenseService; + + @BeforeClass + public void setUp() { + MockitoAnnotations.initMocks(this); + configStorage = new WxCpTpDefaultConfigImpl(); + when(wxCpTpService.getWxCpTpConfigStorage()).thenReturn(configStorage); + wxCpTpLicenseService = new WxCpTpLicenseServiceImpl(wxCpTpService); + } + + + @Test + public void testCrateNewOrder() throws WxErrorException { + String orderId = "OASFNAISFASFA252462"; + String result = "{\n" + + "\t\"errcode\": 0,\n" + + "\t\"errmsg\": \"ok\",\n" + + "\t\"order_id\": \"OASFNAISFASFA252462\"\n" + + "}"; + String url = configStorage.getApiUrl(CREATE_NEW_ORDER) + "?provider_access_token=" + wxCpTpService.getWxCpProviderToken(); + when(wxCpTpService.post(eq(url), any(String.class))).thenReturn(result); + WxCpTpLicenseNewOrderRequest orderRequest = WxCpTpLicenseNewOrderRequest.builder() + .accountCount(WxCpTpLicenseAccountCount.builder().baseCount(5).externalContactCount(6).build()) + .buyerUserId("test") + .corpId("test") + .accountDuration(WxCpTpLicenseAccountDuration.builder().months(5).build()) + .build(); + final WxCpTpLicenseCreateOrderResp newOrder = wxCpTpLicenseService.createNewOrder(orderRequest); + assertNotNull(newOrder); + assertEquals(newOrder.getOrderId(), orderId); + } + + + @Test + public void testCreateRenewOrderJob() throws WxErrorException { + String jobId = "test123456"; + String result = "{\n" + + " \"errcode\":0,\n" + + " \"errmsg\":\"ok\",\n" + + " \"jobid\":\"test123456\",\n" + + " \"invalid_account_list\":[\n" + + " {\n" + + " \"errcode\":1,\n" + + " \"errmsg\":\"error\",\n" + + " \"userid\":\"userid1\",\n" + + " \"type\":1\n" + + " },\n" + + " {\n" + + " \"errcode\":0,\n" + + " \"errmsg\":\"ok\",\n" + + " \"userid\":\"userid2\",\n" + + " \"type\":1\n" + + " }\n" + + " ]\n" + + "}"; + String url = configStorage.getApiUrl(CREATE_RENEW_ORDER_JOB) + "?provider_access_token=" + wxCpTpService.getWxCpProviderToken(); + when(wxCpTpService.post(eq(url), any(String.class))).thenReturn(result); + List accountList = new ArrayList<>(); + accountList.add(WxCpTpLicenseBaseAccount.builder().type(1).userid("userid1").build()); + accountList.add(WxCpTpLicenseBaseAccount.builder().type(1).userid("userid2").build()); + WxCpTpLicenseRenewOrderJobRequest orderJobRequest = WxCpTpLicenseRenewOrderJobRequest.builder() + .jobId("test123456") + .accountList(accountList).build(); + final WxCpTpLicenseRenewOrderJobResp renewOrderJob = wxCpTpLicenseService.createRenewOrderJob(orderJobRequest); + assertNotNull(renewOrderJob); + + assertEquals(renewOrderJob.getJobId(), jobId); + + assertEquals(renewOrderJob.getInvalidAccountList().size(), accountList.size()); + } + + @Test + public void testSubmitRenewOrderJob() throws WxErrorException { + String orderId = "test5915231"; + String result = "{\n" + + "\t\"errcode\": 0,\n" + + "\t\"errmsg\": \"ok\",\n" + + "\t\"order_id\": \"test5915231\"\n" + + "}"; + String url = configStorage.getApiUrl(SUBMIT_ORDER_JOB) + "?provider_access_token=" + wxCpTpService.getWxCpProviderToken(); + when(wxCpTpService.post(eq(url), any(String.class))).thenReturn(result); + WxCpTpLicenseRenewOrderRequest renewOrderRequest = WxCpTpLicenseRenewOrderRequest.builder() + .jobId("test123456") + .accountDuration(WxCpTpLicenseAccountDuration.builder().months(5).build()) + .buyerUserId("test") + .build(); + WxCpTpLicenseCreateOrderResp createOrderResp = wxCpTpLicenseService.submitRenewOrder(renewOrderRequest); + assertNotNull(createOrderResp); + + assertEquals(createOrderResp.getOrderId(), orderId); + } + + @Test + public void testGetOrderList() throws WxErrorException { + String nextCursor = "DSGAKAFA4524"; + String orderId = "test123"; + String result = "{\n" + + "\t\"errcode\": 0,\n" + + "\t\"errmsg\": \"ok\",\n" + + "\t\"next_cursor\":\"DSGAKAFA4524\",\n" + + "\t\"has_more\":1,\n" + + "\t\"order_list\":[\n" + + "\t\t{\n" + + "\t\t\t\"order_id\":\"test123\",\n" + + "\t\t\t\"order_type\":1\n" + + "\t\t}\n" + + "\t]\n" + + "}"; + + String url = configStorage.getApiUrl(LIST_ORDER) + "?provider_access_token=" + wxCpTpService.getWxCpProviderToken(); + when(wxCpTpService.post(eq(url), any(String.class))).thenReturn(result); + WxCpTpLicenseOrderListResp orderList = wxCpTpLicenseService.getOrderList("test", new Date(), new Date(), null, 10); + assertNotNull(orderList); + + assertEquals(orderList.getNextCursor(), nextCursor); + + assertEquals(orderList.getOrderList().get(0).getOrderId(), orderId); + + } + @Test + public void testGetOrder() throws WxErrorException { + String corpId = "ASFASF4254"; + String orderId = "FASASIFJ9W125234"; + String result = "{\n" + + "\t\"errcode\": 0,\n" + + "\t\"errmsg\": \"ok\",\n" + + "\t\"order\":{\n" + + "\t\t\"order_id\":\"FASASIFJ9W125234\",\n" + + "\t\t\"order_type\":1,\n" + + "\t\t\"order_status\":1,\n" + + "\t\t\"corpid\":\"ASFASF4254\",\n" + + "\t\t\"price\":10000,\n" + + "\t\t\"account_count\":{\n" + + "\t \t \"base_count\":100,\n" + + " \t \"external_contact_count\":100\n" + + "\t },\n" + + "\t\t \"account_duration\":\n" + + " \t\t {\n" + + "\t \t \t\"months\":2\n" + + " \t \t \t},\n" + + "\t\t\"create_time\":150000000,\n" + + "\t \"pay_time\":1550000000\n" + + "\t}\n" + + "}"; + String url = configStorage.getApiUrl(GET_ORDER) + "?provider_access_token=" + wxCpTpService.getWxCpProviderToken(); + when(wxCpTpService.post(eq(url), any(String.class))).thenReturn(result); + WxCpTpLicenseOrderInfoResp orderInfo = wxCpTpLicenseService.getOrderInfo(orderId); + assertNotNull(orderInfo); + + assertNotNull(orderInfo.getOrder()); + + assertEquals(orderInfo.getOrder().getOrderId(), orderId); + + assertEquals(orderInfo.getOrder().getCorpId(), corpId); + + + } + + + @Test + public void testGetOrderAccount() throws WxErrorException { + String orderId = "ASFASF4254"; + String activeCode = "FASASIFJ9W125234"; + String result = "{\n" + + "\t\"errcode\": 0,\n" + + "\t\"errmsg\": \"ok\",\n" + + "\t\"next_cursor\": \"ASFASF4254\",\n" + + "\t\"has_more\":1,\n" + + "\t\"account_list\":[\n" + + "\t\t{\n" + + "\t\t\t\"active_code\": \"FASASIFJ9W125234\",\n" + + "\t\t\t\"userid\":\"XXX\",\n" + + "\t\t\t\"type\": 1\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"active_code\": \"code2\",\n" + + "\t\t\t\"userid\":\"XXX\",\n" + + "\t\t\t\"type\": 2\n" + + "\t\t}\n" + + "\t]\n" + + "}"; + + String url = configStorage.getApiUrl(LIST_ORDER_ACCOUNT) + "?provider_access_token=" + wxCpTpService.getWxCpProviderToken(); + when(wxCpTpService.post(eq(url), any(String.class))).thenReturn(result); + WxCpTpLicenseOrderAccountListResp orderAccountList = wxCpTpLicenseService.getOrderAccountList(orderId, 10, null); + assertNotNull(orderAccountList); + + assertNotNull(orderAccountList.getAccountList()); + + assertEquals(orderAccountList.getAccountList().get(0).getActiveCode(), activeCode); + + + } + + + @Test + public void testActiveAccount() throws WxErrorException { + String result = "{\n" + + "\t\"errcode\": 0,\n" + + "\t\"errmsg\": \"ok\"\n" + + "}"; + + String url = configStorage.getApiUrl(ACTIVE_ACCOUNT) + "?provider_access_token=" + wxCpTpService.getWxCpProviderToken(); + when(wxCpTpService.post(eq(url), any(String.class))).thenReturn(result); + WxCpBaseResp wxCpBaseResp = wxCpTpLicenseService.activeCode("123456", "123456", "123456"); + assertNotNull(wxCpBaseResp); + } + + @Test + public void testBatchActiveAccount() throws WxErrorException { + String result = "{\n" + + "\t\"errcode\": 0,\n" + + "\t\"errmsg\": \"ok\",\n" + + "\t\"active_result\":[\n" + + "\t{\n" + + "\t\t\"active_code\" : \"aASFINAJOFASF\",\n" + + "\t\t\"userid\": \"SAGASGSD\",\n" + + "\t\t\"errcode\":0\n" + + "\t},\n" + + "\t{\n" + + "\t\t\"active_code\" : \"ASDEGAFAd\",\n" + + "\t\t\"userid\": \"dsfafD\",\n" + + "\t\t\"errcode\":0\n" + + "\t}]\n" + + "}"; + String url = configStorage.getApiUrl(BATCH_ACTIVE_ACCOUNT) + "?provider_access_token=" + wxCpTpService.getWxCpProviderToken(); + when(wxCpTpService.post(eq(url), any(String.class))).thenReturn(result); + List accountList = new ArrayList<>(); + accountList.add(WxCpTpLicenseActiveAccount.builder().userid("SAGASGSD").activeCode("aASFINAJOFASF").build()); + accountList.add(WxCpTpLicenseActiveAccount.builder().userid("dsfafD").activeCode("ASDEGAFAd").build()); + WxCpTpLicenseBatchActiveResultResp wxCpTpLicenseBatchActiveResultResp = wxCpTpLicenseService.batchActiveCode("123456", accountList); + assertNotNull(wxCpTpLicenseBatchActiveResultResp); + + assertEquals(wxCpTpLicenseBatchActiveResultResp.getActiveResults().size(), accountList.size()); + + assertEquals(wxCpTpLicenseBatchActiveResultResp.getActiveResults().get(0).getActiveCode(), "aASFINAJOFASF"); + } + + + @Test + public void testGetActiveInfoByCode() throws WxErrorException { + String activeCode = "asgasfasfa"; + String result = "{\n" + + "\t\"errcode\": 0,\n" + + "\t\"errmsg\": \"ok\",\n" + + "\t\"active_info\": {\n" + + "\t\t\"active_code\": \"asgasfasfa\",\n" + + "\t\t\"type\": 1,\n" + + "\t\t\"status\": 1,\n" + + "\t\t\"userid\": \"asfasgasg\",\n" + + "\t\t\"create_time\":1640966400,\n" + + "\t\t\"active_time\": 1640966400,\n" + + "\t\t\"expire_time\":1640966400\n" + + "\t}\n" + + "}"; + + String url = configStorage.getApiUrl(GET_ACTIVE_INFO_BY_CODE) + "?provider_access_token=" + wxCpTpService.getWxCpProviderToken(); + when(wxCpTpService.post(eq(url), any(String.class))).thenReturn(result); + WxCpTpLicenseCodeInfoResp activeInfoByCode = wxCpTpLicenseService.getActiveInfoByCode("123456", "safasg"); + assertNotNull(activeInfoByCode); + + assertEquals(activeInfoByCode.getActiveCodeInfo().getActiveCode(), activeCode); + + + } + + + @Test + public void testGetActiveInfoByUser() throws WxErrorException { + String activeCode = "asfaisfhiuaw"; + String userid = "asfasgasga"; + String result = "{\n" + + "\t\"errcode\": 0,\n" + + "\t\"errmsg\": \"ok\",\n" + + "\t\"active_status\": 1,\n" + + "\t\"active_info_list\": \n" + + "\t[\n" + + "\t\t {\n" + + "\t\t\t\"active_code\": \"asfaisfhiuaw\",\n" + + "\t\t\t\"type\": 1,\n" + + "\t\t\t\"userid\": \"asfasgasga\",\n" + + "\t\t\t\"active_time\": 1640966400,\n" + + "\t\t\t\"expire_time\":1640966400\n" + + " \t \t },\n" + + " {\n" + + "\t\t\t\"active_code\": \"gasdawsd\",\n" + + "\t\t\t\"type\": 2,\n" + + "\t\t\t\"userid\": \"asdfasfasf\",\n" + + "\t\t\t\"active_time\":1640966400,\n" + + "\t\t\t\"expire_time\":1640966400\n" + + "\t\t }\n" + + " ]\n" + + "}"; + + String url = configStorage.getApiUrl(GET_ACTIVE_INFO_BY_USER) + "?provider_access_token=" + wxCpTpService.getWxCpProviderToken(); + when(wxCpTpService.post(eq(url), any(String.class))).thenReturn(result); + WxCpTpLicenseActiveInfoByUserResp activeInfoByUser = wxCpTpLicenseService.getActiveInfoByUser("123456", userid); + assertNotNull(activeInfoByUser); + + assertEquals(activeInfoByUser.getActiveStatus().intValue(), 1); + + assertEquals(activeInfoByUser.getActiveInfoList().get(0).getActiveCode(), activeCode); + } + + @Test + public void testBatchGetActiveInfoByUser() throws WxErrorException { + String activeCode = "asgasgasgas"; + String result = "{\n" + + "\t\"errcode\": 0,\n" + + "\t\"errmsg\": \"ok\",\n" + + "\t\"active_info_list\": [\n" + + "\t\t{\n" + + "\t\t\t\"active_code\": \"asgasgasgas\",\n" + + "\t\t\t\"type\": 1,\n" + + "\t\t\t\"status\": 1,\n" + + "\t\t\t\"userid\": \"gadfFDF\",\n" + + "\t\t\t\"create_time\":1640966400,\n" + + "\t\t\t\"active_time\": 1640966400,\n" + + "\t\t\t\"expire_time\":1640966400\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"active_code\": \"awsgdgasdasd\",\n" + + "\t\t\t\"type\": 2,\n" + + "\t\t\t\"status\": 1,\n" + + "\t\t\t\"userid\": \"SGASRDASGAQ\",\n" + + "\t\t\t\"create_time\":1640966400,\n" + + "\t\t\t\"active_time\": 1640966400,\n" + + "\t\t\t\"expire_time\":1640966400\n" + + "\t\t}\n" + + "\t],\n" + + "\t\"invalid_active_code_list\":[\"fasgasga\"]\n" + + "}"; + + + String url = configStorage.getApiUrl(BATCH_GET_ACTIVE_INFO_BY_CODE) + "?provider_access_token=" + wxCpTpService.getWxCpProviderToken(); + when(wxCpTpService.post(eq(url), any(String.class))).thenReturn(result); + Set codes = new HashSet<>(); + codes.add("asgasgasgas"); + codes.add("awsgdgasdasd"); + codes.add("fasgasga"); + WxCpTpLicenseBatchCodeInfoResp codeInfoResp = wxCpTpLicenseService.batchGetActiveInfoByCode(codes, "asfasfas"); + assertNotNull(codeInfoResp); + + assertEquals(codeInfoResp.getActiveCodeInfoList().size() , codes.size() - 1); + + assertNotNull(codeInfoResp.getInvalidActiveCodeList()); + + + } + + + @Test + public void testGetCorpAccountList() throws WxErrorException { + String nextCursor = "asfasdfas"; + String userid = "asdasdasd"; + String result = "{\n" + + "\t\"errcode\": 0,\n" + + "\t\"errmsg\": \"ok\",\n" + + "\t\"next_cursor\":\"asfasdfas\",\n" + + "\t\"has_more\":1,\n" + + "\t\"account_list\":[\n" + + "\t\t{\n" + + "\t\t\t\"userid\": \"asdasdasd\",\n" + + "\t\t\t\"type\": 1,\n" + + "\t\t\t\"expire_time\":1500000000,\n" + + "\t\t\t\"active_time\":1500000000\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"userid\": \"asgasgasdasd\",\n" + + "\t\t\t\"type\": 1,\n" + + "\t\t\t\"expire_time\":1500000000,\n" + + "\t\t\t\"active_time\":1500000000\n" + + "\t\t}\n" + + "\t]\n" + + "}"; + + String url = configStorage.getApiUrl(LIST_ACTIVED_ACCOUNT) + "?provider_access_token=" + wxCpTpService.getWxCpProviderToken(); + when(wxCpTpService.post(eq(url), any(String.class))).thenReturn(result); + WxCpTpLicenseCorpAccountListResp accountList = wxCpTpLicenseService.getCorpAccountList("123456", 10, null); + assertNotNull(accountList); + + assertNotNull(accountList.getOrderList()); + + assertEquals(accountList.getNextCursor(), nextCursor); + + assertEquals(accountList.getOrderList().get(0).getUserid(), userid); + } + + + @Test + public void testBatchTransferLicense() throws WxErrorException { + String handoverUserid = "dazdasfasf"; + String takeoverUserid = "asfasfasf"; + String result = "{\n" + + "\t\"errcode\": 0,\n" + + "\t\"errmsg\": \"ok\",\n" + + "\t\"transfer_result\":[\n" + + "\t{\n" + + "\t\t\"handover_userid\":\"dazdasfasf\",\n" + + "\t\t\"takeover_userid\":\"asfasfasf\",\n" + + "\t\t\"errcode\":0\n" + + "\t}]\n" + + "}"; + + String url = configStorage.getApiUrl(BATCH_TRANSFER_LICENSE) + "?provider_access_token=" + wxCpTpService.getWxCpProviderToken(); + when(wxCpTpService.post(eq(url), any(String.class))).thenReturn(result); + List transferList = new ArrayList<>(); + transferList.add(WxCpTpLicenseTransfer.builder().handoverUserId(handoverUserid).takeoverUserId(takeoverUserid).build()); + WxCpTpLicenseBatchTransferResp licenseBatchTransferResp = wxCpTpLicenseService.batchTransferLicense("123456", transferList); + assertNotNull(licenseBatchTransferResp); + + assertNotNull(licenseBatchTransferResp.getTransferResult()); + + assertEquals(licenseBatchTransferResp.getTransferResult().size(), transferList.size()); + + } + + + + +} diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpOrderServiceImplTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpOrderServiceImplTest.java new file mode 100644 index 000000000..eb0c5a38a --- /dev/null +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpOrderServiceImplTest.java @@ -0,0 +1,156 @@ +package me.chanjar.weixin.cp.tp.service.impl; + +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.bean.order.WxCpTpOrderDetails; +import me.chanjar.weixin.cp.bean.order.WxCpTpOrderListGetResult; +import me.chanjar.weixin.cp.config.WxCpTpConfigStorage; +import me.chanjar.weixin.cp.config.impl.WxCpTpDefaultConfigImpl; +import me.chanjar.weixin.cp.tp.service.WxCpTpOrderService; +import org.apache.commons.lang3.time.DateUtils; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import java.util.Date; +import java.util.List; +import java.util.Objects; + +import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Tp.GET_ORDER; +import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Tp.GET_ORDER_LIST; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.when; +import static org.testng.Assert.*; + +/** + * 应用版本付费订单相关接口测试 + */ +public class WxCpTpOrderServiceImplTest { + + @Mock + private WxCpTpServiceApacheHttpClientImpl wxCpTpService; + + private WxCpTpConfigStorage configStorage; + + private WxCpTpOrderService wxCpTpOrderService; + + @BeforeClass + public void setUp() { + MockitoAnnotations.initMocks(this); + configStorage = new WxCpTpDefaultConfigImpl(); + when(wxCpTpService.getWxCpTpConfigStorage()).thenReturn(configStorage); + wxCpTpOrderService = new WxCpTpOrderServiceImpl(wxCpTpService); + } + + + /** + * 获取订单详情 + */ + @Test + public void testGetOrder() throws WxErrorException { + String orderId = "2018091822ks1sd3s"; + + String result = "" + + "{\n" + + " \"errcode\" : 0,\n" + + " \"errmsg\" : \"ok\",\n" + + " \"orderid\" : \"2018091822ks1sd3s\",\n" + + " \"order_status\" : 1,\n" + + " \"order_type\" : 1,\n" + + " \"paid_corpid\" : \"wwfedd7e5291d63aaa\",\n" + + " \"operator_id\" : \"zhangsan\",\n" + + " \"suiteid\" : \"wx67cce113441ccaaa\",\n" + + " \"appid\" : 1,\n" + + " \"edition_id\" : \"RLS65535\",\n" + + " \"edition_name\" : \"协同版\",\n" + + " \"price\" : 100,\n" + + " \"user_count\" : 1000,\n" + + " \"order_period\": 365,\n" + + " \"order_time\" : 1533702999,\n" + + " \"paid_time\" : 1533702910,\n" + + " \"begin_time\" : 1533702910,\n" + + " \"end_time\" : 1553515904,\n" + + " \"order_from\" : 1,\n" + + " \"operator_corpid\" : \"wwfedd7e5292d63aaa\",\n" + + " \"service_share_amount\" : 60,\n" + + " \"platform_share_amount\" : 10,\n" + + " \"dealer_share_amount\" : 30,\n" + + " \"dealer_corp_info\":\n" + + " {\n" + + " \"corpid\": \"xxxx\",\n" + + " \"corp_name\": \"name\"\n" + + " }\n" + + " }"; + String url = configStorage.getApiUrl(GET_ORDER); + when(wxCpTpService.post(eq(url), any(String.class))).thenReturn(result); + + final WxCpTpOrderDetails orderDetails = wxCpTpOrderService.getOrder(orderId); + + assertNotNull(orderDetails); + + assertEquals(orderDetails.getOrderId(), orderId); + + } + + /** + * 获取订单列表 + */ + @Test + public void testGetOrderList() throws WxErrorException { + String orderId = "2018091822ks1sd3s"; + Date startTime = new Date(); + Date endTime = DateUtils.addDays(startTime, 5); + Integer testMode = 0; + + String result = "" + + " {\n" + + " \"errcode\" : 0,\n" + + " \"errmsg\" : \"ok\",\n" + + " \"order_list\": [\n" + + " {\n" + + " \"orderid\" : \"2018091822ks1sd3s\",\n" + + " \"order_status\" : 1,\n" + + " \"order_type\" : 1,\n" + + " \"paid_corpid\" : \"wwfedd7e5292d63aaa\",\n" + + " \"operator_id\" : \"zhangsan\",\n" + + " \"suiteid\" : \"wx67cce113441cc7a6\",\n" + + " \"appid\" : 1,\n" + + " \"edition_id\" : \"RLS65535\",\n" + + " \"edition_name\" : \"协同版\",\n" + + " \"price\" : 100,\n" + + " \"user_count\" : 1000,\n" + + " \"order_period\": 365,\n" + + " \"order_time\" : 1533702999,\n" + + " \"paid_time\" : 1533702910,\n" + + " \"begin_time\" : 1533702910,\n" + + " \"end_time\" : 1553515904,\n" + + " \"order_from\" : 1,\n" + + " \"operator_corpid\" : \"wwfedd7e5292d63aaa\",\n" + + " \"service_share_amount\" : 60,\n" + + " \"platform_share_amount\" : 10,\n" + + " \"dealer_share_amount\" : 30,\n" + + " \"dealer_corp_info\":\n" + + " {\n" + + " \"corpid\": \"xxxx\",\n" + + " \"corp_name\": \"name\"\n" + + " }\n" + + " }]\n" + + " }"; + + String url = configStorage.getApiUrl(GET_ORDER_LIST); + when(wxCpTpService.post(eq(url), any(String.class))).thenReturn(result); + + final WxCpTpOrderListGetResult orderList = wxCpTpOrderService.getOrderList(startTime, endTime, testMode); + + assertNotNull(orderList); + + final List detailsList = orderList.getOrderList(); + + assertTrue(Objects.nonNull(detailsList) && !detailsList.isEmpty()); + + assertEquals(detailsList.get(0).getOrderId(), orderId); + } + + +} diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/util/crypto/WxCpCryptUtilTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/util/crypto/WxCpCryptUtilTest.java index 62fbce13b..7ec2477b4 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/util/crypto/WxCpCryptUtilTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/util/crypto/WxCpCryptUtilTest.java @@ -1,8 +1,7 @@ package me.chanjar.weixin.cp.util.crypto; -import com.google.common.base.CharMatcher; -import com.google.common.io.BaseEncoding; import org.apache.commons.codec.binary.Base64; +import org.apache.commons.lang3.StringUtils; import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; @@ -16,8 +15,8 @@ public class WxCpCryptUtilTest { public void test() { String encodingAesKey = "jWmYm7qr5nMoAUwZRjGtBxmz3KA1tkAj3ykkR6q2B2C"; final byte[] commonsCodec = Base64.decodeBase64(encodingAesKey + "="); - final byte[] guava = BaseEncoding.base64().decode(CharMatcher.whitespace().removeFrom(encodingAesKey)); - final byte[] guava1 = BaseEncoding.base64().decode(CharMatcher.whitespace().removeFrom(encodingAesKey + "=")); + final byte[] guava = java.util.Base64.getDecoder().decode(StringUtils.remove(encodingAesKey, " ")); + final byte[] guava1 = java.util.Base64.getDecoder().decode(StringUtils.remove(encodingAesKey + "=", " ")); assertEquals(commonsCodec, guava); assertEquals(guava1, guava); } diff --git a/weixin-java-cp/src/test/resources/test-config.sample.xml b/weixin-java-cp/src/test/resources/test-config.sample.xml index 23e83e942..19241aba7 100644 --- a/weixin-java-cp/src/test/resources/test-config.sample.xml +++ b/weixin-java-cp/src/test/resources/test-config.sample.xml @@ -11,6 +11,18 @@ 企业号通讯录里的某个tagid 网页授权获取用户信息回调地址 webhook链接地址的key值 - + + -----BEGIN RSA PRIVATE KEY----- + MIICXAIBAAKBgQCTfm5cxqfglfOV7b/Z7OtTZZoZpk2EPTvVhn/ngsfKR899xRdR + 25s4h8HkK0XhxqYdOGoAdG3Gms+DvCSY/vu3UtImf0eZSNXpKZJBUnvUVjX4ivnr + Ohu2Rjw6O4gPjPnZKw8voCu0Nae1YLeNvFYw48PK7QrqmpHQv1sCd/8zHwIDAQAB + AoGAResz7xgfQghjsgnEHk9BGUY7YHhlG9CZWjYJ0Ro+ksYq9vClBuGHeitk/0CC + Pq7YVVbGbVPELFd8EvNwF/UcJsMlvFis16FzNS60Hn7M/o82gI6AVhSQmocoGhNs + MIKxTnXRqqlKFbCdcSfG+hQP7syHah6Z8UhLYuEA8s/ppd0CQQD99HTSvB4P5FfL + rlKTz6w6uh4qBYl53u5cLQxCRFGgXD6HvPnEwdzQf+2LCVM1zIhyxw2Kak1U467Q + 6JizEuHDTC2YljEbg/j+/AlpA/Ua5HQYnH5yD3DCK7rQyTvqE5gU+CfRbwTbLGre + fk/WJK4iqizgZobNRyUCQGB7jR5b8K7NsX7SoV7v/PFOsoj4G2W5q7LSz4GaoXGl + 3F+dSlXPYHdTow3dzfgVDldEzgoThs5UWMTQvBUZch0= + -----END RSA PRIVATE KEY----- /www/osfile/libcrypto-1_1-x64.dll,libssl-1_1-x64.dll,libcurl-x64.dll,WeWorkFinanceSdk.dll,libWeWorkFinanceSdk_Java.so diff --git a/weixin-java-miniapp/pom.xml b/weixin-java-miniapp/pom.xml index e01606833..426201ed7 100644 --- a/weixin-java-miniapp/pom.xml +++ b/weixin-java-miniapp/pom.xml @@ -7,7 +7,7 @@ com.github.binarywang wx-java - 4.3.0 + 4.4.0 weixin-java-miniapp diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaCloudService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaCloudService.java index 02c363a3a..03fe5a474 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaCloudService.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaCloudService.java @@ -1,6 +1,7 @@ package cn.binarywang.wx.miniapp.api; import cn.binarywang.wx.miniapp.bean.cloud.*; +import cn.binarywang.wx.miniapp.bean.cloud.request.WxCloudSendSmsV2Request; import com.google.gson.JsonArray; import me.chanjar.weixin.common.error.WxErrorException; @@ -539,4 +540,15 @@ Long databaseMigrateImport(String env, String collectionName, String filePath, i * @throws WxErrorException . */ WxCloudDatabaseCollectionGetResult databaseCollectionGet(String env, Long limit, Long offset) throws WxErrorException; + + /** + * 发送携带 URL Link 的短信 + * + * 文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/cloudbase/cloudbase.sendSmsV2.html + * @param request + * @return WxCloudSendSmsV2Result + * @throws WxErrorException + */ + WxCloudSendSmsV2Result sendSmsV2(WxCloudSendSmsV2Request request) throws WxErrorException; + } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaCodeService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaCodeService.java index 7c13818b8..e560a1512 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaCodeService.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaCodeService.java @@ -105,6 +105,14 @@ public interface WxMaCodeService { */ WxMaCodeVersionDistribution getSupportVersion() throws WxErrorException; + /** + * 查询小程序版本信息 + * + * @return 小程序的体验版和线上版本信息 + * @throws WxErrorException 失败时抛出,具体错误码请看此接口的注释文档 + */ + WxMaCodeVersionInfo getVersionInfo() throws WxErrorException; + /** * 设置最低基础库版本(仅供第三方代小程序调用). * diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaImmediateDeliveryService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaImmediateDeliveryService.java index f08f510e3..aeef61723 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaImmediateDeliveryService.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaImmediateDeliveryService.java @@ -7,10 +7,14 @@ import cn.binarywang.wx.miniapp.bean.delivery.BindAccountResponse; import cn.binarywang.wx.miniapp.bean.delivery.CancelOrderRequest; import cn.binarywang.wx.miniapp.bean.delivery.CancelOrderResponse; +import cn.binarywang.wx.miniapp.bean.delivery.FollowWaybillRequest; +import cn.binarywang.wx.miniapp.bean.delivery.FollowWaybillResponse; import cn.binarywang.wx.miniapp.bean.delivery.GetOrderRequest; import cn.binarywang.wx.miniapp.bean.delivery.GetOrderResponse; import cn.binarywang.wx.miniapp.bean.delivery.MockUpdateOrderRequest; import cn.binarywang.wx.miniapp.bean.delivery.MockUpdateOrderResponse; +import cn.binarywang.wx.miniapp.bean.delivery.QueryFollowTraceRequest; +import cn.binarywang.wx.miniapp.bean.delivery.QueryFollowTraceResponse; import cn.binarywang.wx.miniapp.bean.delivery.QueryWaybillTraceRequest; import cn.binarywang.wx.miniapp.bean.delivery.QueryWaybillTraceResponse; import cn.binarywang.wx.miniapp.bean.delivery.TraceWaybillRequest; @@ -129,4 +133,34 @@ QueryWaybillTraceResponse queryWaybillTrace(QueryWaybillTraceRequest request) throws WxErrorException; + /** + * 传运单接口 follow_waybill 订阅微信后台会跟踪运单的状态变化 + *

+   * 文档地址:https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/industry/express/express_open_msg.html
+   * 
+ * + * @param request request + * @return 响应 + * @throws WxErrorException 异常 + */ + FollowWaybillResponse followWaybill(FollowWaybillRequest request) + throws WxErrorException; + + + /** + * 查运单接口 query_follow_trace + * + *
+   * 商户在调用完trace_waybill接口后,可以使用本接口查询到对应运单的详情信息
+   * 文档地址:https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/industry/express/express_open_msg.html
+   * 
+ * + * @param request request + * @return 响应 + * @throws WxErrorException 异常 + */ + QueryFollowTraceResponse queryFollowTrace(QueryFollowTraceRequest request) + throws WxErrorException ; + + } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaLiveService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaLiveService.java index 2d7751948..1473b54a1 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaLiveService.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaLiveService.java @@ -84,7 +84,7 @@ public interface WxMaLiveService { * @return . * @throws WxErrorException . */ - String getSharedCode(Integer roomId, String params) throws WxErrorException; + WxMaLiveSharedCode getSharedCode(Integer roomId, String params) throws WxErrorException; /** * 获取直播房间列表.(分页) diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaProductOrderService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaProductOrderService.java new file mode 100644 index 000000000..793df60a2 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaProductOrderService.java @@ -0,0 +1,76 @@ +package cn.binarywang.wx.miniapp.api; + +import cn.binarywang.wx.miniapp.bean.product.WxMiniBatchGetAfterSaleOrderResponse; +import cn.binarywang.wx.miniapp.bean.product.WxMiniGetAfterSaleOrderResponse; +import cn.binarywang.wx.miniapp.bean.product.WxMiniOrderDeliveryRequest; +import cn.binarywang.wx.miniapp.bean.product.WxMinishopOrderDetailResponse; +import cn.binarywang.wx.miniapp.bean.product.WxMinishopOrderListResponse; +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopBaseResponse; +import java.util.List; +import me.chanjar.weixin.common.error.WxErrorException; + +/** + * 小程序交易组件-标准版-商品服务 + * + * @author boris + */ +public interface WxMaProductOrderService { + + + /** + * 获取订单列表 + * + * @param startCreateTime 否(未填更新时间范围时必填) + * @param endCreateTime 否(未填更新时间范围时必填) + * @param startUpdateTime 否(未填创建时间范围时必填) + * @param endUpdateTime 否(未填创建时间范围时必填) + * @param status 订单状态,枚举值见RequestOrderStatus + * @param page 第几页(最小填1) + * @param pageSize 每页数量(不超过10,000) + * @param source 1:小商店,2:CPS带货 + * @return + * @throws WxErrorException + */ + WxMinishopOrderListResponse getOrderList( + String startCreateTime, + String endCreateTime, + String startUpdateTime, + String endUpdateTime, + Integer status, + Integer page, + Integer pageSize, + Integer source + ) throws WxErrorException; + + + /** + * 获取订单详情 + * + * @param orderId 订单ID,可从获取订单列表中获得 + * @return + */ + WxMinishopOrderDetailResponse getOrderDetail(Long orderId) throws WxErrorException; + + + /** + * 修改订单备注 + * @param orderId 订单id + * @param merchantNotes 备注内容 + */ + void changeMerchantNotes(Long orderId,String merchantNotes) throws WxErrorException; + + WxMaShopBaseResponse deliverySend(WxMiniOrderDeliveryRequest request) + throws WxErrorException; + + WxMiniGetAfterSaleOrderResponse getAfterSaleOrder(Long afterSaleOrderId) + throws WxErrorException; + + WxMiniBatchGetAfterSaleOrderResponse batchGetAfterSaleOrder(List afterSaleOrderIdList) + throws WxErrorException; + + WxMaShopBaseResponse afterSaleAccept(Long orderId, Long addressId) + throws WxErrorException; + + WxMaShopBaseResponse afterSaleReject(Long afterSaleOrderId, String rejectReason) + throws WxErrorException; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaProductService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaProductService.java new file mode 100644 index 000000000..b629772a2 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaProductService.java @@ -0,0 +1,137 @@ +package cn.binarywang.wx.miniapp.api; + +import cn.binarywang.wx.miniapp.bean.product.WxMinishopAddGoodsSkuData; +import cn.binarywang.wx.miniapp.bean.product.WxMinishopAddGoodsSpuData; +import cn.binarywang.wx.miniapp.bean.product.WxMinishopGetBrandResponse; +import cn.binarywang.wx.miniapp.bean.product.WxMinishopGetCategoryResponse; +import cn.binarywang.wx.miniapp.bean.product.WxMinishopGetFrightTemplateResponse; +import cn.binarywang.wx.miniapp.bean.product.WxMinishopOrderListResponse; +import cn.binarywang.wx.miniapp.bean.product.WxMinishopResult; +import cn.binarywang.wx.miniapp.bean.product.WxMinishopSku; +import cn.binarywang.wx.miniapp.bean.product.WxMinishopSkuListResponse; +import cn.binarywang.wx.miniapp.bean.product.WxMinishopSpu; +import cn.binarywang.wx.miniapp.bean.product.WxMinishopSpuGet; +import cn.binarywang.wx.miniapp.bean.product.WxMinishopSpuGetResponse; +import cn.binarywang.wx.miniapp.bean.product.WxMinishopSpuListResponse; +import cn.binarywang.wx.miniapp.bean.product.WxMinishopUpdateGoodsSkuData; +import cn.binarywang.wx.miniapp.bean.shop.request.WxMaShopSpuPageRequest; +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopBaseResponse; +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopGetSpuListResponse; +import java.io.File; +import java.util.List; +import me.chanjar.weixin.common.bean.result.WxMinishopImageUploadResult; +import me.chanjar.weixin.common.error.WxErrorException; + +/** + * 小程序交易组件-商品服务 + * + * @author boris + */ +public interface WxMaProductService { + + WxMinishopImageUploadResult uploadImg(File file, Integer respType, Integer width, Integer height) throws WxErrorException; + + WxMinishopImageUploadResult uploadImg(String imgUrl, Integer respType) throws WxErrorException; + + WxMinishopGetCategoryResponse getCategory(Integer fCatId) throws WxErrorException; + + WxMinishopGetBrandResponse getBrand() throws WxErrorException; + + WxMinishopGetFrightTemplateResponse getFreightTemplate() throws WxErrorException; + + WxMinishopResult addSpu(WxMinishopSpu spuInfo) throws WxErrorException; + + WxMaShopBaseResponse deleteSpu(Integer productId, String outProductId) throws WxErrorException; + + WxMinishopSpuGetResponse getSpu(Integer productId, String outProductId, Integer needEditSpu) + throws WxErrorException; + + WxMinishopSpuListResponse getSpuList(WxMaShopSpuPageRequest request) + throws WxErrorException; + + WxMinishopResult updateSpu(WxMinishopSpu spuInfo) throws WxErrorException; + + WxMaShopBaseResponse listingSpu(Integer productId, String outProductId) + throws WxErrorException; + + WxMaShopBaseResponse delistingSpu(Integer productId, String outProductId) + throws WxErrorException; + + WxMinishopSkuListResponse getSkuList(Long productId, Integer needRealStock, Integer needEditSku) + throws WxErrorException; + + /** + * 小商店新增sku信息 + * + * @param sku + * @return + * @throws WxErrorException + */ + WxMinishopResult minishiopGoodsAddSku(WxMinishopSku sku) throws WxErrorException; + + + /** + * 小商店批量新增sku信息 + * + * @param skuList + * @return + * @throws WxErrorException + */ + WxMinishopResult> minishopGoodsBatchAddSku(List skuList) throws WxErrorException; + + + /** + * 小商店删除sku消息 + * + * @param productId + * @param outProductId + * @param outSkuId + * @param skuId + * @return + * @throws WxErrorException + */ + WxMaShopBaseResponse minishopGoodsDelSku(Long productId, Long outProductId, String outSkuId, Long skuId) throws WxErrorException; + + + /** + * 小商店更新sku + * + * @param sku + * @return + * @throws WxErrorException + */ + WxMinishopResult minishopGoodsUpdateSku(WxMinishopSku sku) throws WxErrorException; + + + /** + * 小商店更新sku价格 + * + * @param productId + * @param outProductId + * @param outSkuId + * @param skuId + * @param salePrice + * @param marketPrice + * @return + * @throws WxErrorException + */ + WxMinishopResult minishopGoodsUpdateSkuPrice(Long productId, + String outProductId, String outSkuId, Long skuId, Long salePrice, Long marketPrice) throws WxErrorException; + + + /** + * 小商店更新sku库存 + * + * @param productId + * @param outProductId + * @param outSkuId + * @param skuId + * @param type + * @param stockNum + * @return + * @throws WxErrorException + */ + WxMinishopResult minishopGoodsUpdateSkuStock(Long productId, + String outProductId, String outSkuId, Long skuId, Integer type, Integer stockNum) throws WxErrorException; + +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaQrcodeService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaQrcodeService.java index ececed036..9e9290890 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaQrcodeService.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaQrcodeService.java @@ -11,7 +11,8 @@ * * 接口A(createWxaCode)加上接口C(createQrcode),总共生成的码数量限制为100,000,请谨慎调用。 * - * 文档地址:https://mp.weixin.qq.com/debug/wxadoc/dev/api/qrcode.html + * 文档地址1:https://mp.weixin.qq.com/debug/wxadoc/dev/api/qrcode.html + * 文档地址2:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/qr-code.html *
* * @author Binary Wang diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaSecCheckService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaSecCheckService.java index a22061a00..b7721b4e7 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaSecCheckService.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaSecCheckService.java @@ -23,7 +23,7 @@ public interface WxMaSecCheckService { * 应用场景举例: * 1)图片智能鉴黄:涉及拍照的工具类应用(如美拍,识图类应用)用户拍照上传检测;电商类商品上架图片检测;媒体类用户文章里的图片检测等; * 2)敏感人脸识别:用户头像;媒体类用户文章里的图片检测;社交类用户上传的图片检测等。频率限制:单个 appId 调用上限为 1000 次/分钟,100,000 次/天 - * 详情请见: https://developers.weixin.qq.com/miniprogram/dev/api/open-api/sec-check/imgSecCheck.html + * 详情请见: https://developers.weixin.qq.com/miniprogram/dev/api/open-api/sec-check/imgSecCheck.html *
* * @param file the file @@ -48,7 +48,7 @@ public interface WxMaSecCheckService { * 用户个人资料违规文字检测; * 媒体新闻类用户发表文章,评论内容检测; * 游戏类用户编辑上传的素材(如答题类小游戏用户上传的问题及答案)检测等。 频率限制:单个 appId 调用上限为 4000 次/分钟,2,000,000 次/天* - * 详情请见: https://developers.weixin.qq.com/miniprogram/dev/api/open-api/sec-check/msgSecCheck.html + * 详情请见: https://developers.weixin.qq.com/miniprogram/dev/api/open-api/sec-check/msgSecCheck.html *
* * @param msgString the msg string @@ -61,9 +61,9 @@ public interface WxMaSecCheckService { /** *
    * 检查一段文本是否含有违法违规内容(新版本接口,主要是request和response做了参数优化)
-   * 详情请见: https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/sec-check/security.msgSecCheck.html
+   * 详情请见: https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/sec-check/security.msgSecCheck.html
    * 
- * @param msgRequest + * @param msgRequest request * @return WxMaMsgSecCheckCheckResponse * @throws WxErrorException the wx error exception */ @@ -79,7 +79,7 @@ public interface WxMaSecCheckService { * 频率限制: * 单个 appId 调用上限为 2000 次/分钟,200,000 次/天;文件大小限制:单个文件大小不超过10M * 详情请见: - * https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/sec-check/security.mediaCheckAsync.html + * https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/sec-check/security.mediaCheckAsync.html *
* * @param mediaUrl 要检测的多媒体url @@ -89,7 +89,6 @@ public interface WxMaSecCheckService { */ WxMaMediaAsyncCheckResult mediaCheckAsync(String mediaUrl, int mediaType) throws WxErrorException; - /** *
    * 异步校验图片/音频是否含有违法违规内容。(新版本接口,主要对request和respone做了参数优化)
@@ -100,14 +99,14 @@ public interface WxMaSecCheckService {
    * 频率限制:
    * 单个 appId 调用上限为 2000 次/分钟,200,000 次/天;文件大小限制:单个文件大小不超过10M
    * 详情请见:
-   * https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/sec-check/security.mediaCheckAsync.html
+   * https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/sec-check/security.mediaCheckAsync.html
    * 
* - * @param medisRequest + * @param request 请求 * @return wx ma media async check result * @throws WxErrorException the wx error exception */ - WxMaMediaAsyncCheckResult mediaCheckAsync(WxMaMediaSecCheckCheckRequest medisRequest) throws WxErrorException; + WxMaMediaAsyncCheckResult mediaCheckAsync(WxMaMediaSecCheckCheckRequest request) throws WxErrorException; } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaService.java index 8b357a847..fb2ef3b9b 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaService.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaService.java @@ -492,4 +492,33 @@ public interface WxMaService extends WxService { */ WxMaSafetyRiskControlService getSafetyRiskControlService(); + /** + * 分享人接口 + * @return WxMaShopSharerService + */ + WxMaShopSharerService getShopSharerService(); + + /** + * 标准交易组件接口 + * @return WxMaProductService + */ + WxMaProductService getProductService(); + + /** + * 小商店-标准交易组件-订单服务 + * @return getProductOrderService + */ + WxMaProductOrderService getProductOrderService(); + + /** + * 小商店-标准交易组件-优惠券 + * @return getWxMaShopCouponService + */ + WxMaShopCouponService getWxMaShopCouponService(); + + /** + * 小程序支付管理-订单支付 + * @return getWxMaShopPayService + */ + WxMaShopPayService getWxMaShopPayService(); } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaShopAfterSaleService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaShopAfterSaleService.java index 97b8aa56d..4f5a3f18d 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaShopAfterSaleService.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaShopAfterSaleService.java @@ -1,9 +1,15 @@ package cn.binarywang.wx.miniapp.api; +import cn.binarywang.wx.miniapp.bean.shop.request.WxMaShopAcceptReturnRequest; import cn.binarywang.wx.miniapp.bean.shop.request.WxMaShopAfterSaleAddRequest; import cn.binarywang.wx.miniapp.bean.shop.request.WxMaShopAfterSaleGetRequest; +import cn.binarywang.wx.miniapp.bean.shop.request.WxMaShopAfterSaleListRequest; import cn.binarywang.wx.miniapp.bean.shop.request.WxMaShopAfterSaleUpdateRequest; +import cn.binarywang.wx.miniapp.bean.shop.request.WxMaShopAfterSaleUploadReturnInfoRequest; +import cn.binarywang.wx.miniapp.bean.shop.request.WxMaShopUploadCerficatesRequest; +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopAfterSaleAddResponse; import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopAfterSaleGetResponse; +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopAfterSaleListResponse; import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopBaseResponse; import me.chanjar.weixin.common.error.WxErrorException; @@ -21,7 +27,7 @@ public interface WxMaShopAfterSaleService { * @return WxMaShopBaseResponse * @throws WxErrorException */ - WxMaShopBaseResponse add(WxMaShopAfterSaleAddRequest request) throws WxErrorException; + WxMaShopAfterSaleAddResponse add(WxMaShopAfterSaleAddRequest request) throws WxErrorException; /** * 获取订单下售后单 @@ -41,4 +47,81 @@ public interface WxMaShopAfterSaleService { */ WxMaShopBaseResponse update(WxMaShopAfterSaleUpdateRequest request) throws WxErrorException; + /** + * 用户取消售后申请 + * @param outAfterSaleId 商家自定义订单ID + * @param afterSaleId 与out_aftersale_id二选一 + * @param openId 用户openid + * @return + * @throws WxErrorException + */ + WxMaShopBaseResponse cancel(String outAfterSaleId, Long afterSaleId, String openId) + throws WxErrorException; + + /** + * 用户上传退货物流 + * @param request + * @return + * @throws WxErrorException + */ + WxMaShopBaseResponse uploadReturnInfo(WxMaShopAfterSaleUploadReturnInfoRequest request) + throws WxErrorException; + + /** + * 商家同意退款 + * @param outAfterSaleId + * @param afterSaleId + * @return + * @throws WxErrorException + */ + WxMaShopBaseResponse acceptRefund(String outAfterSaleId, Long afterSaleId) + throws WxErrorException; + + /** + * 商家同意退货 + * @param request + * @return + * @throws WxErrorException + */ + WxMaShopBaseResponse acceptReturn(WxMaShopAcceptReturnRequest request) + throws WxErrorException; + + /** + * 商家拒绝售后 + * @param outAfterSaleId + * @param afterSaleId + * @return + * @throws WxErrorException + */ + WxMaShopBaseResponse reject(String outAfterSaleId, Long afterSaleId) + throws WxErrorException; + + /** + * 商家上传退款凭证 + * @param request + * @return + * @throws WxErrorException + */ + WxMaShopBaseResponse uploadCertificates(WxMaShopUploadCerficatesRequest request) + throws WxErrorException; + + /** + * 商家更新订单售后期 + * @param outOrderId + * @param orderId + * @param openid + * @param afterSaleDeadline + * @return + * @throws WxErrorException + */ + WxMaShopBaseResponse updateDeadline(String outOrderId, Long orderId, String openid, + Long afterSaleDeadline) throws WxErrorException; + + /** + * 获取售后单详情 + * @param request + * @return + * @throws WxErrorException + */ + WxMaShopAfterSaleListResponse list(WxMaShopAfterSaleListRequest request) throws WxErrorException; } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaShopCouponService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaShopCouponService.java new file mode 100644 index 000000000..bee5a0ec5 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaShopCouponService.java @@ -0,0 +1,40 @@ +package cn.binarywang.wx.miniapp.api; + +import cn.binarywang.wx.miniapp.bean.shop.WxMaShopCouponInfo; +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopBaseResponse; +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopCouponListResponse; +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopCouponResponse; +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopUserCouponListResponse; +import me.chanjar.weixin.common.error.WxErrorException; + +/** + * @author leiin + * @date 2022/7/1 2:49 下午 + */ +public interface WxMaShopCouponService { + + WxMaShopBaseResponse addCoupon(WxMaShopCouponInfo couponInfo) throws WxErrorException; + + WxMaShopCouponResponse getCoupon(String outCouponId) throws WxErrorException; + + WxMaShopCouponListResponse getCouponList(Integer pageSize, + Integer offset) throws WxErrorException; + + WxMaShopBaseResponse updateCoupon(WxMaShopCouponInfo couponInfo) throws WxErrorException; + + WxMaShopBaseResponse updateCouponStatus(String outCouponId, + Integer status) throws WxErrorException; + + WxMaShopBaseResponse updateCouponStock(String outCouponId, Integer isUsedNum, Integer receiveNum) throws WxErrorException; + + WxMaShopBaseResponse addUserCoupon(String openid, String outUserCouponId, + String outCouponId, Integer status, Long recvTime) throws WxErrorException; + + WxMaShopUserCouponListResponse getUserCouponList(Integer pageSize, Integer offset, String openid) throws WxErrorException; + + WxMaShopBaseResponse updateUserCoupon(String openid, String outUserCouponId, + String outCouponId, Long useTime, Long recvTime) throws WxErrorException; + + WxMaShopBaseResponse updateUserCouponStatus(String openid, String outUserCouponId, + String outCouponId, Integer status) throws WxErrorException; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaShopOrderService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaShopOrderService.java index 50b39fb6e..abcbe25ea 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaShopOrderService.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaShopOrderService.java @@ -2,11 +2,11 @@ import cn.binarywang.wx.miniapp.bean.shop.WxMaShopOrderInfo; import cn.binarywang.wx.miniapp.bean.shop.request.WxMaShopOrderPayRequest; -import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopAddOrderResponse; -import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopBaseResponse; -import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopGetOrderResponse; +import cn.binarywang.wx.miniapp.bean.shop.response.*; import me.chanjar.weixin.common.error.WxErrorException; +import java.util.Date; + /** * 小程序交易组件-订单服务 * @@ -19,6 +19,48 @@ public interface WxMaShopOrderService { WxMaShopBaseResponse orderPay(WxMaShopOrderPayRequest request) throws WxErrorException; - WxMaShopGetOrderResponse getOrder(Integer orderId, String outOrderId, String openid) + WxMaShopGetOrderResponse getOrder(Long orderId, String outOrderId, String openid) throws WxErrorException; + + + /** + *
+   *
+   * 获取订单列表
+   *
+   * 请求方式:POST(HTTPS)
+   * 请求地址:请求地址
+   *
+   * 文档地址:文档地址
+   * 
+ * + * @param page 第x页,大于等于1 + * @param pageSize 每页订单数,上限100 + * @param desc 是否时间倒叙 + * @param startCreateTime 起始创建时间 + * @param endCreateTime 最终创建时间 + * @return 订单列表信息 + * @throws WxErrorException . + */ + WxMaShopGetOrderListResponse getOrderList(Integer page, Integer pageSize, Boolean desc, Date startCreateTime, Date endCreateTime) + throws WxErrorException; + + /** + *
+   *
+   * 生成支付参数
+   *
+   * 请求方式:POST(HTTPS)
+   * 请求地址:请求地址
+   *
+   * 文档地址:文档地址
+   * 
+ * + * @param orderId 微信侧订单id + * @param outOrderId 商家自定义订单ID + * @param openid 用户openid + * @return 支付参数 + * @throws WxErrorException . + */ + WxMaShopGetPaymentParamsResponse getPaymentParams(String orderId, String outOrderId, String openid) throws WxErrorException; } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaShopPayService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaShopPayService.java new file mode 100644 index 000000000..b1c3da435 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaShopPayService.java @@ -0,0 +1,24 @@ +package cn.binarywang.wx.miniapp.api; + +import cn.binarywang.wx.miniapp.bean.shop.request.WxMaShopPayCreateOrderRequest; +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopPayCreateOrderResponse; +import me.chanjar.weixin.common.error.WxErrorException; + +/** + * 小程序支付管理订单相关接口 + * + * @author liming1019 + */ +public interface WxMaShopPayService { + + /** + * 创建订单 + * 文档地址:文档地址 + * + * @param request 创建订单参数 + * @return 创建订单结果 + * @throws WxErrorException . + */ + WxMaShopPayCreateOrderResponse createOrder(WxMaShopPayCreateOrderRequest request) + throws WxErrorException; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaShopSharerService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaShopSharerService.java new file mode 100644 index 000000000..76a4e9548 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaShopSharerService.java @@ -0,0 +1,83 @@ +package cn.binarywang.wx.miniapp.api; + +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopSearchSharerResponse; +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopSharerBindResponse; +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopSharerDataSummaryResponse; +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopSharerListResponse; +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopSharerLiveOrderListResponse; +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopSharerLiveSummaryListResponse; +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopSharerUnbindResponse; +import me.chanjar.weixin.common.error.WxErrorException; + +/** + * 分享员 + * @author leiin + * @date 2022/6/18 2:48 下午 + */ +public interface WxMaShopSharerService { + + /** + * 绑定分享员 + * 用来批量邀请分享员 + * @param openids + * @return + * @throws WxErrorException + */ + WxMaShopSharerBindResponse bindSharer(String[] openids) throws WxErrorException; + + /** + * 获取分享员的总带货数据 + * @param openid + * @return + * @throws WxErrorException + */ + WxMaShopSharerDataSummaryResponse getSharerDataSummary(String openid) throws WxErrorException; + + /** + * 获取已经绑定的分享员列表 + * @param page + * @param pageSize + * @return + * @throws WxErrorException + */ + WxMaShopSharerListResponse getSharerList(Integer page, Integer pageSize) throws WxErrorException; + + /** + * 获取分享员的直播间订单汇总 + * @param openid + * @param liveExportId + * @param page + * @param pageSize + * @return + * @throws WxErrorException + */ + WxMaShopSharerLiveOrderListResponse getSharerLiveOrderList(String openid, String liveExportId, + Integer page, Integer pageSize) throws WxErrorException; + + /** + * 获取分享员的直播间带货数据汇总 + * @param openid + * @param page + * @param pageSize + * @return + * @throws WxErrorException + */ + WxMaShopSharerLiveSummaryListResponse getSharerLiveSummaryList(String openid, + Integer page, Integer pageSize) throws WxErrorException; + + /** + * 查看分享员 + * @param openid + * @return + * @throws WxErrorException + */ + WxMaShopSearchSharerResponse searchSharer(String openid) throws WxErrorException; + + /** + * 解绑分享员 + * @param openids + * @return + * @throws WxErrorException + */ + WxMaShopSharerUnbindResponse unbindSharer(String[] openids) throws WxErrorException; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/BaseWxMaServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/BaseWxMaServiceImpl.java index 62ca188d5..4cff1bf16 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/BaseWxMaServiceImpl.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/BaseWxMaServiceImpl.java @@ -79,6 +79,11 @@ public abstract class BaseWxMaServiceImpl implements WxMaService, RequestH private final WxMaMarketingService marketingService = new WxMaMarketingServiceImpl(this); private final WxMaImmediateDeliveryService immediateDeliveryService = new WxMaImmediateDeliveryServiceImpl(this); private final WxMaSafetyRiskControlService safetyRiskControlService = new WxMaSafetyRiskControlServiceImpl(this); + private final WxMaShopSharerService shopSharerService = new WxMaShopSharerServiceImpl(this); + private final WxMaProductService productService = new WxMaProductServiceImpl(this); + private final WxMaProductOrderService productOrderService = new WxMaProductOrderServiceImpl(this); + private final WxMaShopCouponService wxMaShopCouponService = new WxMaShopCouponServiceImpl(this); + private final WxMaShopPayService wxMaShopPayService = new WxMaShopPayServiceImpl(this); private Map configMap; private int retrySleepMillis = 1000; private int maxRetryTimes = 5; @@ -294,12 +299,12 @@ private T executeInternal(RequestExecutor executor, String uri, E d } if (error.getErrorCode() != 0) { - log.error("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", uriWithAccessToken, dataForLog, error); + log.warn("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", uriWithAccessToken, dataForLog, error); throw new WxErrorException(error, e); } return null; } catch (IOException e) { - log.error("\n【请求地址】: {}\n【请求参数】:{}\n【异常信息】:{}", uriWithAccessToken, dataForLog, e.getMessage()); + log.warn("\n【请求地址】: {}\n【请求参数】:{}\n【异常信息】:{}", uriWithAccessToken, dataForLog, e.getMessage()); throw new WxRuntimeException(e); } } @@ -592,4 +597,24 @@ public WxMaImmediateDeliveryService getWxMaImmediateDeliveryService() { @Override public WxMaSafetyRiskControlService getSafetyRiskControlService(){ return this.safetyRiskControlService; } + @Override + public WxMaShopSharerService getShopSharerService() {return this.shopSharerService; } + + @Override + public WxMaProductService getProductService() { return this.productService; } + + @Override + public WxMaProductOrderService getProductOrderService() { + return this.productOrderService; + } + + @Override + public WxMaShopCouponService getWxMaShopCouponService() { + return this.wxMaShopCouponService; + } + + @Override + public WxMaShopPayService getWxMaShopPayService() { + return this.wxMaShopPayService; + } } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaCloudServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaCloudServiceImpl.java index d2ed6e2de..0ef033d2b 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaCloudServiceImpl.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaCloudServiceImpl.java @@ -3,6 +3,7 @@ import cn.binarywang.wx.miniapp.api.WxMaCloudService; import cn.binarywang.wx.miniapp.api.WxMaService; import cn.binarywang.wx.miniapp.bean.cloud.*; +import cn.binarywang.wx.miniapp.bean.cloud.request.WxCloudSendSmsV2Request; import cn.binarywang.wx.miniapp.constant.WxMaConstants; import cn.binarywang.wx.miniapp.json.WxMaGsonBuilder; import cn.binarywang.wx.miniapp.util.JoinerUtils; @@ -410,4 +411,15 @@ public WxCloudDatabaseCollectionGetResult databaseCollectionGet(String env, Long String response = this.wxMaService.post(DATABASE_COLLECTION_GET_URL, params); return WxGsonBuilder.create().fromJson(response, WxCloudDatabaseCollectionGetResult.class); } + + @Override + public WxCloudSendSmsV2Result sendSmsV2(WxCloudSendSmsV2Request request) throws WxErrorException { + // 如果没有指定云环境ID,取默认云环境ID + if (request.getEnv() == null){ + String cloudEnv = this.wxMaService.getWxMaConfig().getCloudEnv(); + request.setEnv(cloudEnv); + } + String response = this.wxMaService.post(SEND_SMS_V2_URL, request); + return WxGsonBuilder.create().fromJson(response, WxCloudSendSmsV2Result.class); + } } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaCodeServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaCodeServiceImpl.java index 37265cfe5..68271254a 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaCodeServiceImpl.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaCodeServiceImpl.java @@ -138,6 +138,12 @@ public WxMaCodeVersionDistribution getSupportVersion() throws WxErrorException { return WxMaCodeVersionDistribution.fromJson(responseContent); } + @Override + public WxMaCodeVersionInfo getVersionInfo() throws WxErrorException { + String responseContent = this.service.post(GET_VERSION_INFO_URL, "{}"); + return WxMaCodeVersionInfo.fromJson(responseContent); + } + @Override public void setSupportVersion(String version) throws WxErrorException { JsonObject param = new JsonObject(); diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaImmediateDeliveryServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaImmediateDeliveryServiceImpl.java index 18f99a860..2bf98d957 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaImmediateDeliveryServiceImpl.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaImmediateDeliveryServiceImpl.java @@ -9,10 +9,14 @@ import cn.binarywang.wx.miniapp.bean.delivery.BindAccountResponse; import cn.binarywang.wx.miniapp.bean.delivery.CancelOrderRequest; import cn.binarywang.wx.miniapp.bean.delivery.CancelOrderResponse; +import cn.binarywang.wx.miniapp.bean.delivery.FollowWaybillRequest; +import cn.binarywang.wx.miniapp.bean.delivery.FollowWaybillResponse; import cn.binarywang.wx.miniapp.bean.delivery.GetOrderRequest; import cn.binarywang.wx.miniapp.bean.delivery.GetOrderResponse; import cn.binarywang.wx.miniapp.bean.delivery.MockUpdateOrderRequest; import cn.binarywang.wx.miniapp.bean.delivery.MockUpdateOrderResponse; +import cn.binarywang.wx.miniapp.bean.delivery.QueryFollowTraceRequest; +import cn.binarywang.wx.miniapp.bean.delivery.QueryFollowTraceResponse; import cn.binarywang.wx.miniapp.bean.delivery.QueryWaybillTraceRequest; import cn.binarywang.wx.miniapp.bean.delivery.QueryWaybillTraceResponse; import cn.binarywang.wx.miniapp.bean.delivery.TraceWaybillRequest; @@ -94,6 +98,7 @@ public BindAccountResponse getBindAccount() throws WxErrorException { */ @Override public AddOrderResponse addOrder(final AddOrderRequest request) throws WxErrorException { + request.getDeliverySign(); return this.parse(this.wxMaService.post(WxMaApiUrlConstants.InstantDelivery.PlaceAnOrder.ADD_ORDER, request), AddOrderResponse.class); } @@ -111,6 +116,7 @@ public AddOrderResponse addOrder(final AddOrderRequest request) throws WxErrorEx */ @Override public GetOrderResponse getOrder(final GetOrderRequest request) throws WxErrorException { + request.getDeliverySign(); return this.parse(this.wxMaService.post(WxMaApiUrlConstants.InstantDelivery.GET_ORDER, request), GetOrderResponse.class); } @@ -127,6 +133,7 @@ public GetOrderResponse getOrder(final GetOrderRequest request) throws WxErrorEx */ @Override public CancelOrderResponse cancelOrder(final CancelOrderRequest request) throws WxErrorException { + request.getDeliverySign(); return this.parse(this.wxMaService.post(WxMaApiUrlConstants.InstantDelivery.Cancel.CANCEL_ORDER, request), CancelOrderResponse.class); } @@ -143,6 +150,7 @@ public CancelOrderResponse cancelOrder(final CancelOrderRequest request) throws */ @Override public AbnormalConfirmResponse abnormalConfirm(final AbnormalConfirmRequest request) throws WxErrorException { + request.getDeliverySign(); return this.parse(this.wxMaService.post(WxMaApiUrlConstants.InstantDelivery.Cancel.ABNORMAL_CONFIRM, request), AbnormalConfirmResponse.class); } @@ -186,6 +194,28 @@ public QueryWaybillTraceResponse queryWaybillTrace( return response; } + @Override + public FollowWaybillResponse followWaybill( + FollowWaybillRequest request) throws WxErrorException { + String responseContent = this.wxMaService.post(InstantDelivery.FOLLOW_WAYBILL_URL, request); + FollowWaybillResponse response = FollowWaybillResponse.fromJson(responseContent); + if (response.getErrcode() == -1) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + return response; + } + + @Override + public QueryFollowTraceResponse queryFollowTrace( + QueryFollowTraceRequest request) throws WxErrorException { + String responseContent = this.wxMaService.post(InstantDelivery.QUERY_FOLLOW_TRACE_URL, request); + QueryFollowTraceResponse response = QueryFollowTraceResponse.fromJson(responseContent); + if (response.getErrcode() == -1) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + return response; + } + /** * 解析响应. * diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaLiveServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaLiveServiceImpl.java index 56c744f6d..68c1c092b 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaLiveServiceImpl.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaLiveServiceImpl.java @@ -87,7 +87,7 @@ public String getPushUrl(Integer roomId) throws WxErrorException { } @Override - public String getSharedCode(Integer roomId, String params) throws WxErrorException { + public WxMaLiveSharedCode getSharedCode(Integer roomId, String params) throws WxErrorException { Map map = new HashMap<>(2); map.put(ROOM_ID, roomId); if (null != params) { @@ -98,7 +98,7 @@ public String getSharedCode(Integer roomId, String params) throws WxErrorExcepti if (jsonObject.get(ERR_CODE).getAsInt() != 0) { throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); } - return jsonObject.get("cdnUrl").getAsString(); + return WxMaGsonBuilder.create().fromJson(responseContent, WxMaLiveSharedCode.class); } @Override diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaProductOrderServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaProductOrderServiceImpl.java new file mode 100644 index 000000000..15ed07a94 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaProductOrderServiceImpl.java @@ -0,0 +1,167 @@ +package cn.binarywang.wx.miniapp.api.impl; + +import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Product.Order.AFTER_SALE_ACCEPT_APPLY; +import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Product.Order.AFTER_SALE_REJECT_APPLY; +import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Product.Order.BATCH_GET_AFTER_SALE_ORDER; +import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Product.Order.GET_AFTER_SALE_ORDER; +import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Product.Order.PRODUCT_DELIVERY_SEND; +import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Product.Order.PRODUCT_ORDER_CHANGE_MERCHANT_NOTES_URL; +import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Product.Order.PRODUCT_ORDER_DETAIL_URL; +import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Product.Order.PRODUCT_ORDER_GET_LIST; + +import cn.binarywang.wx.miniapp.api.WxMaProductOrderService; +import cn.binarywang.wx.miniapp.api.WxMaService; +import cn.binarywang.wx.miniapp.bean.product.WxMiniBatchGetAfterSaleOrderResponse; +import cn.binarywang.wx.miniapp.bean.product.WxMiniGetAfterSaleOrderResponse; +import cn.binarywang.wx.miniapp.bean.product.WxMiniOrderDeliveryRequest; +import cn.binarywang.wx.miniapp.bean.product.WxMinishopOrderDetailResponse; +import cn.binarywang.wx.miniapp.bean.product.WxMinishopOrderListResponse; +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopBaseResponse; +import cn.binarywang.wx.miniapp.json.WxMaGsonBuilder; +import java.util.List; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.error.WxError; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.util.json.GsonHelper; +import me.chanjar.weixin.common.util.json.WxGsonBuilder; + +/** + * 小程序交易组件-标准版-订单服务 + * + * @author boris 详情请见 : https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/business-capabilities/ministore/minishopopencomponent/API/order/get_order_list.html + */ +@RequiredArgsConstructor +@Slf4j +public class WxMaProductOrderServiceImpl implements WxMaProductOrderService { + + private final WxMaService wxMaService; + + + @Override + public WxMinishopOrderListResponse getOrderList( + String startCreateTime, String endCreateTime, String startUpdateTime, + String endUpdateTime, Integer status, Integer page, Integer pageSize, Integer source) + throws WxErrorException { + String responseContent = this.wxMaService + .post(PRODUCT_ORDER_GET_LIST, GsonHelper.buildJsonObject( + "start_create_time", startCreateTime, "end_create_time", endCreateTime, + "start_update_time", startUpdateTime, "end_update_time", endUpdateTime, + "status", status, "page", page, "page_size", pageSize, "source", source)); + + WxMinishopOrderListResponse response = WxMaGsonBuilder.create() + .fromJson(responseContent, WxMinishopOrderListResponse.class); + + if (response.getErrCode() != 0) { + throw new WxErrorException(new WxError(response.getErrCode(), response.getErrMsg())); + } + + return response; + + } + + @Override + public WxMinishopOrderDetailResponse getOrderDetail( + Long orderId) throws WxErrorException { + String responseContent = this.wxMaService + .post(PRODUCT_ORDER_DETAIL_URL, GsonHelper.buildJsonObject( + "order_id", orderId)); + + WxMinishopOrderDetailResponse getDetailResponse = WxMaGsonBuilder.create() + .fromJson(responseContent, WxMinishopOrderDetailResponse.class); + + if (getDetailResponse.getErrCode() != 0) { + throw new WxErrorException( + new WxError(getDetailResponse.getErrCode(), getDetailResponse.getErrMsg())); + } + + return getDetailResponse; + } + + @Override + public void changeMerchantNotes(Long orderId, String merchantNotes) throws WxErrorException { + String responseContent = this.wxMaService + .post(PRODUCT_ORDER_CHANGE_MERCHANT_NOTES_URL, GsonHelper.buildJsonObject( + "order_id", orderId,"merchant_notes",merchantNotes)); + + WxMaShopBaseResponse changeResult = WxMaGsonBuilder.create() + .fromJson(responseContent, WxMaShopBaseResponse.class); + + if (changeResult.getErrCode() != 0) { + throw new WxErrorException( + new WxError(changeResult.getErrCode(), changeResult.getErrMsg())); + } + } + + @Override + public WxMaShopBaseResponse deliverySend(WxMiniOrderDeliveryRequest request) + throws WxErrorException { + String response = this.wxMaService.post(PRODUCT_DELIVERY_SEND, request); + WxMaShopBaseResponse baseResponse = WxMaGsonBuilder.create() + .fromJson(response, WxMaShopBaseResponse.class); + if (baseResponse.getErrCode() != 0) { + throw new WxErrorException( + new WxError(baseResponse.getErrCode(), baseResponse.getErrMsg())); + } + return baseResponse; + } + + @Override + public WxMiniGetAfterSaleOrderResponse getAfterSaleOrder(Long afterSaleOrderId) + throws WxErrorException { + String response = this.wxMaService.post(GET_AFTER_SALE_ORDER, + GsonHelper.buildJsonObject("after_sale_order_id", afterSaleOrderId)); + + WxMiniGetAfterSaleOrderResponse orderResponse = WxMaGsonBuilder.create() + .fromJson(response, WxMiniGetAfterSaleOrderResponse.class); + if (orderResponse.getErrCode() != 0) { + throw new WxErrorException( + new WxError(orderResponse.getErrCode(), orderResponse.getErrMsg())); + } + return orderResponse; + } + + @Override + public WxMiniBatchGetAfterSaleOrderResponse batchGetAfterSaleOrder( + List afterSaleOrderIdList) + throws WxErrorException { + String response = this.wxMaService.post(BATCH_GET_AFTER_SALE_ORDER, + GsonHelper.buildJsonObject("after_sale_order_id_list", afterSaleOrderIdList)); + + WxMiniBatchGetAfterSaleOrderResponse orderResponse = WxMaGsonBuilder.create() + .fromJson(response, WxMiniBatchGetAfterSaleOrderResponse.class); + if (orderResponse.getAfterSaleOrderList() == null) { + throw new WxErrorException( + new WxError(orderResponse.getErrCode(), "售后查询不存在")); + } + return orderResponse; + } + + @Override + public WxMaShopBaseResponse afterSaleAccept(Long orderId, Long addressId) + throws WxErrorException { + String response = this.wxMaService.post(AFTER_SALE_ACCEPT_APPLY, + GsonHelper.buildJsonObject("order_id", orderId, "address_id", addressId)); + WxMaShopBaseResponse baseResponse = WxGsonBuilder.create() + .fromJson(response, WxMaShopBaseResponse.class); + if (baseResponse.getErrCode() != 0) { + throw new WxErrorException( + new WxError(baseResponse.getErrCode(), baseResponse.getErrMsg())); + } + return baseResponse; + } + + @Override + public WxMaShopBaseResponse afterSaleReject(Long afterSaleOrderId, String rejectReason) + throws WxErrorException { + String response = this.wxMaService.post(AFTER_SALE_REJECT_APPLY, + GsonHelper.buildJsonObject("order_id", afterSaleOrderId, "reject_reason", rejectReason)); + WxMaShopBaseResponse baseResponse = WxGsonBuilder.create() + .fromJson(response, WxMaShopBaseResponse.class); + if (baseResponse.getErrCode() != 0) { + throw new WxErrorException( + new WxError(baseResponse.getErrCode(), baseResponse.getErrMsg())); + } + return baseResponse; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaProductServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaProductServiceImpl.java new file mode 100644 index 000000000..9825cfa5d --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaProductServiceImpl.java @@ -0,0 +1,375 @@ +package cn.binarywang.wx.miniapp.api.impl; + +import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Product.OTHER.GET_BRAND; +import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Product.OTHER.GET_CATEGORY; +import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Product.OTHER.GET_FREIGHT_TEMPLATE; +import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Product.OTHER.IMG_UPLOAD; +import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Product.Sku.PRODUCT_ADD_SKU_URL; +import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Product.Sku.PRODUCT_BATCH_ADD_SKU_URL; +import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Product.Sku.PRODUCT_DEL_SKU_URL; +import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Product.Sku.PRODUCT_SKU_LIST; +import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Product.Order.PRODUCT_ORDER_GET_LIST; +import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Product.Sku.PRODUCT_ADD_SKU_URL; +import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Product.Sku.PRODUCT_BATCH_ADD_SKU_URL; +import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Product.Sku.PRODUCT_DEL_SKU_URL; +import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Product.Sku.PRODUCT_UPDATE_SKU_PRICE_URL; +import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Product.Sku.PRODUCT_UPDATE_SKU_STOCK_URL; +import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Product.Sku.PRODUCT_UPDATE_SKU_URL; +import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Product.Spu.PRODUCT_SPU_ADD_URL; +import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Product.Spu.PRODUCT_SPU_DELISTING_URL; +import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Product.Spu.PRODUCT_SPU_DEL_URL; +import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Product.Spu.PRODUCT_SPU_GET_LIST_URL; +import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Product.Spu.PRODUCT_SPU_GET_URL; +import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Product.Spu.PRODUCT_SPU_LISTING_URL; +import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Product.Spu.PRODUCT_SPU_UPDATE_URL; + +import cn.binarywang.wx.miniapp.api.WxMaProductService; +import cn.binarywang.wx.miniapp.api.WxMaService; +import cn.binarywang.wx.miniapp.bean.product.WxMinishopAddGoodsSkuData; +import cn.binarywang.wx.miniapp.bean.product.WxMinishopAddGoodsSpuData; +import cn.binarywang.wx.miniapp.bean.product.WxMinishopOrderListResponse; +import cn.binarywang.wx.miniapp.bean.product.WxMinishopResult; +import cn.binarywang.wx.miniapp.bean.product.WxMinishopSku; +import cn.binarywang.wx.miniapp.bean.product.WxMinishopGetBrandResponse; +import cn.binarywang.wx.miniapp.bean.product.WxMinishopGetCategoryResponse; +import cn.binarywang.wx.miniapp.bean.product.WxMinishopGetFrightTemplateResponse; +import cn.binarywang.wx.miniapp.bean.product.WxMinishopResult; +import cn.binarywang.wx.miniapp.bean.product.WxMinishopSku; +import cn.binarywang.wx.miniapp.bean.product.WxMinishopSkuListResponse; +import cn.binarywang.wx.miniapp.bean.product.WxMinishopSpu; +import cn.binarywang.wx.miniapp.bean.product.WxMinishopSpuGetResponse; +import cn.binarywang.wx.miniapp.bean.product.WxMinishopSpuListResponse; +import cn.binarywang.wx.miniapp.bean.product.WxMinishopUpdateGoodsSkuData; +import cn.binarywang.wx.miniapp.bean.shop.request.WxMaShopSpuPageRequest; +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopBaseResponse; +import cn.binarywang.wx.miniapp.json.WxMaGsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.bean.result.WxMinishopImageUploadResult; +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.util.http.MinishopUploadRequestExecutor; +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.util.json.GsonHelper; +import me.chanjar.weixin.common.util.json.GsonParser; + +/** + * @author boris + */ +@RequiredArgsConstructor +@Slf4j +public class WxMaProductServiceImpl implements WxMaProductService { + + private static final String ERR_CODE = "errcode"; + private final WxMaService wxMaService; + + @Override + public WxMinishopImageUploadResult uploadImg(File file, Integer respType, Integer width, + Integer height) throws WxErrorException { + String url = IMG_UPLOAD + "?upload_type=0" + "&height=" + height + "&width=" + width + "&resp_type=" + respType; + WxMinishopImageUploadResult result = this.wxMaService.execute( + MinishopUploadRequestExecutor.create(this.wxMaService.getRequestHttp()), url, file); + return result; + } + + @Override + public WxMinishopImageUploadResult uploadImg(String imgUrl, Integer respType) throws WxErrorException { + JsonObject jsonObject = GsonHelper.buildJsonObject("img_url", imgUrl); + String url = IMG_UPLOAD + "?upload_type=1" + "&resp_type=" + respType; + String response = this.wxMaService.post(url, jsonObject); + JsonObject respObj = GsonParser.parse(response); + + if (respObj.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(response, WxType.MiniApp)); + } + + return WxMinishopImageUploadResult.fromJson(response); + } + + @Override + public WxMinishopGetCategoryResponse getCategory(Integer fCatId) throws WxErrorException { + JsonObject jsonObject = GsonHelper.buildJsonObject("f_cat_id", fCatId); + String response = this.wxMaService.post(GET_CATEGORY, jsonObject); + JsonObject respObj = GsonParser.parse(response); + + if (respObj.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(response, WxType.MiniApp)); + } + + return WxMaGsonBuilder.create().fromJson(response, WxMinishopGetCategoryResponse.class); + } + + @Override + public WxMinishopGetBrandResponse getBrand() throws WxErrorException { + String response = this.wxMaService.post(GET_BRAND, new Object()); + JsonObject respObj = GsonParser.parse(response); + + if (respObj.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(response, WxType.MiniApp)); + } + + return WxMaGsonBuilder.create().fromJson(response, WxMinishopGetBrandResponse.class); + } + + @Override + public WxMinishopGetFrightTemplateResponse getFreightTemplate() throws WxErrorException { + String response = this.wxMaService.post(GET_FREIGHT_TEMPLATE, new Object()); + JsonObject respObj = GsonParser.parse(response); + + if (respObj.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(response, WxType.MiniApp)); + } + + return WxMaGsonBuilder.create().fromJson(response, WxMinishopGetFrightTemplateResponse.class); + } + + @Override + public WxMinishopResult addSpu(WxMinishopSpu spu) throws WxErrorException { + + String response = this.wxMaService.post(PRODUCT_SPU_ADD_URL, spu); + + JsonObject respObj = GsonParser.parse(response); + + if (respObj.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(response, WxType.MiniApp)); + } + WxMinishopResult result = new WxMinishopResult(); + result.setErrcode(respObj.get("errcode").getAsInt()); + JsonObject dataObj = respObj.get("data").getAsJsonObject(); + WxMinishopAddGoodsSpuData resultData = new WxMinishopAddGoodsSpuData(); + resultData.setProductId(dataObj.get("product_id").getAsLong()); + resultData.setOutProductId(dataObj.get("out_product_id").getAsString()); + resultData.setCreateTime(dataObj.get("create_time").getAsString()); + result.setData(resultData); + return result; + } + + @Override + public WxMaShopBaseResponse deleteSpu(Integer productId, String outProductId) + throws WxErrorException { + String responseContent = this.wxMaService + .post(PRODUCT_SPU_DEL_URL, GsonHelper.buildJsonObject("product_id", productId, + "out_product_id", outProductId)); + JsonObject jsonObject = GsonParser.parse(responseContent); + if (jsonObject.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + return WxMaGsonBuilder.create().fromJson(responseContent, WxMaShopBaseResponse.class); + } + + @Override + public WxMinishopSpuGetResponse getSpu(Integer productId, String outProductId, Integer needEditSpu) + throws WxErrorException { + String response = this.wxMaService + .post(PRODUCT_SPU_GET_URL, GsonHelper.buildJsonObject("product_id", productId, + "out_product_id", outProductId, "need_edit_spu", needEditSpu)); + JsonObject jsonObject = GsonParser.parse(response); + if (jsonObject.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(response, WxType.MiniApp)); + } + + return WxMaGsonBuilder.create().fromJson(response, WxMinishopSpuGetResponse.class); + } + + @Override + public WxMinishopSpuListResponse getSpuList(WxMaShopSpuPageRequest request) + throws WxErrorException { + String responseContent = this.wxMaService.post(PRODUCT_SPU_GET_LIST_URL, request); + JsonObject jsonObject = GsonParser.parse(responseContent); + if (jsonObject.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + return WxMaGsonBuilder.create().fromJson(responseContent, WxMinishopSpuListResponse.class); + } + + @Override + public WxMinishopResult updateSpu(WxMinishopSpu spu) throws WxErrorException { + String response = this.wxMaService.post(PRODUCT_SPU_UPDATE_URL, spu); + + JsonObject respObj = GsonParser.parse(response); + + if (respObj.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(response, WxType.MiniApp)); + } + WxMinishopResult result = new WxMinishopResult(); + result.setErrcode(respObj.get("errcode").getAsInt()); + JsonObject dataObj = respObj.get("data").getAsJsonObject(); + WxMinishopAddGoodsSpuData resultData = new WxMinishopAddGoodsSpuData(); + resultData.setProductId(dataObj.get("product_id").getAsLong()); + resultData.setOutProductId(dataObj.get("out_product_id").getAsString()); + resultData.setUpdateTime(dataObj.get("update_time").getAsString()); + result.setData(resultData); + return result; + } + + @Override + public WxMaShopBaseResponse listingSpu(Integer productId, String outProductId) + throws WxErrorException { + String responseContent = this.wxMaService + .post(PRODUCT_SPU_LISTING_URL, GsonHelper.buildJsonObject("product_id", productId, + "out_product_id", outProductId)); + JsonObject jsonObject = GsonParser.parse(responseContent); + if (jsonObject.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + return WxMaGsonBuilder.create().fromJson(responseContent, WxMaShopBaseResponse.class); + } + + @Override + public WxMaShopBaseResponse delistingSpu(Integer productId, String outProductId) + throws WxErrorException { + String responseContent = this.wxMaService + .post(PRODUCT_SPU_DELISTING_URL, GsonHelper.buildJsonObject("product_id", productId, + "out_product_id", outProductId)); + JsonObject jsonObject = GsonParser.parse(responseContent); + if (jsonObject.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + return WxMaGsonBuilder.create().fromJson(responseContent, WxMaShopBaseResponse.class); + } + + @Override + public WxMinishopSkuListResponse getSkuList(Long productId, Integer needRealStock, Integer needEditSku) + throws WxErrorException { + String responseContent = this.wxMaService + .post(PRODUCT_SKU_LIST, GsonHelper.buildJsonObject("product_id", productId, + "need_edit_sku", needEditSku, "need_real_stock", needRealStock)); + JsonObject jsonObject = GsonParser.parse(responseContent); + if (jsonObject.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + return WxMaGsonBuilder.create().fromJson(responseContent, WxMinishopSkuListResponse.class); + } + + @Override + public WxMinishopResult minishiopGoodsAddSku( + WxMinishopSku sku) throws WxErrorException { + String response = this.wxMaService + .post(PRODUCT_ADD_SKU_URL, sku); + JsonObject jsonObject = GsonParser.parse(response); + if (jsonObject.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(response, WxType.MiniApp)); + } + WxMinishopResult result = new WxMinishopResult(); + result.setErrcode(jsonObject.get("errcode").getAsInt()); + JsonObject dataObj = jsonObject.get("data").getAsJsonObject(); + WxMinishopAddGoodsSkuData resultData = new WxMinishopAddGoodsSkuData(); + resultData.setSkuId(dataObj.get("sku_id").getAsLong()); + resultData.setCreateTime(dataObj.get("create_time").getAsString()); + result.setData(resultData); + return result; + } + + @Override + public WxMinishopResult> minishopGoodsBatchAddSku( + List skuList) throws WxErrorException { + String response = this.wxMaService + .post(PRODUCT_BATCH_ADD_SKU_URL, GsonHelper.buildJsonObject("skus", skuList)); + JsonObject jsonObject = GsonParser.parse(response); + if (jsonObject.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(response, WxType.MiniApp)); + } + + WxMinishopResult result = new WxMinishopResult(); + result.setErrcode(jsonObject.get("errcode").getAsInt()); + JsonArray jsonArray = jsonObject.get("data").getAsJsonArray(); + List skuData = new ArrayList<>(); + for (JsonElement jsonElement : jsonArray) { + JsonObject element = jsonElement.getAsJsonObject(); + WxMinishopAddGoodsSkuData resultData = new WxMinishopAddGoodsSkuData(); + resultData.setSkuId(element.get("sku_id").getAsLong()); + resultData.setOutSkuId(element.get("out_sku_id").getAsString()); + resultData.setCreateTime(element.get("create_time").getAsString()); + skuData.add(resultData); + } + result.setData(skuData); + return result; + } + + @Override + public WxMaShopBaseResponse minishopGoodsDelSku(Long productId, Long outProductId, + String outSkuId, Long skuId) throws WxErrorException { + String response = this.wxMaService + .post(PRODUCT_DEL_SKU_URL, GsonHelper.buildJsonObject("product_id", productId, + "out_product_id", outProductId, "out_sku_id", outSkuId, "sku_id", skuId)); + JsonObject jsonObject = GsonParser.parse(response); + if (jsonObject.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(response, WxType.MiniApp)); + } + return WxMaGsonBuilder.create().fromJson(response, WxMaShopBaseResponse.class); + } + + @Override + public WxMinishopResult minishopGoodsUpdateSku( + WxMinishopSku sku) throws WxErrorException { + String response = this.wxMaService + .post(PRODUCT_UPDATE_SKU_URL, sku); + JsonObject jsonObject = GsonParser.parse(response); + if (jsonObject.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(response, WxType.MiniApp)); + } + WxMinishopResult result = new WxMinishopResult(); + result.setErrcode(jsonObject.get("errcode").getAsInt()); + JsonObject dataObj = jsonObject.get("data").getAsJsonObject(); + WxMinishopUpdateGoodsSkuData resultData = new WxMinishopUpdateGoodsSkuData(); + resultData.setUpdateTime(dataObj.get("update_time").getAsString()); + result.setData(resultData); + return result; + } + + @Override + public WxMinishopResult minishopGoodsUpdateSkuPrice( + Long productId, String outProductId, String outSkuId, Long skuId, Long salePrice, + Long marketPrice) throws WxErrorException { + String response = this.wxMaService + .post(PRODUCT_UPDATE_SKU_PRICE_URL, GsonHelper.buildJsonObject( + "product_id", productId, "out_product_id", outProductId, + "sku_id", skuId, "out_sku_id", outSkuId, "sale_price", salePrice, "market_price", marketPrice)); + JsonObject jsonObject = GsonParser.parse(response); + if (jsonObject.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(response, WxType.MiniApp)); + } + + WxMinishopResult result = new WxMinishopResult(); + result.setErrcode(jsonObject.get("errcode").getAsInt()); + JsonObject dataObj = jsonObject.get("data").getAsJsonObject(); + WxMinishopUpdateGoodsSkuData resultData = new WxMinishopUpdateGoodsSkuData(); + resultData.setUpdateTime(dataObj.get("update_time").getAsString()); + result.setData(resultData); + return result; + } + + @Override + public WxMinishopResult minishopGoodsUpdateSkuStock( + Long productId, String outProductId, String outSkuId, Long skuId, Integer type, + Integer stockNum) throws WxErrorException { + String response = this.wxMaService + .post(PRODUCT_UPDATE_SKU_STOCK_URL, GsonHelper.buildJsonObject( + "product_id", productId, "out_product_id", outProductId, + "sku_id", skuId, "out_sku_id", outSkuId, "type", type, "stock_num", stockNum)); + JsonObject jsonObject = GsonParser.parse(response); + if (jsonObject.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(response, WxType.MiniApp)); + } + + WxMinishopResult result = new WxMinishopResult(); + result.setErrcode(jsonObject.get("errcode").getAsInt()); + JsonObject dataObj = jsonObject.get("data").getAsJsonObject(); + WxMinishopUpdateGoodsSkuData resultData = new WxMinishopUpdateGoodsSkuData(); + resultData.setUpdateTime(dataObj.get("update_time").getAsString()); + result.setData(resultData); + return result; + } + + + +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaSecCheckServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaSecCheckServiceImpl.java index 837674eb6..dc69b3f7f 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaSecCheckServiceImpl.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaSecCheckServiceImpl.java @@ -85,8 +85,8 @@ public WxMaMediaAsyncCheckResult mediaCheckAsync(String mediaUrl, int mediaType) } @Override - public WxMaMediaAsyncCheckResult mediaCheckAsync(WxMaMediaSecCheckCheckRequest medisRequest) throws WxErrorException { - String response = this.service.post(MEDIA_CHECK_ASYNC_URL,medisRequest); + public WxMaMediaAsyncCheckResult mediaCheckAsync(WxMaMediaSecCheckCheckRequest request) throws WxErrorException { + String response = this.service.post(MEDIA_CHECK_ASYNC_URL, request); parseErrorResponse(response); return WxMaGsonBuilder.create().fromJson(response,WxMaMediaAsyncCheckResult.class); } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceHttpClientImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceHttpClientImpl.java index 691497786..f0816fc85 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceHttpClientImpl.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceHttpClientImpl.java @@ -62,10 +62,12 @@ public HttpType getRequestType() { @Override protected String doGetAccessTokenRequest() throws IOException { - String url = StringUtils.isNotEmpty(this.getWxMaConfig().getApiHostUrl()) ? + String url = StringUtils.isNotEmpty(this.getWxMaConfig().getAccessTokenUrl()) ? + this.getWxMaConfig().getAccessTokenUrl() : StringUtils.isNotEmpty(this.getWxMaConfig().getApiHostUrl()) ? WxMaService.GET_ACCESS_TOKEN_URL.replace("https://api.weixin.qq.com", this.getWxMaConfig().getApiHostUrl()) : WxMaService.GET_ACCESS_TOKEN_URL; - + + url = String.format(url, this.getWxMaConfig().getAppid(), this.getWxMaConfig().getSecret()); HttpGet httpGet = null; diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceJoddHttpImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceJoddHttpImpl.java index 90ee6516a..f14d8cd6d 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceJoddHttpImpl.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceJoddHttpImpl.java @@ -46,7 +46,8 @@ public HttpType getRequestType() { @Override protected String doGetAccessTokenRequest() throws IOException { - String url = StringUtils.isNotEmpty(this.getWxMaConfig().getApiHostUrl()) ? + String url = StringUtils.isNotEmpty(this.getWxMaConfig().getAccessTokenUrl()) ? + this.getWxMaConfig().getAccessTokenUrl() : StringUtils.isNotEmpty(this.getWxMaConfig().getApiHostUrl()) ? WxMaService.GET_ACCESS_TOKEN_URL.replace("https://api.weixin.qq.com", this.getWxMaConfig().getApiHostUrl()) : WxMaService.GET_ACCESS_TOKEN_URL; diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceOkHttpImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceOkHttpImpl.java index 0fa49d9d0..6f1fdbfd9 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceOkHttpImpl.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceOkHttpImpl.java @@ -64,7 +64,8 @@ public HttpType getRequestType() { @Override protected String doGetAccessTokenRequest() throws IOException { - String url = StringUtils.isNotEmpty(this.getWxMaConfig().getApiHostUrl()) ? + String url = StringUtils.isNotEmpty(this.getWxMaConfig().getAccessTokenUrl()) ? + this.getWxMaConfig().getAccessTokenUrl() : StringUtils.isNotEmpty(this.getWxMaConfig().getApiHostUrl()) ? WxMaService.GET_ACCESS_TOKEN_URL.replace("https://api.weixin.qq.com", this.getWxMaConfig().getApiHostUrl()) : WxMaService.GET_ACCESS_TOKEN_URL; diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaShopAfterSaleServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaShopAfterSaleServiceImpl.java index 9fd24350a..5641489b4 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaShopAfterSaleServiceImpl.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaShopAfterSaleServiceImpl.java @@ -2,10 +2,16 @@ import cn.binarywang.wx.miniapp.api.WxMaService; import cn.binarywang.wx.miniapp.api.WxMaShopAfterSaleService; +import cn.binarywang.wx.miniapp.bean.shop.request.WxMaShopAcceptReturnRequest; import cn.binarywang.wx.miniapp.bean.shop.request.WxMaShopAfterSaleAddRequest; import cn.binarywang.wx.miniapp.bean.shop.request.WxMaShopAfterSaleGetRequest; +import cn.binarywang.wx.miniapp.bean.shop.request.WxMaShopAfterSaleListRequest; import cn.binarywang.wx.miniapp.bean.shop.request.WxMaShopAfterSaleUpdateRequest; +import cn.binarywang.wx.miniapp.bean.shop.request.WxMaShopAfterSaleUploadReturnInfoRequest; +import cn.binarywang.wx.miniapp.bean.shop.request.WxMaShopUploadCerficatesRequest; +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopAfterSaleAddResponse; import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopAfterSaleGetResponse; +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopAfterSaleListResponse; import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopBaseResponse; import cn.binarywang.wx.miniapp.json.WxMaGsonBuilder; import com.google.gson.JsonObject; @@ -14,6 +20,7 @@ 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.util.json.GsonHelper; import me.chanjar.weixin.common.util.json.GsonParser; import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Shop.Aftersale.*; @@ -37,13 +44,13 @@ public class WxMaShopAfterSaleServiceImpl implements WxMaShopAfterSaleService { * @throws WxErrorException */ @Override - public WxMaShopBaseResponse add(WxMaShopAfterSaleAddRequest request) throws WxErrorException { + public WxMaShopAfterSaleAddResponse add(WxMaShopAfterSaleAddRequest request) throws WxErrorException { String responseContent = this.wxMaService.post(AFTERSALE_ADD, request); JsonObject jsonObject = GsonParser.parse(responseContent); if (jsonObject.get(ERRCODE).getAsInt() != 0) { throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); } - return WxMaGsonBuilder.create().fromJson(responseContent, WxMaShopBaseResponse.class); + return WxMaGsonBuilder.create().fromJson(responseContent, WxMaShopAfterSaleAddResponse.class); } /** @@ -79,4 +86,154 @@ public WxMaShopBaseResponse update(WxMaShopAfterSaleUpdateRequest request) throw } return WxMaGsonBuilder.create().fromJson(responseContent, WxMaShopBaseResponse.class); } + + /** + * 用户取消售后申请 + * @param outAfterSaleId 商家自定义订单ID + * @param afterSaleId 与out_aftersale_id二选一 + * @param openId 用户openid + * @return + * @throws WxErrorException + */ + @Override + public WxMaShopBaseResponse cancel(String outAfterSaleId, Long afterSaleId, String openId) + throws WxErrorException { + JsonObject request = GsonHelper.buildJsonObject("out_aftersale_id", outAfterSaleId, + "aftersale_id", afterSaleId, "openid", openId); + String resp = this.wxMaService.post(AFTERSALE_CANCEL, request); + JsonObject jsonObject = GsonParser.parse(resp); + if (jsonObject.get(ERRCODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(resp, WxType.MiniApp)); + } + return WxMaGsonBuilder.create().fromJson(resp, WxMaShopBaseResponse.class); + } + + /** + * 用户上传退货物流 + * @param request + * @return + * @throws WxErrorException + */ + @Override + public WxMaShopBaseResponse uploadReturnInfo(WxMaShopAfterSaleUploadReturnInfoRequest request) + throws WxErrorException { + String resp = this.wxMaService.post(AFTERSALE_UPLOAD_RETURN_INFO, request); + JsonObject jsonObject = GsonParser.parse(resp); + if (jsonObject.get(ERRCODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(resp, WxType.MiniApp)); + } + return WxMaGsonBuilder.create().fromJson(resp, WxMaShopBaseResponse.class); + } + + /** + * 商家同意退款 + * @param outAfterSaleId + * @param afterSaleId + * @return + * @throws WxErrorException + */ + @Override + public WxMaShopBaseResponse acceptRefund(String outAfterSaleId, Long afterSaleId) + throws WxErrorException { + JsonObject request = GsonHelper.buildJsonObject("out_aftersale_id", outAfterSaleId, + "aftersale_id", afterSaleId); + String resp = this.wxMaService.post(AFTERSALE_ACCEPT_REFUND, request); + JsonObject jsonObject = GsonParser.parse(resp); + if (jsonObject.get(ERRCODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(resp, WxType.MiniApp)); + } + return WxMaGsonBuilder.create().fromJson(resp, WxMaShopBaseResponse.class); + } + + /** + * 商家同意退货 + * @param request + * @return + * @throws WxErrorException + */ + @Override + public WxMaShopBaseResponse acceptReturn(WxMaShopAcceptReturnRequest request) + throws WxErrorException { + String resp = this.wxMaService.post(AFTERSALE_ACCEPT_RETURN, request); + JsonObject jsonObject = GsonParser.parse(resp); + if (jsonObject.get(ERRCODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(resp, WxType.MiniApp)); + } + return WxMaGsonBuilder.create().fromJson(resp, WxMaShopBaseResponse.class); + } + + /** + * 商家拒绝售后 + * @param outAfterSaleId + * @param afterSaleId + * @return + * @throws WxErrorException + */ + @Override + public WxMaShopBaseResponse reject(String outAfterSaleId, Long afterSaleId) + throws WxErrorException { + JsonObject request = GsonHelper.buildJsonObject("out_aftersale_id", outAfterSaleId, + "aftersale_id", afterSaleId); + String resp = this.wxMaService.post(AFTERSALE_REJECT, request); + JsonObject jsonObject = GsonParser.parse(resp); + if (jsonObject.get(ERRCODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(resp, WxType.MiniApp)); + } + return WxMaGsonBuilder.create().fromJson(resp, WxMaShopBaseResponse.class); + } + + /** + * 商家上传退款凭证 + * @param request + * @return + * @throws WxErrorException + */ + @Override + public WxMaShopBaseResponse uploadCertificates(WxMaShopUploadCerficatesRequest request) + throws WxErrorException { + String resp = this.wxMaService.post(AFTERSALE_UPLOAD_CERTIFICATES, request); + JsonObject jsonObject = GsonParser.parse(resp); + if (jsonObject.get(ERRCODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(resp, WxType.MiniApp)); + } + return WxMaGsonBuilder.create().fromJson(resp, WxMaShopBaseResponse.class); + } + + /** + * 商家更新订单售后期 + * @param outOrderId + * @param orderId + * @param openid + * @param afterSaleDeadline + * @return + * @throws WxErrorException + */ + @Override + public WxMaShopBaseResponse updateDeadline(String outOrderId, Long orderId, String openid, + Long afterSaleDeadline) throws WxErrorException { + JsonObject request = GsonHelper.buildJsonObject("out_order_id", outOrderId, + "order_id", orderId, "openid", openid, "after_sale_deadline", afterSaleDeadline); + String resp = this.wxMaService.post(AFTERSALE_UPLOAD_DEADLINE, request); + JsonObject jsonObject = GsonParser.parse(resp); + if (jsonObject.get(ERRCODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(resp, WxType.MiniApp)); + } + return WxMaGsonBuilder.create().fromJson(resp, WxMaShopBaseResponse.class); + } + + /** + * 获取售后单详情 + * @param request + * @return + * @throws WxErrorException + */ + @Override + public WxMaShopAfterSaleListResponse list(WxMaShopAfterSaleListRequest request) throws WxErrorException { + String resp = this.wxMaService.post(AFTERSALE_GET_LIST, request); + JsonObject jsonObject = GsonParser.parse(resp); + if (jsonObject.get(ERRCODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(resp, WxType.MiniApp)); + } + return WxMaGsonBuilder.create().fromJson(resp, WxMaShopAfterSaleListResponse.class); + } } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaShopCouponServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaShopCouponServiceImpl.java new file mode 100644 index 000000000..fecca734b --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaShopCouponServiceImpl.java @@ -0,0 +1,165 @@ +package cn.binarywang.wx.miniapp.api.impl; + +import static cn.binarywang.wx.miniapp.api.impl.WxMaImmediateDeliveryServiceImpl.ERR_CODE; + +import cn.binarywang.wx.miniapp.api.WxMaService; +import cn.binarywang.wx.miniapp.api.WxMaShopCouponService; +import cn.binarywang.wx.miniapp.bean.shop.WxMaShopCouponInfo; +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopBaseResponse; +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopCouponListResponse; +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopCouponResponse; +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopUserCouponListResponse; +import cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Shop.Coupon; +import cn.binarywang.wx.miniapp.json.WxMaGsonBuilder; +import com.google.gson.JsonObject; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +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.util.json.GsonHelper; +import me.chanjar.weixin.common.util.json.GsonParser; + +/** + * @author leiin + * @date 2022/7/1 2:49 下午 + */ +@RequiredArgsConstructor +@Slf4j +public class WxMaShopCouponServiceImpl implements WxMaShopCouponService { + private final WxMaService wxMaService; + + @Override + public WxMaShopBaseResponse addCoupon(WxMaShopCouponInfo couponInfo) throws WxErrorException { + JsonObject json = GsonHelper.buildJsonObject("coupon", couponInfo); + String responseContent = this.wxMaService.post(Coupon.ADD_COUPON, json); + JsonObject jsonObject = GsonParser.parse(responseContent); + if (jsonObject.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + return WxMaGsonBuilder.create().fromJson(responseContent, WxMaShopBaseResponse.class); + } + + @Override + public WxMaShopCouponResponse getCoupon(String outCouponId) throws WxErrorException { + JsonObject json = GsonHelper.buildJsonObject("out_coupon_id", outCouponId); + String responseContent = this.wxMaService.post(Coupon.GET_COUPON, json); + JsonObject jsonObject = GsonParser.parse(responseContent); + if (jsonObject.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + return WxMaGsonBuilder.create().fromJson(responseContent, WxMaShopCouponResponse.class); + } + + @Override + public WxMaShopCouponListResponse getCouponList(Integer pageSize, Integer offset) throws WxErrorException { + JsonObject json = GsonHelper.buildJsonObject("page_size", pageSize, "offset", offset); + String responseContent = this.wxMaService.post(Coupon.GET_COUPON_LIST, json); + JsonObject jsonObject = GsonParser.parse(responseContent); + if (jsonObject.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + return WxMaGsonBuilder.create().fromJson(responseContent, WxMaShopCouponListResponse.class); + } + + @Override + public WxMaShopBaseResponse updateCoupon(WxMaShopCouponInfo couponInfo) throws WxErrorException { + JsonObject json = GsonHelper.buildJsonObject("coupon", couponInfo); + String responseContent = this.wxMaService.post(Coupon.UPDATE_COUPON, json); + JsonObject jsonObject = GsonParser.parse(responseContent); + if (jsonObject.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + return WxMaGsonBuilder.create().fromJson(responseContent, WxMaShopBaseResponse.class); + } + + @Override + public WxMaShopBaseResponse updateCouponStatus(String outCouponId, Integer status) throws WxErrorException { + JsonObject json = GsonHelper.buildJsonObject("out_coupon_id", outCouponId, "status", status); + String responseContent = this.wxMaService.post(Coupon.UPDATE_COUPON_STATUS, json); + JsonObject jsonObject = GsonParser.parse(responseContent); + if (jsonObject.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + return WxMaGsonBuilder.create().fromJson(responseContent, WxMaShopBaseResponse.class); + } + + @Override + public WxMaShopBaseResponse updateCouponStock(String outCouponId, Integer isUsedNum, Integer receiveNum) throws WxErrorException { + JsonObject stockInfo = GsonHelper.buildJsonObject("issued_num", isUsedNum, "receive_num", receiveNum); + JsonObject stock = GsonHelper.buildJsonObject("out_coupon_id", outCouponId, "stock_info", stockInfo); + JsonObject json = GsonHelper.buildJsonObject("coupon_stock", stock); + + String responseContent = this.wxMaService.post(Coupon.UPDATE_COUPON_STOCK, json); + JsonObject jsonObject = GsonParser.parse(responseContent); + if (jsonObject.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + return WxMaGsonBuilder.create().fromJson(responseContent, WxMaShopBaseResponse.class); + } + + @Override + public WxMaShopBaseResponse addUserCoupon(String openid, String outUserCouponId, + String outCouponId, Integer status, Long recvTime) throws WxErrorException { + JsonObject userCoupon = GsonHelper.buildJsonObject("out_user_coupon_id", outUserCouponId, + "out_coupon_id", outCouponId, + "status", status); + JsonObject json = GsonHelper.buildJsonObject("openid", openid, "user_coupon", userCoupon, + "recv_time", recvTime); + + String responseContent = this.wxMaService.post(Coupon.ADD_USER_COUPON, json); + JsonObject jsonObject = GsonParser.parse(responseContent); + if (jsonObject.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + return WxMaGsonBuilder.create().fromJson(responseContent, WxMaShopBaseResponse.class); + } + + @Override + public WxMaShopUserCouponListResponse getUserCouponList(Integer pageSize, Integer offset, String openid) throws WxErrorException { + JsonObject json = GsonHelper.buildJsonObject("page_size", pageSize, "offset", offset, + "openid", openid); + String responseContent = this.wxMaService.post(Coupon.GET_USER_COUPON_LIST, json); + JsonObject jsonObject = GsonParser.parse(responseContent); + if (jsonObject.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + return WxMaGsonBuilder.create().fromJson(responseContent, WxMaShopUserCouponListResponse.class); + } + + @Override + public WxMaShopBaseResponse updateUserCoupon(String openid, String outUserCouponId, + String outCouponId, Long useTime, Long recvTime) throws WxErrorException { + JsonObject extInfo = GsonHelper.buildJsonObject("use_time", useTime); + + JsonObject userCoupon = GsonHelper.buildJsonObject("out_user_coupon_id", outUserCouponId, + "out_coupon_id", outCouponId, "ext_info", extInfo); + + JsonObject json = GsonHelper.buildJsonObject("openid", openid, "user_coupon", userCoupon, + "recv_time", recvTime); + + String responseContent = this.wxMaService.post(Coupon.UPDATE_USER_COUPON, json); + JsonObject jsonObject = GsonParser.parse(responseContent); + if (jsonObject.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + return WxMaGsonBuilder.create().fromJson(responseContent, WxMaShopBaseResponse.class); + } + + @Override + public WxMaShopBaseResponse updateUserCouponStatus(String openid, String outUserCouponId, + String outCouponId, Integer status) throws WxErrorException { + + JsonObject json = GsonHelper.buildJsonObject("openid", openid, + "out_user_coupon_id", outUserCouponId, + "out_coupon_id", outCouponId, + "status", status); + + String responseContent = this.wxMaService.post(Coupon.UPDATE_USER_COUPON_STATUS, json); + JsonObject jsonObject = GsonParser.parse(responseContent); + if (jsonObject.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + return WxMaGsonBuilder.create().fromJson(responseContent, WxMaShopBaseResponse.class); + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaShopOrderServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaShopOrderServiceImpl.java index ff466ded6..409f4fa72 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaShopOrderServiceImpl.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaShopOrderServiceImpl.java @@ -1,17 +1,10 @@ package cn.binarywang.wx.miniapp.api.impl; -import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Shop.Order.ORDER_ADD; -import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Shop.Order.ORDER_CHECK_SCENE; -import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Shop.Order.ORDER_GET; -import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Shop.Order.ORDER_PAY; - import cn.binarywang.wx.miniapp.api.WxMaService; import cn.binarywang.wx.miniapp.api.WxMaShopOrderService; import cn.binarywang.wx.miniapp.bean.shop.WxMaShopOrderInfo; import cn.binarywang.wx.miniapp.bean.shop.request.WxMaShopOrderPayRequest; -import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopAddOrderResponse; -import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopBaseResponse; -import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopGetOrderResponse; +import cn.binarywang.wx.miniapp.bean.shop.response.*; import cn.binarywang.wx.miniapp.json.WxMaGsonBuilder; import com.google.gson.JsonObject; import lombok.RequiredArgsConstructor; @@ -21,6 +14,12 @@ import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.util.json.GsonHelper; import me.chanjar.weixin.common.util.json.GsonParser; +import org.apache.commons.lang3.time.FastDateFormat; + +import java.text.Format; +import java.util.Date; + +import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Shop.Order.*; /** * @author boris @@ -28,6 +27,9 @@ @RequiredArgsConstructor @Slf4j public class WxMaShopOrderServiceImpl implements WxMaShopOrderService { + + private final Format dateFormat = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss"); + private static final String ERR_CODE = "errcode"; private static final String MATCH_KEY = "is_matched"; private final WxMaService wxMaService; @@ -45,34 +47,49 @@ public Boolean checkScene(Integer scene) throws WxErrorException { @Override public WxMaShopAddOrderResponse addOrder(WxMaShopOrderInfo orderInfo) throws WxErrorException { - String responseContent = this.wxMaService.post(ORDER_ADD, orderInfo); - JsonObject jsonObject = GsonParser.parse(responseContent); - if (jsonObject.get(ERR_CODE).getAsInt() != 0) { - throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); - } - return WxMaGsonBuilder.create().fromJson(responseContent, WxMaShopAddOrderResponse.class); + return this.post(ORDER_ADD,orderInfo, WxMaShopAddOrderResponse.class); } @Override public WxMaShopBaseResponse orderPay(WxMaShopOrderPayRequest request) throws WxErrorException { - String responseContent = this.wxMaService.post(ORDER_PAY, request); - JsonObject jsonObject = GsonParser.parse(responseContent); - if (jsonObject.get(ERR_CODE).getAsInt() != 0) { - throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + return this.post(ORDER_PAY,request, WxMaShopBaseResponse.class); + } + + @Override + public WxMaShopGetOrderResponse getOrder(Long orderId, String outOrderId, String openid) throws WxErrorException { + return this.post(ORDER_GET, GsonHelper.buildJsonObject("order_id", orderId, "out_order_id", outOrderId, + "openid", openid), WxMaShopGetOrderResponse.class); + } + + @Override + public WxMaShopGetOrderListResponse getOrderList(Integer page, Integer pageSize, Boolean desc, Date startCreateTime, Date endCreateTime) throws WxErrorException { + JsonObject object = new JsonObject(); + object.addProperty("page", page == null ? 1 : page); + object.addProperty("page_size", pageSize == null ? 10 : pageSize); + object.addProperty("desc", desc ? 1 : 2); + if (startCreateTime != null) { + object.addProperty("start_create_time", this.dateFormat.format(startCreateTime)); + } + if (endCreateTime != null) { + object.addProperty("end_create_time", this.dateFormat.format(endCreateTime)); } - return WxMaGsonBuilder.create().fromJson(responseContent, WxMaShopBaseResponse.class); + return this.post(ORDER_GET_LIST, object, WxMaShopGetOrderListResponse.class); } @Override - public WxMaShopGetOrderResponse getOrder(Integer orderId, String outOrderId, String openid) - throws WxErrorException { - String responseContent = this.wxMaService.post(ORDER_GET, + public WxMaShopGetPaymentParamsResponse getPaymentParams(String orderId, String outOrderId, String openid) throws WxErrorException { + return this.post(ORDER_GET_PAYMENT_PARAMS, GsonHelper.buildJsonObject("order_id", orderId, "out_order_id", outOrderId, - "openid", openid)); + "openid", openid), WxMaShopGetPaymentParamsResponse.class); + } + + + private T post(String url, Object params, Class classOfT) throws WxErrorException { + String responseContent = this.wxMaService.post(url, params); JsonObject jsonObject = GsonParser.parse(responseContent); if (jsonObject.get(ERR_CODE).getAsInt() != 0) { throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); } - return WxMaGsonBuilder.create().fromJson(responseContent, WxMaShopGetOrderResponse.class); + return WxMaGsonBuilder.create().fromJson(responseContent, classOfT); } } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaShopPayServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaShopPayServiceImpl.java new file mode 100644 index 000000000..1a1c45f29 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaShopPayServiceImpl.java @@ -0,0 +1,29 @@ +package cn.binarywang.wx.miniapp.api.impl; + +import cn.binarywang.wx.miniapp.api.WxMaService; +import cn.binarywang.wx.miniapp.api.WxMaShopPayService; +import cn.binarywang.wx.miniapp.bean.shop.request.WxMaShopPayCreateOrderRequest; +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopPayCreateOrderResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.util.json.WxGsonBuilder; + +import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Shop.Pay.CREATE_ORDER; + +/** + * 小程序支付管理订单相关接口 + * + * @author liming1019 + */ +@RequiredArgsConstructor +@Slf4j +public class WxMaShopPayServiceImpl implements WxMaShopPayService { + private final WxMaService wxMaService; + + @Override + public WxMaShopPayCreateOrderResponse createOrder(WxMaShopPayCreateOrderRequest request) throws WxErrorException { + String response = this.wxMaService.post(CREATE_ORDER, request); + return WxGsonBuilder.create().fromJson(response, WxMaShopPayCreateOrderResponse.class); + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaShopSharerServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaShopSharerServiceImpl.java new file mode 100644 index 000000000..af8abe50b --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaShopSharerServiceImpl.java @@ -0,0 +1,113 @@ +package cn.binarywang.wx.miniapp.api.impl; + +import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Shop.Sharer; + +import cn.binarywang.wx.miniapp.api.WxMaService; +import cn.binarywang.wx.miniapp.api.WxMaShopSharerService; +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopSearchSharerResponse; +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopSharerBindResponse; +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopSharerDataSummaryResponse; +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopSharerListResponse; +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopSharerLiveOrderListResponse; +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopSharerLiveSummaryListResponse; +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopSharerUnbindResponse; +import cn.binarywang.wx.miniapp.json.WxMaGsonBuilder; +import com.google.gson.JsonObject; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +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.util.json.GsonHelper; +import me.chanjar.weixin.common.util.json.GsonParser; + +/** + * @author leiin + * @date 2022/6/18 3:38 下午 + */ +@RequiredArgsConstructor +@Slf4j +public class WxMaShopSharerServiceImpl implements WxMaShopSharerService { + private static final String ERR_CODE = "errcode"; + private final WxMaService wxMaService; + + @Override + public WxMaShopSharerBindResponse bindSharer(String[] openids) throws WxErrorException { + JsonObject json = GsonHelper.buildJsonObject("openids", openids); + String responseContent = this.wxMaService.post(Sharer.BIND, json); + JsonObject jsonObject = GsonParser.parse(responseContent); + if (jsonObject.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + return WxMaGsonBuilder.create().fromJson(responseContent, WxMaShopSharerBindResponse.class); + } + + @Override + public WxMaShopSharerDataSummaryResponse getSharerDataSummary(String openid) throws WxErrorException { + JsonObject json = GsonHelper.buildJsonObject("openid", openid); + String responseContent = this.wxMaService.post(Sharer.GET_SHARER_DATA_SUMMARY, json); + JsonObject jsonObject = GsonParser.parse(responseContent); + if (jsonObject.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + return WxMaGsonBuilder.create().fromJson(responseContent, WxMaShopSharerDataSummaryResponse.class); + } + + @Override + public WxMaShopSharerListResponse getSharerList(Integer page, Integer pageSize) throws WxErrorException { + JsonObject json = GsonHelper.buildJsonObject("page", page, "page_size", pageSize); + String responseContent = this.wxMaService.post(Sharer.GET_SHARER_LIST, json); + JsonObject jsonObject = GsonParser.parse(responseContent); + if (jsonObject.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + return WxMaGsonBuilder.create().fromJson(responseContent, WxMaShopSharerListResponse.class); + } + + @Override + public WxMaShopSharerLiveOrderListResponse getSharerLiveOrderList(String openid, String liveExportId, + Integer page, Integer pageSize) throws WxErrorException { + JsonObject json = GsonHelper.buildJsonObject("openid", openid, "live_export_id", liveExportId, + "page", page, "page_size", pageSize); + String responseContent = this.wxMaService.post(Sharer.GET_SHARER_LIVE_ORDER_LIST, json); + JsonObject jsonObject = GsonParser.parse(responseContent); + if (jsonObject.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + return WxMaGsonBuilder.create().fromJson(responseContent, WxMaShopSharerLiveOrderListResponse.class); + } + + @Override + public WxMaShopSharerLiveSummaryListResponse getSharerLiveSummaryList(String openid, + Integer page, Integer pageSize) throws WxErrorException { + JsonObject json = GsonHelper.buildJsonObject("openid", openid, "page", page, "page_size", pageSize); + String responseContent = this.wxMaService.post(Sharer.GET_SHARER_LIVE_SUMMARY_LIST, json); + JsonObject jsonObject = GsonParser.parse(responseContent); + if (jsonObject.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + return WxMaGsonBuilder.create().fromJson(responseContent, WxMaShopSharerLiveSummaryListResponse.class); + } + + @Override + public WxMaShopSearchSharerResponse searchSharer(String openid) throws WxErrorException { + JsonObject json = GsonHelper.buildJsonObject("openid", openid); + String responseContent = this.wxMaService.post(Sharer.SEARCH_SHARER, json); + JsonObject jsonObject = GsonParser.parse(responseContent); + if (jsonObject.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + return WxMaGsonBuilder.create().fromJson(responseContent, WxMaShopSearchSharerResponse.class); + } + + @Override + public WxMaShopSharerUnbindResponse unbindSharer(String[] openids) throws WxErrorException { + JsonObject json = GsonHelper.buildJsonObject("openids", openids); + String responseContent = this.wxMaService.post(Sharer.UNBIND, json); + JsonObject jsonObject = GsonParser.parse(responseContent); + if (jsonObject.get(ERR_CODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + return WxMaGsonBuilder.create().fromJson(responseContent, WxMaShopSharerUnbindResponse.class); + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaCodeLineColor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaCodeLineColor.java index 2afb4c073..388556a7b 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaCodeLineColor.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaCodeLineColor.java @@ -2,6 +2,7 @@ import lombok.AllArgsConstructor; import lombok.Data; +import lombok.NoArgsConstructor; /** *
@@ -12,6 +13,7 @@
  * @author Element
  */
 @Data
+@NoArgsConstructor
 @AllArgsConstructor
 public class WxMaCodeLineColor {
   private String r = "0", g = "0", b = "0";
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaJscode2SessionResult.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaJscode2SessionResult.java
index af113e4ec..1b0f6f28a 100644
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaJscode2SessionResult.java
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaJscode2SessionResult.java
@@ -10,7 +10,8 @@
 /**
  * 
  * code换取session_key接口的响应
- * 文档地址:https://mp.weixin.qq.com/debug/wxadoc/dev/api/api-login.html#wxloginobject
+ * 文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html
+ *
  * 微信返回报文:{"session_key":"nzoqhc3OnwHzeTxJs+inbQ==","openid":"oVBkZ0aYgDMDIywRdgPW8-joxXc4"}
  * 
* @author Binary Wang diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaMediaAsyncCheckResult.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaMediaAsyncCheckResult.java index f4428b959..64351ece6 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaMediaAsyncCheckResult.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaMediaAsyncCheckResult.java @@ -2,7 +2,11 @@ import cn.binarywang.wx.miniapp.json.WxMaGsonBuilder; import com.google.gson.annotations.SerializedName; +import com.thoughtworks.xstream.annotations.XStreamAlias; +import com.thoughtworks.xstream.annotations.XStreamConverter; +import lombok.Builder; import lombok.Data; +import me.chanjar.weixin.common.util.xml.XStreamCDataConverter; import java.io.Serializable; @@ -19,6 +23,60 @@ public class WxMaMediaAsyncCheckResult implements Serializable { @SerializedName("trace_id") private String traceId; + /** + * 综合结果 + */ + @Data + @Builder + @XStreamAlias("result") + public static class ResultBean implements Serializable { + /** + * suggest : risky + * label : 20001 + */ + @SerializedName("suggest") + @XStreamAlias("suggest") + @XStreamConverter(value = XStreamCDataConverter.class) + private String suggest; + @SerializedName("label") + @XStreamAlias("label") + @XStreamConverter(value = XStreamCDataConverter.class) + private String label; + } + + /** + * 详细检测结果 + */ + @Data + @Builder + @XStreamAlias("detail") + public static class DetailBean implements Serializable { + /** + * strategy : content_model + * errcode : 0 + * suggest : risky + * label : 20006 + * prob : 90 + */ + @SerializedName("strategy") + @XStreamAlias("strategy") + @XStreamConverter(value = XStreamCDataConverter.class) + private String strategy; + @SerializedName("errcode") + @XStreamAlias("errcode") + private Integer errcode; + @SerializedName("suggest") + @XStreamAlias("suggest") + @XStreamConverter(value = XStreamCDataConverter.class) + private String suggest; + @SerializedName("label") + @XStreamAlias("label") + @XStreamConverter(value = XStreamCDataConverter.class) + private String label; + @SerializedName("prob") + @XStreamAlias("prob") + private Integer prob; + } public static WxMaMediaAsyncCheckResult fromJson(String json) { return WxMaGsonBuilder.create().fromJson(json, WxMaMediaAsyncCheckResult.class); diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaMessage.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaMessage.java index aa9fd868d..e34d63cd6 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaMessage.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaMessage.java @@ -7,6 +7,7 @@ import com.google.gson.annotations.SerializedName; import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamConverter; +import com.thoughtworks.xstream.annotations.XStreamImplicit; import lombok.Data; import me.chanjar.weixin.common.error.WxRuntimeException; import me.chanjar.weixin.common.util.XmlUtils; @@ -18,6 +19,7 @@ import java.io.InputStream; import java.io.Serializable; import java.nio.charset.StandardCharsets; +import java.util.List; import java.util.Map; /** @@ -144,6 +146,29 @@ public class WxMaMessage implements Serializable { @XStreamConverter(value = XStreamCDataConverter.class) private String statusCode; + /** + * 异步校验图片/音频内容安全 接口版本 + * @since 2.0 + */ + @SerializedName("version") + @XStreamAlias("version") + private Integer version; + /** + * 异步校验图片/音频内容安全 综合结果 + * @since 2.0 + */ + @SerializedName("result") + @XStreamAlias("result") + private WxMaMediaAsyncCheckResult.ResultBean result; + /** + * 异步校验图片/音频内容安全 详细检测结果 + * @since 2.0 + */ + @SerializedName("detail") + @XStreamAlias("detail") + @XStreamImplicit + private List detail; + @SerializedName("Scene") @XStreamAlias("Scene") private Integer scene; diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaUserInfo.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaUserInfo.java index e2f67a771..da1126fd0 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaUserInfo.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaUserInfo.java @@ -12,7 +12,6 @@ public class WxMaUserInfo implements Serializable { private static final long serialVersionUID = 6719822331555402137L; - private String openId; private String nickName; private String gender; private String language; diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/cloud/WxCloudSendSmsV2Result.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/cloud/WxCloudSendSmsV2Result.java new file mode 100644 index 000000000..eacee01b2 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/cloud/WxCloudSendSmsV2Result.java @@ -0,0 +1,44 @@ +package cn.binarywang.wx.miniapp.bean.cloud; + +import cn.binarywang.wx.miniapp.bean.WxMaBaseResponse; +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + +/** + * 发送携带 URL Link 的短信结果 + * + * @author liming1019 + * @date 2022-07-26 + */ +@Data +public class WxCloudSendSmsV2Result extends WxMaBaseResponse implements Serializable { + private static final long serialVersionUID = 4273038291300329985L; + + @SerializedName("send_status_list") + private List sendStatusList; + + @NoArgsConstructor + @Data + public static class SendStatus implements Serializable { + private static final long serialVersionUID = 5765836923681051366L; + + @SerializedName("serial_no") + private String serialNo; + + @SerializedName("phone_number") + private String phoneNumber; + + @SerializedName("code") + private String code; + + @SerializedName("message") + private String message; + + @SerializedName("iso_code") + private String isoCode; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/cloud/request/WxCloudSendSmsV2Request.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/cloud/request/WxCloudSendSmsV2Request.java new file mode 100644 index 000000000..67f926c1f --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/cloud/request/WxCloudSendSmsV2Request.java @@ -0,0 +1,41 @@ +package cn.binarywang.wx.miniapp.bean.cloud.request; + +import com.google.gson.annotations.SerializedName; +import lombok.Builder; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * 发送携带 URL Link 的短信请求 + * + * @author liming1019 + * @date 2022-07-26 + */ +@Data +@Builder +public class WxCloudSendSmsV2Request implements Serializable { + private static final long serialVersionUID = 8917033507660980594L; + + @SerializedName("env") + private String env; + + @SerializedName("url_link") + private String urlLink; + + @SerializedName("template_id") + private String templateId; + + @SerializedName("template_param_list") + private List templateParamList; + + @SerializedName("phone_number_list") + private List phoneNumberList; + + @SerializedName("use_short_name") + private Boolean useShortName; + + @SerializedName("resource_appid") + private String resourceAppid; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeVersionInfo.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeVersionInfo.java new file mode 100644 index 000000000..32999382f --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/code/WxMaCodeVersionInfo.java @@ -0,0 +1,91 @@ +package cn.binarywang.wx.miniapp.bean.code; + +import cn.binarywang.wx.miniapp.json.WxMaGsonBuilder; +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 查询小程序版本信息 + * + * @author LeonXi + * @since 2022-04-13 16:45 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class WxMaCodeVersionInfo implements Serializable { + + private static final long serialVersionUID = 6929700728659511688L; + + /** + * 体验版信息 + */ + @SerializedName("exp_info") + private ExpInfo expInfo; + + /** + * 线上版信息 + */ + @SerializedName("release_info") + private ReleaseInfo releaseInfo; + + public static WxMaCodeVersionInfo fromJson(String json) { + return WxMaGsonBuilder.create().fromJson(json, WxMaCodeVersionInfo.class); + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class ExpInfo implements Serializable { + + private static final long serialVersionUID = 6315578419554592943L; + + /** + * 提交体验版的时间 + */ + @SerializedName("exp_time") + private Long expTime; + + /** + * 体验版版本信息 + */ + @SerializedName("exp_version") + private String expVersion; + + /** + * 体验版版本描述 + */ + @SerializedName("exp_desc") + private String expDesc; + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class ReleaseInfo implements Serializable { + + private static final long serialVersionUID = 2098307354673939939L; + + /** + * 发布线上版的时间 + */ + @SerializedName("release_time") + private Long releaseTime; + + /** + * 线上版版本信息 + */ + @SerializedName("release_version") + private String releaseVersion; + + /** + * 线上版本描述 + */ + @SerializedName("release_desc") + private String releaseDesc; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/FollowWaybillRequest.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/FollowWaybillRequest.java new file mode 100644 index 000000000..92add53aa --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/FollowWaybillRequest.java @@ -0,0 +1,103 @@ +package cn.binarywang.wx.miniapp.bean.delivery; + + +import cn.binarywang.wx.miniapp.json.WxMaGsonBuilder; +import com.google.gson.annotations.SerializedName; +import java.io.Serializable; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +/** + *
+ * 传运单接口 follow_waybil
+ *
+ * 商户使用此接口向微信提供某交易单号对应的运单号。微信后台会跟踪运单的状态变化,在关键物流节点给下单用户推送消息通知。
+ * 
+ * + * @author boris + * @since 2022-04-01 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class FollowWaybillRequest implements Serializable { + + private static final long serialVersionUID = -7538739003766268386L; + + + /** + * 用户openid + *
+   * 是否必填: 是
+   * 描述: 用户openid
+   * 
+ */ + @SerializedName("openid") + private String openid; + + /** + * 寄件人手机号 + *
+   * 是否必填: 否
+   * 描述:
+   * 
+ */ + @SerializedName("sender_phone") + private String senderPhone; + + /** + * 收件人手机号 + *
+   * 是否必填: 否
+   * 描述:部分运力需要用户手机号作为查单依据
+   * 
+ */ + @SerializedName("receiver_phone") + private String receiverPhone; + + /** + * 运单ID + *
+   * 是否必填: 是
+   * 
+ */ + @SerializedName("waybill_id") + private String waybillId; + + /** + * 交易单号(微信支付生成的交易单号,一般以420开头) + *
+   * 是否必填: 是
+   * 
+ */ + @SerializedName("trans_id") + private String transId; + + + /** + * 点击落地页商品卡片跳转路径(建议为订单详情页path),不传默认跳转小程序首页。 + *
+   * 是否必填: 否
+   * 
+ */ + @SerializedName("order_detail_path") + private String orderDetailPath; + + /** + * 商品信息 + *
+   * 是否必填: 是
+   * 
+ */ + @SerializedName("goods_info") + private WaybillGoodsInfo goodsInfo; + + public String toJson() { + return WxMaGsonBuilder.create().toJson(this); + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/FollowWaybillResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/FollowWaybillResponse.java new file mode 100644 index 000000000..748f9465a --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/FollowWaybillResponse.java @@ -0,0 +1,34 @@ +package cn.binarywang.wx.miniapp.bean.delivery; + +import cn.binarywang.wx.miniapp.bean.WxMaBaseResponse; +import cn.binarywang.wx.miniapp.json.WxMaGsonBuilder; +import com.google.gson.annotations.SerializedName; +import java.io.Serializable; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + *
+ * 查运单接口 query_follow_trace 响应参数
+ * 
+ * + * @author boris + * @since 2022-04-01 + */ +@Data +@Accessors(chain = true) +public class FollowWaybillResponse extends WxMaBaseResponse implements Serializable { + + private static final long serialVersionUID = 3773007367000633663L; + + /** + * 查询id. + */ + @SerializedName("waybill_token") + private String waybillToken; + + + public static FollowWaybillResponse fromJson(String json) { + return WxMaGsonBuilder.create().fromJson(json, FollowWaybillResponse.class); + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/QueryFollowTraceRequest.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/QueryFollowTraceRequest.java new file mode 100644 index 000000000..600ea0f14 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/QueryFollowTraceRequest.java @@ -0,0 +1,46 @@ +package cn.binarywang.wx.miniapp.bean.delivery; + + +import cn.binarywang.wx.miniapp.json.WxMaGsonBuilder; +import com.google.gson.annotations.SerializedName; +import java.io.Serializable; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +/** + *
+ * 消息组件-查运单接口 query_follow_trace
+ *
+ * 商户在调用完trace_waybill接口后,可以使用本接口查询到对应运单的详情信息
+ * 
+ * + * @author boris + * @since 2022-04-01 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class QueryFollowTraceRequest implements Serializable { + + private static final long serialVersionUID = -7538739003766268386L; + + + /** + * 查询id + *
+   * 是否必填: 是
+   * 描述: 可以从 传运单接口 follow_waybill 取数据
+   * 
+ */ + @SerializedName("waybill_token") + private String waybillToken; + + public String toJson() { + return WxMaGsonBuilder.create().toJson(this); + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/QueryFollowTraceResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/QueryFollowTraceResponse.java new file mode 100644 index 000000000..a6e698d0d --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/QueryFollowTraceResponse.java @@ -0,0 +1,123 @@ +package cn.binarywang.wx.miniapp.bean.delivery; + +import cn.binarywang.wx.miniapp.bean.WxMaBaseResponse; +import cn.binarywang.wx.miniapp.json.WxMaGsonBuilder; +import com.google.gson.annotations.SerializedName; +import java.io.Serializable; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + *
+ * 消息组件-查运单接口 query_follow_trace 响应参数
+ *
+ * 商户在调用完follow_waybill/trace_waybill接口后,可以使用本接口查询到对应运单的详情信息
+ * 
+ * + * @author boris + * @since 2022-04-01 + */ +@Data +@Accessors(chain = true) +public class QueryFollowTraceResponse extends WxMaBaseResponse implements Serializable { + + private static final long serialVersionUID = 3773007367000633663L; + + /** + * 运单信息. + */ + @SerializedName("waybill_info") + private WaybillInfo waybillInfo; + + /** + * 商品信息 + */ + @SerializedName("shop_info") + private ShopInfo shopInfo; + + /** + * 运力信息. + */ + @SerializedName("delivery_info") + private DeliveryInfo deliveryInfo; + + + public static QueryFollowTraceResponse fromJson(String json) { + return WxMaGsonBuilder.create().fromJson(json, QueryFollowTraceResponse.class); + } + + /** + * 运单信息. + */ + @Data + @Accessors(chain = true) + public static class WaybillInfo implements Serializable { + + private static final long serialVersionUID = -3759074878713856529L; + + /** + * 运单状态 释义 + *
+     *
+     * 0	运单不存在或者未揽收
+     * 1	已揽件
+     * 2	运输中
+     * 3	派件中
+     * 4	已签收
+     * 5	异常
+     * 6	代签收
+     *
+     * 
+ */ + @SerializedName("status") + private Integer status; + + /** + * 查询id. + */ + @SerializedName("waybill_token") + private String waybillToken; + } + + /** + * 商品信息. + */ + @Data + @Accessors(chain = true) + public static class ShopInfo implements Serializable { + + private static final long serialVersionUID = -3759074878713856529L; + + /** + * 配送公司Id. + */ + @SerializedName("goods_info") + private WaybillGoodsInfo goodsInfo; + + + } + + + /** + * 运力信息. + */ + @Data + @Accessors(chain = true) + public static class DeliveryInfo implements Serializable { + + private static final long serialVersionUID = -3759074878713856529L; + + /** + * 配送公司Id. + */ + @SerializedName("delivery_id") + private String deliveryId; + + /** + * 运力公司名称. + */ + @SerializedName("delivery_name") + private String deliveryName; + + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/WaybillGoodsInfo.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/WaybillGoodsInfo.java index 709d316ec..8695efec1 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/WaybillGoodsInfo.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/WaybillGoodsInfo.java @@ -43,7 +43,7 @@ public static class GoodsItem { *
*/ @SerializedName("goods_name") - private Long goodsName; + private String goodsName; /** * 商品图片URL @@ -52,7 +52,7 @@ public static class GoodsItem { *
*/ @SerializedName("goods_img_url") - private Integer goodsImgUrl; + private String goodsImgUrl; } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/base/WxMaDeliveryBaseRequest.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/base/WxMaDeliveryBaseRequest.java index a139ea907..b01b04e76 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/base/WxMaDeliveryBaseRequest.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/delivery/base/WxMaDeliveryBaseRequest.java @@ -113,7 +113,8 @@ public String getDeliverySign() { str = str.concat(getShopOrderId()); } str = str.concat(getAppSecret()); - return DigestUtils.sha1Hex(str); + this.deliverySign = DigestUtils.sha1Hex(str); + return this.deliverySign; } } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/request/WxMaExpressOrderShop.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/request/WxMaExpressOrderShop.java index 41c08f9e8..029f0d44b 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/request/WxMaExpressOrderShop.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/request/WxMaExpressOrderShop.java @@ -6,6 +6,7 @@ import lombok.NoArgsConstructor; import java.io.Serializable; +import java.util.List; /** * 商品信息对象 @@ -55,4 +56,14 @@ public class WxMaExpressOrderShop implements Serializable { @SerializedName("goods_count") private Integer goodsCount; + /** + * 商品详情列表 + *
+   * 是否必填: 否
+   * 描述: 适配多商品场景,用以消息落地页展示。(新规范,新接入商家建议用此字段)
+   * 
+ */ + @SerializedName("detail_list") + private List detailList; + } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/request/WxMaExpressOrderShopDetail.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/request/WxMaExpressOrderShopDetail.java new file mode 100644 index 000000000..638bca6dd --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/express/request/WxMaExpressOrderShopDetail.java @@ -0,0 +1,51 @@ +package cn.binarywang.wx.miniapp.bean.express.request; + + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + + +/** + * 商品详情 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class WxMaExpressOrderShopDetail implements Serializable { + + private static final long serialVersionUID = 5988620921216969796L; + + /** + * 商品名称 + *
+   * 是否必填: 否
+   * 描述: 最多40汉字
+   * 
+ */ + @SerializedName("goods_name") + private String goodsName; + + /** + * 商品图片url + *
+   * 是否必填: 否
+   * 
+ */ + @SerializedName("goods_img_url") + private String goodsImgUrl; + + /** + * 商品详情描述 + *
+   * 是否必填: 否
+   * 描述: 最多40汉字
+   * 
+ */ + @SerializedName("goods_desc") + private String goodsDesc; + +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/live/WxMaLiveGoodInfo.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/live/WxMaLiveGoodInfo.java index 3ef043495..7db60d215 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/live/WxMaLiveGoodInfo.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/live/WxMaLiveGoodInfo.java @@ -27,4 +27,10 @@ public class WxMaLiveGoodInfo implements Serializable { * https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/industry/liveplayer/pendant.html */ private List goodsKey; + + + /** + * 当商品为第三方小程序的商品则填写为对应第三方小程序的appid,自身小程序商品则为'' + */ + private String thirdPartyAppid; } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/live/WxMaLiveResult.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/live/WxMaLiveResult.java index dfb7b1e48..40e649dc3 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/live/WxMaLiveResult.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/live/WxMaLiveResult.java @@ -74,6 +74,11 @@ public static class Goods implements Serializable { */ @SerializedName("third_party_tag") private String thirdPartyTag; + + /** + * 当商品为第三方小程序的商品则填写为对应第三方小程序的appid,自身小程序商品则为'' + */ + private String thirdPartyAppid; } /** diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/live/WxMaLiveSharedCode.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/live/WxMaLiveSharedCode.java new file mode 100644 index 000000000..f27dba87b --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/live/WxMaLiveSharedCode.java @@ -0,0 +1,25 @@ +package cn.binarywang.wx.miniapp.bean.live; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; + +import java.io.Serializable; + +public class WxMaLiveSharedCode implements Serializable { + private static final long serialVersionUID = 8525117884393611947L; + /** + * 分享二维码 + */ + @SerializedName("cdnUrl") + private String cdnUrl; + /** + * 分享路径 + */ + @SerializedName("pagePath") + private String pagePath; + /** + * 分享海报 + */ + @SerializedName("posterUrl") + private String posterUrl; +} \ No newline at end of file diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/MinishopShopCat.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/MinishopShopCat.java new file mode 100644 index 000000000..54015f2ed --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/MinishopShopCat.java @@ -0,0 +1,23 @@ +package cn.binarywang.wx.miniapp.bean.product; + +import com.google.gson.annotations.SerializedName; +import java.io.Serializable; +import lombok.Data; + +/** + * 店铺的商品分类 + */ +@Data +public class MinishopShopCat implements Serializable { + private static final long serialVersionUID = 4179473856929659641L; + + @SerializedName("cat_id") + private Integer shopCatId; + + private String shopCatName; + + private Integer fShopCatId; + + @SerializedName("level") + private Integer catLevel; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMiniAfterSaleDetail.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMiniAfterSaleDetail.java new file mode 100644 index 000000000..edf074b4f --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMiniAfterSaleDetail.java @@ -0,0 +1,24 @@ +package cn.binarywang.wx.miniapp.bean.product; + +import com.google.gson.annotations.SerializedName; +import java.util.List; +import lombok.Data; + +/** + * @author leiin + * @date 2022/6/20 7:16 下午 + */ +@Data +public class WxMiniAfterSaleDetail { + @SerializedName("aftersale_order_list") + private List aftersaleOrderList; + @SerializedName("on_aftersale_order_cnt") + private Integer onAftersaleOrderCnt; + + @Data + public static class AfterSaleOrder { + @SerializedName("aftersale_order_id") + private Long aftersaleOrderId; + private Integer status; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMiniAfterSaleOrder.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMiniAfterSaleOrder.java new file mode 100644 index 000000000..c58e41bae --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMiniAfterSaleOrder.java @@ -0,0 +1,95 @@ +package cn.binarywang.wx.miniapp.bean.product; + +import com.google.gson.annotations.SerializedName; +import java.util.List; +import lombok.Data; + +/** + * @author leiin + * @date 2022/7/11 20:33 + */ +@Data +public class WxMiniAfterSaleOrder { + @SerializedName("order_id") + private Long orderId; + @SerializedName("status") + private String status; + @SerializedName("openid") + private String openid; + @SerializedName("original_order_id") + private Long originalOrderId; + @SerializedName("product_info") + private AfterSaleProductInfo productInfo; + + private AfterSaleDetails details; + @SerializedName("refund_info") + private RefundInfo refundInfo; + @SerializedName("return_info") + private ReturnInfo returnInfo; + @SerializedName("merchant_upload_info") + private MerchantUploadInfo merchantUploadInfo; + @SerializedName("create_time") + private Long createTime; + @SerializedName("update_time") + private Long updateTime; + @SerializedName("reason") + private String reason; + @SerializedName("refund_resp") + private RefundResp refundResp; + private String type; + + @Data + public static class AfterSaleProductInfo { + @SerializedName("product_id") + private Long productId; + @SerializedName("sku_id") + private Long skuId; + @SerializedName("count") + private Integer count; + } + + @Data + public static class AfterSaleDetails { + + @SerializedName("num") + private Integer num; + @SerializedName("desc") + private String desc; + @SerializedName("cancel_time") + private Long cancelTime; + @SerializedName("prove_imgs") + private List proveImgs; + @SerializedName("tel_number") + private String telNumber; + } + + @Data + public static class RefundInfo { + private Long amount; + } + + @Data + public static class ReturnInfo { + @SerializedName("delivery_id") + private String deliveryId; + @SerializedName("waybill_id") + private String waybillId; + @SerializedName("delivery_name") + private String deliveryName; + } + + @Data + public static class MerchantUploadInfo { + @SerializedName("reject_reason") + private String rejectReason; + @SerializedName("refund_certificates") + private List refundCertificates; + } + + @Data + public static class RefundResp { + private String code; + private Integer ret; + private String message; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMiniBatchGetAfterSaleOrderResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMiniBatchGetAfterSaleOrderResponse.java new file mode 100644 index 000000000..504336678 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMiniBatchGetAfterSaleOrderResponse.java @@ -0,0 +1,16 @@ +package cn.binarywang.wx.miniapp.bean.product; + +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopBaseResponse; +import com.google.gson.annotations.SerializedName; +import java.util.List; +import lombok.Data; + +/** + * @author leiin + * @date 2022/7/11 20:59 + */ +@Data +public class WxMiniBatchGetAfterSaleOrderResponse extends WxMaShopBaseResponse { + @SerializedName("after_sale_order_list") + private List afterSaleOrderList; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMiniGetAfterSaleOrderResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMiniGetAfterSaleOrderResponse.java new file mode 100644 index 000000000..06586176e --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMiniGetAfterSaleOrderResponse.java @@ -0,0 +1,15 @@ +package cn.binarywang.wx.miniapp.bean.product; + +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopBaseResponse; +import com.google.gson.annotations.SerializedName; +import lombok.Data; + +/** + * @author leiin + * @date 2022/7/11 20:58 + */ +@Data +public class WxMiniGetAfterSaleOrderResponse extends WxMaShopBaseResponse { + @SerializedName("after_sale_order") + private WxMiniAfterSaleOrder afterSaleOrder; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMiniOrderAfterSaleDetail.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMiniOrderAfterSaleDetail.java new file mode 100644 index 000000000..b5bfbe795 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMiniOrderAfterSaleDetail.java @@ -0,0 +1,24 @@ +package cn.binarywang.wx.miniapp.bean.product; + +import com.google.gson.annotations.SerializedName; +import java.util.List; +import lombok.Data; + +/** + * @author leiin + * @date 2022/6/20 7:16 下午 + */ +@Data +public class WxMiniOrderAfterSaleDetail { + @SerializedName("aftersale_order_list") + private List aftersaleOrderList; + @SerializedName("on_aftersale_order_cnt") + private Integer onAftersaleOrderCnt; + + @Data + public static class AfterSaleOrder { + @SerializedName("aftersale_order_id") + private Long aftersaleOrderId; + private Integer status; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMiniOrderDeliveryRequest.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMiniOrderDeliveryRequest.java new file mode 100644 index 000000000..3307a1161 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMiniOrderDeliveryRequest.java @@ -0,0 +1,41 @@ +package cn.binarywang.wx.miniapp.bean.product; + +import com.google.gson.annotations.SerializedName; +import java.io.Serializable; +import java.util.List; +import lombok.Data; + +/** + * @author leiin + * @date 2022/7/14 19:05 + */ +@Data +public class WxMiniOrderDeliveryRequest { + @SerializedName("order_id") + private Long orderId; + @SerializedName("delivery_list") + private List deliveryList; + + @Data + public static class DeliveryListBean implements Serializable { + @SerializedName("delivery_id") + private String deliveryId; + @SerializedName("is_all_product") + private Boolean isAllProduct; + @SerializedName("waybill_id") + private String waybillId; + @SerializedName("product_infos") + private List productInfoList; + } + + @Data + public static class ProductInfosBean implements Serializable { + + @SerializedName("product_id") + private String productId; + @SerializedName("sku_id") + private String skuId; + @SerializedName("product_cnt") + private Integer productCnt; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopAddGoodsSkuData.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopAddGoodsSkuData.java new file mode 100644 index 000000000..664514078 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopAddGoodsSkuData.java @@ -0,0 +1,16 @@ +package cn.binarywang.wx.miniapp.bean.product; + +import com.google.gson.annotations.SerializedName; +import java.io.Serializable; +import lombok.Data; + +@Data +public class WxMinishopAddGoodsSkuData implements Serializable { + private static final long serialVersionUID = -2596988603027040989L; + @SerializedName("sku_id") + private Long skuId; + @SerializedName("out_sku_id") + private String outSkuId; + @SerializedName("create_time") + private String createTime; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopAddGoodsSpuData.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopAddGoodsSpuData.java new file mode 100644 index 000000000..bf9bb5c75 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopAddGoodsSpuData.java @@ -0,0 +1,16 @@ +package cn.binarywang.wx.miniapp.bean.product; + +import java.io.Serializable; +import lombok.Data; + +@Data +public class WxMinishopAddGoodsSpuData implements Serializable { + private static final long serialVersionUID = 2023708625713948192L; + private Long productId; + + private String outProductId; + + private String createTime; + + private String updateTime; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopAddressInfo.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopAddressInfo.java new file mode 100644 index 000000000..b5dd9e872 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopAddressInfo.java @@ -0,0 +1,28 @@ +package cn.binarywang.wx.miniapp.bean.product; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; + +/** + * @author leiin + * @date 2022/6/20 7:32 下午 + */ +@Data +public class WxMinishopAddressInfo { + @SerializedName("user_name") + private String userName; + @SerializedName("postal_code") + private String postalCode; + @SerializedName("province_name") + private String provinceName; + @SerializedName("city_name") + private String cityName; + @SerializedName("county_name") + private String countyName; + @SerializedName("detail_info") + private String detailInfo; + @SerializedName("national_code") + private String nationalCode; + @SerializedName("tel_number") + private String telNumber; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopDeliveryCompany.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopDeliveryCompany.java new file mode 100644 index 000000000..7534a9455 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopDeliveryCompany.java @@ -0,0 +1,12 @@ +package cn.binarywang.wx.miniapp.bean.product; + +import java.io.Serializable; +import lombok.Data; + +@Data +public class WxMinishopDeliveryCompany implements Serializable { + private static final long serialVersionUID = 3736970376549639779L; + private String deliveryId; + + private String deliveryName; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopDeliveryInfo.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopDeliveryInfo.java new file mode 100644 index 000000000..1a9f844c1 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopDeliveryInfo.java @@ -0,0 +1,62 @@ +package cn.binarywang.wx.miniapp.bean.product; + +import com.google.gson.annotations.SerializedName; +import java.util.List; +import lombok.Data; + +/** + * @author leiin + * @date 2022/6/20 7:28 下午 + */ +@Data +public class WxMinishopDeliveryInfo { + @SerializedName("address_info") + private WxMinishopAddressInfo addressInfo; + @SerializedName("delivery_method") + private String deliveryMethod; + @SerializedName("delivery_product_info") + private List deliveryProductInfo; + @SerializedName("ship_done_time") + private Long shipDoneTime; + @SerializedName("insurance_info") + private InsuranceInfo insuranceInfo; + @SerializedName("deliver_type") + private String deliverType; + @SerializedName("offline_delivery_time") + private Long offlineDeliveryTime; + @SerializedName("offline_pickup_time") + private Long offlinePickupTime; + + @Data + public static class DeliveryProductInfo { + @SerializedName("waybill_id") + private String waybillId; + @SerializedName("delivery_id") + private String deliveryId; + @SerializedName("delivery_time") + private String deliveryTime; + @SerializedName("deliver_type") + private String deliverType; + @SerializedName("delivery_address") + private WxMinishopAddressInfo deliveryAddress; + @SerializedName("product_infos") + private List productInfos; + } + + @Data + public static class InsuranceInfo { + private String type; + @SerializedName("insurance_price") + private Long insurancePrice; + } + + @Data + public static class ProductInfo { + @SerializedName("product_id") + private Long productId; + @SerializedName("sku_id") + private Long skuId; + @SerializedName("product_cnt") + private Long productCnt; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopGetBrandResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopGetBrandResponse.java new file mode 100644 index 000000000..1e9e4862e --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopGetBrandResponse.java @@ -0,0 +1,35 @@ +package cn.binarywang.wx.miniapp.bean.product; + +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopBaseResponse; +import com.google.gson.annotations.SerializedName; +import java.util.List; +import lombok.Data; + +/** + * @author leiin + * @date 2022/7/8 3:46 下午 + */ +@Data +public class WxMinishopGetBrandResponse extends WxMaShopBaseResponse { + private List brands; + + @Data + public static class MinishopBrandItem { + @SerializedName("first_cat_id") + private Integer firstCatId; + @SerializedName("second_cat_id") + private Integer secondCatId; + @SerializedName("third_cat_id") + private Integer thirdCatId; + @SerializedName("brand_info") + private MinishopBrandInfo brandInfo; + } + + @Data + public static class MinishopBrandInfo { + @SerializedName("brand_id") + private Long brandId; + @SerializedName("brand_name") + private String brandName; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopGetCategoryResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopGetCategoryResponse.java new file mode 100644 index 000000000..55954d8b3 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopGetCategoryResponse.java @@ -0,0 +1,30 @@ +package cn.binarywang.wx.miniapp.bean.product; + +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopBaseResponse; +import com.google.gson.annotations.SerializedName; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @author leiin + * @date 2022/7/8 3:39 下午 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class WxMinishopGetCategoryResponse extends WxMaShopBaseResponse { + @SerializedName("cat_list") + private List catList; + + @Data + public static class MinishopCatItem { + + @SerializedName("cat_id") + private Integer catId; + + @SerializedName("f_cat_id") + private Integer fCatId; + + private String name; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopGetFrightTemplateResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopGetFrightTemplateResponse.java new file mode 100644 index 000000000..9b79c1e3f --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopGetFrightTemplateResponse.java @@ -0,0 +1,26 @@ +package cn.binarywang.wx.miniapp.bean.product; + +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopBaseResponse; +import com.google.gson.annotations.SerializedName; +import java.util.List; +import lombok.Data; + +/** + * @author leiin + * @date 2022/7/8 3:46 下午 + */ +@Data +public class WxMinishopGetFrightTemplateResponse extends WxMaShopBaseResponse { + @SerializedName("template_list") + private List templateList; + + @Data + public static class MinishopFeightTemplateItem { + @SerializedName("template_id") + private Long templateId; + private String name; + @SerializedName("valuation_type") + private Integer valuationType; + + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopGoodsSkuAttr.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopGoodsSkuAttr.java new file mode 100644 index 000000000..5b0b2735e --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopGoodsSkuAttr.java @@ -0,0 +1,25 @@ +package cn.binarywang.wx.miniapp.bean.product; + +import com.google.gson.JsonObject; +import com.google.gson.annotations.SerializedName; +import java.io.Serializable; +import lombok.Data; + +@Data +public class WxMinishopGoodsSkuAttr implements Serializable { + private static final long serialVersionUID = -7274443170526394680L; + + @SerializedName("attr_key") + private String attrKey; + + @SerializedName("attr_value") + private String attrValue; + + public JsonObject toJsonObject() { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("attr_key", attrKey); + jsonObject.addProperty("attr_value", attrValue); + + return jsonObject; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopOrderDetail.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopOrderDetail.java new file mode 100644 index 000000000..09da6dd58 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopOrderDetail.java @@ -0,0 +1,48 @@ +package cn.binarywang.wx.miniapp.bean.product; + +import com.google.gson.annotations.SerializedName; +import java.io.Serializable; +import java.util.List; +import lombok.Data; + +/** + * @author leiin + * @date 2021/3/23 + */ +@Data +public class WxMinishopOrderDetail implements Serializable { + private static final long serialVersionUID = 3325843289672341160L; + + /** + * 下单商品信息 + *
+   * 是否必填:是
+   * 
+ */ + @SerializedName("product_infos") + private List productInfos; + + /** + * 支付信息 (当作为返回结果,payorder时action_type!=6时存在) + *
+   * 是否必填:
+   * 
+ */ + @SerializedName("pay_info") + private WxMinishopPayInfo payInfo; + + /** + * 价格信息 + *
+   * 是否必填:
+   * 
+ */ + @SerializedName("price_info") + private WxMinishopPriceInfo priceInfo; + + /** + * 必须调过发货接口才会存在这个字段 + */ + @SerializedName("delivery_info") + private WxMinishopDeliveryInfo deliveryInfo; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopOrderDetailResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopOrderDetailResponse.java new file mode 100644 index 000000000..aa2996ca6 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopOrderDetailResponse.java @@ -0,0 +1,19 @@ +package cn.binarywang.wx.miniapp.bean.product; + +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopBaseResponse; +import lombok.Data; + +/** + * 获取订单详情 回包结构 + * + * @author leiin + * @date 2022/6/20 7:09 下午 + */ +@Data +public class WxMinishopOrderDetailResponse extends WxMaShopBaseResponse { + + /** + * 订单结构 + */ + private WxMinishopOrderResult order; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopOrderListResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopOrderListResponse.java new file mode 100644 index 000000000..ecb4dfd70 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopOrderListResponse.java @@ -0,0 +1,17 @@ +package cn.binarywang.wx.miniapp.bean.product; + +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopBaseResponse; +import com.google.gson.annotations.SerializedName; +import java.util.List; +import lombok.Data; + +/** + * @author leiin + * @date 2022/6/20 7:09 下午 + */ +@Data +public class WxMinishopOrderListResponse extends WxMaShopBaseResponse { + private List orders; + @SerializedName("total_num") + private Long totalNum; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopOrderResult.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopOrderResult.java new file mode 100644 index 000000000..9fb817a6e --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopOrderResult.java @@ -0,0 +1,60 @@ +package cn.binarywang.wx.miniapp.bean.product; + +import com.google.gson.annotations.SerializedName; +import java.io.Serializable; +import lombok.Data; + +/** + * @author leiin + * @date 2021/3/23 + */ +@Data +public class WxMinishopOrderResult implements Serializable { + private static final long serialVersionUID = -2665426592693969921L; + + /** + * 交易组件平台订单ID + */ + @SerializedName("order_id") + private Long orderId; + + /** + * 订单状态 + */ + @SerializedName("status") + private Integer status; + + @SerializedName("create_time") + private String createTime; + + @SerializedName("update_time") + private String updateTime; + /** + * 订单详情 + */ + @SerializedName("order_detail") + private WxMinishopOrderDetail orderDetail; + + @SerializedName("aftersale_detail") + private WxMiniOrderAfterSaleDetail afterSaleDetail; + + /** + * 商家小程序该订单的用户id + */ + @SerializedName("openid") + private String openid; + + @SerializedName("ext_info") + private ExtInfo extInfo; + + @SerializedName("order_type") + private Integer orderType; + + @Data + public static class ExtInfo { + @SerializedName("customer_notes") + private String customerNotes; + @SerializedName("merchant_notes") + private String merchantNotes; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopPayInfo.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopPayInfo.java new file mode 100644 index 000000000..5acb048a6 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopPayInfo.java @@ -0,0 +1,54 @@ +package cn.binarywang.wx.miniapp.bean.product; + +import com.google.gson.annotations.SerializedName; +import java.io.Serializable; +import lombok.Data; + +/** + * @author leiin + * @date 2021/3/23 + */ +@Data +public class WxMinishopPayInfo implements Serializable { + private static final long serialVersionUID = 687488209024968647L; + + @SerializedName("pay_method") + private String payMethod; + + /** + * 预支付ID + *
+   * 是否必填:是
+   * 
+ */ + @SerializedName("prepay_id") + private String prepayId; + + /** + * 预付款时间(拿到prepay_id的时间) + *
+   * 是否必填:是
+   * 
+ */ + @SerializedName("prepay_time") + private String prepayTime; + + // 以下字段仅作为返回数据 + /** + * 支付ID,调过同步订单支付结果且action_type=1时才存在 + *
+   * 是否必填:
+   * 
+ */ + @SerializedName("transaction_id") + private String transactionId; + + /** + * 付款时间(拿到transaction_id的时间) + *
+   * 是否必填:
+   * 
+ */ + @SerializedName("pay_time") + private String payTime; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopPriceInfo.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopPriceInfo.java new file mode 100644 index 000000000..ba146e8e1 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopPriceInfo.java @@ -0,0 +1,44 @@ +package cn.binarywang.wx.miniapp.bean.product; + +import com.google.gson.annotations.SerializedName; +import java.io.Serializable; +import lombok.Data; + +/** + * @author leiin + * @date 2021/3/23 + */ +@Data +public class WxMinishopPriceInfo implements Serializable { + private static final long serialVersionUID = 1588840927992523263L; + + @SerializedName("product_price") + private Integer productPrice; + /** + * 该订单最终的金额(单位:分) + *
+   * 是否必填:是
+   * 
+ */ + @SerializedName("order_price") + private Integer orderPrice; + /** + * 运费(单位:分) + *
+   * 是否必填:是
+   * 
+ */ + @SerializedName("freight") + private Integer freight; + /** + * 优惠金额(单位:分) + *
+   * 是否必填:否
+   * 
+ */ + @SerializedName("discounted_price") + private Integer discountedPrice; + + @SerializedName("is_discounted") + private Boolean isDiscounted; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopProductInfo.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopProductInfo.java new file mode 100644 index 000000000..7342a2c29 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopProductInfo.java @@ -0,0 +1,71 @@ +package cn.binarywang.wx.miniapp.bean.product; + +import com.google.gson.annotations.SerializedName; +import java.io.Serializable; +import java.util.List; +import lombok.Data; + +/** + * @author leiin + * @date 2021/3/23 + */ +@Data +public class WxMinishopProductInfo implements Serializable { + private static final long serialVersionUID = 8979181840150112093L; + /** + * 交易组件平台内部商品ID + */ + @SerializedName("product_id") + private Integer productId; + + @SerializedName("out_product_id") + private String outProductId; + + /** + * 交易组件平台内部skuID,可填0(如果这个product_id下没有sku) + */ + @SerializedName("sku_id") + private Integer skuId; + + @SerializedName("out_sku_id") + private String outSkuId; + /** + * 购买的数量 + *
+   * 是否必填:是
+   * 
+ */ + @SerializedName("sku_cnt") + private Integer skuCnt; + + @SerializedName("on_aftersale_sku_cnt") + private Integer onAftersaleSkuCnt; + + @SerializedName("finish_aftersale_sku_cnt") + private Integer finishAftersaleSkuCnt; + /** + * 生成订单时商品的标题 + *
+   * 是否必填:是
+   * 
+ */ + @SerializedName("title") + private String title; + @SerializedName("thumb_img") + private String thumbImg; + + @SerializedName("sku_attrs") + private List skuAttrs; + /** + * 生成订单时商品的售卖价(单位:分) + *
+   * 是否必填:是
+   * 
+ */ + @SerializedName("sale_price") + private Integer salePrice; + + @SerializedName("market_price") + private Integer marketPrice; +} + diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopResult.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopResult.java new file mode 100644 index 000000000..c47fcddd9 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopResult.java @@ -0,0 +1,14 @@ +package cn.binarywang.wx.miniapp.bean.product; + +import java.io.Serializable; +import lombok.Data; + +@Data +public class WxMinishopResult implements Serializable { + private static final long serialVersionUID = 4323118714581265968L; + private Integer errcode; + + private String errmsg; + + private T data; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopSku.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopSku.java new file mode 100644 index 000000000..9ac563615 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopSku.java @@ -0,0 +1,44 @@ +package cn.binarywang.wx.miniapp.bean.product; + +import com.google.gson.annotations.SerializedName; +import java.io.Serializable; +import java.util.List; +import lombok.Data; + +@Data +public class WxMinishopSku implements Serializable { + private static final long serialVersionUID = 12373392723136246L; + + @SerializedName("product_id") + private Long productId; + + @SerializedName("out_product_id") + private String outProductId; + + @SerializedName("out_sku_id") + private String outSkuId; + + @SerializedName("sku_id") + private Long skuId; + + @SerializedName("thumb_img") + private String thumbImg; + + @SerializedName("sale_price") + private Integer salePrice; + + @SerializedName("market_price") + private Integer marketPrice; + + @SerializedName("stock_num") + private Integer stockNum; + + @SerializedName("sku_code") + private String skuCode; + + @SerializedName("barcode") + private String barCode; + + @SerializedName("sku_attrs") + private List skuAttrs; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopSkuListResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopSkuListResponse.java new file mode 100644 index 000000000..a1713709e --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopSkuListResponse.java @@ -0,0 +1,14 @@ +package cn.binarywang.wx.miniapp.bean.product; + +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopBaseResponse; +import java.util.List; +import lombok.Data; + +/** + * @author leiin + * @date 2022/7/13 20:00 + */ +@Data +public class WxMinishopSkuListResponse extends WxMaShopBaseResponse { + private List skus; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopSpu.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopSpu.java new file mode 100644 index 000000000..b6fe85284 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopSpu.java @@ -0,0 +1,51 @@ +package cn.binarywang.wx.miniapp.bean.product; + +import com.google.gson.annotations.SerializedName; +import java.io.Serializable; +import java.util.List; +import lombok.Data; + +@Data +public class WxMinishopSpu implements Serializable { + private static final long serialVersionUID = 6689040014027161007L; + + @SerializedName("out_product_id") + private String outProductId; + + private String title; + + @SerializedName("sub_title") + private String subTitle; + + @SerializedName("head_img") + private List headImgs; + + @SerializedName("desc_info") + private DescInfo descInfo; + + @SerializedName("brand_id") + private Long brandId; + + @SerializedName("cats") + private List shopCats; + + private List attrs; + + private String model; + + @SerializedName("express_info") + private ExpressInfo expressInfo; + + private List skus; + + @Data + public static class DescInfo { + private List imgs; + } + + @Data + public static class ExpressInfo { + @SerializedName("template_id") + private Long templateId; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopSpuGet.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopSpuGet.java new file mode 100644 index 000000000..f40adc094 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopSpuGet.java @@ -0,0 +1,16 @@ +package cn.binarywang.wx.miniapp.bean.product; + +import java.io.Serializable; +import lombok.Data; + +/** + * @author leiin + * @date 2022/6/20 4:36 下午 + */ +@Data +public class WxMinishopSpuGet implements Serializable { + + private static final long serialVersionUID = -957810527714924409L; + + private WxMinishopSpu spu; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopSpuGetResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopSpuGetResponse.java new file mode 100644 index 000000000..94dff9b4e --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopSpuGetResponse.java @@ -0,0 +1,12 @@ +package cn.binarywang.wx.miniapp.bean.product; + +import lombok.Data; + +/** + * @author leiin + * @date 2022/6/20 4:46 下午 + */ +@Data +public class WxMinishopSpuGetResponse extends WxMinishopResult { + +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopSpuListResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopSpuListResponse.java new file mode 100644 index 000000000..a60d63000 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopSpuListResponse.java @@ -0,0 +1,17 @@ +package cn.binarywang.wx.miniapp.bean.product; + +import com.google.gson.annotations.SerializedName; +import java.util.List; +import lombok.Data; + +/** + * @author leiin + * @date 2022/6/20 4:46 下午 + */ +@Data +public class WxMinishopSpuListResponse extends WxMinishopResult { + @SerializedName("total_num") + private Long totalNum; + + private List spus; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopUpdateGoodsSkuData.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopUpdateGoodsSkuData.java new file mode 100644 index 000000000..446404e4a --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/product/WxMinishopUpdateGoodsSkuData.java @@ -0,0 +1,16 @@ +package cn.binarywang.wx.miniapp.bean.product; + +import com.google.gson.annotations.SerializedName; +import java.io.Serializable; +import lombok.Data; + +@Data +public class WxMinishopUpdateGoodsSkuData implements Serializable { + private static final long serialVersionUID = -2596988603027040989L; + @SerializedName("sku_id") + private Long skuId; + @SerializedName("out_sku_id") + private String outSkuId; + @SerializedName("update_time") + private String updateTime; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/WxMaPromotionInfo.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/WxMaPromotionInfo.java new file mode 100644 index 000000000..332e18720 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/WxMaPromotionInfo.java @@ -0,0 +1,24 @@ +package cn.binarywang.wx.miniapp.bean.shop; + +import com.google.gson.annotations.SerializedName; +import java.io.Serializable; +import lombok.Data; + +/** + * @author leiin + * @date 2022/6/18 3:14 下午 + */ +@Data +public class WxMaPromotionInfo implements Serializable { + + private static final long serialVersionUID = 2090629980847386450L; + + @SerializedName("finder_username") + private String finderUsername; + @SerializedName("finder_nickname") + private String finderNickname; + @SerializedName("sharer_openid") + private String sharerOpenid; + @SerializedName("live_start_time") + private String liveStartTime; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/WxMaShopCouponInfo.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/WxMaShopCouponInfo.java new file mode 100644 index 000000000..e04c362f3 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/WxMaShopCouponInfo.java @@ -0,0 +1,319 @@ +package cn.binarywang.wx.miniapp.bean.shop; + +import com.google.gson.annotations.SerializedName; +import java.io.Serializable; +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author leiin + * @date 2022/7/1 2:57 下午 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class WxMaShopCouponInfo implements Serializable { + + private static final long serialVersionUID = 5807154725645642700L; + + /** + * 是否必填:是 + * 说明:商家侧优惠券ID + */ + @SerializedName("out_coupon_id") + private String outCouponId; + /** + * 是否必填:是 + * 说明:优惠券类型 + */ + @SerializedName("type") + private Integer type; + /** + * 是否必填:是 + * 说明:优惠券推广类型 + */ + @SerializedName("promote_type") + private Integer promoteType; + + @SerializedName("coupon_info") + private CouponInfo couponInfo; + + // 返回参数 + /** + * 优惠券状态 + */ + @SerializedName("status") + private Integer status; + /** + * 创建时间 + */ + @SerializedName("create_time") + private Long createTime; + /** + * 更新时间 + */ + @SerializedName("update_time") + private Long updateTime; + + @SerializedName("coupon_stock") + private CouponStock couponStock; + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class CouponInfo implements Serializable { + + private static final long serialVersionUID = -7913225774910831745L; + + /** + * 是否必填:是 + * 说明:优惠券名 + */ + private String name; + + @SerializedName("promote_info") + private PromoteInfo promoteInfo; + + @SerializedName("discount_info") + private DiscountInfo discountInfo; + + @SerializedName("receive_info") + private ReceiveInfo receiveInfo; + + @SerializedName("valid_info") + private ValidInfo validInfo; + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class PromoteInfo { + @SerializedName("promote_type") + private Integer promoteType; + private PromoteFinder finder; + + @Data + public static class PromoteFinder { + private String nickname; + } + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class DiscountInfo { + + /** + * 是否必填: 否 + * 说明:折扣数,比如5.1折,则填5100,折扣券必需 + */ + @SerializedName("discount_num") + private Integer discountNum; + /** + * 是否必填: 否 + * 说明:减金额,单位为分,直减券、满减券必需 + */ + @SerializedName("discount_fee") + private Long discountFee; + + @SerializedName("discount_condition") + private DiscountCondition discountCondition; + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class DiscountCondition { + + /** + * 是否必填: 否 + * 说明:优惠条件所需的商品数 + */ + @SerializedName("product_cnt") + private Integer productCnt; + /** + * 是否必填: 否 + * 说明:优惠条件所需满足的金额 + */ + @SerializedName("product_price") + private Long productPrice; + /** + * 是否必填: 否 + * 说明:指定商品商家侧ID,商品券必需,最多128个 + */ + @SerializedName("out_product_ids") + private List outProductIds; + + @SerializedName("tradein_info") + private TradeinInfo tradeinInfo; + + @SerializedName("buyget_info") + private BuygetInfo buyget_info; + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class TradeinInfo { + + /** + * 是否必填:否 + * 说明:换购商品商家侧ID,换购券必需 + */ + @SerializedName("out_product_id") + private String outProductId; + /** + * 是否必填:否 + * 说明:需要支付的金额,单位分,换购券必需 + */ + @SerializedName("price") + private Long price; + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class BuygetInfo { + /** + * 是否必填:否 + * 说明:购买商品商家侧ID,买赠券必需 + */ + @SerializedName("buy_out_product_id") + private String buyOutProductId; + /** + * 是否必填:否 + * 说明:购买商品数,买赠券必需 + */ + @SerializedName("buy_product_cnt") + private Integer buyProductCnt; + /** + * 是否必填:否 + * 说明:赠送商品商家侧ID,买赠券必需 + */ + @SerializedName("get_out_product_id") + private String getOutProductId; + /** + * 是否必填:否 + * 说明:赠送商品数,买赠券必需 + */ + @SerializedName("get_product_cnt") + private Integer getProductCnt; + } + } + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class ReceiveInfo { + + /** + * 是否必填:是 + * 说明:领取开始时间 (秒级时间戳) + */ + @SerializedName("start_time") + private Long startTime; + /** + * 是否必填:是 + * 说明:领取结束时间 (秒级时间戳) + */ + @SerializedName("end_time") + private Long endTime; + /** + * 是否必填:是 + * 说明:个人限领张数,只做展示,领券回调时接入方判断有无超领。 + */ + @SerializedName("limit_num_one_person") + private Integer limitNumOnePerson; + /** + * 是否必填:是 + * 说明:总发放量,即初始库存数,只做展示,领券回调时接入方判断有无超领。 + */ + @SerializedName("total_num") + private Integer totalNum; + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class ValidInfo { + + /** + * 是否必填:是 + * 说明:有效期类型,1:商品指定时间区间,2:生效天数,3:生效秒数 + */ + @SerializedName("valid_type") + private Integer validType; + /** + * 是否必填:否 + * 说明:生效天数,有效期类型为2时必需 + */ + @SerializedName("valid_day_num") + private Integer validDayNum; + /** + * 是否必填:否 + * 说明:生效秒数,有效期类型为3时必需 + */ + @SerializedName("valid_second") + private Long validSecond; + /** + * 是否必填:否 + * 说明:生效开始时间,有效期类型为1时必需 + */ + @SerializedName("start_time") + private Long startTime; + /** + * 是否必填:否 + * 说明:生效结束时间,有效期类型为1时必需 + */ + @SerializedName("end_time") + private Long endTime; + } + + @Data + public static class CouponStock { + + /** + * 商家侧优惠券ID + */ + @SerializedName("out_coupon_id") + private String outCouponId; + /** + * 创建时间 + */ + @SerializedName("create_time") + private Long createTime; + /** + * 更新时间 + */ + @SerializedName("update_time") + private Long updateTime; + + @SerializedName("stock_info") + private StockInfo stockInfo; + + @Data + public static class StockInfo { + /** + * 优惠券库存剩余量 + */ + @SerializedName("issued_num") + private Integer issuedNum; + /** + * 优惠卷发放量 + */ + @SerializedName("receive_num") + private Integer receiveNum; + } + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/WxMaShopOrderDetail.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/WxMaShopOrderDetail.java index 661fa3208..c977d48f9 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/WxMaShopOrderDetail.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/WxMaShopOrderDetail.java @@ -14,6 +14,13 @@ public class WxMaShopOrderDetail implements Serializable { private static final long serialVersionUID = 3325843289672341160L; + + /** + * 推广员、分享员信息 + */ + @SerializedName("promotion_info") + private WxMaShopPromotionInfo promotionInfo; + /** * 下单商品信息 *
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/WxMaShopOrderInfo.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/WxMaShopOrderInfo.java
index b942bb6b5..006f41266 100644
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/WxMaShopOrderInfo.java
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/WxMaShopOrderInfo.java
@@ -84,4 +84,53 @@ public class WxMaShopOrderInfo implements Serializable {
   @SerializedName("address_info")
   private WxMaShopAddressInfo addressInfo;
 
+  /**
+   * 订单类型:0,普通单,1,二级商户单
+   * 
+   * 是否必填:是
+   * 
+ */ + @SerializedName("fund_type") + private Integer fundType; // 订单类型:0,普通单,1,二级商户单 + /** + * unix秒级时间戳,订单超时时间,取值:[15min, 1d] + *
+   * 是否必填:是
+   * 
+ */ + @SerializedName("expire_time") + private Long expireTime; // unix秒级时间戳,订单超时时间,取值:[15min, 1d] + /** + * 取值范围,[7,3 * 365],单位:天 + *
+   * 是否必填:选填
+   * 
+ */ + @SerializedName("aftersale_duration") + private Integer aftersaleDuration; // 取值范围,[7,3 * 365],单位:天 + /** + * 会影响主播归因、分享员归因等,从下单前置检查获取 + *
+   * 是否必填:是
+   * 
+ */ + @SerializedName("trace_id") + private String traceId; // 会影响主播归因、分享员归因等,从下单前置检查获取 + /** + * 默认退货地址,退货售后超时时,会让用户将货物寄往此地址 + *
+   * 是否必填:选填
+   * 
œ + */ + @SerializedName("default_receiving_address") + private WxMaShopAddressInfo defaultReceivingAddress; // 默认退货地址,退货售后超时时,会让用户将货物寄往此地址 + /** + * 生成的order_id以字符串形式返回 + *
+   * 是否必填:选填
+   * 
+ */ + @SerializedName("stringify_64bits_number") + private Boolean stringify64bitsNumber; // 生成的order_id以字符串形式返回 + } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/WxMaShopPayInfo.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/WxMaShopPayInfo.java index 7ea749e19..24d772c23 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/WxMaShopPayInfo.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/WxMaShopPayInfo.java @@ -21,6 +21,9 @@ public class WxMaShopPayInfo implements Serializable { @SerializedName("pay_method_type") private Integer payMethodType; + @SerializedName("pay_method") + private String payMethod; + /** * 预支付ID *
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/WxMaShopProductInfo.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/WxMaShopProductInfo.java
index b381b18f6..37898b243 100644
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/WxMaShopProductInfo.java
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/WxMaShopProductInfo.java
@@ -88,5 +88,8 @@ public class WxMaShopProductInfo implements Serializable {
    */
   @SerializedName("real_price")
   private Integer realPrice;
+
+  @SerializedName("sku_real_price")
+  private Integer skuRealPrice;
 }
 
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/WxMaShopPromotionInfo.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/WxMaShopPromotionInfo.java
new file mode 100644
index 000000000..b5c263ad1
--- /dev/null
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/WxMaShopPromotionInfo.java
@@ -0,0 +1,39 @@
+package cn.binarywang.wx.miniapp.bean.shop;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 推广员、分享员信息
+ *
+ * @author zhongjun
+ * @date 2022/5/17
+ **/
+@Data
+public class WxMaShopPromotionInfo implements Serializable {
+  private static final long serialVersionUID = -812058443344709898L;
+  /**
+   * 推广员唯一ID
+   */
+  @SerializedName("promoter_id")
+  private String promoterId;
+
+  /**
+   * 推广员视频号昵称
+   */
+  @SerializedName("finder_nickname")
+  private String finderNickname;
+  /**
+   * 推广员openid
+   */
+  @SerializedName("promoter_openid")
+  private String promoterOpenid;
+
+  /**
+   * 分享员openid
+   */
+  @SerializedName("sharer_openid")
+  private String sharerOpenid;
+}
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/request/WxMaShopAcceptReturnRequest.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/request/WxMaShopAcceptReturnRequest.java
new file mode 100644
index 000000000..58d08b4b4
--- /dev/null
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/request/WxMaShopAcceptReturnRequest.java
@@ -0,0 +1,43 @@
+package cn.binarywang.wx.miniapp.bean.shop.request;
+
+import com.google.gson.annotations.SerializedName;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author leiin
+ * @date 2022/6/28 11:39 上午
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class WxMaShopAcceptReturnRequest implements Serializable {
+  @SerializedName("out_aftersale_id")
+  private String outAftersaleId;
+  @SerializedName("aftersale_id")
+  private Long aftersaleId;
+  @SerializedName("address_info")
+  private RefundAddressInfo addressInfo;
+
+  @Data
+  public static class RefundAddressInfo {
+    @SerializedName("receiver_name")
+    private String receiverName;
+    @SerializedName("detailed_address")
+    private String detailedAddress;
+    @SerializedName("tel_number")
+    private String telNumber;
+    @SerializedName("country")
+    private String country;
+    @SerializedName("province")
+    private String province;
+    @SerializedName("city")
+    private String city;
+    @SerializedName("town")
+    private String town;
+  }
+}
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/request/WxMaShopAfterSaleAddRequest.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/request/WxMaShopAfterSaleAddRequest.java
index 47c33f1ae..f5a00aeb5 100644
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/request/WxMaShopAfterSaleAddRequest.java
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/request/WxMaShopAfterSaleAddRequest.java
@@ -33,6 +33,8 @@ public class WxMaShopAfterSaleAddRequest implements Serializable {
    * product_infos : [{"out_product_id":"234245","out_sku_id":"23424","product_cnt":5}]
    */
 
+  @SerializedName("order_id")
+  private Long orderId;
   @SerializedName("out_order_id")
   private String outOrderId;
   @SerializedName("out_aftersale_id")
@@ -41,8 +43,14 @@ public class WxMaShopAfterSaleAddRequest implements Serializable {
   private String openid;
   @SerializedName("type")
   private Integer type;
-  @SerializedName("create_time")
-  private String createTime;
+  @SerializedName("product_info")
+  private ProductInfosBean productInfo;
+  @SerializedName("orderamt")
+  private Long orderamt;
+  @SerializedName("refund_reason")
+  private String refundReason;
+  @SerializedName("refund_reason_type")
+  private Integer refundReasonType;
   @SerializedName("status")
   private Integer status;
   @SerializedName("finish_all_aftersale")
@@ -51,8 +59,8 @@ public class WxMaShopAfterSaleAddRequest implements Serializable {
   private String path;
   @SerializedName("refund")
   private Long refund;
-  @SerializedName("product_infos")
-  private List productInfos;
+  @SerializedName("media_list")
+  private UploadMediaList mediaList;
 
   @Data
   @Builder
@@ -72,4 +80,12 @@ public static class ProductInfosBean implements Serializable {
     @SerializedName("product_cnt")
     private Integer productCnt;
   }
+
+  @Data
+  public static class UploadMediaList {
+    private Integer type;
+    private String url;
+    @SerializedName("thumb_url")
+    private String thumbUrl;
+  }
 }
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/request/WxMaShopAfterSaleListRequest.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/request/WxMaShopAfterSaleListRequest.java
new file mode 100644
index 000000000..a0c01e8c8
--- /dev/null
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/request/WxMaShopAfterSaleListRequest.java
@@ -0,0 +1,36 @@
+package cn.binarywang.wx.miniapp.bean.shop.request;
+
+import com.google.gson.annotations.SerializedName;
+import java.io.Serializable;
+import java.util.List;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author leiin
+ * @date 2022/6/28 11:39 上午
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class WxMaShopAfterSaleListRequest implements Serializable {
+  @SerializedName("status")
+  private Integer status; //售后单状态,见 AfterSalesState
+  @SerializedName("out_order_id")
+  private String outOrderId; //售后单关联的外部订单号
+  @SerializedName("order_id")
+  private Long orderId; //售后单关联的微信侧订单号
+  @SerializedName("openid")
+  private String openid; //买家openid
+  @SerializedName("begin_create_time")
+  private Long beginCreateTime; //申请时间(单位毫秒)起始
+  @SerializedName("end_create_time")
+  private Long endCreateTime; //申请时间(单位毫秒)结束
+  @SerializedName("offset")
+  private Long offset; //本次拉取的起始位置(从0开始)
+  @SerializedName("limit")
+  private Integer limit; //本次拉取的大小(最大50)
+}
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/request/WxMaShopAfterSaleUpdateRequest.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/request/WxMaShopAfterSaleUpdateRequest.java
index d208b239e..f5679aeb3 100644
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/request/WxMaShopAfterSaleUpdateRequest.java
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/request/WxMaShopAfterSaleUpdateRequest.java
@@ -1,5 +1,6 @@
 package cn.binarywang.wx.miniapp.bean.shop.request;
 
+import cn.binarywang.wx.miniapp.bean.shop.request.WxMaShopAfterSaleAddRequest.UploadMediaList;
 import com.google.gson.annotations.SerializedName;
 import lombok.AllArgsConstructor;
 import lombok.Builder;
@@ -33,6 +34,16 @@ public class WxMaShopAfterSaleUpdateRequest implements Serializable {
   private String openid;
   @SerializedName("out_aftersale_id")
   private String outAftersaleId;
+  @SerializedName("type")
+  private Integer type;
+  @SerializedName("orderamt")
+  private Long orderamt;
+  @SerializedName("refund_reason")
+  private String refundReason;
+  @SerializedName("refund_reason_type")
+  private Integer refundReasonType;
+  @SerializedName("media_list")
+  private UploadMediaList mediaList;
   @SerializedName("status")
   private Integer status;
   @SerializedName("finish_all_aftersale")
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/request/WxMaShopAfterSaleUploadReturnInfoRequest.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/request/WxMaShopAfterSaleUploadReturnInfoRequest.java
new file mode 100644
index 000000000..aa7f71392
--- /dev/null
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/request/WxMaShopAfterSaleUploadReturnInfoRequest.java
@@ -0,0 +1,31 @@
+package cn.binarywang.wx.miniapp.bean.shop.request;
+
+import com.google.gson.annotations.SerializedName;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author leiin
+ * @date 2022/6/28 11:39 上午
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class WxMaShopAfterSaleUploadReturnInfoRequest implements Serializable {
+  @SerializedName("out_aftersale_id")
+  private String outAftersaleId;
+  @SerializedName("aftersale_id")
+  private Long aftersaleId;
+  @SerializedName("openid")
+  private String openid;
+  @SerializedName("delivery_id")
+  private String deliveryId;
+  @SerializedName("waybill_id")
+  private String waybillId;
+  @SerializedName("delivery_name")
+  private String deliveryName;
+}
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/request/WxMaShopDeliverySendRequest.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/request/WxMaShopDeliverySendRequest.java
index bf8acced5..47615c5e5 100644
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/request/WxMaShopDeliverySendRequest.java
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/request/WxMaShopDeliverySendRequest.java
@@ -1,5 +1,6 @@
 package cn.binarywang.wx.miniapp.bean.shop.request;
 
+import cn.binarywang.wx.miniapp.bean.shop.request.WxMaShopAfterSaleAddRequest.ProductInfosBean;
 import com.google.gson.annotations.SerializedName;
 import lombok.AllArgsConstructor;
 import lombok.Builder;
@@ -38,6 +39,8 @@ public class WxMaShopDeliverySendRequest implements Serializable {
   private Integer finishAllDelivery;
   @SerializedName("delivery_list")
   private List deliveryList;
+  @SerializedName("ship_done_time")
+  private String shipDoneTme;
 
   @Data
   @Builder
@@ -53,5 +56,7 @@ public static class DeliveryListBean implements Serializable {
     private String deliveryId;
     @SerializedName("waybill_id")
     private String waybillId;
+    @SerializedName("product_info_list")
+    private List productInfoList;
   }
 }
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/request/WxMaShopPayCreateOrderRequest.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/request/WxMaShopPayCreateOrderRequest.java
new file mode 100644
index 000000000..085a70eec
--- /dev/null
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/request/WxMaShopPayCreateOrderRequest.java
@@ -0,0 +1,47 @@
+package cn.binarywang.wx.miniapp.bean.shop.request;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author liming1019
+ * @date 2022/8/10
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class WxMaShopPayCreateOrderRequest implements Serializable {
+  private static final long serialVersionUID = -5597409427574429095L;
+
+  @SerializedName("openid")
+  private String openid;
+  @SerializedName("combine_trade_no")
+  private String combineTradeNo;
+  @SerializedName("expire_time")
+  private Long expireTime;
+  @SerializedName("sub_orders")
+  private List subOrders;
+
+  @NoArgsConstructor
+  @AllArgsConstructor
+  @Data
+  @Builder
+  public static class SubOrdersDTO {
+    @SerializedName("mchid")
+    private String mchid;
+    @SerializedName("amount")
+    private Integer amount;
+    @SerializedName("trade_no")
+    private String tradeNo;
+    @SerializedName("description")
+    private String description;
+  }
+}
+
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/request/WxMaShopUploadCerficatesRequest.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/request/WxMaShopUploadCerficatesRequest.java
new file mode 100644
index 000000000..4e4aae4db
--- /dev/null
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/request/WxMaShopUploadCerficatesRequest.java
@@ -0,0 +1,28 @@
+package cn.binarywang.wx.miniapp.bean.shop.request;
+
+import com.google.gson.annotations.SerializedName;
+import java.io.Serializable;
+import java.util.List;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author leiin
+ * @date 2022/6/28 11:39 上午
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class WxMaShopUploadCerficatesRequest implements Serializable {
+  @SerializedName("out_aftersale_id")
+  private String outAftersaleId;
+  @SerializedName("aftersale_id")
+  private Long aftersaleId;
+  @SerializedName("refund_desc")
+  private String refundDesc;
+  @SerializedName("certificates")
+  private List certificates;
+}
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopAfterSaleAddResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopAfterSaleAddResponse.java
new file mode 100644
index 000000000..c376d3bcb
--- /dev/null
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopAfterSaleAddResponse.java
@@ -0,0 +1,15 @@
+package cn.binarywang.wx.miniapp.bean.shop.response;
+
+import com.google.gson.annotations.SerializedName;
+import java.io.Serializable;
+import lombok.Data;
+
+/**
+ * @author leiin
+ * @date 2022/6/28 11:29 上午
+ */
+@Data
+public class WxMaShopAfterSaleAddResponse extends WxMaShopBaseResponse implements Serializable {
+  @SerializedName("aftersale_id")
+  private String aftersaleId;
+}
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopAfterSaleGetResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopAfterSaleGetResponse.java
index ac8f68db6..2261ad3dd 100644
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopAfterSaleGetResponse.java
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopAfterSaleGetResponse.java
@@ -1,5 +1,6 @@
 package cn.binarywang.wx.miniapp.bean.shop.response;
 
+import cn.binarywang.wx.miniapp.bean.shop.request.WxMaShopAfterSaleAddRequest.UploadMediaList;
 import com.google.gson.annotations.SerializedName;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
@@ -29,24 +30,43 @@ public static class AftersaleInfosBean implements Serializable {
      * product_infos : [{"out_product_id":"234245","out_sku_id":"23424","product_cnt":5}]
      */
 
-    @SerializedName("out_order_id")
-    private String outOrderId;
+    @SerializedName("aftersale_id")
+    private Long aftersaleId;
     @SerializedName("out_aftersale_id")
     private String outAftersaleId;
-    @SerializedName("openid")
-    private String openid;
+    @SerializedName("out_order_id")
+    private String outOrderId;
+    @SerializedName("order_id")
+    private Long orderId;
+    @SerializedName("product_info")
+    private List productInfo;
     @SerializedName("type")
     private Integer type;
-    @SerializedName("create_time")
-    private String createTime;
-    @SerializedName("path")
-    private String path;
+    @SerializedName("return_info")
+    private ReturnInfo returnInfo;
+    @SerializedName("orderamt")
+    private Long orderamt;
+    @SerializedName("refund_reason")
+    private String refundReason;
+    @SerializedName("refund_reason_type")
+    private Integer refundReasonType;
+    @SerializedName("media_list")
+    private UploadMediaList mediaList;
     @SerializedName("status")
     private Integer status;
-    @SerializedName("refund")
-    private Long refund;
-    @SerializedName("product_infos")
-    private List productInfos;
+    @SerializedName("create_time")
+    private String createTime;
+    @SerializedName("update_time")
+    private String updateTime;
+    @SerializedName("openid")
+    private String openid;
+    @SerializedName("refund_pay_detail")
+    private RefundPayDetail refund_pay_detail;
+    @SerializedName("return_id")
+    private String returnId;
+    @SerializedName("complaint_order_id_list")
+    private List complaintOrderIdList;
+
 
     @Data
     public static class ProductInfosBean implements Serializable {
@@ -58,10 +78,32 @@ public static class ProductInfosBean implements Serializable {
 
       @SerializedName("out_product_id")
       private String outProductId;
+      @SerializedName("product_id")
+      private Long productId;
       @SerializedName("out_sku_id")
       private String outSkuId;
+      @SerializedName("sku_id")
+      private Long skuId;
       @SerializedName("product_cnt")
       private Integer productCnt;
     }
+
+    @Data
+    public static class ReturnInfo {
+      @SerializedName("order_return_time")
+      private Long orderReturnTime;
+      @SerializedName("delivery_id")
+      private String deliveryId;
+      @SerializedName("waybill_id")
+      private String waybillId;
+      @SerializedName("delivery_name")
+      private String deliveryName;
+    }
+
+    @Data
+    public static class RefundPayDetail {
+      @SerializedName("refund_id")
+      private String refundId;
+    }
   }
 }
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopAfterSaleListResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopAfterSaleListResponse.java
new file mode 100644
index 000000000..1e4fb93ad
--- /dev/null
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopAfterSaleListResponse.java
@@ -0,0 +1,25 @@
+package cn.binarywang.wx.miniapp.bean.shop.response;
+
+import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopAfterSaleGetResponse.AftersaleInfosBean;
+import com.google.gson.annotations.SerializedName;
+import java.io.Serializable;
+import java.util.List;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author leiin
+ * @date 2022/6/28 11:39 上午
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class WxMaShopAfterSaleListResponse extends WxMaShopBaseResponse implements Serializable {
+  @SerializedName("has_more")
+  private Boolean hasMore;
+  @SerializedName("after_sales_orders")
+  private List afterSalesOrders;
+}
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopBaseResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopBaseResponse.java
index 4332c130c..2156be229 100644
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopBaseResponse.java
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopBaseResponse.java
@@ -21,7 +21,7 @@ public class WxMaShopBaseResponse implements Serializable {
    * 
*/ @SerializedName("errcode") - private Integer errcode; + private Integer errCode; /** * 错误信息 @@ -30,5 +30,5 @@ public class WxMaShopBaseResponse implements Serializable { *
*/ @SerializedName("errmsg") - private String errmsg; + private String errMsg; } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopCouponListResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopCouponListResponse.java new file mode 100644 index 000000000..5d77c360f --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopCouponListResponse.java @@ -0,0 +1,23 @@ +package cn.binarywang.wx.miniapp.bean.shop.response; + +import cn.binarywang.wx.miniapp.bean.shop.WxMaShopCouponInfo; +import com.google.gson.annotations.SerializedName; +import java.util.List; +import lombok.Data; + +/** + * @author leiin + * @date 2022/7/1 3:34 下午 + */ +@Data +public class WxMaShopCouponListResponse extends WxMaShopBaseResponse { + @SerializedName("total_num") + private Long totalNum; + @SerializedName("result_list") + private List resultList; + + @Data + public static class ResponseCouponResult { + private WxMaShopCouponInfo coupon; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopCouponResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopCouponResponse.java new file mode 100644 index 000000000..f83c159d1 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopCouponResponse.java @@ -0,0 +1,18 @@ +package cn.binarywang.wx.miniapp.bean.shop.response; + +import cn.binarywang.wx.miniapp.bean.shop.WxMaShopCouponInfo; +import lombok.Data; + +/** + * @author leiin + * @date 2022/7/1 3:34 下午 + */ +@Data +public class WxMaShopCouponResponse extends WxMaShopBaseResponse { + private ResponseCouponResult result; + + @Data + public static class ResponseCouponResult { + private WxMaShopCouponInfo coupon; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopGetOrderListResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopGetOrderListResponse.java new file mode 100644 index 000000000..059684339 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopGetOrderListResponse.java @@ -0,0 +1,30 @@ +package cn.binarywang.wx.miniapp.bean.shop.response; + +import cn.binarywang.wx.miniapp.bean.shop.WxMaShopOrderResult; +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; + +/** + * @author leiin + * @date 2021/3/23 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class WxMaShopGetOrderListResponse extends WxMaShopBaseResponse implements Serializable { + private static final long serialVersionUID = -81207907908726897L; + + /** + * 订单满足条件的总数 + */ + @SerializedName("total_num") + private Integer totalNum; + + /** + * 订单列表 + */ + @SerializedName("order") + private WxMaShopOrderResult order; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopGetPaymentParamsResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopGetPaymentParamsResponse.java new file mode 100644 index 000000000..fc1bc4767 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopGetPaymentParamsResponse.java @@ -0,0 +1,41 @@ +package cn.binarywang.wx.miniapp.bean.shop.response; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; + +/** + * 生成支付参数响应 + * + * @author zhongjun + * @date 2022/5/17 + **/ +@Data +@EqualsAndHashCode(callSuper = true) +public class WxMaShopGetPaymentParamsResponse extends WxMaShopBaseResponse implements Serializable { + private static final long serialVersionUID = -8796836131438585559L; + + @SerializedName("payment_params") + private PaymentParams paymentParams; + + @Getter + @Setter + public static class PaymentParams { + + private String timeStamp; + + private String nonceStr; + + @SerializedName("package") + private String packageValue; + + private String signType; + + private String paySign; + } + +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopPayCreateOrderResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopPayCreateOrderResponse.java new file mode 100644 index 000000000..85cd3e390 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopPayCreateOrderResponse.java @@ -0,0 +1,40 @@ +package cn.binarywang.wx.miniapp.bean.shop.response; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * @author liming1019 + * @date 2022/8/10 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class WxMaShopPayCreateOrderResponse extends WxMaShopBaseResponse implements Serializable { + private static final long serialVersionUID = -375471325664721192L; + + @SerializedName("payment_params") + private PaymentParamsDTO paymentParams; + + @NoArgsConstructor + @Data + public static class PaymentParamsDTO { + @SerializedName("timeStamp") + private Integer timeStamp; + @SerializedName("nonceStr") + private String nonceStr; + @SerializedName("package") + private String packageX; + @SerializedName("paySign") + private String paySign; + @SerializedName("signType") + private String signType; + } +} + diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopSearchSharerResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopSearchSharerResponse.java new file mode 100644 index 000000000..9366a5014 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopSearchSharerResponse.java @@ -0,0 +1,24 @@ +package cn.binarywang.wx.miniapp.bean.shop.response; + +import com.google.gson.annotations.SerializedName; +import java.io.Serializable; +import lombok.Data; + +/** + * @author leiin + * @date 2022/6/18 2:58 下午 + */ +@Data +public class WxMaShopSearchSharerResponse extends WxMaShopBaseResponse implements Serializable { + + private static final long serialVersionUID = 2049214239752832818L; + + @SerializedName("invited_time") + private Long invitedTime; + @SerializedName("bind_time") + private Long bindTime; + @SerializedName("nickname") + private String nickname; + @SerializedName("bind_status") + private Integer bindStatus; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopSharerBindResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopSharerBindResponse.java new file mode 100644 index 000000000..d88a48298 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopSharerBindResponse.java @@ -0,0 +1,40 @@ +package cn.binarywang.wx.miniapp.bean.shop.response; + +import com.google.gson.annotations.SerializedName; +import java.io.Serializable; +import java.util.List; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; + +/** + * @author leiin + * @date 2022/6/18 2:51 下午 + */ +@Data +public class WxMaShopSharerBindResponse extends WxMaShopBaseResponse implements Serializable { + + private static final long serialVersionUID = 5648529892711033276L; + + @SerializedName("success_list") + private List successList; + + @SerializedName("fail_list") + private List failList; + + @SerializedName("refuse_list") + private List refuseList; + + @SerializedName("result_list") + private List resultList; + + @Getter + @Setter + public static class ResultListItem { + private String openid; + @SerializedName("result_code") + private Integer resultCode; + @SerializedName("reason_code") + private Integer reasonCode; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopSharerDataSummaryResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopSharerDataSummaryResponse.java new file mode 100644 index 000000000..304bf3d18 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopSharerDataSummaryResponse.java @@ -0,0 +1,21 @@ +package cn.binarywang.wx.miniapp.bean.shop.response; + +import com.google.gson.annotations.SerializedName; +import java.io.Serializable; +import lombok.Data; + +/** + * @author leiin + * @date 2022/6/18 2:53 下午 + */ +@Data +public class WxMaShopSharerDataSummaryResponse extends WxMaShopBaseResponse implements Serializable { + + private static final long serialVersionUID = 3985829585979186778L; + + private Long gmv; + @SerializedName("order_cnt") + private Long orderCnt; + @SerializedName("user_cnt") + private Long userCnt; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopSharerListResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopSharerListResponse.java new file mode 100644 index 000000000..c49c0c5f0 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopSharerListResponse.java @@ -0,0 +1,30 @@ +package cn.binarywang.wx.miniapp.bean.shop.response; + +import com.google.gson.annotations.SerializedName; +import java.io.Serializable; +import java.util.List; +import lombok.Data; + +/** + * @author leiin + * @date 2022/6/18 2:55 下午 + */ +@Data +public class WxMaShopSharerListResponse extends WxMaShopBaseResponse implements Serializable { + + private static final long serialVersionUID = -8533731677643022825L; + + private List sharers; + @SerializedName("total_num") + private Integer totalNum; + + @Data + public static class SharerInfo { + private String openid; + @SerializedName("invited_time") + private Long invitedTime; + @SerializedName("bind_time") + private Long bindTime; + private String nickname; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopSharerLiveOrderListResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopSharerLiveOrderListResponse.java new file mode 100644 index 000000000..319b72668 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopSharerLiveOrderListResponse.java @@ -0,0 +1,34 @@ +package cn.binarywang.wx.miniapp.bean.shop.response; + +import cn.binarywang.wx.miniapp.bean.shop.WxMaShopOrderDetail; +import com.google.gson.annotations.SerializedName; +import java.io.Serializable; +import java.util.List; +import lombok.Data; + +/** + * @author leiin + * @date 2022/6/18 2:56 下午 + */ +@Data +public class WxMaShopSharerLiveOrderListResponse extends WxMaShopBaseResponse implements Serializable { + + private static final long serialVersionUID = -4190199778148290127L; + + private List orders; + + @SerializedName("total_num") + private Integer totalNum; + + @Data + public static class WxMaShopOrderItem { + @SerializedName("order_id") + private Long orderId; + @SerializedName("out_order_id") + private String outOrderId; + private Integer status; + private String path; + @SerializedName("order_detail") + private WxMaShopOrderDetail orderDetail; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopSharerLiveSummaryListResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopSharerLiveSummaryListResponse.java new file mode 100644 index 000000000..bb3fa927b --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopSharerLiveSummaryListResponse.java @@ -0,0 +1,41 @@ +package cn.binarywang.wx.miniapp.bean.shop.response; + +import com.google.gson.annotations.SerializedName; +import java.io.Serializable; +import java.util.List; +import lombok.Data; + +/** + * @author leiin + * @date 2022/6/18 2:57 下午 + */ +@Data +public class WxMaShopSharerLiveSummaryListResponse extends WxMaShopBaseResponse implements Serializable { + + private static final long serialVersionUID = -2085366863029618067L; + + private List lives; + + @SerializedName("total_num") + private Integer totalNum; + + @Data + public static class LiveSummaryItem { + @SerializedName("live_export_id") + private String liveExportId; + @SerializedName("live_nickname") + private String liveNickname; + @SerializedName("live_start_time") + private Long liveStartTime; + @SerializedName("live_end_time") + private Long liveEndTime; + @SerializedName("live_status") + private Long liveStatus; + @SerializedName("gmv") + private Long gmv; + @SerializedName("order_cnt") + private Long orderCnt; + @SerializedName("user_cnt") + private Long userCnt; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopSharerUnbindResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopSharerUnbindResponse.java new file mode 100644 index 000000000..6ce228a8c --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopSharerUnbindResponse.java @@ -0,0 +1,25 @@ +package cn.binarywang.wx.miniapp.bean.shop.response; + +import com.google.gson.annotations.SerializedName; +import java.io.Serializable; +import java.util.List; +import lombok.Data; + +/** + * @author leiin + * @date 2022/6/18 3:00 下午 + */ +@Data +public class WxMaShopSharerUnbindResponse extends WxMaShopBaseResponse implements Serializable { + + private static final long serialVersionUID = -9015680115600175408L; + + @SerializedName("success_list") + private List successList; + + @SerializedName("fail_list") + private List failList; + + @SerializedName("refuse_list") + private List refuseList; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopUserCouponListResponse.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopUserCouponListResponse.java new file mode 100644 index 000000000..6f615554b --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/shop/response/WxMaShopUserCouponListResponse.java @@ -0,0 +1,76 @@ +package cn.binarywang.wx.miniapp.bean.shop.response; + +import com.google.gson.annotations.SerializedName; +import java.io.Serializable; +import java.util.List; +import lombok.Data; + +/** + * @author leiin + * @date 2022/7/1 3:59 下午 + */ +@Data +public class WxMaShopUserCouponListResponse extends WxMaShopBaseResponse implements Serializable { + + private static final long serialVersionUID = 3264119403757388410L; + + @SerializedName("total_num") + private Long totalNum; + @SerializedName("result_list") + private List resultList; + + @Data + public static class UserCouponResultItem { + + /** + * 商家侧用户优惠券ID + */ + @SerializedName("out_user_coupon_id") + private String outUserCouponId; + /** + * openid + */ + @SerializedName("openid") + private String openid; + /** + * 商家侧优惠券ID + */ + @SerializedName("out_coupon_id") + private String outCouponId; + /** + * 用户优惠券状态 + */ + @SerializedName("status") + private Integer status; + /** + * 用户优惠券创建时间 + */ + @SerializedName("create_time") + private Long createTime; + /** + * 用户优惠券更新时间 + */ + @SerializedName("update_time") + private Long updateTime; + /** + * 用户优惠券有效开始时间 + */ + @SerializedName("start_time") + private Long startTime; + /** + * 用户优惠券有效结束时间 + */ + @SerializedName("end_time") + private Long endTime; + + @SerializedName("ext_info") + private UserCouponExtInfo extInfo; + + @Data + public static class UserCouponExtInfo { + @SerializedName("use_time") + private Long useTime; + } + } + +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/config/WxMaConfig.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/config/WxMaConfig.java index b8ba1e188..208710b75 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/config/WxMaConfig.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/config/WxMaConfig.java @@ -250,4 +250,19 @@ public interface WxMaConfig { * @return 自定义的api域名地址 */ String getApiHostUrl(); + + /** + * 获取自定义的获取accessToken地址,用于向自定义统一服务获取accessToken + * + * @return 自定义的获取accessToken地址 + */ + String getAccessTokenUrl(); + + /** + * 设置自定义的获取accessToken地址 + * 可用于设置获取accessToken的自定义服务 + * + * @param accessTokenUrl 自定义的获取accessToken地址 + */ + void setAccessTokenUrl(String accessTokenUrl); } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/config/impl/AbstractWxMaRedisConfig.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/config/impl/AbstractWxMaRedisConfig.java index 19d3a00f6..aabdd4893 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/config/impl/AbstractWxMaRedisConfig.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/config/impl/AbstractWxMaRedisConfig.java @@ -1,10 +1,11 @@ package cn.binarywang.wx.miniapp.config.impl; -import com.github.jedis.lock.JedisLock; import me.chanjar.weixin.common.error.WxRuntimeException; import redis.clients.jedis.Jedis; +import redis.clients.jedis.params.SetParams; import java.io.File; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; @@ -223,16 +224,21 @@ public void setExpiresTime(long expiresTime) { */ private class DistributedLock implements Lock { - private JedisLock lock; + private final String LOCK_SUCCESS = "OK"; + + private final Long RELEASE_SUCCESS = 1L; + + private String lockKey; private DistributedLock(String key) { - this.lock = new JedisLock(getRedisKey(key)); + this.lockKey = key; } @Override public void lock() { try (Jedis jedis = getConfiguredJedis()) { - if (!lock.acquire(jedis)) { + + if (!acquire(jedis)) { throw new WxRuntimeException("acquire timeouted"); } } catch (InterruptedException e) { @@ -240,10 +246,11 @@ public void lock() { } } + @Override public void lockInterruptibly() throws InterruptedException { try (Jedis jedis = getConfiguredJedis()) { - if (!lock.acquire(jedis)) { + if (!acquire(jedis)) { throw new WxRuntimeException("acquire timeouted"); } } @@ -252,7 +259,7 @@ public void lockInterruptibly() throws InterruptedException { @Override public boolean tryLock() { try (Jedis jedis = getConfiguredJedis()) { - return lock.acquire(jedis); + return acquire(jedis); } catch (InterruptedException e) { throw new WxRuntimeException("lock failed", e); } @@ -261,14 +268,14 @@ public boolean tryLock() { @Override public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { try (Jedis jedis = getConfiguredJedis()) { - return lock.acquire(jedis); + return acquire(jedis); } } @Override public void unlock() { try (Jedis jedis = getConfiguredJedis()) { - lock.release(jedis); + releaseDistributedLock(jedis); } } @@ -277,5 +284,54 @@ public Condition newCondition() { throw new WxRuntimeException("unsupported method"); } + + /** + * 尝试获取锁 有限次数的重试 + * + * @param jedis + * @return + * @throws InterruptedException + */ + private Boolean acquire(Jedis jedis) throws InterruptedException { + Integer i = 0; + do { + i++; + boolean locked = tryGetDistributedLock(jedis); + if (locked) { + return true; + } else { + Thread.sleep(100L); + } + } while (i < 20); + return false; + } + + /** + * 尝试获取锁 + * + * @param jedis + * @return + */ + private Boolean tryGetDistributedLock(Jedis jedis) { + Long millisecondsToExpire = 2L; + Long threadId = Thread.currentThread().getId(); + String result = jedis.set(this.lockKey, threadId.toString(), SetParams.setParams().nx().px(millisecondsToExpire)); + return LOCK_SUCCESS.equals(result); + } + + + /** + * 释放分布式锁 + * + * @param jedis + * @return 是否释放成功 + */ + private Boolean releaseDistributedLock(Jedis jedis) { + Long threadId = Thread.currentThread().getId(); + String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; + Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(threadId.toString())); + return RELEASE_SUCCESS.equals(result); + } + } } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/config/impl/WxMaDefaultConfigImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/config/impl/WxMaDefaultConfigImpl.java index c05d6f1aa..074603091 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/config/impl/WxMaDefaultConfigImpl.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/config/impl/WxMaDefaultConfigImpl.java @@ -56,6 +56,7 @@ public class WxMaDefaultConfigImpl implements WxMaConfig { protected volatile Lock cardApiTicketLock = new ReentrantLock(); private volatile ApacheHttpClientBuilder apacheHttpClientBuilder; private String apiHostUrl; + private String accessTokenUrl; /** * 会过期的数据提前过期时间,默认预留200秒的时间 @@ -303,6 +304,11 @@ public void setApiHostUrl(String apiHostUrl) { this.apiHostUrl = apiHostUrl; } + @Override + public void setAccessTokenUrl(String accessTokenUrl) { + this.accessTokenUrl = accessTokenUrl; + } + @Override public String getAppid() { return appid; diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/constant/WxMaApiUrlConstants.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/constant/WxMaApiUrlConstants.java index 4377b148b..e6c8535b9 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/constant/WxMaApiUrlConstants.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/constant/WxMaApiUrlConstants.java @@ -42,6 +42,7 @@ public interface Cloud { String DATABASE_UPDATE_URL = "https://api.weixin.qq.com/tcb/databaseupdate"; String DATABASE_DELETE_URL = "https://api.weixin.qq.com/tcb/databasedelete"; String DATABASE_ADD_URL = "https://api.weixin.qq.com/tcb/databaseadd"; + String SEND_SMS_V2_URL = "https://api.weixin.qq.com/tcb/sendsmsv2"; } public interface Msg { @@ -70,6 +71,7 @@ public interface Code { String GET_SUPPORT_VERSION_URL = "https://api.weixin.qq.com/cgi-bin/wxopen/getweappsupportversion"; String SET_SUPPORT_VERSION_URL = "https://api.weixin.qq.com/cgi-bin/wxopen/setweappsupportversion"; String UNDO_CODE_AUDIT_URL = "https://api.weixin.qq.com/wxa/undocodeaudit"; + String GET_VERSION_INFO_URL = "https://api.weixin.qq.com/wxa/getversioninfo"; } public interface Express { @@ -399,6 +401,48 @@ public interface Ocr { String FILE_COMM = "https://api.weixin.qq.com/cv/ocr/comm"; } + public interface Product { + interface Spu { + String PRODUCT_SPU_ADD_URL = "https://api.weixin.qq.com/product/spu/add"; + String PRODUCT_SPU_DEL_URL = "https://api.weixin.qq.com/product/spu/del"; + String PRODUCT_SPU_GET_URL = "https://api.weixin.qq.com/product/spu/get"; + String PRODUCT_SPU_GET_LIST_URL = "https://api.weixin.qq.com/product/spu/get_list"; + String PRODUCT_SPU_UPDATE_URL = "https://api.weixin.qq.com/product/spu/update"; + String PRODUCT_SPU_LISTING_URL = "https://api.weixin.qq.com/product/spu/listing"; + String PRODUCT_SPU_DELISTING_URL = "https://api.weixin.qq.com/product/spu/delisting"; + } + + interface Sku { + String PRODUCT_ADD_SKU_URL = "https://api.weixin.qq.com/product/sku/add"; + String PRODUCT_BATCH_ADD_SKU_URL = "https://api.weixin.qq.com/product/sku/batch_add"; + String PRODUCT_DEL_SKU_URL = "https://api.weixin.qq.com/product/sku/del"; + String PRODUCT_UPDATE_SKU_URL = "https://api.weixin.qq.com/product/sku/update"; + String PRODUCT_UPDATE_SKU_PRICE_URL = "https://api.weixin.qq.com/product/sku/update_price"; + String PRODUCT_UPDATE_SKU_STOCK_URL = "https://api.weixin.qq.com/product/stock/update"; + String PRODUCT_SKU_LIST = "https://api.weixin.qq.com/product/sku/get_list"; + } + + interface Order { + String PRODUCT_ORDER_GET_LIST = "https://api.weixin.qq.com/product/order/get_list"; + String PRODUCT_ORDER_DETAIL_URL = "https://api.weixin.qq.com/product/order/get"; + String PRODUCT_ORDER_CHANGE_MERCHANT_NOTES_URL = "https://api.weixin.qq.com/product/order/change_merchant_notes"; + + String PRODUCT_DELIVERY_SEND = "https://api.weixin.qq.com/product/delivery/send"; + + String GET_AFTER_SALE_ORDER = "https://api.weixin.qq.com/product/order/getaftersaleorder"; + String BATCH_GET_AFTER_SALE_ORDER = "https://api.weixin.qq.com/product/order/batchgetaftersaleorder"; + String AFTER_SALE_ACCEPT_APPLY = "https://api.weixin.qq.com/product/order/acceptapply"; + String AFTER_SALE_REJECT_APPLY = "https://api.weixin.qq.com/product/order/rejectrefund"; + } + + interface OTHER { + String GET_CATEGORY = "https://api.weixin.qq.com/product/category/get"; + String GET_BRAND = "https://api.weixin.qq.com/product/brand/get"; + String GET_FREIGHT_TEMPLATE = "https://api.weixin.qq.com/product/delivery/get_freight_template"; + String IMG_UPLOAD = "https://api.weixin.qq.com/product/img/upload"; + } + } + public interface Shop { interface Spu { String SPU_ADD_URL = "https://api.weixin.qq.com/shop/spu/add"; @@ -417,6 +461,8 @@ interface Order { String ORDER_ADD = "https://api.weixin.qq.com/shop/order/add"; String ORDER_PAY = "https://api.weixin.qq.com/shop/order/pay"; String ORDER_GET = "https://api.weixin.qq.com/shop/order/get"; + String ORDER_GET_LIST = "https://api.weixin.qq.com/shop/order/get_list"; + String ORDER_GET_PAYMENT_PARAMS = "https://api.weixin.qq.com/shop/order/getpaymentparams"; } interface Register { @@ -455,9 +501,44 @@ interface Delivery { } interface Aftersale { - String AFTERSALE_ADD = "https://api.weixin.qq.com/shop/aftersale/add"; - String AFTERSALE_GET = "https://api.weixin.qq.com/shop/aftersale/get"; - String AFTERSALE_UPDATE = "https://api.weixin.qq.com/shop/aftersale/update"; + String AFTERSALE_ADD = "https://api.weixin.qq.com/shop/ecaftersale/add"; + String AFTERSALE_CANCEL = "https://api.weixin.qq.com/shop/ecaftersale/cancel"; + String AFTERSALE_UPDATE = "https://api.weixin.qq.com/shop/ecaftersale/update"; + String AFTERSALE_UPLOAD_RETURN_INFO = "https://api.weixin.qq.com/shop/ecaftersale/uploadreturninfo"; + String AFTERSALE_ACCEPT_REFUND = "https://api.weixin.qq.com/shop/ecaftersale/acceptrefund"; + String AFTERSALE_ACCEPT_RETURN = "https://api.weixin.qq.com/shop/ecaftersale/acceptreturn"; + String AFTERSALE_REJECT = "https://api.weixin.qq.com/shop/ecaftersale/reject"; + String AFTERSALE_UPLOAD_CERTIFICATES = "https://api.weixin.qq.com/shop/ecaftersale/upload_certificates"; + String AFTERSALE_UPLOAD_DEADLINE = "https://api.weixin.qq.com/shop/aftersale/update_deadline"; + String AFTERSALE_GET_LIST = "https://api.weixin.qq.com/shop/ecaftersale/get_list"; + String AFTERSALE_GET = "https://api.weixin.qq.com/shop/ecaftersale/get"; + } + + interface Sharer { + String BIND = "https://api.weixin.qq.com/shop/sharer/bind"; + String GET_SHARER_DATA_SUMMARY = "https://api.weixin.qq.com/shop/sharer/get_sharer_data_summary"; + String GET_SHARER_LIST = "https://api.weixin.qq.com/shop/sharer/get_sharer_list"; + String GET_SHARER_LIVE_ORDER_LIST = "https://api.weixin.qq.com/shop/sharer/get_sharer_live_order_list"; + String GET_SHARER_LIVE_SUMMARY_LIST = "https://api.weixin.qq.com/shop/sharer/get_sharer_live_summary_list"; + String SEARCH_SHARER = "https://api.weixin.qq.com/shop/sharer/search_sharer"; + String UNBIND = "https://api.weixin.qq.com/shop/sharer/unbind"; + } + + interface Coupon { + String ADD_COUPON = "https://api.weixin.qq.com/shop/coupon/add"; + String GET_COUPON = "https://api.weixin.qq.com/shop/coupon/get"; + String GET_COUPON_LIST = "https://api.weixin.qq.com/shop/coupon/get_list"; + String UPDATE_COUPON = "https://api.weixin.qq.com/shop/coupon/update"; + String UPDATE_COUPON_STATUS = "https://api.weixin.qq.com/shop/coupon/update_status"; + String UPDATE_COUPON_STOCK = "https://api.weixin.qq.com/shop/coupon/update_coupon_stock"; + String ADD_USER_COUPON = "https://api.weixin.qq.com/shop/coupon/add_user_coupon"; + String GET_USER_COUPON_LIST = "https://api.weixin.qq.com/shop/coupon/get_usercoupon_list"; + String UPDATE_USER_COUPON = "https://api.weixin.qq.com/shop/coupon/update_user_coupon"; + String UPDATE_USER_COUPON_STATUS = "https://api.weixin.qq.com/shop/coupon/update_usercoupon_status"; + } + + interface Pay { + String CREATE_ORDER = "https://api.weixin.qq.com/shop/pay/createorder"; } } @@ -550,6 +631,18 @@ public interface InstantDelivery { */ String QUERY_WAYBILL_TRACE_URL = "https://api.weixin.qq.com/cgi-bin/express/delivery/open_msg/query_trace"; + /** + * 物流服务-消息组件-传运单接口(订阅消息) follow_waybill + * 商户在调用完trace_waybill接口后,可以使用本接口查询到对应运单的详情信息 + */ + String FOLLOW_WAYBILL_URL = "https://api.weixin.qq.com/cgi-bin/express/delivery/open_msg/follow_waybill"; + + /** + * 物流服务-消息组件-查运单接口(订阅消息) query_follow_trace + * 商户在调用完trace_waybill接口后,可以使用本接口查询到对应运单的详情信息 + */ + String QUERY_FOLLOW_TRACE_URL = "https://api.weixin.qq.com/cgi-bin/express/delivery/open_msg/query_follow_trace"; + /** * 下单接口. diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/message/WxMaMessageRouter.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/message/WxMaMessageRouter.java index 031c688c5..026babdd3 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/message/WxMaMessageRouter.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/message/WxMaMessageRouter.java @@ -7,6 +7,7 @@ import me.chanjar.weixin.common.api.WxErrorExceptionHandler; import me.chanjar.weixin.common.api.WxMessageDuplicateChecker; import me.chanjar.weixin.common.api.WxMessageInMemoryDuplicateChecker; +import me.chanjar.weixin.common.api.WxMessageInMemoryDuplicateCheckerSingleton; import me.chanjar.weixin.common.session.InternalSession; import me.chanjar.weixin.common.session.InternalSessionManager; import me.chanjar.weixin.common.session.StandardSessionManager; @@ -48,7 +49,52 @@ public WxMaMessageRouter(WxMaService wxMaService) { 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), namedThreadFactory); this.sessionManager = new StandardSessionManager(); this.exceptionHandler = new LogExceptionHandler(); - this.messageDuplicateChecker = new WxMessageInMemoryDuplicateChecker(); + this.messageDuplicateChecker = WxMessageInMemoryDuplicateCheckerSingleton.getInstance(); + } + + /** + * 使用自定义的 {@link ExecutorService}. + */ + public WxMaMessageRouter(WxMaService wxMaService, ExecutorService executorService) { + this.wxMaService = wxMaService; + this.executorService = executorService; + this.sessionManager = new StandardSessionManager(); + this.exceptionHandler = new LogExceptionHandler(); + this.messageDuplicateChecker = WxMessageInMemoryDuplicateCheckerSingleton.getInstance(); + } + + /** + * 系统退出前,应该调用该方法 + */ + public void shutDownExecutorService() { + this.executorService.shutdown(); + } + + /** + * 系统退出前,应该调用该方法,增加了超时时间检测 + */ + public void shutDownExecutorService(Integer second) { + this.executorService.shutdown(); + try { + if (!this.executorService.awaitTermination(second, TimeUnit.SECONDS)) { + this.executorService.shutdownNow(); + if (!this.executorService.awaitTermination(second, TimeUnit.SECONDS)) + log.error("线程池未关闭!"); + } + } catch (InterruptedException ie) { + this.executorService.shutdownNow(); + Thread.currentThread().interrupt(); + } + } + + /** + *
+   * 设置自定义的 {@link ExecutorService}
+   * 如果不调用该方法,默认使用内置的
+   * 
+ */ + public void setExecutorService(ExecutorService executorService) { + this.executorService = executorService; } /** @@ -61,7 +107,7 @@ public WxMaMessageRouterRule rule() { /** * 处理微信消息. */ - private WxMaXmlOutMessage route(final WxMaMessage wxMessage, final Map context) { + public WxMaXmlOutMessage route(final WxMaMessage wxMessage, final Map context) { if (isMsgDuplicated(wxMessage)) { // 如果是重复消息,那么就不做处理 return null; @@ -137,6 +183,10 @@ private boolean isMsgDuplicated(WxMaMessage wxMessage) { messageId.append("-").append(wxMessage.getToUser()); } + if (StringUtils.isNotEmpty(wxMessage.getTraceId())) { + messageId.append("-").append(wxMessage.getTraceId()); + } + return this.messageDuplicateChecker.isDuplicate(messageId.toString()); } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/crypt/WxMaCryptUtils.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/crypt/WxMaCryptUtils.java index f1a05d001..0222265e4 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/crypt/WxMaCryptUtils.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/crypt/WxMaCryptUtils.java @@ -14,6 +14,7 @@ import com.google.common.io.BaseEncoding; import me.chanjar.weixin.common.error.WxRuntimeException; import org.apache.commons.codec.binary.Base64; +import org.apache.commons.lang3.StringUtils; import org.bouncycastle.jce.provider.BouncyCastleProvider; import cn.binarywang.wx.miniapp.config.WxMaConfig; @@ -28,7 +29,7 @@ public class WxMaCryptUtils extends me.chanjar.weixin.common.util.crypto.WxCrypt public WxMaCryptUtils(WxMaConfig config) { this.appidOrCorpid = config.getAppid(); this.token = config.getToken(); - this.aesKey = BaseEncoding.base64().decode(CharMatcher.whitespace().removeFrom(config.getAesKey())); + this.aesKey = java.util.Base64.getDecoder().decode(StringUtils.remove(config.getAesKey(), " ")); } /** diff --git a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaCloudServiceImplTest.java b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaCloudServiceImplTest.java index 69d6cc990..4b7235ba9 100644 --- a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaCloudServiceImplTest.java +++ b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaCloudServiceImplTest.java @@ -2,6 +2,7 @@ import cn.binarywang.wx.miniapp.api.WxMaService; import cn.binarywang.wx.miniapp.bean.cloud.*; +import cn.binarywang.wx.miniapp.bean.cloud.request.WxCloudSendSmsV2Request; import cn.binarywang.wx.miniapp.test.ApiTestModule; import com.google.common.collect.ImmutableSortedMap; import com.google.common.collect.Lists; @@ -394,4 +395,17 @@ public void testDatabaseCollectionGet() throws WxErrorException { assertThat(result.getCollections()[0].getIndexCount()).isGreaterThan(0); assertThat(result.getCollections()[0].getIndexSize()).isGreaterThan(0); } + + @Test + public void testSendSmsV2() throws WxErrorException { + WxCloudSendSmsV2Request request = WxCloudSendSmsV2Request.builder() + .urlLink("https://wxaurl.cn/xxxxxx") + .templateId("844110") + .templateParamList(Arrays.asList(new String[]{"能力上新"})) + .phoneNumberList(Arrays.asList("+8612345678910")) + .build(); + + final WxCloudSendSmsV2Result result = this.wxMaService.getCloudService().sendSmsV2(request); + assertThat(result).isNotNull(); + } } diff --git a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaCodeServiceImplTest.java b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaCodeServiceImplTest.java index 0a4aca45e..bac7bab5b 100644 --- a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaCodeServiceImplTest.java +++ b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaCodeServiceImplTest.java @@ -1,25 +1,21 @@ package cn.binarywang.wx.miniapp.api.impl; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.testng.annotations.*; - import cn.binarywang.wx.miniapp.api.WxMaCodeService; import cn.binarywang.wx.miniapp.api.WxMaService; -import cn.binarywang.wx.miniapp.bean.code.WxMaCategory; -import cn.binarywang.wx.miniapp.bean.code.WxMaCodeAuditStatus; -import cn.binarywang.wx.miniapp.bean.code.WxMaCodeCommitRequest; -import cn.binarywang.wx.miniapp.bean.code.WxMaCodeExtConfig; -import cn.binarywang.wx.miniapp.bean.code.WxMaCodeSubmitAuditRequest; -import cn.binarywang.wx.miniapp.bean.code.WxMaCodeVersionDistribution; +import cn.binarywang.wx.miniapp.bean.code.*; import cn.binarywang.wx.miniapp.config.WxMaConfig; import cn.binarywang.wx.miniapp.test.ApiTestModule; import com.google.inject.Inject; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; -import static org.testng.Assert.*; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; /** * @author Charming @@ -143,6 +139,12 @@ public void testGetSupportVersion() throws Exception { System.out.println(distribution); } + @Test + public void testGetVersionInfo() throws Exception { + WxMaCodeVersionInfo versionInfo = wxService.getCodeService().getVersionInfo(); + System.out.println(versionInfo); + } + @Test public void testSetSupportVersion() throws Exception { wxService.getCodeService().setSupportVersion("1.2.0"); diff --git a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaLiveServiceImplTest.java b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaLiveServiceImplTest.java index b9a5b9412..2f497935c 100644 --- a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaLiveServiceImplTest.java +++ b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaLiveServiceImplTest.java @@ -4,6 +4,7 @@ import cn.binarywang.wx.miniapp.bean.live.WxMaCreateRoomResult; import cn.binarywang.wx.miniapp.bean.live.WxMaLiveResult; import cn.binarywang.wx.miniapp.bean.live.WxMaLiveRoomInfo; +import cn.binarywang.wx.miniapp.bean.live.WxMaLiveSharedCode; import cn.binarywang.wx.miniapp.test.ApiTestModule; import com.google.inject.Inject; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; @@ -95,7 +96,7 @@ public void getPushUrl() throws Exception { @Test public void getSharedCode() throws Exception { - String result = this.wxService.getLiveService().getSharedCode(39, null); + WxMaLiveSharedCode result = this.wxService.getLiveService().getSharedCode(39, null); System.out.println(result); } diff --git a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaShopAfterSaleServiceImplTest.java b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaShopAfterSaleServiceImplTest.java index 75538a151..9839cbf4c 100644 --- a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaShopAfterSaleServiceImplTest.java +++ b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaShopAfterSaleServiceImplTest.java @@ -38,12 +38,11 @@ public void testAdd() throws WxErrorException { .outAftersaleId("318092069606883328X") .openid("odIi15CuQ0IQviqsnUMy6CKNetrMX") .type(1) - .createTime("2021-08-20 00:00:00") .status(1) .finishAllAftersale(0) .path("/pages/aftersale.html?out_aftersale_id=318092069606883328X") .refund(100L) - .productInfos(new ArrayList<>(Arrays.asList(productInfosBean))) + .productInfo(productInfosBean) .build(); WxMaShopBaseResponse response = wxService.getShopAfterSaleService().add(request); assertThat(response).isNotNull(); diff --git a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaShopPayServiceImplTest.java b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaShopPayServiceImplTest.java new file mode 100644 index 000000000..bf509b8b3 --- /dev/null +++ b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaShopPayServiceImplTest.java @@ -0,0 +1,40 @@ +package cn.binarywang.wx.miniapp.api.impl; + +import cn.binarywang.wx.miniapp.api.WxMaService; +import cn.binarywang.wx.miniapp.bean.shop.request.WxMaShopPayCreateOrderRequest; +import cn.binarywang.wx.miniapp.bean.shop.response.WxMaShopPayCreateOrderResponse; +import cn.binarywang.wx.miniapp.test.ApiTestModule; +import com.google.inject.Inject; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import java.util.Arrays; + +import static org.assertj.core.api.Assertions.assertThat; + +@Test +@Guice(modules = ApiTestModule.class) +public class WxMaShopPayServiceImplTest { + + @Inject + private WxMaService wxService; + + @Test + public void testCreateOrder() throws Exception { + WxMaShopPayCreateOrderRequest request = + WxMaShopPayCreateOrderRequest.builder() + .openid("") + .combineTradeNo("") + .expireTime(1234L) + .subOrders(Arrays.asList(WxMaShopPayCreateOrderRequest.SubOrdersDTO.builder() + .mchid("") + .amount(0) + .tradeNo("") + .description("") + .build() + )) + .build(); + WxMaShopPayCreateOrderResponse response = wxService.getWxMaShopPayService().createOrder(request); + assertThat(response).isNotNull(); + } +} diff --git a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/test/AddOrderJsonTest.java b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/test/AddOrderJsonTest.java new file mode 100644 index 000000000..b072eff18 --- /dev/null +++ b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/test/AddOrderJsonTest.java @@ -0,0 +1,20 @@ +package cn.binarywang.wx.miniapp.test; + +import cn.binarywang.wx.miniapp.bean.delivery.AddOrderRequest; +import me.chanjar.weixin.common.util.json.WxGsonBuilder; +import org.testng.annotations.Test; + +public class AddOrderJsonTest { + + /** + * 验证转化Json时是否有deliverySign + */ + @Test + public void test(){ + AddOrderRequest request = new AddOrderRequest(); + request.setShopId("1"); + request.setAppSecret("2"); + request.getDeliverySign(); + System.out.printf(WxGsonBuilder.create().toJson(request)); + } +} diff --git a/weixin-java-mp/pom.xml b/weixin-java-mp/pom.xml index e8c924c0d..c03cb4e1e 100644 --- a/weixin-java-mp/pom.xml +++ b/weixin-java-mp/pom.xml @@ -7,7 +7,7 @@ com.github.binarywang wx-java - 4.3.0 + 4.4.0 weixin-java-mp diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMerchantInvoiceService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMerchantInvoiceService.java index 795c848b3..ed41c53e5 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMerchantInvoiceService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMerchantInvoiceService.java @@ -13,7 +13,7 @@ * 73100: 开票平台错误 *

* 流程文档: https://developers.weixin.qq.com/doc/offiaccount/WeChat_Invoice/E_Invoice/Vendor_and_Invoicing_Platform_Mode_Instruction.html - * 接口文档: https://developers.weixin.qq.com/doc/offiaccount/WeChat_Invoice/E_Invoice/Vendor_API_List.html + * 接口文档: https://developers.weixin.qq.com/doc/offiaccount/WeChat_Invoice/E_Invoice/Vendor_API_List.html * * @author Mario Luo */ diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouter.java index 263305c0d..e55e49909 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouter.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouter.java @@ -6,6 +6,7 @@ import me.chanjar.weixin.common.api.WxErrorExceptionHandler; import me.chanjar.weixin.common.api.WxMessageDuplicateChecker; import me.chanjar.weixin.common.api.WxMessageInMemoryDuplicateChecker; +import me.chanjar.weixin.common.api.WxMessageInMemoryDuplicateCheckerSingleton; import me.chanjar.weixin.common.session.InternalSession; import me.chanjar.weixin.common.session.InternalSessionManager; import me.chanjar.weixin.common.session.StandardSessionManager; @@ -72,7 +73,7 @@ public WxMpMessageRouter(WxMpService wxMpService) { ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("WxMpMessageRouter-pool-%d").build(); this.executorService = new ThreadPoolExecutor(DEFAULT_THREAD_POOL_SIZE, DEFAULT_THREAD_POOL_SIZE, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), namedThreadFactory); - this.messageDuplicateChecker = new WxMessageInMemoryDuplicateChecker(); + this.messageDuplicateChecker = WxMessageInMemoryDuplicateCheckerSingleton.getInstance(); this.sessionManager = new StandardSessionManager(); this.exceptionHandler = new LogExceptionHandler(); } @@ -83,18 +84,34 @@ public WxMpMessageRouter(WxMpService wxMpService) { public WxMpMessageRouter(WxMpService wxMpService, ExecutorService executorService) { this.wxMpService = wxMpService; this.executorService = executorService; - this.messageDuplicateChecker = new WxMessageInMemoryDuplicateChecker(); + this.messageDuplicateChecker = WxMessageInMemoryDuplicateCheckerSingleton.getInstance(); this.sessionManager = new StandardSessionManager(); this.exceptionHandler = new LogExceptionHandler(); } /** - * 如果使用默认的 {@link ExecutorService},则系统退出前,应该调用该方法. + * 系统退出前,应该调用该方法 */ public void shutDownExecutorService() { this.executorService.shutdown(); } + /** + * 系统退出前,应该调用该方法,增加了超时时间检测 + */ + public void shutDownExecutorService(Integer second) { + this.executorService.shutdown(); + try { + if (!this.executorService.awaitTermination(second, TimeUnit.SECONDS)) { + this.executorService.shutdownNow(); + if (!this.executorService.awaitTermination(second, TimeUnit.SECONDS)) + log.error("线程池未关闭!"); + } + } catch (InterruptedException ie) { + this.executorService.shutdownNow(); + Thread.currentThread().interrupt(); + } + } /** *

diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/BaseWxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/BaseWxMpServiceImpl.java
index e12e30493..b8d1792c2 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/BaseWxMpServiceImpl.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/BaseWxMpServiceImpl.java
@@ -87,7 +87,7 @@ public abstract class BaseWxMpServiceImpl implements WxMpService, RequestH
   private WxMpTemplateMsgService templateMsgService = new WxMpTemplateMsgServiceImpl(this);
   @Getter
   @Setter
-  private final WxMpSubscribeMsgService subscribeMsgService = new WxMpSubscribeMsgServiceImpl(this);
+  private WxMpSubscribeMsgService subscribeMsgService = new WxMpSubscribeMsgServiceImpl(this);
   @Getter
   @Setter
   private WxMpDeviceService deviceService = new WxMpDeviceServiceImpl(this);
@@ -105,7 +105,7 @@ public abstract class BaseWxMpServiceImpl implements WxMpService, RequestH
   private WxMpAiOpenService aiOpenService = new WxMpAiOpenServiceImpl(this);
   @Getter
   @Setter
-  private final WxMpWifiService wifiService = new WxMpWifiServiceImpl(this);
+  private WxMpWifiService wifiService = new WxMpWifiServiceImpl(this);
   @Getter
   @Setter
   private WxMpMarketingService marketingService = new WxMpMarketingServiceImpl(this);
@@ -435,12 +435,12 @@ protected  T executeInternal(RequestExecutor executor, String uri, E
       }
 
       if (error.getErrorCode() != 0) {
-        log.error("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", uriWithAccessToken, dataForLog, error);
+        log.warn("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", uriWithAccessToken, dataForLog, error);
         throw new WxErrorException(error, e);
       }
       return null;
     } catch (IOException e) {
-      log.error("\n【请求地址】: {}\n【请求参数】:{}\n【异常信息】:{}", uriWithAccessToken, dataForLog, e.getMessage());
+      log.warn("\n【请求地址】: {}\n【请求参数】:{}\n【异常信息】:{}", uriWithAccessToken, dataForLog, e.getMessage());
       throw new WxErrorException(e);
     }
   }
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMerchantInvoiceServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMerchantInvoiceServiceImpl.java
index 11883cded..4631a2e2c 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMerchantInvoiceServiceImpl.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMerchantInvoiceServiceImpl.java
@@ -1,7 +1,9 @@
 package me.chanjar.weixin.mp.api.impl;
 
 import com.google.common.collect.ImmutableMap;
+import com.google.gson.FieldNamingPolicy;
 import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
 import com.google.gson.JsonObject;
 import lombok.AllArgsConstructor;
 import me.chanjar.weixin.common.error.WxErrorException;
@@ -97,7 +99,7 @@ public MerchantInvoicePlatformInfo getMerchantInvoicePlatform(MerchantInvoicePla
    */
   private  T doCommonInvoiceHttpPost(WxMpApiUrl url, Object data, Class resultClass) throws WxErrorException {
     String json = "";
-    final Gson gson = WxMpGsonBuilder.create();
+    final Gson gson = this.createGson();
     if (data != null) {
       json = gson.toJson(data);
     }
@@ -108,4 +110,10 @@ private  T doCommonInvoiceHttpPost(WxMpApiUrl url, Object data, Class resu
 
     return gson.fromJson(responseText, resultClass);
   }
+
+  private Gson createGson() {
+    GsonBuilder gsonBuilder = new GsonBuilder();
+    gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
+    return gsonBuilder.create();
+  }
 }
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/ClearOutInvoiceRequest.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/ClearOutInvoiceRequest.java
index d0d0f6a9a..7b90a0797 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/ClearOutInvoiceRequest.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/ClearOutInvoiceRequest.java
@@ -6,13 +6,18 @@
 
 /**
  * 发票充红请求参数
+ *
+ * @author Mario Luo
  */
 @Data
 public class ClearOutInvoiceRequest implements Serializable {
+  private static final long serialVersionUID = 36469746428007271L;
+
   private ClearOutInvoiceInfo invoiceinfo;
 
   @Data
   public static class ClearOutInvoiceInfo implements Serializable {
+    private static final long serialVersionUID = -9119257155033644495L;
 
     /**
      * 用户的openid 用户知道是谁在开票
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/InvoiceAuthDataRequest.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/InvoiceAuthDataRequest.java
index 092e16410..cef469099 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/InvoiceAuthDataRequest.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/InvoiceAuthDataRequest.java
@@ -1,23 +1,29 @@
 package me.chanjar.weixin.mp.bean.invoice.merchant;
 
+import com.google.gson.annotations.SerializedName;
 import lombok.Data;
 
 import java.io.Serializable;
 
 /**
  * 获取电子开票用户授权数据
+ *
+ * @author Mario Luo
  */
 @Data
 public class InvoiceAuthDataRequest implements Serializable {
+  private static final long serialVersionUID = -7423619297443219650L;
 
   /**
    * 开票平台在微信的标识号,商户需要找开票平台提供
    */
+  @SerializedName("s_pappid")
   private String sPappid;
 
   /**
    * 订单id,在商户内单笔开票请求的唯一识别号
    */
+  @SerializedName("order_id")
   private String orderId;
 
 }
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/InvoiceAuthDataResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/InvoiceAuthDataResult.java
index 99d8f57cc..433c700c9 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/InvoiceAuthDataResult.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/InvoiceAuthDataResult.java
@@ -7,9 +7,12 @@
 
 /**
  * 用户开票认证信息返回结果DTO
+ *
+ * @author Mario Luo
  */
 @Data
 public class InvoiceAuthDataResult implements Serializable {
+  private static final long serialVersionUID = 7199243456761896912L;
 
   /**
    * 订单授权状态,当errcode为0时会出现
@@ -28,6 +31,8 @@ public class InvoiceAuthDataResult implements Serializable {
 
   @Data
   public static class UserAuthInfo implements Serializable {
+    private static final long serialVersionUID = 3132380567762544927L;
+
     /**
      * 个人抬头
      */
@@ -41,6 +46,8 @@ public static class UserAuthInfo implements Serializable {
 
   @Data
   public static class UserField implements Serializable {
+    private static final long serialVersionUID = 2114368427010646381L;
+
     private String title;
     private String phone;
     private String email;
@@ -49,6 +56,8 @@ public static class UserField implements Serializable {
 
   @Data
   public static class BizField implements Serializable {
+    private static final long serialVersionUID = 1799355181972008881L;
+
     private String title;
     private String taxNo;
     private String addr;
@@ -60,6 +69,8 @@ public static class BizField implements Serializable {
 
   @Data
   public static class KeyValuePair implements Serializable {
+    private static final long serialVersionUID = -1068075389526145791L;
+
     private String key;
     private String value;
   }
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/InvoiceAuthPageRequest.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/InvoiceAuthPageRequest.java
index 07a8a24e5..0b50111df 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/InvoiceAuthPageRequest.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/InvoiceAuthPageRequest.java
@@ -1,23 +1,29 @@
 package me.chanjar.weixin.mp.bean.invoice.merchant;
 
+import com.google.gson.annotations.SerializedName;
 import lombok.Data;
 
 import java.io.Serializable;
 
 /**
  * 获取授权地址的输入参数
+ *
+ * @author Mario Luo
  */
 @Data
 public class InvoiceAuthPageRequest implements Serializable {
+  private static final long serialVersionUID = -804002889404266929L;
 
   /**
    * 开票平台在微信的标识号,商户需要找开票平台提供
    */
+  @SerializedName("s_pappid")
   private String sPappid;
 
   /**
    * 订单id,在商户内单笔开票请求的唯一识别号
    */
+  @SerializedName("order_id")
   private String orderId;
 
   /**
@@ -33,6 +39,7 @@ public class InvoiceAuthPageRequest implements Serializable {
   /**
    * 授权成功后跳转页面。本字段只有在source为H5的时候需要填写,引导用户在微信中进行下一步流程。app开票因为从外部app拉起微信授权页,授权完成后自动回到原来的app,故无需填写。
    */
+  @SerializedName("redirect_url")
   private String redirectUrl;
 
   /**
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/InvoiceAuthPageResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/InvoiceAuthPageResult.java
index d137adb49..1ab3513bf 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/InvoiceAuthPageResult.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/InvoiceAuthPageResult.java
@@ -6,9 +6,12 @@
 
 /**
  * 获取授权链接返回结果DTO
+ *
+ * @author Mario Luo
  */
 @Data
 public class InvoiceAuthPageResult implements Serializable {
+  private static final long serialVersionUID = 2922797121045894425L;
 
   /**
    * 授权页地址
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/InvoiceAuthPageSetting.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/InvoiceAuthPageSetting.java
index dbc04816e..83a72c852 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/InvoiceAuthPageSetting.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/InvoiceAuthPageSetting.java
@@ -5,19 +5,27 @@
 import java.io.Serializable;
 import java.util.List;
 
+/**
+ * @author Mario Luo
+ */
 @Data
 public class InvoiceAuthPageSetting implements Serializable {
+  private static final long serialVersionUID = 4585269585619597753L;
 
   private AuthField authField;
 
   @Data
   public static class AuthField implements Serializable {
+    private static final long serialVersionUID = 7341329271546930795L;
+
     private UserField userField;
     private BizField bizField;
   }
 
   @Data
   public static class UserField implements Serializable {
+    private static final long serialVersionUID = -128178697394854697L;
+
     private Integer showTitle;
     private Integer showPhone;
     private Integer showEmail;
@@ -28,6 +36,8 @@ public static class UserField implements Serializable {
 
   @Data
   public static class BizField implements Serializable {
+    private static final long serialVersionUID = -8277885344416192644L;
+
     private Integer showTitle;
     private Integer showTaxNo;
     private Integer showAddr;
@@ -45,6 +55,8 @@ public static class BizField implements Serializable {
 
   @Data
   public static class CustomField implements Serializable {
+    private static final long serialVersionUID = -3838241240210071209L;
+
     /**
      * 字段名
      */
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/InvoiceRejectRequest.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/InvoiceRejectRequest.java
index 0d48cd79f..992faa4d2 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/InvoiceRejectRequest.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/InvoiceRejectRequest.java
@@ -1,23 +1,29 @@
 package me.chanjar.weixin.mp.bean.invoice.merchant;
 
+import com.google.gson.annotations.SerializedName;
 import lombok.Data;
 
 import java.io.Serializable;
 
 /**
  * 拒绝开票请求参数
+ *
+ * @author Mario Luo
  */
 @Data
 public class InvoiceRejectRequest implements Serializable {
+  private static final long serialVersionUID = -5303749544133451879L;
 
   /**
    * 开票平台标示
    */
+  @SerializedName("s_pappid")
   private String sPappid;
 
   /**
    * 订单id
    */
+  @SerializedName("order_id")
   private String orderId;
 
   /**
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/InvoiceResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/InvoiceResult.java
index 6f4da63a2..184b57970 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/InvoiceResult.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/InvoiceResult.java
@@ -6,9 +6,12 @@
 
 /**
  * 电子发票信息查询结果
+ *
+ * @author Mario Luo
  */
 @Data
 public class InvoiceResult implements Serializable {
+  private static final long serialVersionUID = 7896888653261133444L;
 
   /**
    * 发票相关信息
@@ -17,6 +20,8 @@ public class InvoiceResult implements Serializable {
 
   @Data
   public static class InvoiceDetail implements Serializable {
+    private static final long serialVersionUID = -3465795497702734126L;
+
     /**
      * 发票流水号
      */
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/MakeOutInvoiceRequest.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/MakeOutInvoiceRequest.java
index d9336eac1..666bdb97e 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/MakeOutInvoiceRequest.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/MakeOutInvoiceRequest.java
@@ -7,9 +7,12 @@
 
 /**
  * 开票信息请求参数
+ *
+ * @author Mario Luo
  */
 @Data
 public class MakeOutInvoiceRequest implements Serializable {
+  private static final long serialVersionUID = 2089481479917841771L;
 
   private InvoiceInfo invoiceinfo;
 
@@ -18,6 +21,8 @@ public class MakeOutInvoiceRequest implements Serializable {
    */
   @Data
   public static class InvoiceInfo implements Serializable {
+    private static final long serialVersionUID = 8492738482767944634L;
+
     /**
      * 维修openid
      */
@@ -145,6 +150,8 @@ public static class InvoiceInfo implements Serializable {
    */
   @Data
   public static class InvoiceDetailItem implements Serializable {
+    private static final long serialVersionUID = 2981363715996297681L;
+
     /**
      * 发票性质
      */
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/MerchantInvoicePlatformInfo.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/MerchantInvoicePlatformInfo.java
index 9c54b82c1..32adbc29a 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/MerchantInvoicePlatformInfo.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/MerchantInvoicePlatformInfo.java
@@ -1,14 +1,18 @@
 package me.chanjar.weixin.mp.bean.invoice.merchant;
 
+import com.google.gson.annotations.SerializedName;
 import lombok.Data;
 
 import java.io.Serializable;
 
 /**
  * 商户的开票平台信息
+ *
+ * @author Mario Luo
  */
 @Data
 public class MerchantInvoicePlatformInfo implements Serializable {
+  private static final long serialVersionUID = -2388214622725430530L;
 
   /**
    * 微信支付商户号
@@ -18,5 +22,6 @@ public class MerchantInvoicePlatformInfo implements Serializable {
   /**
    * 为该商户提供开票服务的开票平台 id ,由开票平台提供给商户
    */
+  @SerializedName("s_pappid")
   private String sPappid;
 }
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/MerchantInvoicePlatformInfoWrapper.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/MerchantInvoicePlatformInfoWrapper.java
index 035146616..fb79122fc 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/MerchantInvoicePlatformInfoWrapper.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/merchant/MerchantInvoicePlatformInfoWrapper.java
@@ -6,9 +6,12 @@
 
 /**
  * 设置商户联系信息和发票过时时间参数
+ *
+ * @author Mario Luo
  */
 @Data
 public class MerchantInvoicePlatformInfoWrapper implements Serializable {
+  private static final long serialVersionUID = 7994013978048258576L;
 
   private MerchantInvoicePlatformInfo paymchInfo;
 
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/reimburse/InvoiceBatchRequest.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/reimburse/InvoiceBatchRequest.java
index 48c878ba6..ce7b1860f 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/reimburse/InvoiceBatchRequest.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/reimburse/InvoiceBatchRequest.java
@@ -22,7 +22,6 @@
 @NoArgsConstructor
 @AllArgsConstructor
 public class InvoiceBatchRequest implements Serializable {
-
   private static final long serialVersionUID = -9121443117105107231L;
 
   /**
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/reimburse/InvoiceCommodityInfo.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/reimburse/InvoiceCommodityInfo.java
index a75874efa..2d4786341 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/reimburse/InvoiceCommodityInfo.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/reimburse/InvoiceCommodityInfo.java
@@ -2,6 +2,8 @@
 
 import lombok.Data;
 
+import java.io.Serializable;
+
 /**
  * 
  * 发票商品信息
@@ -10,7 +12,8 @@
  * @since 2021-03-23
  */
 @Data
-public class InvoiceCommodityInfo {
+public class InvoiceCommodityInfo implements Serializable {
+  private static final long serialVersionUID = 5139576099614652523L;
 
   /**
    * 项目(商品)名称
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/reimburse/InvoiceInfoRequest.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/reimburse/InvoiceInfoRequest.java
index 8a9b09f42..0dd960681 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/reimburse/InvoiceInfoRequest.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/reimburse/InvoiceInfoRequest.java
@@ -22,10 +22,8 @@
 @NoArgsConstructor
 @AllArgsConstructor
 public class InvoiceInfoRequest implements Serializable {
-
   private static final long serialVersionUID = 7854633127026139444L;
 
-
   /**
   * 发票卡券的card_id
   * 
@@ -45,8 +43,6 @@ public class InvoiceInfoRequest implements Serializable {
   @SerializedName("encrypt_code")
   private String encryptCode;
 
-
-
   public String toJson() {
     return WxMpGsonBuilder.create().toJson(this);
   }
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/reimburse/InvoiceInfoResponse.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/reimburse/InvoiceInfoResponse.java
index 0dded411c..5572f3c45 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/reimburse/InvoiceInfoResponse.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/reimburse/InvoiceInfoResponse.java
@@ -7,17 +7,20 @@
 import me.chanjar.weixin.common.util.json.GsonParser;
 import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
 
+import java.io.Serializable;
 import java.util.List;
 
 /**
  * 
  * 查询报销发票信息响应对象
  * 
+ * * @author xiaoyu * @since 2021-03-23 */ @Data -public class InvoiceInfoResponse { +public class InvoiceInfoResponse implements Serializable { + private static final long serialVersionUID = -4835089274990526299L; /** * 发票ID diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/reimburse/InvoiceUserInfo.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/reimburse/InvoiceUserInfo.java index 1d8d70924..3fc60b0b9 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/reimburse/InvoiceUserInfo.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/reimburse/InvoiceUserInfo.java @@ -3,17 +3,20 @@ import com.google.gson.annotations.SerializedName; import lombok.Data; +import java.io.Serializable; import java.util.List; /** *
  * 用户可在发票票面看到的主要信息
  * 
+ * * @author xiaoyu * @since 2021-03-23 */ @Data -public class InvoiceUserInfo { +public class InvoiceUserInfo implements Serializable { + private static final long serialVersionUID = 4970283608560240497L; /** * 发票加税合计金额,以分为单位 diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/reimburse/UpdateInvoiceStatusRequest.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/reimburse/UpdateInvoiceStatusRequest.java index 7e3b6e363..16a7901ca 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/reimburse/UpdateInvoiceStatusRequest.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/reimburse/UpdateInvoiceStatusRequest.java @@ -21,7 +21,6 @@ @NoArgsConstructor @AllArgsConstructor public class UpdateInvoiceStatusRequest implements Serializable { - private static final long serialVersionUID = -4122242332481909977L; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/reimburse/UpdateStatusBatchRequest.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/reimburse/UpdateStatusBatchRequest.java index e117d94d1..17f6a68cd 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/reimburse/UpdateStatusBatchRequest.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/invoice/reimburse/UpdateStatusBatchRequest.java @@ -22,7 +22,6 @@ @NoArgsConstructor @AllArgsConstructor public class UpdateStatusBatchRequest implements Serializable { - private static final long serialVersionUID = 7016357689566912199L; /** * 用户openid diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlMessage.java index 6a1d6c169..1e5e8eb32 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlMessage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlMessage.java @@ -189,6 +189,12 @@ public class WxMpXmlMessage implements Serializable { /////////////////////////////////////// // 群发消息返回的结果 /////////////////////////////////////// + /** + * 群发的消息ID + */ + @XStreamAlias("MsgID") + @JacksonXmlProperty(localName = "MsgID") + private Long massMsgId; /** * 群发的结果. */ diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/crypto/WxMpCryptUtil.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/crypto/WxMpCryptUtil.java index 9f22dbed3..b14023ef9 100755 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/crypto/WxMpCryptUtil.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/crypto/WxMpCryptUtil.java @@ -20,6 +20,9 @@ import com.google.common.base.CharMatcher; import com.google.common.io.BaseEncoding; import me.chanjar.weixin.mp.config.WxMpConfigStorage; +import org.apache.commons.lang3.StringUtils; + +import java.util.Base64; public class WxMpCryptUtil extends me.chanjar.weixin.common.util.crypto.WxCryptUtil { @@ -40,7 +43,7 @@ public WxMpCryptUtil(WxMpConfigStorage wxMpConfigStorage) { this.token = token; this.appidOrCorpid = appId; - this.aesKey = BaseEncoding.base64().decode(CharMatcher.whitespace().removeFrom(encodingAesKey)); + this.aesKey = Base64.getDecoder().decode(StringUtils.remove(encodingAesKey, " ")); } } diff --git a/weixin-java-open/pom.xml b/weixin-java-open/pom.xml index 5d77bf3b9..ed9c62e81 100644 --- a/weixin-java-open/pom.xml +++ b/weixin-java-open/pom.xml @@ -7,7 +7,7 @@ com.github.binarywang wx-java - 4.3.0 + 4.4.0 weixin-java-open diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenComponentService.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenComponentService.java index d56d8d432..6c31c4921 100644 --- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenComponentService.java +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenComponentService.java @@ -15,6 +15,10 @@ import me.chanjar.weixin.open.bean.minishop.goods.*; import me.chanjar.weixin.open.bean.minishop.limitdiscount.LimitDiscountGoods; import me.chanjar.weixin.open.bean.result.*; +import me.chanjar.weixin.open.bean.tcb.ShareCloudBaseEnvRequest; +import me.chanjar.weixin.open.bean.tcb.ShareCloudBaseEnvResponse; +import me.chanjar.weixin.open.bean.tcbComponent.GetShareCloudBaseEnvResponse; +import me.chanjar.weixin.open.bean.tcbComponent.GetTcbEnvListResponse; import org.jetbrains.annotations.Nullable; import java.io.File; @@ -130,9 +134,9 @@ public interface WxOpenComponentService { */ String FAST_REGISTER_PERSONAL_WEAPP_SEARCH_URL = "https://api.weixin.qq.com/wxa/component/fastregisterpersonalweapp?action=query"; - /** - * 快速创建试用小程序接口. - */ + /** + * 快速创建试用小程序接口. + */ String FAST_REGISTER_BETA_WEAPP_URL = "https://api.weixin.qq.com/wxa/component/fastregisterbetaweapp"; /** @@ -184,6 +188,13 @@ public interface WxOpenComponentService { String MINISHOP_GET_DELIVERY_COMPANY_URL = "https://api.weixin.qq.com/product/delivery/get_company_list"; + String BATCH_GET_ENVID_URL = "https://api.weixin.qq.com/componenttcb/batchgetenvid"; + + String DESCRIBE_ENVS_URL = "https://api.weixin.qq.com/componenttcb/describeenvs"; + + String MODIFY_ENV_URL = "https://api.weixin.qq.com/tcb/modifyenv"; + + String BATCH_SHARE_ENV = "https://api.weixin.qq.com/componenttcb/batchshareenv"; /** * Gets wx mp service by appid. @@ -408,7 +419,7 @@ public interface WxOpenComponentService { * @return the wx mp o auth 2 access token * @throws WxErrorException the wx error exception * @see WxMpService#getOAuth2Service() - * @deprecated 2021-05-21: 已修正公众号相关接口,请使用:WxOpenCommpentService.getWxMpServiceByAppid(mpAppId).getOAuth2Service().getAccessToken(code) + * @deprecated 2021-05-21: 已修正公众号相关接口,请使用:WxOpenComponentService.getWxMpServiceByAppid(mpAppId).getOAuth2Service().getAccessToken(code) */ @Deprecated WxOAuth2AccessToken oauth2getAccessToken(String appid, String code) throws WxErrorException; @@ -600,9 +611,9 @@ public interface WxOpenComponentService { * https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/Register_Mini_Programs/fastregisterpersonalweapp.html * 快速创建个人小程序 * - * @param idname 个人用户名字 - * @param wxuser 个人用户微信号 - * @param componentPhone 第三方联系电话 + * @param idname 个人用户名字 + * @param wxuser 个人用户微信号 + * @param componentPhone 第三方联系电话 * @return the wx open result * @throws WxErrorException */ @@ -622,7 +633,7 @@ public interface WxOpenComponentService { * https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/beta_Mini_Programs/fastregister.html * 注册试用小程序 * - * @param name 小程序名称 + * @param name 小程序名称 * @param openid 微信用户的openid(不是微信号) * @return the wx open result * @throws WxErrorException @@ -1020,4 +1031,44 @@ public interface WxOpenComponentService { * @return */ WxOpenResult updateLimitDiscountStatus(String appId, Long taskId, Integer status) throws WxErrorException; + + /** + * 查询环境共享信息 + * https://developers.weixin.qq.com/doc/oplatform/openApi/OpenApiDoc/cloudbase-batch/env-mgnt/getShareCloudbaseEnv.html + * + * @param appids 要查询的appid + * @return + */ + GetShareCloudBaseEnvResponse getShareCloudBaseEnv(List appids) throws WxErrorException; + + + /** + * 获取环境信息 + * https://developers.weixin.qq.com/doc/oplatform/openApi/OpenApiDoc/cloudbase-batch/env-mgnt/getTcbEnvList.html + * + * @return + * @throws WxErrorException + */ + GetTcbEnvListResponse getTcbEnvList() throws WxErrorException; + + /** + * 转换云环境 + * https://developers.weixin.qq.com/doc/oplatform/openApi/OpenApiDoc/cloudbase-batch/env-mgnt/changeTcbEnv.html + * + * @param env 环境id + * @return + * @throws WxErrorException + */ + WxOpenResult changeTcbEnv(String env) throws WxErrorException; + + + /** + * 环境共享 + * https://developers.weixin.qq.com/doc/oplatform/openApi/OpenApiDoc/cloudbase-batch/env-mgnt/shareCloudbaseEnv.html + * + * @param request + * @return + * @throws WxErrorException + */ + ShareCloudBaseEnvResponse shareCloudBaseEnv(ShareCloudBaseEnvRequest request) throws WxErrorException; } diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaPrivacyService.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaPrivacyService.java index 4bf78f53b..c8ee243f4 100644 --- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaPrivacyService.java +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaPrivacyService.java @@ -1,14 +1,13 @@ package me.chanjar.weixin.open.api; import me.chanjar.weixin.common.error.WxErrorException; -import me.chanjar.weixin.open.bean.ma.privacy.GetPrivacySettingResult; -import me.chanjar.weixin.open.bean.ma.privacy.SetPrivacySetting; -import me.chanjar.weixin.open.bean.ma.privacy.UploadPrivacyFileResult; +import me.chanjar.weixin.open.bean.ma.privacy.*; import org.jetbrains.annotations.Nullable; /** - * 微信第三方平台 小程序用户隐私保护指引接口 + * 微信第三方平台 小程序用户隐私保护指引接口 / 申请隐私接口(从2022年4月18日开始,部分小程序前端 api 需申请后,方可使用。该接口用于获取“需申请并审核通过”后才可使用的接口列表。) * https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/privacy_config/set_privacy_setting.html + * https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/apply_api/get_privacy_interface.html * * @author 广州跨界 */ @@ -29,6 +28,16 @@ public interface WxOpenMaPrivacyService { */ String OPEN_UPLOAD_PRIVACY_FILE = "https://api.weixin.qq.com/cgi-bin/component/uploadprivacyextfile"; + /** + * 4 获取接口列表 从2022年4月18日开始,部分小程序前端 api 需申请后 + */ + String GET_PRIVATE_INTERFACE = "https://api.weixin.qq.com/wxa/security/get_privacy_interface"; + + /** + * 5 申请接口 从2022年4月18日开始,部分小程序前端 api 需申请后 + */ + String APPLY_PRIVATE_INTERFACE = "https://api.weixin.qq.com/wxa/security/apply_privacy_interface"; + /** * 查询小程序用户隐私保护指引 @@ -62,4 +71,27 @@ public interface WxOpenMaPrivacyService { * @throws WxErrorException 如果出错,抛出此异常 */ UploadPrivacyFileResult uploadPrivacyFile(String content) throws WxErrorException; + + + /** + * 隐私接口-获取接口列表 + * 从2022年4月18日开始,部分小程序前端 api 需申请后,方可使用。该接口用于获取“需申请并审核通过”后才可使用的接口列表。 + * 文档地址:https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/apply_api/get_privacy_interface.html + * + * @return 获取结果 + * @throws WxErrorException 如果出错,抛出此异常 + */ + GetPrivacyInterfaceResult getPrivacyInterface() throws WxErrorException; + + + /** + * 隐私接口-申请接口 + * 从2022年4月18日开始,部分小程序前端 api 需申请后,方可使用。该接口用于获取“需申请并审核通过”后才可使用的接口列表。 + * 文档地址:https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/apply_api/get_privacy_interface.html + * + * @param dto 请求参数 + * @return 获取结果 + * @throws WxErrorException 如果出错,抛出此异常 + */ + ApplyPrivacyInterfaceResult applyPrivacyInterface(ApplyPrivacyInterface dto) throws WxErrorException; } diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaService.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaService.java index f907ff9be..c79c1cc29 100644 --- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaService.java +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaService.java @@ -238,6 +238,24 @@ public interface WxOpenMaService extends WxMaService { */ String API_AUDIT_UPLOAD_MEDIA = "https://api.weixin.qq.com/wxa/uploadmedia"; + /** + * 小程序管理-获取公众号关联的小程序 + */ + String API_WX_AMP_LINK_GET = "https://api.weixin.qq.com/cgi-bin/wxopen/wxamplinkget"; + /** + * 小程序管理-关联小程序 + */ + String API_WX_AMP_LINK_CREATE = "https://api.weixin.qq.com/cgi-bin/wxopen/wxamplink"; + /** + * 小程序管理-解除已关联的小程序 + */ + String API_WX_AMP_LINK_UN = "https://api.weixin.qq.com/cgi-bin/wxopen/wxampunlink"; + + /** + * 小程序管理-查询小程序版本信息 + */ + String API_GET_VERSION_INFO = "https://api.weixin.qq.com/wxa/getversioninfo"; + /** * 获得小程序的域名配置信息 * @@ -645,4 +663,56 @@ WxOpenMaDomainResult modifyDomain(String action, List requestDomains, Li * @return */ WxMaAuditMediaUploadResult uploadMedia(File file) throws WxErrorException; + + /** + *
+   * 获取公众号关联的小程序
+   * 请求方式:POST(HTTPS)
+   * 请求地址:https://api.weixin.qq.com/cgi-bin/wxopen/wxamplinkget?access_token=TOKEN
+   * 文档地址:https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/Official__Accounts/Mini_Program_Management_Permission.html
+   * 
+   * @return 公众号关联的小程序
+   */
+  WxAmpLinkResult getWxAmpLink() throws WxErrorException;
+
+  /**
+   * 
+   * 关联小程序
+   * 关联流程(需要公众号和小程序管理员双方确认):
+   * 1、第三方平台调用接口发起关联
+   * 2、公众号管理员收到模板消息,同意关联小程序。
+   * 3、小程序管理员收到模板消息,同意关联公众号。
+   * 4、关联成功
+   * 等待管理员同意的中间状态可使用“获取公众号关联的小程序”接口进行查询。
+   * 请求方式:POST(HTTPS)
+   * 请求地址:https://api.weixin.qq.com/cgi-bin/wxopen/wxamplink?access_token=TOKEN
+   * 文档地址:https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/Official__Accounts/Mini_Program_Management_Permission.html
+   * 
+   * @param appid 小程序 appid
+   * @param notifyUsers 是否发送模板消息通知公众号粉丝
+   * @param showProfile 是否展示公众号主页中
+   * @return 响应结果
+   */
+  WxOpenResult wxAmpLink(String appid, String notifyUsers, String showProfile) throws WxErrorException;
+
+  /**
+   * 
+   * 解除已关联的小程序
+   * 请求方式:POST(HTTPS)
+   * 请求地址:https://api.weixin.qq.com/cgi-bin/wxopen/wxampunlink?access_token=TOKEN
+   * 文档地址:https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/Official__Accounts/Mini_Program_Management_Permission.html
+   * 
+   * @param appid 小程序 appid
+   * @return 响应结果
+   */
+  WxOpenResult wxAmpUnLink(String appid) throws WxErrorException;
+
+  /**
+   * 查询小程序版本信息
+   *
+   * @return the wx open result
+   * @throws WxErrorException the wx error exception
+   */
+  WxOpenVersioninfoResult getVersionInfo() throws WxErrorException;
+
 }
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenComponentServiceImpl.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenComponentServiceImpl.java
index 28bd71cb5..9589a9843 100644
--- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenComponentServiceImpl.java
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenComponentServiceImpl.java
@@ -1,6 +1,7 @@
 package me.chanjar.weixin.open.api.impl;
 
 import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
+import com.google.gson.Gson;
 import com.google.gson.JsonArray;
 import com.google.gson.JsonObject;
 import com.google.gson.reflect.TypeToken;
@@ -28,6 +29,10 @@
 import me.chanjar.weixin.open.bean.minishop.limitdiscount.LimitDiscountGoods;
 import me.chanjar.weixin.open.bean.minishop.limitdiscount.LimitDiscountSku;
 import me.chanjar.weixin.open.bean.result.*;
+import me.chanjar.weixin.open.bean.tcb.ShareCloudBaseEnvRequest;
+import me.chanjar.weixin.open.bean.tcb.ShareCloudBaseEnvResponse;
+import me.chanjar.weixin.open.bean.tcbComponent.GetShareCloudBaseEnvResponse;
+import me.chanjar.weixin.open.bean.tcbComponent.GetTcbEnvListResponse;
 import me.chanjar.weixin.open.util.json.WxOpenGsonBuilder;
 import org.apache.commons.lang3.StringUtils;
 import org.jetbrains.annotations.Nullable;
@@ -467,8 +472,8 @@ public WxOAuth2AccessToken oauth2refreshAccessToken(String appId, String refresh
 
   @Override
   public String oauth2buildAuthorizationUrl(String appId, String redirectURI, String scope, String state) {
-    return String.format(CONNECT_OAUTH2_AUTHORIZE_URL,
-      appId, URIUtil.encodeURIComponent(redirectURI), scope, StringUtils.trimToEmpty(state), getWxOpenConfigStorage().getComponentAppId());
+    return String.format(CONNECT_OAUTH2_AUTHORIZE_URL, appId, URIUtil.encodeURIComponent(redirectURI), scope,
+      StringUtils.trimToEmpty(state), getWxOpenConfigStorage().getComponentAppId());
   }
 
   @Override
@@ -1222,4 +1227,37 @@ public WxOpenResult updateLimitDiscountStatus(String appId, Long taskId, Integer
 
     return WxOpenGsonBuilder.create().fromJson(response, WxOpenResult.class);
   }
+
+  @Override
+  public GetShareCloudBaseEnvResponse getShareCloudBaseEnv(List appids) throws WxErrorException {
+    JsonObject jsonObject = new JsonObject();
+    JsonArray jsonArray = new JsonArray();
+    for(String appId : appids) {
+      jsonArray.add(appId);
+    }
+    jsonObject.add("appids", jsonArray);
+    String response = post(BATCH_GET_ENVID_URL, jsonObject.toString());
+    return WxOpenGsonBuilder.create().fromJson(response, GetShareCloudBaseEnvResponse.class);
+  }
+
+  @Override
+  public GetTcbEnvListResponse getTcbEnvList() throws WxErrorException {
+    String response = post(DESCRIBE_ENVS_URL, new JsonObject().toString());
+    return WxOpenGsonBuilder.create().fromJson(response, GetTcbEnvListResponse.class);
+  }
+
+  @Override
+  public WxOpenResult changeTcbEnv(String env) throws WxErrorException {
+    JsonObject jsonObject = new JsonObject();
+    jsonObject.addProperty("env", env);
+    String response = post(MODIFY_ENV_URL, jsonObject.toString());
+    return WxOpenGsonBuilder.create().fromJson(response, WxOpenResult.class);
+  }
+
+  @Override
+  public ShareCloudBaseEnvResponse shareCloudBaseEnv(ShareCloudBaseEnvRequest request) throws WxErrorException {
+    Gson gson = new Gson();
+    String response = post(BATCH_SHARE_ENV, gson.toJson(request));
+    return WxOpenGsonBuilder.create().fromJson(response, ShareCloudBaseEnvResponse.class);
+  }
 }
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenInMemoryConfigStorage.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenInMemoryConfigStorage.java
index 4a01dd4ec..f8dd345ee 100644
--- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenInMemoryConfigStorage.java
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenInMemoryConfigStorage.java
@@ -257,6 +257,7 @@ private static class WxOpenInnerConfigStorage implements WxMpConfigStorage, WxMa
     private final String appId;
     private WxMpHostConfig hostConfig;
     private String apiHostUrl;
+    private String accessTokenUrl;
 
     /**
      * 小程序原始ID
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMaPrivacyServiceImpl.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMaPrivacyServiceImpl.java
index f7deb523c..d8eb840c9 100644
--- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMaPrivacyServiceImpl.java
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMaPrivacyServiceImpl.java
@@ -6,9 +6,7 @@
 import me.chanjar.weixin.common.error.WxError;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.open.api.WxOpenMaPrivacyService;
-import me.chanjar.weixin.open.bean.ma.privacy.GetPrivacySettingResult;
-import me.chanjar.weixin.open.bean.ma.privacy.SetPrivacySetting;
-import me.chanjar.weixin.open.bean.ma.privacy.UploadPrivacyFileResult;
+import me.chanjar.weixin.open.bean.ma.privacy.*;
 import me.chanjar.weixin.open.util.json.WxOpenGsonBuilder;
 import org.jetbrains.annotations.Nullable;
 
@@ -52,4 +50,16 @@ public UploadPrivacyFileResult uploadPrivacyFile(String content) throws WxErrorE
 //    return WxOpenGsonBuilder.create().fromJson(json, UploadPrivacyFileResult.class);
     throw new WxErrorException(new WxError(5003, "暂未实现用户隐私指引内容上传"));
   }
+
+  @Override
+  public GetPrivacyInterfaceResult getPrivacyInterface() throws WxErrorException {
+    String json = wxMaService.get(GET_PRIVATE_INTERFACE, "");
+    return WxOpenGsonBuilder.create().fromJson(json, GetPrivacyInterfaceResult.class);
+  }
+
+  @Override
+  public ApplyPrivacyInterfaceResult applyPrivacyInterface(ApplyPrivacyInterface dto) throws WxErrorException {
+    String json = wxMaService.post(APPLY_PRIVATE_INTERFACE, dto);
+    return WxOpenGsonBuilder.create().fromJson(json, ApplyPrivacyInterfaceResult.class);
+  }
 }
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMaServiceImpl.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMaServiceImpl.java
index 7188a669c..9bca8b5e9 100644
--- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMaServiceImpl.java
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMaServiceImpl.java
@@ -406,6 +406,30 @@ public WxMaAuditMediaUploadResult uploadMedia(File file) throws WxErrorException
     return (WxMaAuditMediaUploadResult) this.execute(AuditMediaUploadRequestExecutor.create(getRequestHttp()), API_AUDIT_UPLOAD_MEDIA, file);
   }
 
+  @Override
+  public WxAmpLinkResult getWxAmpLink() throws WxErrorException {
+    String response = post(API_WX_AMP_LINK_GET, "{}");
+    return WxMaGsonBuilder.create().fromJson(response, WxAmpLinkResult.class);
+  }
+
+  @Override
+  public WxOpenResult wxAmpLink(String appid, String notifyUsers, String showProfile) throws WxErrorException {
+    JsonObject params = new JsonObject();
+    params.addProperty("appid", appid);
+    params.addProperty("notify_users", notifyUsers);
+    params.addProperty("show_profile", showProfile);
+    String response = post(API_WX_AMP_LINK_CREATE, GSON.toJson(params));
+    return WxMaGsonBuilder.create().fromJson(response, WxOpenResult.class);
+  }
+
+  @Override
+  public WxOpenResult wxAmpUnLink(String appid) throws WxErrorException {
+    JsonObject params = new JsonObject();
+    params.addProperty("appid", appid);
+    String response = post(API_WX_AMP_LINK_UN, GSON.toJson(params));
+    return WxMaGsonBuilder.create().fromJson(response, WxOpenResult.class);
+  }
+
   private JsonArray toJsonArray(List strList) {
     JsonArray jsonArray = new JsonArray();
     if (strList != null && !strList.isEmpty()) {
@@ -415,4 +439,11 @@ private JsonArray toJsonArray(List strList) {
     }
     return jsonArray;
   }
+
+  @Override
+  public WxOpenVersioninfoResult getVersionInfo() throws WxErrorException {
+    JsonObject params = new JsonObject();
+    String response = post(API_GET_VERSION_INFO, GSON.toJson(params));
+    return WxMaGsonBuilder.create().fromJson(response, WxOpenVersioninfoResult.class);
+  }
 }
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMpOAuth2ServiceImpl.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMpOAuth2ServiceImpl.java
index 406e36348..3f990ecfe 100644
--- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMpOAuth2ServiceImpl.java
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMpOAuth2ServiceImpl.java
@@ -28,7 +28,7 @@ public WxOpenMpOAuth2ServiceImpl(WxOpenComponentService wxOpenComponentService,
 
   /**
    * 第三方平台代公众号发起网页授权
-   * 文档地址:https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/Before_Develop/Official_Accounts/official_account_website_authorization.html
+   * 文档地址:第三方平台代公众号发起网页授权
    *
    * @param code 微信授权code
    * @return 微信用户信息
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenServiceAbstractImpl.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenServiceAbstractImpl.java
index fa89d0937..845441c2d 100644
--- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenServiceAbstractImpl.java
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenServiceAbstractImpl.java
@@ -1,5 +1,6 @@
 package me.chanjar.weixin.open.api.impl;
 
+import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.common.enums.WxType;
 import me.chanjar.weixin.common.error.WxError;
 import me.chanjar.weixin.common.error.WxErrorException;
@@ -17,8 +18,8 @@
 /**
  * @author 007
  */
+@Slf4j
 public abstract class WxOpenServiceAbstractImpl implements WxOpenService, RequestHttp {
-  private final Logger log = LoggerFactory.getLogger(this.getClass());
   private WxOpenComponentService wxOpenComponentService = new WxOpenComponentServiceImpl(this);
   private WxOpenConfigStorage wxOpenConfigStorage;
 
@@ -46,17 +47,17 @@ public void setWxOpenConfigStorage(WxOpenConfigStorage wxOpenConfigStorage) {
   protected  T execute(RequestExecutor executor, String uri, E data) throws WxErrorException {
     try {
       T result = executor.execute(uri, data, WxType.Open);
-      this.log.debug("\n【请求地址】: {}\n【请求参数】:{}\n【响应数据】:{}", uri, data, result);
+      log.debug("\n【请求地址】: {}\n【请求参数】:{}\n【响应数据】:{}", uri, data, result);
       return result;
     } catch (WxErrorException e) {
       WxError error = e.getError();
       if (error.getErrorCode() != 0) {
-        this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", uri, data, error);
+        log.warn("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", uri, data, error);
         throw new WxErrorException(error, e);
       }
       return null;
     } catch (IOException e) {
-      this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【异常信息】:{}", uri, data, e.getMessage());
+      log.warn("\n【请求地址】: {}\n【请求参数】:{}\n【异常信息】:{}", uri, data, e.getMessage());
       throw new WxRuntimeException(e);
     }
   }
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/WxOpenAuthorizerInfo.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/WxOpenAuthorizerInfo.java
index a80dab030..0888a30d4 100644
--- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/WxOpenAuthorizerInfo.java
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/WxOpenAuthorizerInfo.java
@@ -23,6 +23,16 @@ public class WxOpenAuthorizerInfo implements Serializable {
   private Map businessInfo;
   private String alias;
   private String qrcodeUrl;
+  /**
+   * 帐号状态
+   * 类型	说明
+   * 1	正常
+   * 14	已注销
+   * 16	已封禁
+   * 18	已告警
+   * 19	已冻结
+   */
+  private Integer accountStatus;
   /**
    * 账号介绍
    */
@@ -33,8 +43,30 @@ public class WxOpenAuthorizerInfo implements Serializable {
    */
   private MiniProgramInfo miniProgramInfo;
 
+  /**
+   * 小程序注册方式
+   * 类型	说明
+   * 0	普通方式注册
+   * 2	通过复用公众号创建小程序 api 注册
+   * 6	通过法人扫脸创建企业小程序 api 注册
+   * 13	通过创建试用小程序 api 注册
+   * 15	通过联盟控制台注册
+   * 16	通过创建个人小程序 api 注册
+   * 17	通过创建个人交易小程序 api 注册
+   * 19	通过试用小程序转正 api 注册
+   * 22	通过复用商户号创建企业小程序 api 注册
+   * 23	通过复用商户号转正 api 注册
+   */
+  private Integer registerType;
+
+  /**
+   * 小程序基础配置信息
+   */
+  private BasicConfig basicConfig;
+
   @Data
-  public class MiniProgramInfo {
+  public static class MiniProgramInfo implements Serializable {
+    private static final long serialVersionUID = 8857028017332191988L;
     @SerializedName("visit_status")
     private Integer visitStatus;
     /**
@@ -44,13 +76,15 @@ public class MiniProgramInfo {
     private List categories;
 
     @Data
-    public class Category {
+    public static class Category implements Serializable {
+      private static final long serialVersionUID = -5771529867281696141L;
       private String first;
       private String second;
     }
 
     @Data
-    public class Network {
+    public static class Network implements Serializable {
+      private static final long serialVersionUID = -18932624803859857L;
       @SerializedName("RequestDomain")
       private List requestDomain;
       @SerializedName("WsRequestDomain")
@@ -63,4 +97,13 @@ public class Network {
       private List bizDomain;
     }
   }
+
+  @Data
+  public static class BasicConfig implements Serializable {
+    private static final long serialVersionUID = -8857028017332191989L;
+    @SerializedName("is_phone_configured")
+    private Boolean isPhoneConfigured;
+    @SerializedName("is_email_configured")
+    private Boolean isEmailConfigured;
+  }
 }
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/ma/WxMaOpenCommitStandardExt.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/ma/WxMaOpenCommitStandardExt.java
index 2d4b71391..73c2356db 100644
--- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/ma/WxMaOpenCommitStandardExt.java
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/ma/WxMaOpenCommitStandardExt.java
@@ -35,13 +35,12 @@
  */
 @Data
 public class WxMaOpenCommitStandardExt implements Serializable {
-
   private static final long serialVersionUID = 4595618023108631477L;
 
   /**
    * 授权小程序Appid,可填入商户小程序AppID,以区分不同商户
    */
-  @SerializedName("create_time")
+  @SerializedName("extAppid")
   private String extAppId;
 
   /**
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/ma/privacy/ApplyPrivacyInterface.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/ma/privacy/ApplyPrivacyInterface.java
new file mode 100644
index 000000000..b92a68027
--- /dev/null
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/ma/privacy/ApplyPrivacyInterface.java
@@ -0,0 +1,47 @@
+package me.chanjar.weixin.open.bean.ma.privacy;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+/**
+ * 申请隐私接口
+ *
+ * @author 广州跨界
+ */
+@Getter
+@Setter
+public class ApplyPrivacyInterface {
+
+  /**
+   * 接口英文名称,如:wx.chooseAddress/wx.choosePoi/wx.getLocation/wx.onLocationChange/wx.chooseLocation
+   */
+  @SerializedName("api_name")
+  private String apiName;
+
+  /**
+   * 申请说原因,不超过300个字符;需要以utf-8编码提交,否则会出现审核失败
+   */
+  @SerializedName("content")
+  private String content;
+
+  /**
+   * (辅助网页)例如,上传官网网页链接用于辅助审核
+   */
+  @SerializedName("url_list")
+  private List urlList;
+
+  /**
+   * (辅助图片)填写图片的url ,最多10个
+   */
+  @SerializedName("pic_list")
+  private List picList;
+
+  /**
+   * (辅助视频)填写视频的链接 ,最多支持1个;视频格式只支持mp4格式
+   */
+  @SerializedName("video_list")
+  private List videoList;
+}
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/ma/privacy/ApplyPrivacyInterfaceResult.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/ma/privacy/ApplyPrivacyInterfaceResult.java
new file mode 100644
index 000000000..c394ad687
--- /dev/null
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/ma/privacy/ApplyPrivacyInterfaceResult.java
@@ -0,0 +1,23 @@
+package me.chanjar.weixin.open.bean.ma.privacy;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Getter;
+import lombok.Setter;
+import me.chanjar.weixin.open.bean.result.WxOpenResult;
+
+/**
+ * 获取接口列表 响应
+ *
+ * @author 广州跨界
+ */
+@Getter
+@Setter
+public class ApplyPrivacyInterfaceResult extends WxOpenResult {
+
+  /**
+   * 审核ID
+   */
+  @SerializedName("audit_id")
+  private Long auditId;
+
+}
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/ma/privacy/GetPrivacyInterfaceResult.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/ma/privacy/GetPrivacyInterfaceResult.java
new file mode 100644
index 000000000..d016536c2
--- /dev/null
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/ma/privacy/GetPrivacyInterfaceResult.java
@@ -0,0 +1,92 @@
+package me.chanjar.weixin.open.bean.ma.privacy;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Getter;
+import lombok.Setter;
+import me.chanjar.weixin.open.bean.result.WxOpenResult;
+import org.springframework.lang.Nullable;
+
+import java.util.List;
+
+/**
+ * 获取接口列表 响应
+ *
+ * @author 广州跨界
+ */
+@Getter
+@Setter
+public class GetPrivacyInterfaceResult extends WxOpenResult {
+
+  /**
+   * 隐私接口列表
+   */
+  @SerializedName("interface_list")
+  private List interfaceList;
+
+
+  /**
+   * 隐私接口
+   */
+  @Getter
+  @Setter
+  public static class Interface {
+
+    /**
+     * 接口英文名称,如:wx.chooseAddress/wx.choosePoi/wx.getLocation/wx.onLocationChange/wx.chooseLocation
+     */
+    @SerializedName("api_name")
+    private String apiName;
+
+    /**
+     * 接口中文名称,如:获取用户收货地址/选择位置,支持模糊定位(精确到市)和精确定位混选/获取当前的地理位置、速度/监听实时地理位置变化事件/打开地图选择位置
+     */
+    @SerializedName("api_ch_name")
+    private String apiChName;
+
+    /**
+     * api描述
+     */
+    @SerializedName("api_desc")
+    private String apiDesc;
+
+    /**
+     * 申请时间 ,该字段发起申请后才会有
+     */
+    @Nullable
+    @SerializedName("apply_time")
+    private String applyTime;
+
+    /**
+     * 接口状态,该字段发起申请后才会有,1待申请开通,2无权限,3申请中,4申请失败,5已开通
+     */
+    @Nullable
+    @SerializedName("status")
+    private String status;
+
+    /**
+     * 申请单号,该字段发起申请后才会有
+     */
+    @Nullable
+    @SerializedName("audit_id")
+    private String auditId;
+
+    /**
+     * 申请被驳回原因或者无权限,该字段申请驳回时才会有
+     */
+    @Nullable
+    @SerializedName("fail_reason")
+    private String failReason;
+
+    /**
+     * api文档链接
+     */
+    @SerializedName("api_link")
+    private String apiLink;
+
+    /**
+     * 分组名,如:地理位置
+     */
+    @SerializedName("group_name")
+    private String groupName;
+  }
+}
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/message/WxOpenMaSubmitAuditMessage.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/message/WxOpenMaSubmitAuditMessage.java
index d74f3d8d5..202a42253 100644
--- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/message/WxOpenMaSubmitAuditMessage.java
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/message/WxOpenMaSubmitAuditMessage.java
@@ -47,4 +47,10 @@ public class WxOpenMaSubmitAuditMessage implements Serializable {
    */
   @SerializedName("feedback_stuff")
   private String feedbackStuff;
+
+  /**
+   * 用于声明是否不使用“代码中检测出但是未配置的隐私相关接口”
+   */
+  @SerializedName("privacy_api_not_use")
+  private Boolean privacyApiNotUse;
 }
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/result/WxAmpLinkResult.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/result/WxAmpLinkResult.java
new file mode 100644
index 000000000..51604ee64
--- /dev/null
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/result/WxAmpLinkResult.java
@@ -0,0 +1,111 @@
+package me.chanjar.weixin.open.bean.result;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+/**
+ * 公众号关联的小程序
+ *
+ * @author zhongjun
+ * @date 2022/4/29
+ **/
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class WxAmpLinkResult extends WxOpenResult{
+
+  /**
+   * 关联的小程序列表,具有 items 字段,内带有参数
+   */
+  @SerializedName("wxopens")
+  private WxOpen wxOpen;
+
+  @Getter
+  @Setter
+  public static class WxOpen{
+    @SerializedName("items")
+    private List items;
+  }
+
+  @Getter
+  @Setter
+  public static class Item{
+
+    /**
+     * 关联状态
+     * 1:已关联;
+     * 2:等待小程序管理员确认中;
+     * 3:小程序管理员拒绝关联
+     * 12:等待公众号管理员确认中;
+     */
+    private Integer status;
+
+    /**
+     * 小程序appid
+     */
+    private String appid;
+
+    /**
+     * 小程序 gh_id
+     */
+    private String username;
+
+    /**
+     * 小程序名称
+     */
+    private String nickname;
+
+    /**
+     * 是否在公众号管理页展示中
+     */
+    private Integer selected;
+
+    /**
+     * 是否展示在附近的小程序中
+     */
+    @SerializedName("nearby_display_status")
+    private Integer nearbyDisplayStatus;
+
+    /**
+     * 是否已经发布
+     */
+    private Integer released;
+
+    /**
+     * 头像 url
+     */
+    @SerializedName("headimg_url")
+    private String headImgUrl;
+
+    /**
+     * 小程序邮箱
+     */
+    private String email;
+
+    /**
+     * 微信认证及支付信息
+     */
+    @SerializedName("func_info")
+    private List funcInfo;
+
+  }
+
+  @Getter
+  @Setter
+  public static class FuncInfo{
+    /**
+     * 微信认证及支付信息,0 表示未开通,1 表示开通
+     */
+    private Integer status;
+
+    private String name;
+
+    private Long id;
+
+  }
+}
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/result/WxOpenVersioninfoResult.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/result/WxOpenVersioninfoResult.java
new file mode 100644
index 000000000..f2ed02f25
--- /dev/null
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/result/WxOpenVersioninfoResult.java
@@ -0,0 +1,74 @@
+package me.chanjar.weixin.open.bean.result;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import me.chanjar.weixin.open.util.json.WxOpenGsonBuilder;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 小程序版本信息
+ *
+ * @author cocoa
+ * @date 20220727
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class WxOpenVersioninfoResult extends WxOpenResult  {
+
+  private static final long serialVersionUID = -1042219138582803275L;
+
+  @SerializedName("exp_info")
+  ExpInfo expInfo;
+
+  @SerializedName("release_info")
+  ReleaseInfo releaseInfo;
+
+  @Override
+  public String toString() {
+    return WxOpenGsonBuilder.create().toJson(this);
+  }
+
+  @Data
+  public static class ReleaseInfo {
+    /**
+     * 发布线上版的时间
+     */
+    @SerializedName("release_time")
+    private Long releaseTime;
+    /**
+     * 线上版版本信息
+     */
+    @SerializedName("release_version")
+    private String releaseVersion;
+    /**
+     * 线上版本描述
+     */
+    @SerializedName("release_desc")
+    private String releaseDesc;
+  }
+
+
+  @Data
+  public static class ExpInfo {
+    /**
+     * 提交体验版的时间
+     */
+    @SerializedName("exp_time")
+    private Long expTime;
+    /**
+     * 头像已使用修改次数(本月)
+     */
+    @SerializedName("exp_version")
+    private String expVersion;
+    /**
+     * 头像修改次数总额度(本月)
+     */
+    @SerializedName("exp_desc")
+    private String expDesc;
+  }
+
+
+}
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/tcb/ShareCloudBaseEnvRequest.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/tcb/ShareCloudBaseEnvRequest.java
new file mode 100644
index 000000000..dd64f15cc
--- /dev/null
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/tcb/ShareCloudBaseEnvRequest.java
@@ -0,0 +1,32 @@
+package me.chanjar.weixin.open.bean.tcb;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class ShareCloudBaseEnvRequest implements Serializable {
+  private static final long serialVersionUID = 410566969624593042L;
+
+  @SerializedName("data")
+  private List data;
+
+  @Data
+  @Builder
+  @AllArgsConstructor
+  @NoArgsConstructor
+  public static class DataDTO implements Serializable {
+    @SerializedName("env")
+    private String env;
+    @SerializedName("appids")
+    private List appids;
+  }
+}
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/tcb/ShareCloudBaseEnvResponse.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/tcb/ShareCloudBaseEnvResponse.java
new file mode 100644
index 000000000..ff40dd725
--- /dev/null
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/tcb/ShareCloudBaseEnvResponse.java
@@ -0,0 +1,28 @@
+package me.chanjar.weixin.open.bean.tcb;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Builder;
+import lombok.Data;
+import me.chanjar.weixin.open.bean.result.WxOpenResult;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+@Builder
+public class ShareCloudBaseEnvResponse extends WxOpenResult implements Serializable {
+  private static final long serialVersionUID = 316444074975118997L;
+
+  @SerializedName("err_list")
+  private List errList;
+
+  @Data
+  public static class ErrListDTO implements Serializable {
+    @SerializedName("env")
+    private String env;
+    @SerializedName("appid")
+    private String appid;
+    @SerializedName("errmsg")
+    private String errmsg;
+  }
+}
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/tcbComponent/GetShareCloudBaseEnvResponse.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/tcbComponent/GetShareCloudBaseEnvResponse.java
new file mode 100644
index 000000000..d498e3073
--- /dev/null
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/tcbComponent/GetShareCloudBaseEnvResponse.java
@@ -0,0 +1,35 @@
+package me.chanjar.weixin.open.bean.tcbComponent;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+import me.chanjar.weixin.open.bean.result.WxOpenResult;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+public class GetShareCloudBaseEnvResponse extends WxOpenResult implements Serializable {
+  private static final long serialVersionUID = -6267755285547585403L;
+
+  @SerializedName("relation_data")
+  private List relationData;
+
+  @SerializedName("err_list")
+  private List errList;
+
+  @Data
+  public static class RelationDataDTO implements Serializable {
+    @SerializedName("appid")
+    private String appid;
+    @SerializedName("env_list")
+    private List envList;
+  }
+
+  @Data
+  public static class ErrListDTO implements Serializable {
+    @SerializedName("appid")
+    private String appid;
+    @SerializedName("errmsg")
+    private String errmsg;
+  }
+}
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/tcbComponent/GetTcbEnvListResponse.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/tcbComponent/GetTcbEnvListResponse.java
new file mode 100644
index 000000000..6551b4d3d
--- /dev/null
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/tcbComponent/GetTcbEnvListResponse.java
@@ -0,0 +1,38 @@
+package me.chanjar.weixin.open.bean.tcbComponent;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+import me.chanjar.weixin.open.bean.result.WxOpenResult;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+public class GetTcbEnvListResponse extends WxOpenResult implements Serializable {
+  private static final long serialVersionUID = -5896318347861752798L;
+
+  @SerializedName("info_list")
+  private List infoList;
+
+  @Data
+  public static class InfoListDTO implements Serializable {
+    @SerializedName("env")
+    private String env;
+    @SerializedName("alias")
+    private String alias;
+    @SerializedName("create_time")
+    private String createTime;
+    @SerializedName("update_time")
+    private String updateTime;
+    @SerializedName("status")
+    private String status;
+    @SerializedName("package_id")
+    private String packageId;
+    @SerializedName("package_name")
+    private String packageName;
+    @SerializedName("dbinstance_id")
+    private String dbinstanceId;
+    @SerializedName("bucket_id")
+    private String bucketId;
+  }
+}
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/util/WxOpenCryptUtil.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/util/WxOpenCryptUtil.java
index b507e0daa..e6c8ce992 100644
--- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/util/WxOpenCryptUtil.java
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/util/WxOpenCryptUtil.java
@@ -3,6 +3,9 @@
 import com.google.common.base.CharMatcher;
 import com.google.common.io.BaseEncoding;
 import me.chanjar.weixin.open.api.WxOpenConfigStorage;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.Base64;
 
 /**
  * @author 007
@@ -25,6 +28,6 @@ public WxOpenCryptUtil(WxOpenConfigStorage wxOpenConfigStorage) {
 
     this.token = token;
     this.appidOrCorpid = appId;
-    this.aesKey = BaseEncoding.base64().decode(CharMatcher.whitespace().removeFrom(encodingAesKey));
+    this.aesKey = Base64.getDecoder().decode(StringUtils.remove(encodingAesKey, " "));
   }
 }
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/util/json/WxOpenAuthorizerInfoGsonAdapter.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/util/json/WxOpenAuthorizerInfoGsonAdapter.java
index 2fb4e7957..7e4439ec0 100644
--- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/util/json/WxOpenAuthorizerInfoGsonAdapter.java
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/util/json/WxOpenAuthorizerInfoGsonAdapter.java
@@ -12,6 +12,12 @@
  * @author 007
  */
 public class WxOpenAuthorizerInfoGsonAdapter implements JsonDeserializer {
+
+  private static final String VERIFY_TYPE_INFO = "verify_type_info";
+  private static final String SERVICE_TYPE_INFO = "service_type_info";
+  private static final String MINI_PROGRAM_INFO = "MiniProgramInfo";
+  private static final String BASIC_CONFIG = "basic_config";
+
   @Override
   public WxOpenAuthorizerInfo deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
     WxOpenAuthorizerInfo authorizationInfo = new WxOpenAuthorizerInfo();
@@ -23,20 +29,27 @@ public WxOpenAuthorizerInfo deserialize(JsonElement jsonElement, Type type, Json
     authorizationInfo.setPrincipalName(GsonHelper.getString(jsonObject, "principal_name"));
     authorizationInfo.setAlias(GsonHelper.getString(jsonObject, "alias"));
     authorizationInfo.setQrcodeUrl(GsonHelper.getString(jsonObject, "qrcode_url"));
+    authorizationInfo.setAccountStatus(GsonHelper.getInteger(jsonObject, "account_status"));
     authorizationInfo.setSignature(GsonHelper.getString(jsonObject, "signature"));
+    authorizationInfo.setRegisterType(GsonHelper.getInteger(jsonObject, "register_type"));
 
-    if (jsonObject.has("service_type_info")) {
-      authorizationInfo.setServiceTypeInfo(GsonHelper.getInteger(jsonObject.getAsJsonObject("service_type_info"), "id"));
+    if (jsonObject.has(SERVICE_TYPE_INFO)) {
+      authorizationInfo.setServiceTypeInfo(GsonHelper.getInteger(jsonObject.getAsJsonObject(SERVICE_TYPE_INFO), "id"));
+    }
+    if (jsonObject.has(VERIFY_TYPE_INFO)) {
+      authorizationInfo.setVerifyTypeInfo(GsonHelper.getInteger(jsonObject.getAsJsonObject(VERIFY_TYPE_INFO), "id"));
     }
-    if (jsonObject.has("verify_type_info")) {
-      authorizationInfo.setVerifyTypeInfo(GsonHelper.getInteger(jsonObject.getAsJsonObject("verify_type_info"), "id"));
+    if(jsonObject.has(BASIC_CONFIG)){
+      authorizationInfo.setBasicConfig(WxOpenGsonBuilder.create().fromJson(jsonObject.get(BASIC_CONFIG),
+        new TypeToken(){
+        }.getType()));
     }
     Map businessInfo = WxOpenGsonBuilder.create().fromJson(jsonObject.get("business_info"),
       new TypeToken>() {
       }.getType());
     authorizationInfo.setBusinessInfo(businessInfo);
-    if (jsonObject.has("MiniProgramInfo")) {
-      WxOpenAuthorizerInfo.MiniProgramInfo miniProgramInfo = WxOpenGsonBuilder.create().fromJson(jsonObject.get("MiniProgramInfo"),
+    if (jsonObject.has(MINI_PROGRAM_INFO)) {
+      WxOpenAuthorizerInfo.MiniProgramInfo miniProgramInfo = WxOpenGsonBuilder.create().fromJson(jsonObject.get(MINI_PROGRAM_INFO),
         new TypeToken() {
         }.getType());
       authorizationInfo.setMiniProgramInfo(miniProgramInfo);
diff --git a/weixin-java-open/src/test/java/me/chanjar/weixin/open/api/impl/WxOpenComponentServiceImplTest.java b/weixin-java-open/src/test/java/me/chanjar/weixin/open/api/impl/WxOpenComponentServiceImplTest.java
index c9fefec02..aa7344815 100644
--- a/weixin-java-open/src/test/java/me/chanjar/weixin/open/api/impl/WxOpenComponentServiceImplTest.java
+++ b/weixin-java-open/src/test/java/me/chanjar/weixin/open/api/impl/WxOpenComponentServiceImplTest.java
@@ -3,10 +3,18 @@
 import com.google.inject.Inject;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.open.api.WxOpenComponentService;
+import me.chanjar.weixin.open.bean.result.WxOpenResult;
+import me.chanjar.weixin.open.bean.tcb.ShareCloudBaseEnvRequest;
+import me.chanjar.weixin.open.bean.tcb.ShareCloudBaseEnvResponse;
+import me.chanjar.weixin.open.bean.tcbComponent.GetShareCloudBaseEnvResponse;
+import me.chanjar.weixin.open.bean.tcbComponent.GetTcbEnvListResponse;
 import me.chanjar.weixin.open.test.ApiTestModule;
+import org.testng.Assert;
 import org.testng.annotations.Guice;
 import org.testng.annotations.Test;
 
+import java.util.Arrays;
+
 /**
  * 单元测试类.
  *
@@ -171,4 +179,32 @@ public void testFastRegisterWeappSearch() {
   public void testStartPushTicket() throws WxErrorException {
     wxOpenComponentService.startPushTicket();
   }
+
+  @Test
+  public void testGetShareCloudBaseEnv() throws WxErrorException {
+    GetShareCloudBaseEnvResponse response = wxOpenComponentService.getShareCloudBaseEnv(Arrays.asList("wxad2ee6fa2df2c46d"));
+    Assert.assertNotNull(response);
+  }
+
+  @Test
+  public void testGetTcbEnvListv() throws WxErrorException {
+    GetTcbEnvListResponse response = wxOpenComponentService.getTcbEnvList();
+    Assert.assertNotNull(response);
+  }
+
+  @Test
+  public void testChangeTcbEnv() throws WxErrorException {
+    WxOpenResult response = wxOpenComponentService.changeTcbEnv("test");
+    Assert.assertNotNull(response);
+  }
+
+  @Test
+  public void testShareCloudBaseEnv() throws WxErrorException {
+    ShareCloudBaseEnvRequest request = ShareCloudBaseEnvRequest.builder()
+      .data(Arrays.asList(ShareCloudBaseEnvRequest.DataDTO.builder()
+        .env("test-env-6gni9ity244a6ea3").appids(Arrays.asList("wx5fe6bb43205e9e07")).build()))
+      .build();
+    ShareCloudBaseEnvResponse response = wxOpenComponentService.shareCloudBaseEnv(request);
+    Assert.assertNotNull(response);
+  }
 }
diff --git a/weixin-java-open/src/test/java/me/chanjar/weixin/open/bean/result/WxOpenAuthorizerInfoResultTest.java b/weixin-java-open/src/test/java/me/chanjar/weixin/open/bean/result/WxOpenAuthorizerInfoResultTest.java
new file mode 100644
index 000000000..63c453335
--- /dev/null
+++ b/weixin-java-open/src/test/java/me/chanjar/weixin/open/bean/result/WxOpenAuthorizerInfoResultTest.java
@@ -0,0 +1,131 @@
+package me.chanjar.weixin.open.bean.result;
+
+import me.chanjar.weixin.open.util.json.WxOpenGsonBuilder;
+import org.testng.annotations.Test;
+
+/**
+ * @title: 获取授权帐号详情 信息反序列化测试
+ * @author: trifolium
+ * @date: 2022/6/7
+ * @modified :
+ */
+public class WxOpenAuthorizerInfoResultTest {
+
+  @Test
+  public void testDeserialization() {
+
+    String json = "{\n" +
+      "  \"authorizer_info\": {\n" +
+      "    \"nick_name\": \"美妆饰品\",\n" +
+      "    \"head_img\": \"http:\\/\\/wx.qlogo.cn\\/mmopen\\/jJSbu4Te5iuiaM0dFnKVUEE83n2yH5cQStb\\/0\",\n" +
+      "    \"service_type_info\": {\n" +
+      "      \"id\": 0\n" +
+      "    },\n" +
+      "    \"verify_type_info\": {\n" +
+      "      \"id\": -1\n" +
+      "    },\n" +
+      "    \"user_name\": \"gh_c43395cb652e\",\n" +
+      "    \"alias\": \"\",\n" +
+      "    \"qrcode_url\": \"http:\\/\\/mmbiz.qpic.cn\\/mmbiz_jpg\\/kPmmhe6g\\/0\",\n" +
+      "    \"business_info\": {\n" +
+      "      \"open_pay\": 0,\n" +
+      "      \"open_shake\": 0,\n" +
+      "      \"open_scan\": 0,\n" +
+      "      \"open_card\": 0,\n" +
+      "      \"open_store\": 0\n" +
+      "    },\n" +
+      "    \"idc\": 1,\n" +
+      "    \"principal_name\": \"个人\",\n" +
+      "    \"signature\": \"做美装,精美饰品等搭配教学\",\n" +
+      "    \"MiniProgramInfo\": {\n" +
+      "      \"network\": {\n" +
+      "        \"RequestDomain\": [\"https:\\/\\/weixin.qq.com\"],\n" +
+      "        \"WsRequestDomain\": [\"wss:\\/\\/weixin.qq.com\"],\n" +
+      "        \"UploadDomain\": [\"https:\\/\\/weixin.qq.com\"],\n" +
+      "        \"DownloadDomain\": [\"https:\\/\\/weixin.qq.com\"],\n" +
+      "        \"BizDomain\": [],\n" +
+      "        \"UDPDomain\": [],\n" +
+      "        \"TCPDomain\": [],\n" +
+      "        \"PrefetchDNSDomain\": [],\n" +
+      "        \"NewRequestDomain\": [],\n" +
+      "        \"NewWsRequestDomain\": [],\n" +
+      "        \"NewUploadDomain\": [],\n" +
+      "        \"NewDownloadDomain\": [],\n" +
+      "        \"NewBizDomain\": [],\n" +
+      "        \"NewUDPDomain\": [],\n" +
+      "        \"NewTCPDomain\": [],\n" +
+      "        \"NewPrefetchDNSDomain\": []\n" +
+      "      },\n" +
+      "      \"categories\": [{\n" +
+      "        \"first\": \"生活服务\",\n" +
+      "        \"second\": \"丽人服务\"\n" +
+      "      }, {\n" +
+      "        \"first\": \"旅游服务\",\n" +
+      "        \"second\": \"旅游资讯\"\n" +
+      "      }, {\n" +
+      "        \"first\": \"物流服务\",\n" +
+      "        \"second\": \"查件\"\n" +
+      "      }],\n" +
+      "      \"visit_status\": 0\n" +
+      "    },\n" +
+      "    \"register_type\": 0,\n" +
+      "    \"account_status\": 1,\n" +
+      "    \"basic_config\": {\n" +
+      "      \"is_phone_configured\": true,\n" +
+      "      \"is_email_configured\": true\n" +
+      "    }\n" +
+      "  },\n" +
+      "  \"authorization_info\": {\n" +
+      "    \"authorizer_appid\": \"wx326eecacf7370d4e\",\n" +
+      "    \"authorizer_refresh_token\": \"refreshtoken@@@RU0Sgi7bD6apS7frS9gj8Sbws7OoDejK9Z-cm0EnCzg\",\n" +
+      "    \"func_info\": [{\n" +
+      "      \"funcscope_category\": {\n" +
+      "        \"id\": 3\n" +
+      "      },\n" +
+      "      \"confirm_info\": {\n" +
+      "        \"need_confirm\": 0,\n" +
+      "        \"already_confirm\": 0,\n" +
+      "        \"can_confirm\": 0\n" +
+      "      }\n" +
+      "    }, {\n" +
+      "      \"funcscope_category\": {\n" +
+      "        \"id\": 7\n" +
+      "      }\n" +
+      "    }, {\n" +
+      "      \"funcscope_category\": {\n" +
+      "        \"id\": 17\n" +
+      "      }\n" +
+      "    }, {\n" +
+      "      \"funcscope_category\": {\n" +
+      "        \"id\": 18\n" +
+      "      },\n" +
+      "      \"confirm_info\": {\n" +
+      "        \"need_confirm\": 0,\n" +
+      "        \"already_confirm\": 0,\n" +
+      "        \"can_confirm\": 0\n" +
+      "      }\n" +
+      "    }, {\n" +
+      "      \"funcscope_category\": {\n" +
+      "        \"id\": 19\n" +
+      "      }\n" +
+      "    }, {\n" +
+      "      \"funcscope_category\": {\n" +
+      "        \"id\": 30\n" +
+      "      },\n" +
+      "      \"confirm_info\": {\n" +
+      "        \"need_confirm\": 0,\n" +
+      "        \"already_confirm\": 0,\n" +
+      "        \"can_confirm\": 0\n" +
+      "      }\n" +
+      "    }, {\n" +
+      "      \"funcscope_category\": {\n" +
+      "        \"id\": 115\n" +
+      "      }\n" +
+      "    }]\n" +
+      "  }\n" +
+      "}\n";
+
+    System.out.println(WxOpenGsonBuilder.create().fromJson(json, WxOpenAuthorizerInfoResult.class));
+  }
+
+}
diff --git a/weixin-java-pay/pom.xml b/weixin-java-pay/pom.xml
index 6ecd99596..c65aeb95d 100644
--- a/weixin-java-pay/pom.xml
+++ b/weixin-java-pay/pom.xml
@@ -5,7 +5,7 @@
   
     com.github.binarywang
     wx-java
-    4.3.0
+    4.4.0
   
   4.0.0
 
@@ -35,11 +35,6 @@
       commons-lang3
     
 
-    
-      commons-beanutils
-      commons-beanutils
-      1.9.4
-    
     
       org.bouncycastle
       bcpkix-jdk15on
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/ModifySettlementRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/ModifySettlementRequest.java
index 8623b5cd6..e374d952a 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/ModifySettlementRequest.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/ModifySettlementRequest.java
@@ -26,6 +26,12 @@ public class ModifySettlementRequest implements Serializable {
    */
   @SerializedName("account_type")
   private AccountTypeEnum accountType;
+  /**
+   * 开户名称
+   */
+  @SpecEncrypt
+  @SerializedName("account_name")
+  private String accountName;
   /**
    * 开户银行
    */
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/WxPayApplyment4SubCreateRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/WxPayApplyment4SubCreateRequest.java
index fe956af23..2bfd5be41 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/WxPayApplyment4SubCreateRequest.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/WxPayApplyment4SubCreateRequest.java
@@ -64,7 +64,7 @@ public class WxPayApplyment4SubCreateRequest implements Serializable {
   private BankAccountInfo bankAccountInfo;
 
   /**
-   * 结算银行账户
+   * 补充材料
    */
   @SerializedName("addition_info")
   private AdditionInfo additionInfo;
@@ -80,6 +80,17 @@ public class WxPayApplyment4SubCreateRequest implements Serializable {
   public static class ContactInfo implements Serializable {
     private static final long serialVersionUID = 1L;
 
+    /**
+     * 超级管理员类型
+     * 1、主体为“个体工商户/企业/政府机关/事业单位/社会组织”,可选择:LEGAL:经营者/法人,SUPER:经办人 。(经办人:经商户授权办理微信支付业务的人员)。
+     * 枚举值:
+     * LEGAL:经营者/法人
+     * SUPER:经办人
+     * 示例值:LEGAL
+     */
+    @SerializedName("contact_type")
+    private String contactType;
+
     /**
      * 超级管理员姓名
      */
@@ -87,6 +98,22 @@ public static class ContactInfo implements Serializable {
     @SpecEncrypt
     private String contactName;
 
+    /**
+     * 超级管理员证件类型
+     * 当超级管理员类型是经办人时,请上传超级管理员证件类型。
+     * IDENTIFICATION_TYPE_IDCARD:中国大陆居民-身份证
+     * IDENTIFICATION_TYPE_OVERSEA_PASSPORT:其他国家或地区居民-护照
+     * IDENTIFICATION_TYPE_HONGKONG_PASSPORT:中国香港居民-来往内地通行证
+     * IDENTIFICATION_TYPE_MACAO_PASSPORT:中国澳门居民-来往内地通行证
+     * IDENTIFICATION_TYPE_TAIWAN_PASSPORT:中国台湾居民-来往大陆通行证
+     * IDENTIFICATION_TYPE_FOREIGN_RESIDENT:外国人居留证
+     * IDENTIFICATION_TYPE_HONGKONG_MACAO_RESIDENT:港澳居民证
+     * IDENTIFICATION_TYPE_TAIWAN_RESIDENT:台湾居民证
+     * 示例值:IDENTIFICATION_TYPE_IDCARD
+     */
+    @SerializedName("contact_id_doc_type")
+    private String contactIdDocType;
+
     /**
      * 超级管理员身份证件号码
      * 1、“超级管理员身份证号码”与“超级管理员微信openid”,二选一必填。
@@ -97,6 +124,58 @@ public static class ContactInfo implements Serializable {
     @SpecEncrypt
     private String contactIdNumber;
 
+    /**
+     * 超级管理员证件正面照片
+     * 1、当超级管理员类型是经办人时,请上传超级管理员证件的正面照片。
+     * 2、若证件类型为身份证,请上传人像面照片。
+     * 3、可上传1张图片,请填写通过图片上传API预先上传图片生成好的MediaID。
+     * 4、请上传彩色照片or彩色扫描件or复印件(需加盖公章鲜章),可添加“微信支付”相关水印(如微信支付认证)。
+     * 示例值:jTpGmxUXqRTvDujqhThn4ReFxikqJ5YW6zFQ
+     */
+    @SerializedName("contact_id_doc_copy")
+    private String contactIdDocCopy;
+
+    /**
+     * 超级管理员证件反面照片
+     * 1、当超级管理员类型是经办人时,请上传超级管理员证件的反面照片。
+     * 2、若证件类型为护照,无需上传反面照片。
+     * 3、可上传1张图片,请填写通过图片上传API预先上传图片生成好的MediaID。
+     * 4、请上传彩色照片or彩色扫描件or复印件(需加盖公章鲜章),可添加“微信支付”相关水印(如微信支付认证)。
+     * 示例值:jTpGmxUX3FBWVQ5NJTZvvDujqhThn4ReFxikqJ5YW6zFQ
+     */
+    @SerializedName("contact_id_doc_copy_back")
+    private String contactIdDocCopyBack;
+
+    /**
+     * 超级管理员证件有效期开始时间
+     * 1、当超级管理员类型是经办人时,请上传证件有效期开始时间。
+     * 2、请按照示例值填写。
+     * 3、结束时间大于开始时间。
+     * 示例值:2019-06-06
+     */
+    @SerializedName("contact_period_begin")
+    private String contactPeriodBegin;
+
+    /**
+     * 超级管理员证件有效期结束时间
+     * 1、当超级管理员类型是经办人时,请上传证件有效期结束时间。
+     * 2、请按照示例值填写,若证件有效期为长期,请填写:长期。
+     * 3、结束时间大于开始时间。
+     * 示例值:2026-06-06
+     */
+    @SerializedName("contact_period_end")
+    private String contactPeriodEnd;
+
+    /**
+     * 业务办理授权函
+     * 1、当超级管理员类型是经办人时,请上传业务办理授权函。
+     * 2、请参照[示例图]打印业务办理授权函,全部信息需打印,不支持手写商户信息,并加盖公章。
+     * 3、可上传1张图片,请填写通过图片上传API预先上传图片生成好的MediaID。
+     * 示例值:47ZC6GC-vnrbEny_Ie_An5-tCpqxucuxi-vByf3Gjm7KEIUv0OF4wFNIO4kqg05InE4d2I6_H7I4
+     */
+    @SerializedName("business_authorization_letter")
+    private String businessAuthorizationLetter;
+
     /**
      * 超级管理员微信openid
      * 1、“超级管理员身份证件号码”与“超级管理员微信openid”,二选一必填。
@@ -140,6 +219,12 @@ public static class SubjectInfo implements Serializable {
     @SerializedName("subject_type")
     private SubjectTypeEnum subjectType;
 
+    /**
+     * 是否是金融机构
+     */
+    @SerializedName("finance_institution")
+    private Boolean financeInstitution;
+
     /**
      * 营业执照
      */
@@ -171,11 +256,11 @@ public static class SubjectInfo implements Serializable {
     private IdentityInfo identityInfo;
 
     /**
-     * 最终受益人信息(UBO]
+     * 最终受益人信息列表(UBO)
      */
-    @SerializedName("ubo_info")
+    @SerializedName("ubo_info_list")
     @SpecEncrypt
-    private UboInfo uboInfo;
+    private List uboInfoList;
 
     /**
      * 小微辅助证明材料(subjectType为小微商户时必填)
@@ -210,6 +295,21 @@ public static class BusinessLicenseInfo implements Serializable {
        */
       @SerializedName("legal_person")
       private String legalPerson;
+      /**
+       * 注册地址
+       */
+      @SerializedName("license_address")
+      private String licenseAddress;
+      /**
+       * 有效期限开始日期
+       */
+      @SerializedName("period_begin")
+      private String periodBegin;
+      /**
+       * 有效期限结束日期
+       */
+      @SerializedName("period_end")
+      private String periodEnd;
     }
 
     @Data
@@ -255,7 +355,7 @@ public static class CertificateInfo implements Serializable {
 
 
       /**
-       * 法人姓名
+       * 法定代表人
        */
       @SerializedName("legal_person")
       private String legalPerson;
@@ -314,12 +414,24 @@ public static class OrganizationInfo implements Serializable {
     public static class IdentityInfo implements Serializable {
       private static final long serialVersionUID = 1683704338370383827L;
 
+      /**
+       * 证件持有人类型
+       */
+      @SerializedName("id_holder_type")
+      private IdTypeEnum idHolderType;
+
       /**
        * 证件类型
        */
       @SerializedName("id_doc_type")
       private IdTypeEnum idDocType;
 
+      /**
+       * 法定代表人说明函
+       */
+      @SerializedName("authorize_letter_copy")
+      private IdTypeEnum authorizeLetterCopy;
+
       /**
        * 身份证信息
        */
@@ -338,7 +450,7 @@ public static class IdentityInfo implements Serializable {
        * 经营者/法人是否为受益人
        */
       @SerializedName("owner")
-      private boolean owner;
+      private Boolean owner;
 
       @Data
       @Builder
@@ -357,7 +469,6 @@ public static class IdCardInfo implements Serializable {
          */
         @SerializedName("id_card_national")
         private String idCardNational;
-
         /**
          * 身份证姓名
          */
@@ -370,6 +481,12 @@ public static class IdCardInfo implements Serializable {
         @SerializedName("id_card_number")
         @SpecEncrypt
         private String idCardNumber;
+        /**
+         * 身份证居住地址
+         */
+        @SerializedName("id_card_address")
+        @SpecEncrypt
+        private String idCardAddress;
         /**
          * 身份证有效期开始时间
          */
@@ -391,10 +508,15 @@ public static class IdCardInfo implements Serializable {
       public static class IdDocInfo implements Serializable {
         private static final long serialVersionUID = 7335589815924447719L;
         /**
-         * 证件照片
+         * 证件正面照片
          */
         @SerializedName("id_doc_copy")
         private String idDocCopy;
+        /**
+         * 证件反面照片
+         */
+        @SerializedName("id_doc_copy_back")
+        private String idDocCopyBack;
 
         /**
          * 证件姓名
@@ -409,6 +531,12 @@ public static class IdDocInfo implements Serializable {
         @SerializedName("id_doc_number")
         @SpecEncrypt
         private String idDocNumber;
+        /**
+         * 身份证居住地址
+         */
+        @SerializedName("id_card_address")
+        @SpecEncrypt
+        private String idCardAddress;
         /**
          * 证件有效期开始时间
          */
@@ -432,45 +560,46 @@ public static class UboInfo implements Serializable {
       /**
        * 证件类型
        */
-      @SerializedName("id_type")
-      private IdTypeEnum idType;
+      @SerializedName("ubo_id_doc_type")
+      private IdTypeEnum uboIdDocType;
       /**
-       * 身份证人像面照片
+       * 证件正面照片
        */
-      @SerializedName("id_card_copy")
-      private String idCardCopy;
+      @SerializedName("ubo_id_doc_copy")
+      private String uboIdDocCopy;
       /**
-       * 身份证国徽面照片
+       * 证件反面照片
        */
-      @SerializedName("id_card_national")
-      private String idCardNational;
+      @SerializedName("ubo_id_doc_copy_back")
+      private String uboIdDocCopyBack;
       /**
-       * 证件照片
+       * 证件姓名
        */
-      @SerializedName("id_doc_copy")
-      private String idDocCopy;
+      @SerializedName("ubo_id_doc_name")
+      @SpecEncrypt
+      private String uboIdDocName;
       /**
-       * 受益人姓名
+       * 证件号码
        */
-      @SerializedName("name")
+      @SerializedName("ubo_id_doc_number")
       @SpecEncrypt
-      private String name;
+      private String uboIdDocNumber;
       /**
-       * 证件号码
+       * 证件居住地址
        */
-      @SerializedName("id_number")
+      @SerializedName("ubo_id_doc_address")
       @SpecEncrypt
-      private String idNumber;
+      private String uboIdDocAddress;
       /**
        * 证件有效期开始时间
        */
-      @SerializedName("id_period_begin")
-      private String idPeriodBegin;
+      @SerializedName("ubo_period_begin")
+      private String uboPeriodBegin;
       /**
        * 证件有效期结束时间
        */
-      @SerializedName("id_period_end")
-      private String idPeriodEnd;
+      @SerializedName("ubo_period_end")
+      private String uboPeriodEnd;
     }
 
     @Data
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/enums/CertTypeEnum.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/enums/CertTypeEnum.java
index f7415fdc3..91d0c5370 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/enums/CertTypeEnum.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/enums/CertTypeEnum.java
@@ -40,14 +40,6 @@ public enum CertTypeEnum {
    * 基金会法人登记证书
    */
   CERTIFICATE_TYPE_2396,
-  /**
-   * 慈善组织公开募捐资格证书
-   */
-  CERTIFICATE_TYPE_2397,
-  /**
-   * 农民专业合作社法人营业执照
-   */
-  CERTIFICATE_TYPE_2398,
   /**
    * 宗教活动场所登记证
    */
@@ -56,5 +48,17 @@ public enum CertTypeEnum {
    * 其他证书/批文/证明
    */
   CERTIFICATE_TYPE_2400,
+  /**
+   * 执业许可证/执业证
+   */
+  CERTIFICATE_TYPE_2520,
+  /**
+   * 基层群众性自治组织特别法人统一社会信用代码证
+   */
+  CERTIFICATE_TYPE_2521,
+  /**
+   * 农村集体经济组织登记证
+   */
+  CERTIFICATE_TYPE_2522,
   ;
 }
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/enums/IdTypeEnum.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/enums/IdTypeEnum.java
index d65c502b8..a46cc8456 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/enums/IdTypeEnum.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/applyment/enums/IdTypeEnum.java
@@ -25,5 +25,17 @@ public enum IdTypeEnum {
    * 中国台湾居民-来往大陆通行证
    */
   IDENTIFICATION_TYPE_TAIWAN_PASSPORT,
+  /**
+   * 外国人居留证
+   */
+  IDENTIFICATION_TYPE_FOREIGN_RESIDENT,
+  /**
+   * 港澳居民证
+   */
+  IDENTIFICATION_TYPE_HONGKONG_MACAO_RESIDENT,
+  /**
+   * 台湾居民证
+   */
+  IDENTIFICATION_TYPE_TAIWAN_RESIDENT,
   ;
 }
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/BankAccountResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/BankAccountResult.java
new file mode 100644
index 000000000..5f67a2bad
--- /dev/null
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/BankAccountResult.java
@@ -0,0 +1,30 @@
+package com.github.binarywang.wxpay.bean.bank;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 对私银行卡号开户银行信息
+ *
+ * @author zhongjun
+ **/
+@Data
+public class BankAccountResult implements Serializable {
+
+  private static final long serialVersionUID = -8226859146533243501L;
+
+  /**
+   * 根据卡号查询到的银行列表数据的总条数,未查询到对应银行列表时默认返回0,最大不超过两百条。
+   */
+  @SerializedName("total_count")
+  private Integer totalCount;
+
+  @SerializedName("data")
+  private List data;
+
+}
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/BankBranchesResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/BankBranchesResult.java
new file mode 100644
index 000000000..72cc4f6a7
--- /dev/null
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/BankBranchesResult.java
@@ -0,0 +1,176 @@
+package com.github.binarywang.wxpay.bean.bank;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 支行列表
+ *
+ * @author hupeng
+ **/
+@Data
+public class BankBranchesResult implements Serializable {
+
+  private static final long serialVersionUID = -3500020131951579476L;
+
+  /**
+   * 
+   * 字段名:查询数据总条数
+   * 变量名:total_count
+   * 是否必填:是
+   * 类型:int
+   * 描述:
+   *  经过条件筛选,查询到的支行总数
+   *  示例值:10
+   * 
+ */ + @SerializedName("total_count") + private Integer totalCount; + + /** + *
+   * 字段名:本次查询条数
+   * 变量名:count
+   * 是否必填:是
+   * 类型:int
+   * 描述:
+   *  本次查询到的支行数据条数
+   *  示例值:10
+   * 
+ */ + @SerializedName("count") + private Integer count; + + /** + *
+   * 字段名:支行列表
+   * 变量名:data
+   * 是否必填:否
+   * 类型:array
+   * 描述:
+   *  单次查询返回的支行列表结果数组
+   * 
+ */ + @SerializedName("data") + private List data; + + /** + *
+   * 字段名:本次查询偏移量
+   * 变量名:offset
+   * 是否必填:是
+   * 类型:int
+   * 描述:
+   *  该次请求资源的起始位置,请求中包含偏移量时应答消息返回相同偏移量,否则返回默认值0
+   *  示例值:0
+   * 
+ */ + @SerializedName("offset") + private Integer offset; + + /** + *
+   * 字段名:分页链接
+   * 变量名:offset
+   * 是否必填:是
+   * 类型:object
+   * 描述:
+   *  返回前后页和当前页面的访问链接
+   * 
+ */ + @SerializedName("links") + private PageLink links; + + /** + *
+   * 字段名:开户银行
+   * 变量名:account_bank
+   * 是否必填:是
+   * 类型:string[1, 128]
+   * 描述:
+   *  查询到的支行所属开户银行的名称,非直连银行统一为其他银行
+   *  示例值:招商银行其他银行
+   * 
+ */ + @SerializedName("account_bank") + private String accountBank; + + /** + *
+   * 字段名:开户银行编码
+   * 变量名:account_bank_code
+   * 是否必填:是
+   * 类型:int
+   * 描述:
+   *  查询到的支行所属开户银行的开户银行编码,可用于付款到银行卡等场景中指定银行卡的开户银行
+   *  示例值:1001
+   * 
+ */ + @SerializedName("account_bank_code") + private Integer accountBankCode; + + /** + *
+   * 字段名:银行别名
+   * 变量名:bank_alias
+   * 是否必填:是
+   * 类型:string[1, 128]
+   * 描述:
+   *  查询到的支行所属银行的银行别名
+   *  示例值:工商银行深圳前海微众银行
+   * 
+ */ + @SerializedName("bank_alias") + private String bankAlias; + + /** + *
+   * 字段名:银行别名编码
+   * 变量名:bank_alias_code
+   * 是否必填:是
+   * 类型:string[1, 32]
+   * 描述:
+   *  查询到的支行所属银行的银行别名编码,用于校验回包
+   *  示例值:1000006247
+   * 
+ */ + @SerializedName("bank_alias_code") + private String bankAliasCode; + + @Getter + @Setter + public static class BankBranch { + /** + *
+     * 字段名:开户银行支行名称
+     * 变量名:bank_branch_name
+     * 是否必填:是
+     * 类型:string[1, 128]
+     * 描述:
+     *  开户银行支行名称,用于开户银行为其他银行的情况下,在入驻、修改结算银行卡、企业付款等场景下填写结算银行卡信息。
+     *  示例值:中国工商银行上海市周浦支行
+     * 
+ */ + @SerializedName("bank_branch_name") + private String bankBranchName; + + /** + *
+     * 字段名:开户银行支行联行号
+     * 变量名:bank_branch_id
+     * 是否必填:是
+     * 类型:string[1, 64]
+     * 描述:
+     *  开户银行支行的联行号,用于开户银行为其他银行的情况下,在入驻、修改结算银行卡、企业付款等场景下填写结算银行卡信息。
+     *  示例值:102290072311
+     * 
+ */ + @SerializedName("bank_branch_id") + private String bankBranchId; + } +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/BankInfo.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/BankInfo.java new file mode 100644 index 000000000..005963b87 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/BankInfo.java @@ -0,0 +1,41 @@ +package com.github.binarywang.wxpay.bean.bank; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; + +/** + * 银行信息 + * + * @author zhongjun + * @date 2022/5/12 + **/ +@Data +public class BankInfo { + /** + * 银行别名 + */ + @SerializedName("bank_alias") + private String bankAlias; + /** + * 银行别名编码 + */ + @SerializedName("bank_alias_code") + private String bankAliasCode; + /** + * 开户银行 + */ + @SerializedName("account_bank") + private String accountBank; + /** + * 开户银行编码 + */ + @SerializedName("account_bank_code") + private Integer accountBankCode; + /** + * 是否需要填写支行 + */ + @SerializedName("need_bank_branch") + private Boolean needBankBranch; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/BankingResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/BankingResult.java new file mode 100644 index 000000000..407ad5fc5 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/BankingResult.java @@ -0,0 +1,64 @@ +package com.github.binarywang.wxpay.bean.bank; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; +import java.util.List; + +/** + * 个人业务的银行列表 + * + * @author zhongjun + **/ +@Data +public class BankingResult implements Serializable { + private static final long serialVersionUID = -8372812998971715894L; + + /** + * 银行列表数据的总条数,调用方需要根据总条数分页查询 + */ + @SerializedName("total_count") + private Integer totalCount; + + /** + * 本次查询银行列表返回的数据条数 + */ + @SerializedName("count") + private Integer count; + + /** + * 该次请求资源的起始位置,请求中包含偏移量时应答消息返回相同偏移量,否则返回默认值0。 + */ + @SerializedName("offset") + private Integer offset; + + @SerializedName("data") + private List data; + + @SerializedName("links") + private Link links; + + @Getter + @Setter + public static class Link { + /** + * 下一页链接 + */ + @SerializedName("next") + private String next; + /** + * 上一页链接 + */ + @SerializedName("prev") + private String prev; + /** + * 当前链接 + */ + @SerializedName("self") + private String self; + } + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/CitiesResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/CitiesResult.java new file mode 100644 index 000000000..b5bf87c81 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/CitiesResult.java @@ -0,0 +1,80 @@ +package com.github.binarywang.wxpay.bean.bank; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; +import java.util.List; + +/** + * 城市列表 + * + * @author hupeng + **/ +@Data +public class CitiesResult implements Serializable { + + private static final long serialVersionUID = -6089905695087974693L; + + /** + *
+   * 字段名:查询数据总条数
+   * 变量名:total_count
+   * 是否必填:是
+   * 类型:int
+   * 描述:
+   *  查询到的省份数据总条数
+   *  示例值:10
+   * 
+ */ + @SerializedName("total_count") + private Integer totalCount; + + /** + *
+   * 字段名:城市列表
+   * 变量名:data
+   * 是否必填:否
+   * 类型:array
+   * 描述:
+   *  查询返回的城市列表结果
+   * 
+ */ + @SerializedName("data") + private List data; + + @Getter + @Setter + public static class CityInfo { + /** + *
+     * 字段名:城市名称
+     * 变量名:city_name
+     * 是否必填:是
+     * 类型:string[1, 256]
+     * 描述:
+     *  城市名称
+     *  示例值:北京市
+     * 
+ */ + @SerializedName("city_name") + private String cityName; + + /** + *
+     * 字段名:城市编码
+     * 变量名:city_code
+     * 是否必填:是
+     * 类型:int
+     * 描述:
+     *  城市编码,唯一标识一座城市,用于结合银行别名编码查询支行列表
+     *  示例值:10
+     * 
+ */ + @SerializedName("city_code") + private Integer cityCode; + } + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/PageLink.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/PageLink.java new file mode 100644 index 000000000..419cdc3c9 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/PageLink.java @@ -0,0 +1,62 @@ +package com.github.binarywang.wxpay.bean.bank; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; +import java.util.List; + +/** + * 支行列表 + * + * @author hupeng + **/ +@Data +public class PageLink implements Serializable { + + private static final long serialVersionUID = -2624233403271204837L; + + /** + *
+   * 字段名:下一页链接
+   * 变量名:next
+   * 是否必填:否
+   * 类型:string[1, 2048]
+   * 描述:
+   *  使用同样的limit进行下一页查询时的相对请求链接,使用方需要自行根据当前域名进行拼接。如果已经到最后时,为空
+   *  示例值:/v3/capital/capitallhh/banks/1001/branches?offset=10&limit=5
+   * 
+ */ + @SerializedName("next") + private String next; + + /** + *
+   * 字段名:上一页链接
+   * 变量名:prev
+   * 是否必填:否
+   * 类型:string[1, 2048]
+   * 描述:
+   *  使用同样的limit进行上一页查询时的相对请求链接,使用方需要自行根据当前域名进行拼接。如果是第一页,为空
+   *  示例值:/v3/capital/capitallhh/banks/1001/branchesoffset=0&limit=5
+   * 
+ */ + @SerializedName("prev") + private String prev; + + /** + *
+   * 字段名:当前链接
+   * 变量名:self
+   * 是否必填:否
+   * 类型:string[1, 2048]
+   * 描述:
+   *  当前的相对请求链接,使用方需要自行根据当前域名进行拼接
+   *  示例值:/v3/capital/capitallhh/banks/1001/branches?offset=5&limit=5
+   * 
+ */ + @SerializedName("self") + private String self; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/ProvincesResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/ProvincesResult.java new file mode 100644 index 000000000..6525fc1c9 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/bank/ProvincesResult.java @@ -0,0 +1,81 @@ +package com.github.binarywang.wxpay.bean.bank; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; +import java.util.List; + +/** + * 省份列表 + * + * @author hupeng + **/ +@Data +public class ProvincesResult implements Serializable { + + private static final long serialVersionUID = -4118613374545722650L; + + /** + *
+   * 字段名:查询数据总条数
+   * 变量名:total_count
+   * 是否必填:是
+   * 类型:int
+   * 描述:
+   *  查询到的省份数据总条数
+   *  示例值:10
+   * 
+ */ + @SerializedName("total_count") + private Integer totalCount; + + /** + *
+   * 字段名:省份列表
+   * 变量名:data
+   * 是否必填:否
+   * 类型:array
+   * 描述:
+   *  查询到的省份列表数组
+   * 
+ */ + @SerializedName("data") + private List data; + + @Getter + @Setter + public static class ProvinceInfo { + + /** + *
+     * 字段名:省份名称
+     * 变量名:province_name
+     * 是否必填:是
+     * 类型:string[1, 256]
+     * 描述:
+     *  省份名称
+     *  示例值:广东省
+     * 
+ */ + @SerializedName("province_name") + private String provinceName; + + /** + *
+     * 字段名:省份编码
+     * 变量名:province_code
+     * 是否必填:是
+     * 类型:int
+     * 描述:
+     *  省份编码,唯一标识一个省份,用于根据省份编码查询省份下的城市列表数据
+     *  示例值:22
+     * 
+ */ + @SerializedName("province_code") + private Integer provinceCode; + } + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/complaint/ComplaintDetailResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/complaint/ComplaintDetailResult.java index f62c9c1dd..a76c92405 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/complaint/ComplaintDetailResult.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/complaint/ComplaintDetailResult.java @@ -10,14 +10,13 @@ /** * 微信消费者投诉2.0 - * 查询投诉单列表返回的实体 + * 查询投诉单列表接口 和 查询投诉单详情接口返回的实体 * * @author jmdhappy * @date 2022-3-19 */ @Data public class ComplaintDetailResult implements Serializable { - private static final long serialVersionUID = -6201692411535927503L; /** @@ -61,7 +60,7 @@ public class ComplaintDetailResult implements Serializable { *
*/ @SerializedName("complainted_mchid") - private String complaintedMchid; + private String complainedMchid; /** *
@@ -233,4 +232,42 @@ public static class ComplaintOrder implements Serializable {
    */
   @SerializedName("user_complaint_times")
   private Integer userComplaintTimes;
+
+  /**
+   * 
+   * 字段名:问题类型
+   * 是否必填:否
+   * 描述:问题类型为申请退款的单据是需要最高优先处理的单据
+   * REFUND:申请退款
+   * SERVICE_NOT_WORK:服务权益未生效
+   * OTHERS:其他类型
+   * 示例值:REFUND
+   * 
+ */ + @SerializedName("problem_type") + private String problemType; + + /** + *
+   * 字段名:用户投诉次数
+   * 是否必填:否
+   * 描述:仅当问题类型为申请退款时, 有值, (单位:分)
+   * 示例值:10
+   * 
+ */ + @SerializedName("apply_refund_amount") + private Integer applyRefundAmount; + + /** + *
+   * 字段名:用户投诉次数
+   * 是否必填:否
+   * 描述:用户标签列表
+   * TRUSTED:可信,此类用户满足极速退款条件
+   * OTHERS:其它,此类用户不满足极速退款条件
+   * 示例值:[TRUSTED]
+   * 
+ */ + @SerializedName("user_tag_list") + private String[] userTagList; } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/complaint/NegotiationHistoryResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/complaint/NegotiationHistoryResult.java index 4e5ab4197..b6f265fd8 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/complaint/NegotiationHistoryResult.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/complaint/NegotiationHistoryResult.java @@ -67,7 +67,7 @@ public static class NegotiationHistory implements Serializable { *
*/ @SerializedName("complaint_media_list") - private List complaintMediaList; + private List complaintMediaList; @Data public static class ComplaintMedia implements Serializable { @@ -97,7 +97,7 @@ public static class ComplaintMedia implements Serializable { *
*/ @SerializedName("media_url") - private String mediaUrl; + private List mediaUrl; } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/complaint/ResponseRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/complaint/ResponseRequest.java index 24e287773..57684ec0b 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/complaint/ResponseRequest.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/complaint/ResponseRequest.java @@ -8,6 +8,7 @@ import lombok.NoArgsConstructor; import java.io.Serializable; +import java.util.List; /** * 微信消费者投诉2.0 @@ -65,7 +66,7 @@ public class ResponseRequest implements Serializable { *
*/ @SerializedName("response_images") - private String responseImages; + private List responseImages; /** *
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/DeclarationQueryRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/DeclarationQueryRequest.java
new file mode 100644
index 000000000..beaa3f260
--- /dev/null
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/DeclarationQueryRequest.java
@@ -0,0 +1,125 @@
+package com.github.binarywang.wxpay.bean.customs;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * @author xifenzhu
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@Accessors(chain = true)
+public class DeclarationQueryRequest implements Serializable {
+
+  private static final long serialVersionUID = -251403491989628142L;
+  /**
+   * 
+   * 字段名:机构APPID
+   * 变量名:appid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信分配的公众账号ID
+   *  示例值:wxd678efh567hg6787
+   * 
+ */ + @SerializedName(value = "appid") + private String appid; + + /** + *
+   * 字段名:商户号
+   * 变量名:mchid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信支付分配的商户号
+   *  示例值:1230000109
+   * 
+ */ + @SerializedName(value = "mchid") + private String mchid; + + /** + *
+   * 字段名:订单类型
+   * 变量名:order_type
+   * 是否必填:是
+   * 类型:string(16)
+   * 描述:
+   *  4种订单号类型,选择一种
+   *  out_trade_no   商户订单号
+   *  transaction_id  微信支付订单号
+   *  sub_order_no  商户子订单号
+   *  sub_order_id  微信子订单号
+   *  示例值:out_trade_no
+   * 
+ */ + @SerializedName(value = "order_type") + private String orderType; + + /** + *
+   * 字段名:订单号
+   * 变量名:order_no
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  根据订单号类型,传入不同的订单号码
+   *  示例值:20150806125346
+   * 
+ */ + @SerializedName(value = "order_no") + private String orderNo; + + /** + *
+   * 字段名:海关
+   * 变量名:customs
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  海关代码, 枚举值参见参数规定-海关列表(https://pay.weixin.qq.com/wiki/doc/api/wxpay/ch/declarecustom_ch/chapter2_3.shtml#menu11)
+   *  示例值:SHANGHAI_ZS
+   * 
+ */ + @SerializedName(value = "customs") + private String customs; + + /** + *
+   * 字段名:偏移量
+   * 变量名:offset
+   * 是否必填:是
+   * 类型:int
+   * 描述:
+   *  非0整数,该次请求资源的起始位置,从0开始计数。调用方选填,默认为0
+   *  示例值:0
+   * 
+ */ + @SerializedName(value = "offset") + private String offset; + + /** + *
+   * 字段名:请求最大记录条数
+   * 变量名:limit
+   * 是否必填:是
+   * 类型:int
+   * 描述:
+   *  非0非负的整数,该次请求可返回的最大资源条数。调用方选填,默认值建议为20
+   *  示例值:20
+   * 
+ */ + @SerializedName(value = "limit") + private String limit; + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/DeclarationQueryResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/DeclarationQueryResult.java new file mode 100644 index 000000000..e84370ca1 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/DeclarationQueryResult.java @@ -0,0 +1,337 @@ +package com.github.binarywang.wxpay.bean.customs; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.List; + +/** + * @author xifenzhu + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class DeclarationQueryResult implements Serializable { + + private static final long serialVersionUID = 7776809282150143165L; + /** + *
+   * 字段名:机构APPID
+   * 变量名:appid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信分配的公众账号ID
+   *  示例值:wxd678efh567hg6787
+   * 
+ */ + @SerializedName(value = "appid") + private String appid; + + /** + *
+   * 字段名:商户号
+   * 变量名:mchid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信支付分配的商户号
+   *  示例值:1230000109
+   * 
+ */ + @SerializedName(value = "mchid") + private String mchid; + + /** + *
+   * 字段名:微信支付返回的订单号
+   * 变量名:transaction_id
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信分配的公众账号ID
+   *  示例值:1000320306201511078440737890
+   * 
+ */ + @SerializedName(value = "transaction_id") + private String transactionId; + + /** + *
+   * 字段名:核验机构
+   * 变量名:verify_department
+   * 是否必填:是
+   * 类型:string(16)
+   * 描述:
+   *  核验机构代码
+   *  UNIONPAY:银联
+   *  NETSUNION:网联
+   *  OTHERS:其他
+   *  示例值:UNIONPAY
+   * 
+ */ + @SerializedName(value = "verify_department") + private String verifyDepartment; + + /** + *
+   * 字段名:核验机构交易流水号
+   * 变量名:Verify_department_trade_id
+   * 是否必填:是
+   * 类型:string(64)
+   * 描述:
+   *  交易流水号,来自验核机构,如银联记录的交易流水号,供商户报备海关
+   *  示例值:2018112288340107038204310100000
+   * 
+ */ + @SerializedName(value = "verify_department_trade_id") + private String verifyDepartmentTradeId; + + /** + *
+   * 字段名:偏移量
+   * 变量名:offset
+   * 是否必填:是
+   * 类型:int
+   * 描述:
+   *  非0整数,该次请求资源的起始位置,从0开始计数。调用方选填,默认为0
+   *  示例值:0
+   * 
+ */ + @SerializedName(value = "offset") + private Integer offset; + + /** + *
+   * 字段名:请求最大记录条数
+   * 变量名:limit
+   * 是否必填:是
+   * 类型:int
+   * 描述:
+   *  非0非负的整数,该次请求可返回的最大资源条数。调用方选填,默认值建议为20
+   *  示例值:20
+   * 
+ */ + @SerializedName(value = "limit") + private Integer limit; + + /** + *
+   * 字段名:查询结果总条数
+   * 变量名:total_count
+   * 是否必填:是
+   * 类型:int
+   * 描述:
+   *  查询结果总条数
+   *  示例值:1
+   * 
+ */ + @SerializedName(value = "total_count") + private Integer totalCount; + + /** + *
+   * 字段名:报关数据包
+   * 变量名:data
+   * 是否必填:是
+   * 类型:array
+   * 描述:
+   *  报关单结果数组,具体内容参见下方描述
+   *  示例值:
+   * 
+ */ + @SerializedName(value = "data") + private List data; + + /** + * 驳回原因详情 + */ + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + @Accessors(chain = true) + public static class DeclarationData { + /** + *
+     * 字段名:商户子订单号
+     * 变量名:sub_order_no
+     * 是否必填:否
+     * 类型:string(32)
+     * 描述:
+     *  微信子订单号,如有拆单则返回
+     *  示例值:20150806125346
+     * 
+ */ + @SerializedName(value = "sub_order_no") + private String subOrderNo; + + /** + *
+     * 字段名:微信子订单号
+     * 变量名:sub_order_id
+     * 是否必填:否
+     * 类型:string(32)
+     * 描述:
+     *  商户子订单号,如有拆单则必传
+     *  注意:仅适用于机构模式
+     *  示例值:20150806125346
+     * 
+ */ + @SerializedName(value = "sub_order_id") + private String subOrderId; + + /** + *
+     * 字段名:商户海关备案号
+     * 变量名:merchant_customs_no
+     * 是否必填:是
+     * 类型:string(32)
+     * 描述:
+     *  商户在海关登记的备案号
+     *  示例值:123456
+     * 
+ */ + @SerializedName(value = "mch_customs_no") + private String merchantCustomsNo; + + /** + *
+     * 字段名:海关
+     * 变量名:customs
+     * 是否必填:是
+     * 类型:string(32)
+     * 描述:
+     *  海关代码, 枚举值参见参数规定-海关列表(https://pay.weixin.qq.com/wiki/doc/api/wxpay/ch/declarecustom_ch/chapter2_3.shtml#menu11)
+     *  示例值:SHANGHAI_ZS
+     * 
+ */ + @SerializedName(value = "customs") + private String customs; + + /** + *
+     * 字段名:关税
+     * 变量名:duty
+     * 是否必填:否
+     * 类型:int
+     * 描述:
+     *  关税,以分为单位,非必填项,不会提交给海关
+     *  示例值:888
+     * 
+ */ + @SerializedName(value = "duty") + private Integer duty; + + /** + *
+     * 字段名:货币类型
+     * 变量名:fee_type
+     * 是否必填:否
+     * 类型:string(32)
+     * 描述:
+     *  微信支付订单支付时使用的币种,暂只支持人民币CNY,如有拆单则必传
+     *  示例值:CNY
+     * 
+ */ + @SerializedName(value = "fee_type") + private String feeType; + + /** + *
+     * 字段名:子订单金额
+     * 变量名:order_fee
+     * 是否必填:否
+     * 类型:int
+     * 描述:
+     *  子订单金额,以分为单位,不能超过原订单金额,order_fee=transport_fee+product_fee(应付金额=物流费+商品价格),如有拆单则必传
+     *  示例值:888
+     * 
+ */ + @SerializedName(value = "order_fee") + private Integer orderFee; + + /** + *
+     * 字段名:物流费用
+     * 变量名:transport_fee
+     * 是否必填:否
+     * 类型:int
+     * 描述:
+     *  物流费用,以分为单位,如有拆单则必传
+     *  示例值:888
+     * 
+ */ + @SerializedName(value = "transport_fee") + private Integer transportFee; + + /** + *
+     * 字段名:商品费用
+     * 变量名:product_fee
+     * 是否必填:否
+     * 类型:int
+     * 描述:
+     *  商品费用,以分为单位,如有拆单则必传
+     *  示例值:888
+     * 
+ */ + @SerializedName(value = "product_fee") + private Integer productFee; + + /** + *
+     * 字段名:报关状态
+     * 变量名:state
+     * 是否必填:是
+     * 类型:string(32)
+     * 描述:
+     *  申报结果状态码
+     *  PROCESSING:申报中
+     *  UNDECLARED:未申报
+     *  SUBMITTED:已修改未申报
+     *  SUCCESS:申报成功
+     *  FAIL:申报失败
+     *  EXCEPT:海关接口异常
+     *  示例值:PROCESSING
+     * 
+ */ + @SerializedName(value = "state") + private String state; + + /** + *
+     * 字段名:报关结果说明
+     * 变量名:explanation
+     * 是否必填:是
+     * 类型:string(128)
+     * 描述:
+     *  申报结果说明,如果状态是失败或异常,显示失败原因
+     *  示例值:支付单已存在并且为非退单状态
+     * 
+ */ + @SerializedName(value = "explanation") + private String explanation; + + /** + *
+     * 字段名:最后更新时间
+     * 变量名:modify_time
+     * 是否必填:是
+     * 类型:string(32)
+     * 描述:
+     *  最后更新时间,该时间取自微信服务器
+     *  示例值:2015-09-01T10:00:00+08:00
+     * 
+ */ + @SerializedName(value = "modify_time") + private String modifyTime; + } +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/DeclarationRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/DeclarationRequest.java new file mode 100644 index 000000000..64cf86b03 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/DeclarationRequest.java @@ -0,0 +1,191 @@ +package com.github.binarywang.wxpay.bean.customs; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * @author xifenzhu + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class DeclarationRequest implements Serializable { + + private static final long serialVersionUID = -170115210896346836L; + /** + *
+   * 字段名:机构APPID
+   * 变量名:appid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信分配的公众账号ID
+   *  示例值:wxd678efh567hg6787
+   * 
+ */ + @SerializedName(value = "appid") + private String appid; + + /** + *
+   * 字段名:商户号
+   * 变量名:mchid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信支付分配的商户号
+   *  示例值:1230000109
+   * 
+ */ + @SerializedName(value = "mchid") + private String mchid; + + /** + *
+   * 字段名:商户订单号
+   * 变量名:out_trade_no
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一
+   *  示例值:20150806125346
+   * 
+ */ + @SerializedName(value = "out_trade_no") + private String outTradeNo; + + /** + *
+   * 字段名:微信支付返回的订单号
+   * 变量名:transaction_id
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信分配的公众账号ID
+   *  示例值:1000320306201511078440737890
+   * 
+ */ + @SerializedName(value = "transaction_id") + private String transactionId; + + /** + *
+   * 字段名:海关
+   * 变量名:customs
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  海关代码, 枚举值参见参数规定-海关列表(https://pay.weixin.qq.com/wiki/doc/api/wxpay/ch/declarecustom_ch/chapter2_3.shtml#menu11)
+   *  示例值:SHANGHAI_ZS
+   * 
+ */ + @SerializedName(value = "customs") + private String customs; + + /** + *
+   * 字段名:商户海关备案号
+   * 变量名:merchant_customs_no
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  商户在海关登记的备案号
+   *  示例值:123456
+   * 
+ */ + @SerializedName(value = "merchant_customs_no") + private String merchantCustomsNo; + + /** + *
+   * 字段名:关税
+   * 变量名:duty
+   * 是否必填:否
+   * 类型:int
+   * 描述:
+   *  关税,以分为单位,非必填项,不会提交给海关
+   *  示例值:888
+   * 
+ */ + @SerializedName(value = "duty") + private Integer duty; + + /** + *
+   * 字段名:商户子订单号
+   * 变量名:sub_order_no
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  商户子订单号,如有拆单则必传
+   *  注意:仅适用于机构模式
+   *  示例值:20150806125346
+   * 
+ */ + @SerializedName(value = "sub_order_no") + private String subOrderNo; + + /** + *
+   * 字段名:货币类型
+   * 变量名:fee_type
+   * 是否必填:否
+   * 类型:string(32)
+   * 描述:
+   *  微信支付订单支付时使用的币种,暂只支持人民币CNY,如有拆单则必传
+   *  示例值:CNY
+   * 
+ */ + @SerializedName(value = "fee_type") + private String feeType; + + /** + *
+   * 字段名:子订单金额
+   * 变量名:order_fee
+   * 是否必填:否
+   * 类型:int
+   * 描述:
+   *  子订单金额,以分为单位,不能超过原订单金额,order_fee=transport_fee+product_fee(应付金额=物流费+商品价格),如有拆单则必传
+   *  示例值:888
+   * 
+ */ + @SerializedName(value = "order_fee") + private Integer orderFee; + + /** + *
+   * 字段名:物流费用
+   * 变量名:transport_fee
+   * 是否必填:否
+   * 类型:int
+   * 描述:
+   *  物流费用,以分为单位,如有拆单则必传
+   *  示例值:888
+   * 
+ */ + @SerializedName(value = "transport_fee") + private Integer transportFee; + + /** + *
+   * 字段名:商品费用
+   * 变量名:product_fee
+   * 是否必填:否
+   * 类型:int
+   * 描述:
+   *  商品费用,以分为单位,如有拆单则必传
+   *  示例值:888
+   * 
+ */ + @SerializedName(value = "product_fee") + private Integer productFee; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/DeclarationResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/DeclarationResult.java new file mode 100644 index 000000000..06f604f74 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/DeclarationResult.java @@ -0,0 +1,158 @@ +package com.github.binarywang.wxpay.bean.customs; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * @author xifengzhu + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class DeclarationResult implements Serializable { + + private static final long serialVersionUID = -5895139329545995308L; + /** + *
+   * 字段名:机构APPID
+   * 变量名:appid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信分配的公众账号ID
+   *  示例值:wxd678efh567hg6787
+   * 
+ */ + @SerializedName(value = "appid") + private String appid; + + /** + *
+   * 字段名:商户号
+   * 变量名:mchid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信支付分配的商户号
+   *  示例值:1230000109
+   * 
+ */ + @SerializedName(value = "mchid") + private String mchid; + + /** + *
+   * 字段名:商户订单号
+   * 变量名:out_trade_no
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一
+   *  示例值:wxd678efh567hg6787
+   * 
+ */ + @SerializedName(value = "20150806125346") + private String outTradeNo; + + /** + *
+   * 字段名:微信支付返回的订单号
+   * 变量名:transaction_id
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信分配的公众账号ID
+   *  示例值:1000320306201511078440737890
+   * 
+ */ + @SerializedName(value = "transaction_id") + private String transactionId; + + /** + *
+   * 字段名:报关状态
+   * 变量名:state
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  申报结果状态码
+   *  PROCESSING:申报中
+   *  UNDECLARED:未申报
+   *  SUBMITTED:已修改未申报
+   *  SUCCESS:申报成功
+   *  FAIL:申报失败
+   *  EXCEPT:海关接口异常
+   *  示例值:PROCESSING
+   * 
+ */ + @SerializedName(value = "state") + private String state; + + /** + *
+   * 字段名:商户子订单号
+   * 变量名:sub_order_no
+   * 是否必填:否
+   * 类型:string(32)
+   * 描述:
+   *  微信子订单号,如有拆单则返回
+   *  示例值:20150806125346
+   * 
+ */ + @SerializedName(value = "sub_order_no") + private String subOrderNo; + + /** + *
+   * 字段名:微信子订单号
+   * 变量名:sub_order_id
+   * 是否必填:否
+   * 类型:string(32)
+   * 描述:
+   *  商户子订单号,如有拆单则必传
+   *  注意:仅适用于机构模式
+   *  示例值:20150806125346
+   * 
+ */ + @SerializedName(value = "sub_order_id") + private String subOrderId; + + /** + *
+   * 字段名:核验机构
+   * 变量名:verify_department
+   * 是否必填:是
+   * 类型:string(16)
+   * 描述:
+   *  核验机构代码
+   *  UNIONPAY:银联
+   *  NETSUNION:网联
+   *  OTHERS:其他
+   *  示例值:UNIONPAY
+   * 
+ */ + @SerializedName(value = "verify_department") + private String verifyDepartment; + + /** + *
+   * 字段名:核验机构交易流水号
+   * 变量名:Verify_department_trade_id
+   * 是否必填:是
+   * 类型:string(64)
+   * 描述:
+   *  交易流水号,来自验核机构,如银联记录的交易流水号,供商户报备海关
+   *  示例值:2018112288340107038204310100000
+   * 
+ */ + @SerializedName(value = "verify_department_trade_id") + private String verifyDepartmentTradeId; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/RedeclareRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/RedeclareRequest.java new file mode 100644 index 000000000..d3645d13d --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/RedeclareRequest.java @@ -0,0 +1,136 @@ +package com.github.binarywang.wxpay.bean.customs; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * @author xifengzhu + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class RedeclareRequest implements Serializable { + private static final long serialVersionUID = -5092107027805161479L; + + /** + *
+   * 字段名:机构APPID
+   * 变量名:appid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信分配的公众账号ID
+   *  示例值:wxd678efh567hg6787
+   * 
+ */ + @SerializedName(value = "appid") + private String appid; + + /** + *
+   * 字段名:商户号
+   * 变量名:mchid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信支付分配的商户号
+   *  示例值:1230000109
+   * 
+ */ + @SerializedName(value = "mchid") + private String mchid; + + /** + *
+   * 字段名:微信订单号
+   * 变量名:transaction_id
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  out_trade_no, transaction_id二选一传入
+   *  示例值:1000320306201511078440737890
+   * 
+ */ + @SerializedName(value = "transaction_id") + private String transactionId; + + /** + *
+   * 字段名:商户订单号
+   * 变量名:out_trade_no
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  out_trade_no, transaction_id二选一传入
+   *  示例值:20150806125346
+   * 
+ */ + @SerializedName(value = "out_trade_no") + private String outTradeNo; + + /** + *
+   * 字段名:商户子订单号
+   * 变量名:sub_order_no
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  商户子订单号,如有拆单则必传
+   *  注意:仅适用于机构模式
+   *  示例值:20150806125346
+   * 
+ */ + @SerializedName(value = "sub_order_no") + private String subOrderNo; + + /** + *
+   * 字段名:微信子订单号
+   * 变量名:sub_order_id
+   * 是否必填:否
+   * 类型:string(32)
+   * 描述:
+   *  商户子订单号,如有拆单则必传
+   *  注意:仅适用于机构模式
+   *  示例值:20150806125346
+   * 
+ */ + @SerializedName(value = "sub_order_id") + private String subOrderId; + + /** + *
+   * 字段名:海关
+   * 变量名:customs
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  海关代码, 枚举值参见参数规定-海关列表(https://pay.weixin.qq.com/wiki/doc/api/wxpay/ch/declarecustom_ch/chapter2_3.shtml#menu11)
+   *  示例值:SHANGHAI_ZS
+   * 
+ */ + @SerializedName(value = "customs") + private String customs; + + /** + *
+   * 字段名:商户海关备案号
+   * 变量名:merchant_customs_no
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  商户在海关登记的备案号
+   *  示例值:123456
+   * 
+ */ + @SerializedName(value = "merchant_customs_no") + private String merchantCustomsNo; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/RedeclareResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/RedeclareResult.java new file mode 100644 index 000000000..25e09d7c0 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/RedeclareResult.java @@ -0,0 +1,156 @@ +package com.github.binarywang.wxpay.bean.customs; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * @author xifengzhu + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class RedeclareResult implements Serializable { + + private static final long serialVersionUID = 8863516626598050095L; + /** + *
+   * 字段名:机构APPID
+   * 变量名:appid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信分配的公众账号ID
+   *  示例值:wxd678efh567hg6787
+   * 
+ */ + @SerializedName(value = "appid") + private String appid; + + /** + *
+   * 字段名:商户号
+   * 变量名:mchid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信支付分配的商户号
+   *  示例值:1230000109
+   * 
+ */ + @SerializedName(value = "mchid") + private String mchid; + + /** + *
+   * 字段名:微信订单号
+   * 变量名:transaction_id
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信支付返回的订单号
+   *  示例值:1000320306201511078440737890
+   * 
+ */ + @SerializedName(value = "transaction_id") + private String transactionId; + + /** + *
+   * 字段名:商户订单号
+   * 变量名:out_trade_no
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一
+   *  示例值:20150806125346
+   * 
+ */ + @SerializedName(value = "out_trade_no") + private String outTradeNo; + + /** + *
+   * 字段名:商户子订单号
+   * 变量名:sub_order_no
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  商户子订单号,如有拆单则必传
+   *  注意:仅适用于机构模式
+   *  示例值:20150806125346
+   * 
+ */ + @SerializedName(value = "sub_order_no") + private String subOrderNo; + + /** + *
+   * 字段名:微信子订单号
+   * 变量名:sub_order_id
+   * 是否必填:否
+   * 类型:string(32)
+   * 描述:
+   *  商户子订单号,如有拆单则必传
+   *  注意:仅适用于机构模式
+   *  示例值:20150806125346
+   * 
+ */ + @SerializedName(value = "sub_order_id") + private String subOrderId; + + /** + *
+   * 字段名:报关状态
+   * 变量名:state
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  申报结果状态码
+   *  PROCESSING:申报中
+   *  UNDECLARED:未申报
+   *  SUBMITTED:已修改未申报
+   *  SUCCESS:申报成功
+   *  FAIL:申报失败
+   *  EXCEPT:海关接口异常
+   *  示例值:PROCESSING
+   * 
+ */ + @SerializedName(value = "state") + private String state; + + /** + *
+   * 字段名:报关结果说明
+   * 变量名:explanation
+   * 是否必填:是
+   * 类型:string(128)
+   * 描述:
+   *  申报结果说明,如果状态是失败或异常,显示失败原因
+   *  示例值:支付单已存在并且为非退单状态
+   * 
+ */ + @SerializedName(value = "explanation") + private String explanation; + + /** + *
+   * 字段名:最后更新时间
+   * 变量名:modify_time
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  最后更新时间,该时间取自微信服务器
+   *  示例值:2015-09-01T10:00:00+08:00
+   * 
+ */ + @SerializedName(value = "modify_time") + private String modifyTime; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/VerifyCertificateRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/VerifyCertificateRequest.java new file mode 100644 index 000000000..767a4ce8d --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/VerifyCertificateRequest.java @@ -0,0 +1,156 @@ +package com.github.binarywang.wxpay.bean.customs; + +import com.github.binarywang.wxpay.v3.SpecEncrypt; +import com.google.gson.annotations.SerializedName; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author xifengzhu + */ +@Data +public class VerifyCertificateRequest implements Serializable { + private static final long serialVersionUID = 721089103541592315L; + /** + *
+   * 字段名:机构APPID
+   * 变量名:appid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信分配的公众账号ID
+   *  示例值:wxd678efh567hg6787
+   * 
+ */ + @SerializedName(value = "appid") + private String appid; + + /** + *
+   * 字段名:商户号
+   * 变量名:mchid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信支付分配的商户号
+   *  示例值:1230000109
+   * 
+ */ + @SerializedName(value = "mchid") + private String mchid; + + /** + *
+   * 字段名:商户订单号
+   * 变量名:out_trade_no
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一
+   *  示例值:20150806125346
+   * 
+ */ + @SerializedName(value = "out_trade_no") + private String outTradeNo; + + /** + *
+   * 字段名:微信支付返回的订单号
+   * 变量名:transaction_id
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信分配的公众账号ID
+   *  示例值:1000320306201511078440737890
+   * 
+ */ + @SerializedName(value = "transaction_id") + private String transactionId; + + /** + *
+   * 字段名:海关
+   * 变量名:customs
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  海关代码, 枚举值参见参数规定-海关列表(https://pay.weixin.qq.com/wiki/doc/api/wxpay/ch/declarecustom_ch/chapter2_3.shtml#menu11)
+   *  示例值:SHANGHAI_ZS
+   * 
+ */ + @SerializedName(value = "customs") + private String customs; + + /** + *
+   * 字段名:商户海关备案号
+   * 变量名:merchant_customs_no
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  商户在海关登记的备案号
+   *  示例值:123456
+   * 
+ */ + @SerializedName(value = "merchant_customs_no") + private String merchantCustomsNo; + + /** + *
+   * 字段名:商户子订单号
+   * 变量名:sub_order_no
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  商户子订单号,如有拆单则必传
+   *  注意:仅适用于机构模式
+   *  示例值:20150806125346
+   * 
+ */ + @SerializedName(value = "sub_order_no") + private String subOrderNo; + + /** + *
+   * 字段名:证件类型
+   * 变量名:certificate_type
+   * 是否必填:是
+   * 类型:string(16)
+   * 描述:
+   *  请传固定值IDCARD,暂只支持大陆身份证
+   *  示例值:IDCARD
+   * 
+ */ + @SerializedName(value = "certificate_type") + private String certificateType; + + /** + *
+   * 字段名:证件号
+   * 变量名:certificate_id
+   * 是否必填:是
+   * 类型:string
+   * 描述:
+   *  用户大陆身份证号,尾号为字母X的身份证号,请大写字母X。该字段需要进行加密
+   *  示例值:330821198809085211
+   * 
+ */ + @SerializedName(value = "certificate_id") + private String certificateId; + + /** + *
+   * 字段名:证件姓名
+   * 变量名:certificate_name
+   * 是否必填:是
+   * 类型:string
+   * 描述:
+   *  证件姓名,字段值需要进行加密
+   *  示例值:330821198809085211
+   * 
+ */ + @SerializedName(value = "certificate_name") + private String certificateName; + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/VerifyCertificateResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/VerifyCertificateResult.java new file mode 100644 index 000000000..d97049cb4 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/VerifyCertificateResult.java @@ -0,0 +1,93 @@ +package com.github.binarywang.wxpay.bean.customs; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * @author xifengzhu + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class VerifyCertificateResult implements Serializable { + private static final long serialVersionUID = -8578640869555299753L; + /** + *
+   * 字段名:机构APPID
+   * 变量名:appid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信分配的公众账号ID
+   *  示例值:wxd678efh567hg6787
+   * 
+ */ + @SerializedName(value = "appid") + private String appid; + + /** + *
+   * 字段名:商户号
+   * 变量名:mchid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信支付分配的商户号
+   *  示例值:1230000109
+   * 
+ */ + @SerializedName(value = "mchid") + private String mchid; + + /** + *
+   * 字段名:商户订单号
+   * 变量名:out_trade_no
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一
+   *  示例值:20150806125346
+   * 
+ */ + @SerializedName(value = "out_trade_no") + private String outTradeNo; + + /** + *
+   * 字段名:微信支付返回的订单号
+   * 变量名:transaction_id
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信分配的公众账号ID
+   *  示例值:1000320306201511078440737890
+   * 
+ */ + @SerializedName(value = "transaction_id") + private String transactionId; + + /** + *
+   * 字段名:身份核验结果
+   * 变量名:certificate_check_result
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  订购人和支付人身份信息校验结果
+   *  SAME:身份信息校验匹配
+   *  DIFFERENT:身份信息校验不匹配
+   *  示例值:SAME
+   * 
+ */ + @SerializedName(value = "certificate_check_result") + private String certificateCheckResult; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/ApplymentsRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/ApplymentsRequest.java index ac17e18cd..9b0c6b660 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/ApplymentsRequest.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/ApplymentsRequest.java @@ -6,12 +6,13 @@ import lombok.NoArgsConstructor; import java.io.Serializable; +import java.util.List; /** *
  * 电商平台,可使用该接口,帮助其二级商户进件成为微信支付商户。
- * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/applyments/chapter3_1.shtml
+ * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_1_8.shtml
  * 
*/ @Data @@ -41,18 +42,37 @@ public class ApplymentsRequest implements Serializable { * 是否必填:是 * 类型:string(4) * 描述: - * 枚举值: - * 2401:小微商户,指无营业执照的商户。 + * 非小微的主体类型需与营业执照/登记证书上一致,可参考选择主体指引,枚举值如下。 + * 2401:小微商户,指无营业执照的个人商家。 + * 2500:个人卖家,指无营业执照,已持续从事电子商务经营活动满6个月,且期间经营收入累计超过20万元的个人商家。(若选择该主体,请在“补充说明”填写相关描述)。 * 4:个体工商户,营业执照上的主体类型一般为个体户、个体工商户、个体经营。 * 2:企业,营业执照上的主体类型一般为有限公司、有限责任公司。 - * 3:党政、机关及事业单位,包括国内各级、各类政府机构、事业单位等(如:公安、党团、司法、交通、旅游、工商税务、市政、医疗、教育、学校等机构)。 - * 1708:其他组织,不属于企业、政府/事业单位的组织机构(如社会团体、民办非企业、基金会),要求机构已办理组织机构代码证。 - * 示例值:2401 + * 3:事业单位,包括国内各类事业单位,如:医疗、教育、学校等单位。 + * 2502:政府机关,包括各级、各类政府机关,如机关党委、税务、民政、人社、工商、商务、市监等。 + * 1708:社会组织,包括社会团体、民办非企业、基金会、基层群众性自治组织、农村集体经济组织等组织。 + * 示例值:2 *
*/ @SerializedName(value = "organization_type") private String organizationType; + /** + *
+   * 字段名:是否金融机构
+   * 变量名:finance_institution
+   * 是否必填:条件选填
+   * 类型:bool
+   * 描述:
+   *  选填,请根据申请主体的实际情况填写,可参考选择金融机构指引:
+   *  1、若商户主体是金融机构,则填写:true。
+   *  2、若商户主体不是金融机构,则填写:false。
+   *  若未传入将默认填写:false。
+   *  示例值:true
+   * 
+ */ + @SerializedName(value = "finance_institution") + private Boolean financeInstitution; + /** *
    * 字段名:+营业执照/登记证书信息
@@ -60,9 +80,9 @@ public class ApplymentsRequest implements Serializable {
    * 是否必填:条件选填
    * 类型:object
    * 描述:
-   *  1、主体为“小微”时,不填。
+   *  1、主体为“小微/个人卖家”时,不填。
    *  2、主体为“个体工商户/企业”时,请上传营业执照。
-   *  3、主体为“党政、机关及事业单位/其他组织”时,请上传登记证书。
+   *  3、主体为“政府机关/事业单位/社会组织”时,请上传登记证书。
    * 
*/ @SerializedName(value = "business_license_info") @@ -70,38 +90,75 @@ public class ApplymentsRequest implements Serializable { /** *
-   * 字段名:+组织机构代码证信息
-   * 变量名:organization_cert_info
+   * 字段名:+金融机构许可证信息
+   * 变量名:finance_institution_info
    * 是否必填:条件选填
    * 类型:object
-   * 描述:主体为企业/党政、机关及事业单位/其他组织,且证件号码不是18位时必填。
+   * 描述:当主体是金融机构时,必填
    * 
*/ - @SerializedName(value = "organization_cert_info") - private OrganizationCertInfo organizationCertInfo; + @SerializedName(value = "finance_institution_info") + private FinanceInstitutionInfo financeInstitutionInfo; + + /** + * 字段名:证件持有人类型 + * 变量名:id_holder_type + * 是否必填:条件选填 + * 类型:string + * 描述: + * 1. 主体类型为政府机关/事业单位时选传: + * (1)若上传的是法人证件,则不需要上传该字段。 + * (2)若因特殊情况,无法提供法人证件时,可上传经办人。 (经办人:经商户授权办理微信支付业务的人员,授权范围包括但不限于签约,入驻过程需完成账户验证)。 + * 2. 主体类型为企业/个体户/社会组织时,默认为经营者/法人,不需要上传该字段。 + * LEGAL:法人 + * SUPER:经办人 + * 示例值:LEGAL + */ + @SerializedName(value = "id_holder_type") + private String idHolderType; /** *
    * 字段名:经营者/法人证件类型
    * 变量名:id_doc_type
-   * 是否必填:否
+   * 是否必填:条件选填
    * 类型:string(64)
    * 描述:
-   *  1、主体为“小微”,只可选择:身份证。
-   *  2、主体为“个体户/企业/党政、机关及事业单位/其他组织”,可选择:任一证件类型。
-   *  3、若没有填写,系统默认选择:身份证。
-   *  枚举值:
+   *  1、当证件持有人类型为经营者/法人时,需要填写。其他情况,无需上传。
+   *  2、主体为“小微/个人卖家”,可选择:身份证。
+   *  3、主体为“个体户/企业/事业单位/社会组织”:可选择任一证件类型,主体为“政府机关”仅支持中国大陆居民-身份证类型。
+   *  4、若没有填写,系统默认选择:身份证。
+   *  枚举值:
    *  IDENTIFICATION_TYPE_MAINLAND_IDCARD:中国大陆居民-身份证
    *  IDENTIFICATION_TYPE_OVERSEA_PASSPORT:其他国家或地区居民-护照
-   *  IDENTIFICATION_TYPE_HONGKONG:中国香港居民–来往内地通行证
-   *  IDENTIFICATION_TYPE_MACAO:中国澳门居民–来往内地通行证
-   *  IDENTIFICATION_TYPE_TAIWAN:中国台湾居民–来往大陆通行证
-   *  示例值:IDENTIFICATION_TYPE_MACAO
+   *  IDENTIFICATION_TYPE_HONGKONG:中国香港居民--来往内地通行证
+   *  IDENTIFICATION_TYPE_MACAO:中国澳门居民--来往内地通行证
+   *  IDENTIFICATION_TYPE_TAIWAN:中国台湾居民--来往大陆通行证
+   *  IDENTIFICATION_TYPE_FOREIGN_RESIDENT:外国人居留证
+   *  IDENTIFICATION_TYPE_HONGKONG_MACAO_RESIDENT:港澳居民证
+   *  IDENTIFICATION_TYPE_TAIWAN_RESIDENT:台湾居民证
+   *  示例值:IDENTIFICATION_TYPE_MAINLAND_IDCARD
    * 
*/ @SerializedName(value = "id_doc_type") private String idDocType; + /** + *
+   * 字段名:法定代表人说明函
+   * 变量名:authorize_letter_copy
+   * 是否必填:条件选填
+   * 类型:string(256)
+   * 描述:
+   *  1、当证件持有人类型为经办人时,必须上传。其他情况,无需上传。
+   *  2、若因特殊情况,无法提供法定代表人证件时,请参照示例图打印法定代表人说明函,全部信息需打印,不支持手写商户信息,并加盖公章。
+   *  3、可上传1张图片,请填写通过图片上传API预先上传图片生成好的MediaID。
+   *  示例值:47ZC6GC-vnrbEny_Ie_An5-tCpqxucuxi-vByf3Gjm7KEIUv0OF4wFNIO4kqg05InE4d2I6_H7I4
+   * 
+ */ + @SerializedName(value = "authorize_letter_copy") + private String authorizeLetterCopy; + /** *
    * 字段名:+经营者/法人身份证信息
@@ -109,8 +166,7 @@ public class ApplymentsRequest implements Serializable {
    * 是否必填:条件选填
    * 类型:object
    * 描述:
-   *  请填写经营者/法人的身份证信息
-   *  证件类型为“身份证”时填写。
+   *  当证件持有人类型为经营者/法人且证件类型为“身份证”时填写。
    *
    * 
*/ @@ -124,7 +180,7 @@ public class ApplymentsRequest implements Serializable { * 变量名:id_doc_info * 是否必填:条件选填 * 类型:object - * 描述:证件类型为“来往内地通行证、来往大陆通行证、护照”时填写。 + * 描述:当证件持有人类型为经营者/法人且证件类型不为“身份证”时填写。 *
*/ @SerializedName(value = "id_doc_info") @@ -146,27 +202,31 @@ public class ApplymentsRequest implements Serializable { /** *
-   * 字段名:是否填写结算账户信息
-   * 变量名:need_account_info
-   * 是否必填:是
+   * 字段名:最终受益人信息列表
+   * 变量名:ubo_info_list
+   * 是否必填:条件选填
    * 类型:bool
    * 描述:
-   *  可根据实际情况,填写“true”或“false”。
-   *  1、若为“true”,则需填写结算账户信息。
-   *  2、若为“false”,则无需填写结算账户信息。
-   *  示例值:true
+   *  仅企业需要填写。
+   *  若经营者/法人不是最终受益所有人,则需提填写受益所有人信息,最多上传4个。
+   *  若经营者/法人是最终受益所有人之一,可在此填写其他受益所有人信息,最多上传3个。
+   *  根据国家相关法律法规,需要提供公司受益所有人信息,受益所有人需符合至少以下条件之一:
+   *  1、直接或者间接拥有超过25%公司股权或者表决权的自然人。
+   *  2、通过人事、财务等其他方式对公司进行控制的自然人。
+   *  3、公司的高级管理人员,包括公司的经理、副经理、财务负责人、上市公司董事会秘书和公司章程规定的其他人员。
    * 
*/ - @SerializedName(value = "need_account_info") - private Boolean needAccountInfo; + @SerializedName(value = "ubo_info_list") + @SpecEncrypt + private List uboInfoList; /** *
    * 字段名:+结算账户信息
    * 变量名:account_info
-   * 是否必填:条件选填
+   * 是否必填:是
    * 类型:object
-   * 描述:若"是否填写结算账户信息"填写为“true”, 则必填,填写为“false”不填 。
+   * 描述:请填写商家提现收款的银行账户信息
    * 
*/ @SerializedName(value = "account_info") @@ -200,6 +260,18 @@ public class ApplymentsRequest implements Serializable { @SerializedName(value = "sales_scene_info") private SalesSceneInfo salesSceneInfo; + /** + *
+   * 字段名:+结算规则
+   * 变量名:settlement_info
+   * 是否必填:否
+   * 类型:object
+   * 描述:请填写商家的结算费率规则、所属行业等信息。若电商平台未传入,系统将填写默认值
+   * 
+ */ + @SerializedName(value = "settlement_info") + private SettlementInfo settlementInfo; + /** *
    * 字段名:商户简称
@@ -207,7 +279,7 @@ public class ApplymentsRequest implements Serializable {
    * 是否必填:是
    * 类型:string(64)
    * 描述:
-   *  UTF-8格式,中文占3个字节,即最多16个汉字长度。将在支付完成页向买家展示,需与商家的实际售卖商品相符 。
+   *  UTF-8格式,中文占3个字节,即最多21个汉字长度。将在支付完成页向买家展示,需与商家的实际售卖商品相符 。
    *  示例值:腾讯
    * 
*/ @@ -221,9 +293,10 @@ public class ApplymentsRequest implements Serializable { * 是否必填:否 * 类型:string(1024) * 描述: - * 1、若店铺业务包含互联网售药,则需上传特殊资质-《互联网药品交易服务证》。 - * 2、最多可上传5张照片,请填写通过图片上传接口预先上传图片生成好的MediaID 。 - * 示例值:[\"jTpGmxUX3FBWVQ5NJInE4d2I6_H7I4\"] + * 1、根据商户经营业务要求提供相关资质,详情查看《行业对应特殊资质》。 + * 2、请提供为“申请商家主体”所属的特殊资质,可授权使用总公司/分公司的特殊资 质; + * 3、最多可上传5张照片,请填写通过图片上传接口预先上传图片生成好的MediaID 。 + * 示例值:jTpGmxUX3FBWVQ5NJInE4d2I6_H7I4 *
*/ @SerializedName(value = "qualifications") @@ -236,8 +309,8 @@ public class ApplymentsRequest implements Serializable { * 是否必填:否 * 类型:string(1024) * 描述: - * 最多可上传5张照片,请填写通过图片上传接口预先上传图片生成好的MediaID 。 - * 示例值:[\"jTpGmg05InE4d2I6_H7I4\"] + * 根据实际审核情况,额外要求提供。最多可上传5张照片,请填写通过图片上传接口预先上传图片生成好的MediaID 。 + * 示例值:jTpGmg05InE4d2I6_H7I4 *
*/ @SerializedName(value = "business_addition_pics") @@ -248,9 +321,9 @@ public class ApplymentsRequest implements Serializable { * 字段名:补充说明 * 变量名:business_addition_desc * 是否必填:否 - * 类型:string(256) + * 类型:string(512) * 描述: - * 可填写512字以内 。 + * 1、若主体为“个人卖家”,该字段必传,则需填写描述“ 该商户已持续从事电子商务经营活动满6个月,且期间经营收入累计超过20万元。” * 示例值:特殊情况,说明原因 *
*/ @@ -262,20 +335,52 @@ public class ApplymentsRequest implements Serializable { public static class BusinessLicenseInfo implements Serializable { /** *
-     * 字段名:证件扫描件
+     * 字段名:证书类型
+     * 变量名:cert_type
+     * 是否必填:条件选填
+     * 类型:string
+     * 描述:
+     *  1、主体为“政府机关/事业单位/社会组织”时,请上传登记证书类型。
+     *  2、主体为“个体工商户/企业”时,不填。
+     *
+     *  当主体为事业单位时,选择此枚举值:
+     *  CERTIFICATE_TYPE_2388:事业单位法人证书
+     *
+     *  当主体为政府机关,选择此枚举值:
+     *  CERTIFICATE_TYPE_2389:统一社会信用代码证书
+     *
+     *  当主体为社会组织,选择以下枚举值之一:
+     *  CERTIFICATE_TYPE_2389:统一社会信用代码证书
+     *  CERTIFICATE_TYPE_2394:社会团体法人登记证书
+     *  CERTIFICATE_TYPE_2395:民办非企业单位登记证书
+     *  CERTIFICATE_TYPE_2396:基金会法人登记证书
+     *  CERTIFICATE_TYPE_2399:宗教活动场所登记证
+     *  CERTIFICATE_TYPE_2400:政府部门下发的其他有效证明文件
+     *  CERTIFICATE_TYPE_2520:执业许可证/执业证
+     *  CERTIFICATE_TYPE_2521:基层群众性自治组织特别法人统一社会信用代码证
+     *  CERTIFICATE_TYPE_2522:农村集体经济组织登记证
+     *  示例值:CERTIFICATE_TYPE_2388
+     * 
+ */ + @SerializedName(value = "cert_type") + private String certType; + + /** + *
+     * 字段名:营业执照扫描件
      * 变量名:business_license_copy
      * 是否必填:是
      * 类型:string(256)
      * 描述:
      *  1、主体为“个体工商户/企业”时,请上传营业执照的证件图片。
-     *  2、主体为“党政、机关及事业单位/其他组织”时,请上传登记证书的证件图片。
-     *  3、可上传1张图片,请填写通过图片上传接口预先上传图片生成好的MediaID 。
+     *  2、主体为“政府机关/事业单位/社会组织”时,请上传登记证书的证件图片。
+     *  3、可上传1张图片,请填写通过图片上传API预先上传图片生成好的MediaID 。
      *  4、图片要求:
      *  (1)请上传证件的彩色扫描件或彩色数码拍摄件,黑白复印件需加盖公章(公章信息需完整) 。
      *  (2)不得添加无关水印(非微信支付商户申请用途的其他水印)。
      *  (3)需提供证件的正面拍摄件,完整、照面信息清晰可见。信息不清晰、扭曲、压缩变形、反光、不完整均不接受。
      *  (4)不接受二次剪裁、翻拍、PS的证件照片。
-     *  示例值: 47ZC6GC-vnrbEny__Ie_An5-tCpqxucuxi-vByf3Gjm7KE53JXvGy9tqZm2XAUf-4KGprrKhpVBDIUv0OF4wFNIO4kqg05InE4d2I6_H7I4
+     *  示例值:47ZC6GC-vnrbEny__Ie_An5-tCpqxucuxi-vByf3Gjm7KE53JXvGy9tqZm2XAUf-4KGprrKhpVBDIUv0OF4wFNIO4kqg05InE4d2I6_H7I4
      * 
*/ @SerializedName(value = "business_license_copy") @@ -283,15 +388,14 @@ public static class BusinessLicenseInfo implements Serializable { /** *
-     * 字段名:证件注册号
+     * 字段名:营业执照注册号
      * 变量名:business_license_number
      * 是否必填:是
      * 类型:string(18)
      * 描述:
-     *  1、主体为“个体工商户/企业”时,请填写营业执照上的注册号/统一社会信用代码,须为15位数字或 18位数字|大写字母。
-     *  2、主体为“党政、机关及事业单位/其他组织”时,请填写登记证书的证书编号。
+     *  1、主体为“个体工商户/企业”时,请填写营业执照上的注册号/统一社会信用代码,须为18位数字|大写字母。
+     *  2、主体为“政府机关/事业单位/社会组织”时,请填写登记证书的证书编号。
      *  示例值:123456789012345678
-     *  特殊规则:长度最小15个字节
      * 
*/ @SerializedName(value = "business_license_number") @@ -305,7 +409,7 @@ public static class BusinessLicenseInfo implements Serializable { * 类型:string(128) * 描述: * 1、请填写营业执照/登记证书的商家名称,2~110个字符,支持括号 。 - * 2、个体工商户/党政、机关及事业单位,不能以“公司”结尾。 + * 2、个体工商户/政府机关/事业单位/社会组织,不能以“公司”结尾。 * 3、个体工商户,若营业执照上商户名称为空或为“无”,请填写"个体户+经营者姓名",如“个体户张三” 。 * 示例值:腾讯科技有限公司 *
@@ -334,7 +438,7 @@ public static class BusinessLicenseInfo implements Serializable { * 是否必填:条件选填 * 类型:string(128) * 描述: - * 主体为“党政、机关及事业单位/其他组织”时必填,请填写登记证书的注册地址。 + * 主体为“政府机关/事业单位/社会组织”时必填,请填写登记证书的注册地址。 * 示例值:深圳南山区科苑路 *
*/ @@ -348,11 +452,10 @@ public static class BusinessLicenseInfo implements Serializable { * 是否必填:条件选填 * 类型:string(256) * 描述: - * 1、主体为“党政、机关及事业单位/其他组织”时必填,请填写证件有效期。 + * 1、主体为“政府机关/事业单位/社会组织”时必填,请填写证件有效期。 * 2、若证件有效期为长期,请填写:长期。 * 3、结束时间需大于开始时间。 - * 4、有效期必须大于60天,即结束时间距当前时间需超过60天。 - * 示例值:[\"2014-01-01\",\"长期\"] + * 示例值:["2014-01-01","长期"] *
*/ @SerializedName(value = "business_time") @@ -362,52 +465,41 @@ public static class BusinessLicenseInfo implements Serializable { @Data @NoArgsConstructor - public static class OrganizationCertInfo implements Serializable { + public static class FinanceInstitutionInfo implements Serializable { /** *
-     * 字段名:组织机构代码证照片
-     * 变量名:organization_copy
+     * 字段名:金融机构类型
+     * 变量名:finance_type
      * 是否必填:是
-     * 类型:string(256)
+     * 类型:string
      * 描述:
-     *  可上传1张图片,请填写通过图片上传接口预先上传图片生成好的MediaID。
-     *  示例值:vByf3Gjm7KE53JXv\prrKhpVBDIUv0OF4wFNIO4kqg05InE4d2I6_H7I4
+     *  金融机构类型需与营业执照/登记证书上一致,可参考选择金融机构指引。
+     *  BANK_AGENT:银行业, 适用于商业银行、政策性银行、农村合作银行、村镇银行、开发性金融机构等
+     *  PAYMENT_AGENT:支付机构, 适用于非银行类支付机构
+     *  INSURANCE:保险业, 适用于保险、保险中介、保险代理、保险经纪等保险类业务
+     *  TRADE_AND_SETTLE:交易及结算类金融机构, 适用于交易所、登记结算类机构、银行卡清算机构、资金清算中心等
+     *  OTHER:其他金融机构, 适用于财务公司、信托公司、金融资产管理公司、金融租赁公司、汽车金融公司、贷款公司、货币经纪公司、消费金融公司、证券业、金融控股公司、股票、期货、货币兑换、小额贷款公司、金融资产管理、担保公司、商业保理公司、典当行、融资租赁公司、财经咨询等其他金融业务
+     *  示例值:BANK_AGENT
      * 
*/ - @SerializedName(value = "organization_copy") - private String organizationCopy; + @SerializedName(value = "finance_type") + private String financeType; /** *
-     * 字段名:组织机构代码
-     * 变量名:organization_number
+     * 字段名:金融机构许可证图片
+     * 变量名:finance_license_pics
      * 是否必填:是
-     * 类型:string(256)
+     * 类型:array
      * 描述:
-     *  1、请填写组织机构代码证上的组织机构代码。
-     *  2、可填写9或10位 数字|字母|连字符。
-     *  示例值:12345679-A
+     *  1、根据所属金融机构类型的许可证要求提供,详情查看金融机构指引。
+     *  2、请提供为“申请商家主体”所属的许可证,可授权使用总公司/分公司的特殊资质。
+     *  3、最多可上传5张照片,请填写通过图片上传API预先上传图片生成好的MediaID。
+     *  示例值:47ZC6GC-vnrbEny__Ie_An5-tCpqxucuxi-vByf3Gjm7KE53JXvGy9tqZm2XAUf-4KGprrKhpVBDIUv0OF4wFNIO4kqg05InE4d2I6_H7I4
      * 
*/ - @SerializedName(value = "organization_number") - private String organizationNumber; - - /** - *
-     * 字段名:组织机构代码有效期限
-     * 变量名:organization_time
-     * 是否必填:是
-     * 类型:string(256)
-     * 描述:
-     *  1、请填写组织机构代码证的有效期限,注意参照示例中的格式。
-     *  2、若证件有效期为长期,请填写:长期。
-     *  3、结束时间需大于开始时间。
-     *  4、有效期必须大于60天,即结束时间距当前时间需超过60天。
-     *  示例值:[\"2014-01-01\",\"长期\"]
-     * 
- */ - @SerializedName(value = "organization_time") - private String organizationTime; + @SerializedName(value = "finance_license_pics") + private String financeLicensePics; } @@ -421,9 +513,10 @@ public static class IdCardInfo implements Serializable { * 是否必填:是 * 类型:string(256) * 描述: - * 1、请上传经营者/法定代表人的身份证人像面照片。 - * 2、可上传1张图片,请填写通过图片上传接口预先上传图片生成好的MediaID。 - * 示例值:xpnFuAxhBTEO_PvWkfSCJ3zVIn001D8daLC-ehEuo0BJqRTvDujqhThn4ReFxikqJ5YW6zFQ + * 1、证件类型为“身份证”时,上传身份证人像面照片。 + * 2、可上传1张图片,请填写通过图片上传API预先上传图片生成好的MediaID。 + * 3、请上传彩色照片or彩色扫描件or复印件(需加盖公章鲜章),可添加“微信支付”相关水印(如微信支付认证)。 + * 示例值:jTpGmxUX3FBWVQ5NJTZvlKX_gdU4cRz7z5NxpnFuAxhBTEO_PvWkfSCJ3zVIn001D8daLC-ehEuo0BJqRTvDujqhThn4ReFxikqJ5YW6zFQ *
*/ @SerializedName(value = "id_card_copy") @@ -436,9 +529,10 @@ public static class IdCardInfo implements Serializable { * 是否必填:是 * 类型:string(256) * 描述: - * 1、请上传经营者/法定代表人的身份证国徽面照片。 - * 2、可上传1张图片,请填写通过图片上传接口预先上传图片生成好的MediaID 。 - * 示例值:vByf3Gjm7KE53JXvGy9tqZm2XAUf-4KGprrKhpVBDIUv0OF4wFNIO4kqg05InE4d2I6_H7I4 + * 1、证件类型为“身份证”时,上传身份证国徽面照片。 + * 2、可上传1张图片,请填写通过图片上传API预先上传图片生成好的MediaID 。 + * 3、请上传彩色照片or彩色扫描件or复印件(需加盖公章鲜章),可添加“微信支付”相关水印(如微信支付认证)。 + * 示例值:47ZC6GC-vnrbEny__Ie_An5-tCpqxuZm2XAUf-4KGprrKhpVBDIUv0OF4wFNIO4kqg05InE4d2I6_H7I4 *
*/ @SerializedName(value = "id_card_national") @@ -452,9 +546,8 @@ public static class IdCardInfo implements Serializable { * 类型:string(256) * 描述: * 1、请填写经营者/法定代表人对应身份证的姓名,2~30个中文字符、英文字符、符号。 - * 2、该字段需进行加密处理,加密方法详见敏感信息加密说明。 - * 示例值:pVd1HJ6v/69bDnuC4EL5Kz4jBHLiCa8MRtelw/wDa4SzfeespQO/0kjiwfqdfg== - * 字段加密:使用APIv3定义的方式加密 + * 2、该字段需进行加密处理,加密方法详见敏感信息加密说明。(提醒:必须在HTTP头中上送Wechatpay-Serial) + * 示例值:pVd1HJ6zyvPedzGaV+X3qtmrq9bb9tPROvwia4ibL+F6mfjbzQIzfb3HHLEjC4EL5Kz4jBHLiCyOb+tI0m2qhZ9evAM+Jv1z0NVa8MRtelw/wDa4SzfeespQO/0kjiwfqdfg== *
*/ @SerializedName(value = "id_card_name") @@ -466,12 +559,11 @@ public static class IdCardInfo implements Serializable { * 字段名:身份证号码 * 变量名:id_card_number * 是否必填:是 - * 类型:string(18) + * 类型:string(256) * 描述: * 1、请填写经营者/法定代表人对应身份证的号码。 - * 2、15位数字或17位数字+1位数字|X ,该字段需进行加密处理,加密方法详见敏感信息加密说明。 - * 示例值:zV+BEmytMNQCqQ8juwEc4P4TG5xzchG/5IL9DBd+Z0zZXkw==4 - * 特殊规则:长度最小15个字节 + * 2、15位数字或17位数字+1位数字|X ,该字段需进行加密处理,加密方法详见敏感信息加密说明。(提醒:必须在HTTP头中上送Wechatpay-Serial) + * 示例值:AOZdYGISxo4y44/UgZ69bdu9X+tfMUJ9dl+LetjM45/zMbrYu+wWZ8gn4CT3JZKGZjduGdtkRJJp0/0eow96uY1Pk7Rq79Jtt7+I8juwEc4P4TG5xzchG/5IL9DBd+Z0zZXkw== *
*/ @SerializedName(value = "id_card_number") @@ -480,15 +572,46 @@ public static class IdCardInfo implements Serializable { /** *
-     * 字段名:身份证有效期限
+     * 字段名:身份证居住地址
+     * 变量名:id_card_address
+     * 是否必填:条件选填
+     * 类型:string(512)
+     * 描述:
+     *  1、主体类型为企业时,需要填写。其他主体类型,无需上传。
+     *  2、请按照身份证住址填写,如广东省深圳市南山区xx路xx号xx室
+     *  3、该字段需进行加密处理,加密方法详见敏感信息加密说明。(提醒:必须在HTTP头中上送Wechatpay-Serial)
+     *  示例值:AOZdYGISxo4y44/UgZ69bdu9X+tfMUJ9dl+LetjM45/zMbrYu+wWZ8gn4CTdo+D/m9MrPg+V4p0/0eow96uY1Pk7Rq79Jtt7+I8juwEc4P4TG5xzchG/5IL9DBd+Z0zZXkw==
+     * 
+ */ + @SerializedName(value = "id_card_address") + @SpecEncrypt + private String idCardAddress; + + /** + *
+     * 字段名:身份证开始时间
+     * 变量名:id_card_valid_time_begin
+     * 是否必填:是
+     * 类型:string(128)
+     * 描述:
+     *  1、请按照示例值填写。
+     *  2、结束时间大于开始时间。
+     *  示例值:2019-06-06
+     * 
+ */ + @SerializedName(value = "id_card_valid_time_begin") + private String idCardValidTimeBegin; + + /** + *
+     * 字段名:身份证结束时间
      * 变量名:id_card_valid_time
      * 是否必填:是
      * 类型:string(128)
      * 描述:
-     *  1、请填写身份证有效期的结束时间,注意参照示例中的格式。
-     *  2、若证件有效期为长期,请填写:长期。
-     *  3、证件有效期需大于60天。
-     *  示例值:2026-06-06,长期
+     *  1、请按照示例值填写,若证件有效期为长期,请填写:长期。
+     *  2、结束时间大于开始时间。
+     *  示例值:2026-06-06
      * 
*/ @SerializedName(value = "id_card_valid_time") @@ -499,6 +622,39 @@ public static class IdCardInfo implements Serializable { @Data @NoArgsConstructor public static class IdDocInfo implements Serializable { + /** + *
+     * 字段名:证件正面照片
+     * 变量名:id_doc_copy
+     * 是否必填:是
+     * 类型:string(256)
+     * 描述:
+     *  1、证件类型不为“身份证”时,上传证件正面照片。
+     *  2、可上传1张图片,请填写通过图片图片上传API预先上传图片生成好的MediaID。
+     *  3、请上传彩色照片or彩色扫描件or复印件(需加盖公章鲜章),可添加“微信支付”相关水印(如微信支付认证)。
+     *  示例值:jTpGmxUX3FBWVQ5NJTZvlKX_gdU4cRz7z5NxpnFuAxhBTEO_PvWkfSCJ3zVIn001D8daLC-ehEuo0BJqRTvDujqhThn4ReFxikqJ5YW6zFQ
+     * 
+ */ + @SerializedName(value = "id_doc_copy") + private String idDocCopy; + + /** + *
+     * 字段名:证件反面照片
+     * 变量名:id_doc_copy_back
+     * 是否必填:条件选填
+     * 类型:string(256)
+     * 描述:
+     *  1、若证件类型为来往通行证、外国人居留证、港澳居住证、台湾居住证时,上传证件反面照片。
+     *  2、若证件类型为护照,无需上传反面照片。
+     *  3、可上传1张图片,请填写通过图片上传API预先上传图片生成好的MediaID 。
+     *  4、请上传彩色照片or彩色扫描件or复印件(需加盖公章鲜章),可添加“微信支付”相关水印(如微信支付认证)。
+     *  示例值:47ZC6GC-vnrbEny__Ie_An5-tCpqxucuxi-vByf3Gjm7KE53JXvGy9tqZm2XAUf-4KGprrKhpVBDIUv0OF4wFNIO4kqg05InE4d2I6_H7I4
+     * 
+ */ + @SerializedName(value = "id_doc_copy_back") + private String idDocCopyBack; + /** *
      * 字段名:证件姓名
@@ -506,8 +662,9 @@ public static class IdDocInfo implements Serializable {
      * 是否必填:是
      * 类型:string(128)
      * 描述:
-     *  请填写经营者/法人姓名。
-     *  示例值:jTpGmxUX3FBWVQ5NJTZvlKX_gdU4LC-ehEuo0BJqRTvDujqhThn4ReFxikqJ5YW6zFQ
+     *  1、请填写经营者/法人姓名。
+     *  2、该字段需进行加密处理,加密方法详见敏感信息加密说明。(提醒:必须在HTTP头中上送Wechatpay-Serial)
+     *  示例值:jTpGmxUX3FBWVQ5NJTZvlKX_gdU4cRz7z5NxpnFuAxhBTEO_PvWkfSCJ3zVIn001D8daLC-ehEuo0BJqRTvDujqhThn4ReFxikqJ5YW6zFQ
      * 
*/ @SerializedName(value = "id_doc_name") @@ -519,10 +676,11 @@ public static class IdDocInfo implements Serializable { * 字段名:证件号码 * 变量名:id_doc_number * 是否必填:是 - * 类型:string(128) + * 类型:string(256) * 描述: * 7~11位 数字|字母|连字符 。 - * 示例值:jTpGmxUX3FBWVQ5NJTZvlKX_go0BJqRTvDujqhThn4ReFxikqJ5YW6zFQ + * 该字段需进行加密处理,加密方法详见敏感信息加密说明。(提醒:必须在HTTP头中上送Wechatpay-Serial) + * 示例值:jTpGmxUX3FBWVQ5NJTZvlKX_gdU4cRz7z5NxpnFuAxhBTEO_PvWkfSCJ3zVIn001D8daLC-ehEuo0BJqRTvDujqhThn4ReFxikqJ5YW6zFQ *
*/ @SerializedName(value = "id_doc_number") @@ -531,29 +689,45 @@ public static class IdDocInfo implements Serializable { /** *
-     * 字段名:证件照片
-     * 变量名:id_doc_copy
+     * 字段名:证件居住地址
+     * 变量名:id_doc_address
+     * 是否必填:条件选填
+     * 类型:string(512)
+     * 描述:
+     *  1、主体类型为企业时,需要填写。其他主体类型,无需上传。
+     *  2、请按照证件上住址填写,若证件上无住址则按照实际住址填写,如广东省深圳市南山区xx路xx号xx室。
+     *  3、该字段需进行加密处理,加密方法详见敏感信息加密说明。(提醒:必须在HTTP头中上送Wechatpay-Serial)
+     *  示例值:jTpGmxUX3FBWVQ5NJTZvlKX_gdU4cRz7z5NxpnFuAxhBTEO_PvWkfSCJ3zVIn001D8daLC-ehEuo0BJqRTvDujqhThn4ReFxikqJ5YW6zFQ
+     * 
+ */ + @SerializedName(value = "id_doc_address") + @SpecEncrypt + private String idDocAddress; + + /** + *
+     * 字段名:证件有效期开始时间
+     * 变量名:doc_period_begin
      * 是否必填:是
-     * 类型:string(256)
+     * 类型:string(128)
      * 描述:
-     *  1、可上传1张图片,请填写通过图片上传接口预先上传图片生成好的MediaID。
-     *  2、2M内的彩色图片,格式可为bmp、png、jpeg、jpg或gif 。
-     *  示例值:xi-vByf3Gjm7KE53JXvGy9tqZm2XAUf-4KGprrKhpVBDIUv0OF4wFNIO4kqg05InE4d2I6_H7I4
+     *  1、请按照示例值填写
+     *  2、结束时间大于开始时间
+     *  示例值:2019-06-06
      * 
*/ - @SerializedName(value = "id_doc_copy") - private String idDocCopy; + @SerializedName(value = "doc_period_begin") + private String docPeriodBegin; /** *
-     * 字段名:证件结束日期
+     * 字段名:证件有效期结束时间
      * 变量名:doc_period_end
      * 是否必填:是
      * 类型:string(128)
      * 描述:
-     *  1、请按照示例值填写。
-     *  2、若证件有效期为长期,请填写:长期。
-     *  3、证件有效期需大于60天 。
+     *  1、请按照示例值填写,若证件有效期为长期,请填写:长期。
+     *  2、结束时间大于开始时间。
      *  示例值:2020-01-02
      * 
*/ @@ -562,6 +736,144 @@ public static class IdDocInfo implements Serializable { } + @Data + @NoArgsConstructor + public static class UboInfo implements Serializable { + /** + *
+     * 字段名:证件类型
+     * 变量名:ubo_id_doc_type
+     * 是否必填:是
+     * 类型:string
+     * 描述:
+     *  请填写受益人的证件类型。
+     *  枚举值:
+     *  IDENTIFICATION_TYPE_MAINLAND_IDCARD:中国大陆居民-身份证
+     *  IDENTIFICATION_TYPE_OVERSEA_PASSPORT:其他国家或地区居民-护照
+     *  IDENTIFICATION_TYPE_HONGKONG:中国香港居民--来往内地通行证
+     *  IDENTIFICATION_TYPE_MACAO:中国澳门居民--来往内地通行证
+     *  IDENTIFICATION_TYPE_TAIWAN:中国台湾居民--来往大陆通行证
+     *  IDENTIFICATION_TYPE_FOREIGN_RESIDENT:外国人居留证
+     *  IDENTIFICATION_TYPE_HONGKONG_MACAO_RESIDENT:港澳居民证
+     *  IDENTIFICATION_TYPE_TAIWAN_RESIDENT:台湾居民证
+     *  示例值:IDENTIFICATION_TYPE_MAINLAND_IDCARD
+     * 
+ */ + @SerializedName(value = "ubo_id_doc_type") + private String uboIdDocType; + + /** + *
+     * 字段名:证件正面照片
+     * 变量名:ubo_id_doc_copy
+     * 是否必填:是
+     * 类型:string(256)
+     * 描述:
+     *  1、请上传受益人证件的正面照片。
+     *  2、若证件类型为身份证,请上传人像面照片。
+     *  3、可上传1张图片,请填写通过图片上传API预先上传图片生成好的MediaID。
+     *  4、请上传彩色照片or彩色扫描件or复印件(需加盖公章鲜章),可添加“微信支付”相关水印(如微信支付认证)。
+     *  示例值:jTpGmxUXqRTvDujqhThn4ReFxikqJ5YW6zFQ
+     * 
+ */ + @SerializedName(value = "ubo_id_doc_copy") + private String uboIdDocCopy; + + /** + *
+     * 字段名:证件反面照片
+     * 变量名:ubo_id_doc_copy_back
+     * 是否必填:条件选填
+     * 类型:string(256)
+     * 描述:
+     *  1、请上传受益人证件的反面照片。
+     *  2、若证件类型为护照,无需上传反面照片。
+     *  3、可上传1张图片,请填写通过图片上传API预先上传图片生成好的MediaID。
+     *  4、请上传彩色照片or彩色扫描件or复印件(需加盖公章鲜章),可添加“微信支付”相关水印(如微信支付认证)。
+     *  示例值:jTpGmxUX3FBWVQ5NJTZvvDujqhThn4ReFxikqJ5YW6zFQ
+     * 
+ */ + @SerializedName(value = "ubo_id_doc_copy_back") + private String uboIdDocCopyBack; + + /** + *
+     * 字段名:证件姓名
+     * 变量名:ubo_id_doc_name
+     * 是否必填:是
+     * 类型:string(128)
+     * 描述:
+     *  该字段需进行加密处理,加密方法详见敏感信息加密说明。(提醒:必须在HTTP头中上送Wechatpay-Serial)
+     *  示例值:AOZdYGISxo4y44/Ug4P4TG5xzchG/5IL9DBd+Z0zZXkw==
+     * 
+ */ + @SerializedName(value = "ubo_id_doc_name") + @SpecEncrypt + private String uboIdDocName; + + /** + *
+     * 字段名:证件号码
+     * 变量名:ubo_id_doc_number
+     * 是否必填:是
+     * 类型:string(256)
+     * 描述:
+     *  该字段需进行加密处理,加密方法详见敏感信息加密说明。(提醒:必须在HTTP头中上送Wechatpay-Serial)
+     *  示例值:AOZdYGISxo4y44/Ug4P4TG5xzchG/5IL9DBd+Z0zZXkw==
+     * 
+ */ + @SerializedName(value = "ubo_id_doc_number") + @SpecEncrypt + private String uboIdDocNumber; + + /** + *
+     * 字段名:证件居住地址
+     * 变量名:ubo_id_doc_address
+     * 是否必填:条件选填
+     * 类型:string(512)
+     * 描述:
+     *  1、请按照证件上住址填写,若证件上无住址则按照实际住址填写,如广东省深圳市南山区xx路xx号xx室。
+     *  2、 该字段需进行加密处理,加密方法详见敏感信息加密说明。(提醒:必须在HTTP头中上送Wechatpay-Serial)
+     *  示例值:pVd1HJ6zyvPedzGaV+X3qtmrq9bb9tPROvwia4ibL+F6mfjbzQIzfDa4SzfeespQO/0kjiwfqdfg==
+     * 
+ */ + @SerializedName(value = "ubo_id_doc_address") + @SpecEncrypt + private String uboIdDocAddress; + + /** + *
+     * 字段名:证件有效期开始时间
+     * 变量名:ubo_id_doc_period_begin
+     * 是否必填:是
+     * 类型:string(128)
+     * 描述:
+     *  1、请按照示例值填写。
+     *  2、结束时间大于开始时间。
+     *  示例值:2019-06-06
+     * 
+ */ + @SerializedName(value = "ubo_id_doc_period_begin") + private String uboIdDocPeriodBegin; + + /** + *
+     * 字段名:证件有效期结束时间
+     * 变量名:ubo_id_doc_period_end
+     * 是否必填:是
+     * 类型:string(128)
+     * 描述:
+     *  1、请按照示例值填写,若证件有效期为长期,请填写:长期。
+     *  2、结束时间大于开始时间。
+     *  示例值:2026-06-06
+     * 
+ */ + @SerializedName(value = "ubo_id_doc_period_end") + private String uboIdDocPeriodEnd; + + } + @Data @NoArgsConstructor public static class AccountInfo implements Serializable { @@ -572,9 +884,9 @@ public static class AccountInfo implements Serializable { * 是否必填:是 * 类型:string(2) * 描述: - * 1、若主体为企业/党政、机关及事业单位/其他组织,可填写:74-对公账户。 - * 2、若主体为小微,可填写:75-对私账户。 - * 3、若主体为个体工商户,可填写:74-对公账户或75-对私账户。 + * 1、若主体为企业/政府机关/事业单位/社会组织,可填写:74-对公账户。 + * 2、主体为小微/个人卖家,可选择:75-对私账户。 + * 3、若主体为个体工商户,可填写:74-对公账户、75-对私账户。 * 示例值:75 *
*/ @@ -588,7 +900,8 @@ public static class AccountInfo implements Serializable { * 是否必填:是 * 类型:string(10) * 描述: - * 详细参见开户银行对照表。 + * 对私银行调用:查询支持个人业务的银行列表API + * 对公银行调用:查询支持对公业务的银行列表API。 * 示例值:工商银行 *
*/ @@ -604,8 +917,8 @@ public static class AccountInfo implements Serializable { * 描述: * 1、选择经营者个人银行卡时,开户名称必须与身份证姓名一致。 * 2、选择对公账户时,开户名称必须与营业执照上的“商户名称”一致。 - * 3、该字段需进行加密处理,加密方法详见敏感信息加密说明。 - * 示例值:AOZdYGISxo4yw96uY1Pk7Rq79Jtt7+I8juwEc4P4TG5xzchG/5IL9DBd+Z0zZXkw== + * 3、该字段需进行加密处理,加密方法详见敏感信息加密说明。(提醒:必须在HTTP头中上送Wechatpay-Serial) + * 示例值:AOZdYGISxo4y44/UgZ69bdu9X+tfMUJ9dl+LetjM45/zMbrYu+wWZ8gn4CTdo+D/m9MrPg+V4sm73oxqdQu/hj7aWyDl4GQtPXVdaztB9jVbVZh3QFzV+BEmytMNQp9dt1uWJktlfdDdLR3AMWyMB377xd+m9bSr/ioDTzagEcGe+vLYiKrzcroQv3OR0p3ppFYoQ3IfYeU/04S4t9rNFL+kyblK2FCCqQ11NdbbHoCrJc7NV4oASq6ZFonjTtgjjgKsadIKHXtb3JZKGZjduGdtkRJJp0/0eow96uY1Pk7Rq79Jtt7+I8juwEc4P4TG5xzchG/5IL9DBd+Z0zZXkw== *
*/ @SerializedName(value = "account_name") @@ -620,6 +933,8 @@ public static class AccountInfo implements Serializable { * 类型:string(12) * 描述: * 至少精确到市,详细参见省市区编号对照表。 + * 注: + * 仅当省市区编号对照表中无对应的省市区编号时,可向上取该银行对应市级编号或省级编号。 * 示例值:110000 *
*/ @@ -633,8 +948,8 @@ public static class AccountInfo implements Serializable { * 是否必填:条件选填 * 类型:string(64) * 描述: - * 1、17家直连银行无需填写,如为其他银行,开户银行全称(含支行)和开户银行联行号二选一。 - * 2、详细参见开户银行全称(含支行)对照表。 + * 1、根据开户银行查询接口中的“是否需要填写支行”判断是否需要填写。如为其他银行,开户银行全称(含支行)和开户银行联行号二选一。 + * 2、详细需调用查询支行列表API查看查询结果。 * 示例值:402713354941 *
*/ @@ -648,10 +963,9 @@ public static class AccountInfo implements Serializable { * 是否必填:条件选填 * 类型:string(128) * 描述: - * 1、17家直连银行无需填写,如为其他银行,开户银行全称(含支行)和开户银行联行号二选一。 - * 2、需填写银行全称,如"深圳农村商业银行XXX支行" 。 - * 3、详细参见开户银行全称(含支行)对照表。 - * 示例值:施秉县农村信用合作联社城关信用社 + * 1、根据开户银行查询接口中的“是否需要填写支行”判断是否需要填写。如为其他银行,开户银行全称(含支行)和开户银行联行号二选一。 + * 2、详细需调用查询支行列表API查看查询结果。 + * 示例值:中国工商银行股份有限公司北京市分行营业部 * */ @SerializedName(value = "bank_name") @@ -665,7 +979,7 @@ public static class AccountInfo implements Serializable { * 类型:string(128) * 描述: * 1、数字,长度遵循系统支持的对公/对私卡号长度要求表。 - * 2、该字段需进行加密处理,加密方法详见敏感信息加密说明。 + * 2、该字段需进行加密处理,加密方法详见敏感信息加密说明。(提醒:必须在HTTP头中上送Wechatpay-Serial) * 示例值: d+xT+MQCvrLHUVDWv/8MR/dB7TkXLVfSrUxMPZy6jWWYzpRrEEaYQE8ZRGYoeorwC+w== * */ @@ -673,6 +987,70 @@ public static class AccountInfo implements Serializable { @SpecEncrypt private String accountNumber; + /** + *
+     * 字段名:+银行帐户证明材料
+     * 变量名:account_cert_info
+     * 是否必填:否
+     * 类型:string(128)
+     * 描述:
+     *  1. 当主体类型是“政府机关/事业单位”时或所属行业为“党费”时,支持在有合法资金管理关系的情况下结算账户设置为非同名。
+     *  2. 若结算账户设置为非同名,则需填写非同名证明材料,若结算账户为同名,则无需填写。
+     * 
+ */ + @SerializedName(value = "account_cert_info") + private AccountCertInfo accountCertInfo; + + @Data + @NoArgsConstructor + public static class AccountCertInfo implements Serializable { + /** + *
+       * 字段名:结算证明函
+       * 变量名:settlement_cert_pic
+       * 是否必填:是
+       * 类型:string(256)
+       * 描述:
+       *  1. 请参照示例图打印结算证明函。
+       *  2、可上传1张图片,请填写通过图片上传API预先上传图片生成好的MediaID。
+       *  示例值:47ZC6GC-vnrbEny_Ie_An5-tCpqxucuxi-vByf3Gjm7KEIUv0OF4wFNIO4kqg05InE4d2I6_H7I4
+       * 
+ */ + @SerializedName(value = "settlement_cert_pic") + private String settlementCertPic; + + /** + *
+       * 字段名:关系证明函
+       * 变量名:relation_cert_pic
+       * 是否必填:是
+       * 类型:string(256)
+       * 描述:
+       *  1. 请参照示例图打印关系证明函。
+       *  2、可上传1张图片,请填写通过图片上传API预先上传图片生成好的MediaID。
+       *  示例值:47ZC6GC-vnrbEny_Ie_An5-tCpqxucuxi-vByf3Gjm7KEIUv0OF4wFNIO4kqg05InE4d2I6_H7I4
+       * 
+ */ + @SerializedName(value = "relation_cert_pic") + private String relationCertPic; + + /** + *
+       * 字段名:其他补充证明
+       * 变量名:other_cert_pics
+       * 是否必填:是
+       * 类型:array
+       * 描述:
+       *  1. 请提供非同名结算的法律法规、政策通知、政府或上级部门公文等证明文件,以作上述材料的补充证明。
+       *  2、可上传1-3张图片,请填写通过图片上传API预先上传图片生成好的MediaID。
+       *  示例值:47ZC6GC-vnrbEny_Ie_An5-tCpqxucuxi-vByf3Gjm7KEIUv0OF4wFNIO4kqg05InE4d2I6_H7I4
+       * 
+ */ + @SerializedName(value = "other_cert_pics") + private String otherCertPics; + + } + } @Data @@ -685,8 +1063,8 @@ public static class ContactInfo implements Serializable { * 是否必填:是 * 类型:string(2) * 描述: - * 1、小微商户,选择:65-法人/经营者。 - * 2、个体工商户/企业/党政、机关及事业单位/其他组织,可选择:65-法人/经营者、66- 负责人。 (负责人:经商户授权办理微信支付业务的人员,授权范围包括但不限于签约,入驻过程需完成账户验证)。 + * 1、主体为“小微/个人卖家 ”,可选择:65-经营者/法人。 + * 2、主体为“个体工商户/企业/政府机关/事业单位/社会组织”,可选择:65-经营者/法人、66- 经办人。 (经办人:经商户授权办理微信支付业务的人员)。 * 示例值:65 * */ @@ -701,8 +1079,8 @@ public static class ContactInfo implements Serializable { * 类型:string(256) * 描述: * 1、若管理员类型为“法人”,则该姓名需与法人身份证姓名一致。 - * 2、若管理员类型为“经办人”,则可填写实际经办人的姓名。 - * 3、该字段需进行加密处理,加密方法详见敏感信息加密说明。 + * 2、若管理员类型为“经办人”,则可填写实际负责人的姓名。 + * 3、该字段需进行加密处理,加密方法详见敏感信息加密说明。(提醒:必须在HTTP头中上送Wechatpay-Serial) * (后续该管理员需使用实名微信号完成签约) * 示例值: pVd1HJ6zyvPedzGaV+X3IdGdbDnuC4Eelw/wDa4SzfeespQO/0kjiwfqdfg== * @@ -711,24 +1089,128 @@ public static class ContactInfo implements Serializable { @SpecEncrypt private String contactName; + /** + *
+     * 字段名:超级管理员证件类型
+     * 变量名:contact_id_doc_type
+     * 是否必填:条件选填
+     * 类型:string
+     * 描述:
+     *  当超级管理员类型是经办人时,请上传超级管理员证件类型。
+     *  IDENTIFICATION_TYPE_MAINLAND_IDCARD:中国大陆居民-身份证
+     *  IDENTIFICATION_TYPE_OVERSEA_PASSPORT:其他国家或地区居民-护照
+     *  IDENTIFICATION_TYPE_HONGKONG:中国香港居民--来往内地通行证
+     *  IDENTIFICATION_TYPE_MACAO:中国澳门居民--来往内地通行证
+     *  IDENTIFICATION_TYPE_TAIWAN:中国台湾居民--来往大陆通行证
+     *  IDENTIFICATION_TYPE_FOREIGN_RESIDENT:外国人居留证
+     *  IDENTIFICATION_TYPE_HONGKONG_MACAO_RESIDENT:港澳居民证
+     *  IDENTIFICATION_TYPE_TAIWAN_RESIDENT:台湾居民证
+     *  示例值:IDENTIFICATION_TYPE_MAINLAND_IDCARD
+     * 
+ */ + @SerializedName(value = "contact_id_doc_type") + private String contactIdDocType; + /** *
      * 字段名:超级管理员身份证件号码
      * 变量名:contact_id_card_number
-     * 是否必填:是
+     * 是否必填:条件选填
      * 类型:string(256)
      * 描述:
-     *  1、若管理员类型为法人,则该身份证号码需与法人身份证号码一致。若管理员类型为经办人,则可填写实际经办人的身份证号码。
+     *  1、若超级管理员类型为法人,则该身份证号码需与法人身份证号码一致。若超级管理员类型为经办人,则可填写实际经办人的身份证号码。
      *  2、可传身份证、来往内地通行证、来往大陆通行证、护照等证件号码。
      *  3、超级管理员签约时,校验微信号绑定的银行卡实名信息,是否与该证件号码一致。
-     *  4、该字段需进行加密处理,加密方法详见敏感信息加密说明。
-     *  示例值:pVd1HJ6zmty7/mYNxLMpRSvMRtelw/wDa4SzfeespQO/0kjiwfqdfg==
+     *  4、该字段需进行加密处理,加密方法详见敏感信息加密说明。(提醒:必须在HTTP头中上送Wechatpay-Serial)
+     *  示例值:pVd1HJ6zyvPedzGaV+X3qtmrq9bb9tPROvwia4ibL+F6mfjbzQIzfb3HHDnuC4EL5Kz4jBHLiCyOb+tI0m2qhZ9evAM+Jv1z0NVa8MRtelw/wDa4SzfeespQO/0kjiwfqdfg==
      * 
*/ @SerializedName(value = "contact_id_card_number") @SpecEncrypt private String contactIdCardNumber; + /** + *
+     * 字段名:超级管理员证件正面照片
+     * 变量名:contact_id_doc_copy
+     * 是否必填:条件选填
+     * 类型:string(256)
+     * 描述:
+     *  1、当超级管理员类型是经办人时,请上传超级管理员证件的正面照片。
+     *  2、若证件类型为身份证,请上传人像面照片。
+     *  3、可上传1张图片,请填写通过图片上传API预先上传图片生成好的MediaID。
+     *  4、请上传彩色照片or彩色扫描件or复印件(需加盖公章鲜章),可添加“微信支付”相关水印(如微信支付认证)。
+     *  示例值:jTpGmxUX3FBWVQ5NJTZvvDujqhThn4ReFxikqJ5YW6zFQ
+     * 
+ */ + @SerializedName(value = "contact_id_doc_copy") + private String contactIdDocCopy; + + /** + *
+     * 字段名:超级管理员证件反面照片
+     * 变量名:contact_id_doc_copy_back
+     * 是否必填:条件选填
+     * 类型:string(256)
+     * 描述:
+     *  1、当超级管理员类型是经办人时,请上传超级管理员证件的反面照片。
+     *  2、若证件类型为护照,无需上传反面照片。
+     *  3、可上传1张图片,请填写通过图片上传API预先上传图片生成好的MediaID。
+     *  4、请上传彩色照片or彩色扫描件or复印件(需加盖公章鲜章),可添加“微信支付”相关水印(如微信支付认证)。
+     *  示例值:jTpGmxUX3FBWVQ5NJTZvvDujqhThn4ReFxikqJ5YW6zFQ
+     * 
+ */ + @SerializedName(value = "contact_id_doc_copy_back") + private String contactIdDocCopyBack; + + /** + *
+     * 字段名:超级管理员证件有效期开始时间
+     * 变量名:contact_id_doc_period_begin
+     * 是否必填:条件选填
+     * 类型:string(128)
+     * 描述:
+     *  1、当超级管理员类型是经办人时,请上传证件有效期开始时间。
+     *  2、请按照示例值填写。
+     *  3、结束时间大于开始时间。
+     *  示例值:2019-06-06
+     * 
+ */ + @SerializedName(value = "contact_id_doc_period_begin") + private String contactIdDocPeriodBegin; + + /** + *
+     * 字段名:超级管理员证件有效期结束时间
+     * 变量名:contact_id_doc_period_end
+     * 是否必填:条件选填
+     * 类型:string(128)
+     * 描述:
+     *  1、当超级管理员类型是经办人时,请上传证件有效期结束时间。
+     *  2、请按照示例值填写,若证件有效期为长期,请填写:长期。
+     *  3、结束时间大于开始时间。
+     *  示例值:2026-06-06
+     * 
+ */ + @SerializedName(value = "contact_id_doc_period_end") + private String contactIdDocPeriodEnd; + + /** + *
+     * 字段名:业务办理授权函
+     * 变量名:business_authorization_letter
+     * 是否必填:条件选填
+     * 类型:string(256)
+     * 描述:
+     *  1、当超级管理员类型是经办人时,请上传业务办理授权函。
+     *  2、请参照示例图打印业务办理授权函,全部信息需打印,不支持手写商户信息,并加盖公章。
+     *  3、可上传1张图片,请填写通过图片上传API预先上传图片生成好的MediaID。
+     *  示例值:47ZC6GC-vnrbEny_Ie_An5-tCpqxucuxi-vByf3Gjm7KEIUv0OF4wFNIO4kqg05InE4d2I6_H7I4
+     * 
+ */ + @SerializedName(value = "business_authorization_letter") + private String businessAuthorizationLetter; + /** *
      * 字段名:超级管理员手机
@@ -737,7 +1219,7 @@ public static class ContactInfo implements Serializable {
      * 类型:string(256)
      * 描述:
      *  1、请填写管理员的手机号,11位数字, 用于接收微信支付的重要管理信息及日常操作验证码 。
-     *  2、该字段需进行加密处理,加密方法详见敏感信息加密说明。
+     *  2、该字段需进行加密处理,加密方法详见敏感信息加密说明。(提醒:必须在HTTP头中上送Wechatpay-Serial)
      *  示例值:pVd1HJ6zyvPedzGaV+X3qtmrq9bb9tPROvwia4ibL+F6mfjbzQIzfb3HHLEjZ4YiNWWNeespQO/0kjiwfqdfg==
      * 
*/ @@ -752,9 +1234,10 @@ public static class ContactInfo implements Serializable { * 是否必填:是 * 类型:string(256) * 描述: - * 1、用于接收微信支付的开户邮件及日常业务通知。 - * 2、需要带@,遵循邮箱格式校验 。 - * 3、该字段需进行加密处理,加密方法详见敏感信息加密说明。 + * 1、主体类型为“小微商户/个人卖家”可选填,其他主体需必填。 + * 2、用于接收微信支付的开户邮件及日常业务通知。 + * 3、需要带@,遵循邮箱格式校验 。 + * 4、该字段需进行加密处理,加密方法详见敏感信息加密说明。(提醒:必须在HTTP头中上送Wechatpay-Serial) * 示例值:pVd1HJ6zyvPedzGaV+X3qtmrq9bb9tPROvwia4ibL+FWWNUlw/wDa4SzfeespQO/0kjiwfqdfg== * */ @@ -800,9 +1283,13 @@ public static class SalesSceneInfo implements Serializable { *
      * 字段名:店铺二维码
      * 变量名:store_qr_code
-     * 是否必填:1、店铺二维码 or 店铺链接二选一必填。 2、若为电商小程序,可上传店铺页面的小程序二维码。 3、请填写通过图片上传接口预先上传图片生成好的MediaID,仅能上传1张图片 。 示例值:jTpGmxUX3FBWVQ5NJTZvlKX_gdU4cRz7z5NxpnFuAxhBTEO1D8daLC-ehEuo0BJqRTvDujqhThn4ReFxikqJ5YW6zFQ
+     * 是否必填:二选一
      * 类型:string(256)
      * 描述:
+     *  1、店铺二维码 or 店铺链接二选一必填。
+     *  2、若为电商小程序,可上传店铺页面的小程序二维码。
+     *  3、请填写通过图片上传API预先上传图片生成好的MediaID,仅能上传1张图片 。
+     *  示例值:jTpGmxUX3FBWVQ5NJTZvlKX_gdU4cRz7z5NxpnFuAxhBTEO_PvWkfSCJ3zVIn001D8daLC-ehEuo0BJqRTvDujqhThn4ReFxikqJ5YW6zFQ
      * 
*/ @SerializedName(value = "store_qr_code") @@ -815,6 +1302,9 @@ public static class SalesSceneInfo implements Serializable { * 是否必填:否 * 类型:string(256) * 描述: + * 1、商户自定义字段,可填写已认证的小程序AppID,认证主体需与二级商户主体一致; + * 2、完成入驻后, 系统发起二级商户号与该AppID的绑定(即配置为sub_appid,可在发起支付时传入) + * 示例值:wxa123344545577 * */ @SerializedName(value = "mini_program_sub_appid") @@ -822,4 +1312,39 @@ public static class SalesSceneInfo implements Serializable { } + @Data + @NoArgsConstructor + public static class SettlementInfo implements Serializable { + /** + *
+     * 字段名:结算规则ID
+     * 变量名:settlement_id
+     * 是否必填:否
+     * 类型:int
+     * 描述:
+     *  1、选填,请选择二级商户的结算规则ID,需匹配电商平台开通工具箱选择的费率档位,详细参见电商二级商户结算规则对照表;https://kf.qq.com/faq/220228qEfuAz220228bMFji6.html
+     *  2、若电商平台未传入,将默认选择0.6%费率对应的结算规则id;
+     *  示例值:719
+     * 
+ */ + @SerializedName(value = "settlement_id") + private Integer settlementId; + + /** + *
+     * 字段名:所属行业
+     * 变量名:qualification_type
+     * 是否必填:二选一
+     * 类型:string[1, 200]
+     * 描述:
+     *  1、选填,请填写二级商户所属的行业名称,映射特殊资质要求,详细参见电商二级商户结算规则对照表;
+     *  2、若电商平台未传入,将默认填写无需特殊资质的行业名称;
+     *  示例值:零售批发/生活娱乐/其他
+     * 
+ */ + @SerializedName(value = "qualification_type") + private String qualificationType; + + } + } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/PartnerTransactionsRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/PartnerTransactionsRequest.java index ccfcc5f60..5fbc02a77 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/PartnerTransactionsRequest.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/PartnerTransactionsRequest.java @@ -1,6 +1,8 @@ package com.github.binarywang.wxpay.bean.ecommerce; import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; @@ -11,13 +13,15 @@ /** * 普通支付(电商收付通)API *
- * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pages/e_transactions.shtml
+ * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pages/e_transactions.shtml
  * 
* * @author cloudX */ @Data +@Builder @NoArgsConstructor +@AllArgsConstructor public class PartnerTransactionsRequest implements Serializable { private static final long serialVersionUID = -1550405819444680465L; @@ -277,6 +281,7 @@ public static class Discount implements Serializable { @Data @NoArgsConstructor + @AllArgsConstructor public static class Amount implements Serializable { private static final long serialVersionUID = -4967636398225864273L; @@ -312,6 +317,7 @@ public static class Amount implements Serializable { @Data @NoArgsConstructor + @AllArgsConstructor public static class Payer implements Serializable { private static final long serialVersionUID = -3946401119476159971L; diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/PartnerTransactionsResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/PartnerTransactionsResult.java index a79dae78e..2c9086e7f 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/PartnerTransactionsResult.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/PartnerTransactionsResult.java @@ -12,10 +12,12 @@ *
  *   文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/e_transactions/chapter3_5.shtml
  * 
+ * @author cloudX */ @Data @NoArgsConstructor public class PartnerTransactionsResult implements Serializable { + private static final long serialVersionUID = 2371448241965534820L; /** *
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/ProfitSharingOrdersUnSplitAmountRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/ProfitSharingOrdersUnSplitAmountRequest.java
new file mode 100644
index 000000000..b2d8bc4c1
--- /dev/null
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/ProfitSharingOrdersUnSplitAmountRequest.java
@@ -0,0 +1,36 @@
+package com.github.binarywang.wxpay.bean.ecommerce;
+
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+
+/**
+ * 查询订单剩余待分金额API 请求对象
+ *
+ * @author mshyh
+ * @date 2022/05/26
+ */
+
+
+@Data
+@NoArgsConstructor
+public class ProfitSharingOrdersUnSplitAmountRequest {
+
+  /**
+   * 
+   * 字段名:微信订单号
+   * 变量名:transaction_id
+   * 是否必填:是
+   * 类型:string[1, 32]
+   * 描述:微信支付订单号
+   * 示例值:4208450740201411110007820472
+   * 
+ */ + @SerializedName(value = "transaction_id") + private String transactionId; + + + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/ProfitSharingOrdersUnSplitAmountResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/ProfitSharingOrdersUnSplitAmountResult.java new file mode 100644 index 000000000..0469965a4 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/ProfitSharingOrdersUnSplitAmountResult.java @@ -0,0 +1,47 @@ +package com.github.binarywang.wxpay.bean.ecommerce; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; + + + +/** + * 查询订单剩余待分金额API 结果响应 + * + * @author mshyh + * @date 2022/05/26 + */ + +@Data +@NoArgsConstructor +public class ProfitSharingOrdersUnSplitAmountResult { + + /** + *
+   * 字段名:微信支付订单号
+   * 变量名:transaction_id
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:微信支付订单号。
+   * 示例值:4208450740201411110007820472
+   * 
+ */ + @SerializedName(value = "transaction_id") + private String transactionId; + + /** + *
+   * 字段名:订单剩余待分金额
+   * 变量名:unsplit_amount
+   * 是否必填:是
+   * 类型:int
+   * 描述:订单剩余待分金额,整数,单位为分。
+   * 示例值:1000
+   * 
+ */ + @SerializedName(value = "unsplit_amount") + private Integer unsplitAmount; + + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/ProfitSharingResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/ProfitSharingResult.java index 09cc3e843..6cadd8d82 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/ProfitSharingResult.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/ProfitSharingResult.java @@ -16,8 +16,8 @@ @Data @NoArgsConstructor public class ProfitSharingResult implements Serializable { - private static final long serialVersionUID = 9026456165403642050L; + /** *
    * 字段名:二级商户号
@@ -278,5 +278,18 @@ public static class Receiver implements Serializable {
      */
     @SerializedName(value = "receiver_account")
     private String receiverAccount;
+
+    /**
+     * 
+     * 字段名:分账明细单号
+     * 变量名:detail_id
+     * 类型:string[1,64]
+     * 是否必填:是 (查询明细结果时是必有的)
+     * 描述:微信分账明细单号,每笔分账业务执行的明细单号,可与资金账单对账使用
+     * 示例值:3601111111111111111111
+     * 
+ */ + @SerializedName(value = "detail_id") + private String detailId; } } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/RefundsResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/RefundsResult.java index c83fdf4a5..b1139be56 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/RefundsResult.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/RefundsResult.java @@ -66,7 +66,7 @@ public class RefundsResult implements Serializable { *
*/ @SerializedName(value = "create_time") - private Date createTime; + private String createTime; /** *
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/ReturnOrdersResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/ReturnOrdersResult.java
index 5655139d0..c833b1733 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/ReturnOrdersResult.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/ReturnOrdersResult.java
@@ -163,6 +163,6 @@ public class ReturnOrdersResult implements Serializable {
    * 
*/ @SerializedName(value = "finish_time") - private Date finishTime; + private String finishTime; } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/SignatureHeader.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/SignatureHeader.java index bd50ac89d..7d894fcd8 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/SignatureHeader.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/SignatureHeader.java @@ -1,5 +1,7 @@ package com.github.binarywang.wxpay.bean.ecommerce; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; @@ -10,7 +12,9 @@ * 文档地址: https://wechatpay-api.gitbook.io/wechatpay-api-v3/qian-ming-zhi-nan-1/qian-ming-yan-zheng */ @Data +@Builder @NoArgsConstructor +@AllArgsConstructor public class SignatureHeader implements Serializable { private static final long serialVersionUID = -6958015499416059949L; /** diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entpay/EntPayRedpackRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entpay/EntPayRedpackRequest.java index 762499e69..7f78e66b2 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entpay/EntPayRedpackRequest.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entpay/EntPayRedpackRequest.java @@ -148,6 +148,11 @@ protected boolean isWxWorkSign() { return true; } + @Override + protected String[] getIgnoredParamsForSign() { + return new String[]{"sign_type"}; + } + @Override protected void storeMap(Map map) { map.put("mch_billno", mchBillNo); diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/PartnerTransferRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/PartnerTransferRequest.java index ce4738ae1..9a25f4ac8 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/PartnerTransferRequest.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/PartnerTransferRequest.java @@ -10,7 +10,7 @@ /** * 发起批量转账API *
- * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transfer_partner/chapter3_1.shtml
+ * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transfer_partner/chapter3_1.shtml
  * 
* * @author xiaoqiang diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/BatchesQueryResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/BatchesQueryResult.java new file mode 100644 index 000000000..d547471b8 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/BatchesQueryResult.java @@ -0,0 +1,384 @@ +package com.github.binarywang.wxpay.bean.merchanttransfer; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.List; + +/** + * The type Batches query result. + * + * @author glz + * @date 2022-6-11 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class BatchesQueryResult implements Serializable { + private static final long serialVersionUID = -4160610913430904527L; + /** + *
+   * 字段名:最大资源条数
+   * 变量名:limit
+   * 是否必填:否
+   * 类型:int
+   * 描述:
+   *  query该次请求可返回的最大资源(转账明细单)条数,最小20条,最大100条,不传则默认20条。不足20条按实际条数返回
+   * 示例值:20
+   * 
+ */ + @SerializedName("limit") + private Integer limit; + + /** + *
+   * 字段名:请求资源起始位置
+   * 变量名:transfer_batch
+   * 是否必填:否
+   * 类型:int
+   * 描述:
+   *  query该次请求资源(转账明细单)的起始位置,从0开始,转账明细单列表为空时不返回
+   * 示例值:1
+   * 
+ */ + @SerializedName("offset") + private Integer offset; + /** + *
+   * 字段名:转账批次单
+   * 变量名:transfer_batch
+   * 是否必填:是
+   * 类型:object
+   * 描述:
+   *  转账批次单基本信息
+   * 
+ */ + @SerializedName("transfer_batch") + private TransferBatch transferBatch; + + /** + *
+   * 字段名:转账明细单列表
+   * 变量名:transfer_detail_list
+   * 是否必填:否
+   * 类型:array
+   * 描述:
+   *  body发起批量转账的明细列表,最多三千笔
+   * 
+ */ + @SerializedName("transfer_detail_list") + private List transferDetailList; + + /** + * The type Transfer batch. + */ + @Data + @Accessors(chain = true) + public class TransferBatch implements Serializable { + /** + *
+     * 字段名:商户号
+     * 变量名:mchid
+     * 是否必填:是
+     * 类型:string[1,32]
+     * 描述:
+     *  微信支付分配的商户号
+     * 示例值:1900001109
+     * 
+ */ + @SerializedName("mchid") + private String mchid; + + /** + *
+     * 字段名:商家批次单号
+     * 变量名:out_batch_no
+     * 是否必填:是
+     * 类型:string[1,32]
+     * 描述:
+     *  商户系统内部的商家批次单号,在商户系统内部唯一
+     * 示例值:plfk2020042013
+     * 
+ */ + @SerializedName("out_batch_no") + private String outBatchNo; + + /** + *
+     * 字段名:微信批次单号
+     * 变量名:batch_id
+     * 是否必填:是
+     * 类型:string[1,32]
+     * 描述:
+     *  微信批次单号,微信商家转账系统返回的唯一标识
+     * 示例值:1030000071100999991182020050700019480001
+     * 
+ */ + @SerializedName("batch_id") + private String batchId; + + /** + *
+     * 字段名:直连商户的appid
+     * 变量名:appid
+     * 是否必填:是
+     * 类型:string[1,32]
+     * 描述:
+     *  申请商户号的appid或商户号绑定的appid(企业号corpid即为此appid)
+     * 示例值:wxf636efh567hg4356
+     * 
+ */ + @SerializedName("appid") + private String appid; + + /** + *
+     * 字段名:批次状态
+     * 变量名:batch_status
+     * 是否必填:是
+     * 类型:string[1,32]
+     * 描述:
+     *  枚举值:
+     * WAIT_PAY:待付款,商户员工确认付款阶段
+     * ACCEPTED:已受理。批次已受理成功,若发起批量转账的30分钟后,转账批次单仍处于该状态,可能原因是商户账户余额不足等。商户可查询账户资金流水,若该笔转账批次单的扣款已经发生,则表示批次已经进入转账中,请再次查单确认
+     * PROCESSING:转账中。已开始处理批次内的转账明细单
+     * FINISHED:已完成。批次内的所有转账明细单都已处理完成
+     * CLOSED:已关闭。可查询具体的批次关闭原因确认
+     * 示例值:ACCEPTED
+     * 
+ */ + @SerializedName("batch_status") + private String batchStatus; + + /** + *
+     * 字段名:批次类型
+     * 变量名:batch_type
+     * 是否必填:是
+     * 类型:string[1,32]
+     * 描述:
+     *  枚举值:
+     * API:API方式发起
+     * WEB:页面方式发起
+     * 示例值:API
+     * 
+ */ + @SerializedName("batch_type") + private String batchType; + + /** + *
+     * 字段名:批次名称
+     * 变量名:batch_name
+     * 是否必填:是
+     * 类型:string[1,32]
+     * 描述:
+     *  该笔批量转账的名称
+     * 示例值:2019年1月深圳分部报销单
+     * 
+ */ + @SerializedName("batch_name") + private String batchName; + + /** + *
+     * 字段名:批次备注
+     * 变量名:batch_remark
+     * 是否必填:是
+     * 类型:string[1,32]
+     * 描述:
+     *  转账说明,UTF8编码,最多允许32个字符
+     * 示例值:2019年1月深圳分部报销单
+     * 
+ */ + @SerializedName("batch_remark") + private String batchRemark; + + /** + *
+     * 字段名:批次关闭原因
+     * 变量名:close_reason
+     * 是否必填:否
+     * 类型:string[1,64]
+     * 描述:
+     *  如果批次单状态为“CLOSED”(已关闭),则有关闭原因
+     * MERCHANT_REVOCATION:商户主动撤销
+     * OVERDUE_CLOSE:系统超时关闭
+     * 示例值:OVERDUE_CLOSE
+     * 
+ */ + @SerializedName("close_reason") + private String closeReason; + + /** + *
+     * 字段名:转账总金额
+     * 变量名:total_amount
+     * 是否必填:是
+     * 类型:int
+     * 描述:
+     *  转账金额单位为分
+     * 示例值:4000000
+     * 
+ */ + @SerializedName("total_amount") + private Integer totalAmount; + + /** + *
+     * 字段名:转账总笔数
+     * 变量名:total_num
+     * 是否必填:是
+     * 类型:int
+     * 描述:
+     *  一个转账批次单最多发起三千笔转账
+     * 示例值:200
+     * 
+ */ + @SerializedName("total_num") + private Integer totalNum; + + /** + *
+     * 字段名:批次创建时间
+     * 变量名:create_time
+     * 是否必填:否
+     * 类型:string[1,32]
+     * 描述:
+     *  批次受理成功时返回,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss.sss+TIMEZONE,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss.sss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35.120+08:00表示北京时间2015年05月20日13点29分35秒
+     * 示例值:2015-05-20T13:29:35.120+08:00
+     * 
+ */ + @SerializedName("create_time") + private String createTime; + + /** + *
+     * 字段名:批次更新时间
+     * 变量名:update_time
+     * 是否必填:否
+     * 类型:string[1,32]
+     * 描述:
+     *  批次最近一次状态变更的时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss.sss+TIMEZONE,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss.sss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35.120+08:00表示北京时间2015年05月20日13点29分35秒
+     * 示例值:2015-05-20T13:29:35.120+08:00
+     * 
+ */ + @SerializedName("update_time") + private String updateTime; + + /** + *
+     * 字段名:转账成功金额
+     * 变量名:success_amount
+     * 是否必填:否
+     * 类型:int
+     * 描述:
+     *  转账成功的金额,单位为分。当批次状态为“PROCESSING”(转账中)时,转账成功金额随时可能变化
+     * 示例值:3900000
+     * 
+ */ + @SerializedName("success_amount") + private Integer successAmount; + + /** + *
+     * 字段名:转账成功笔数
+     * 变量名:success_num
+     * 是否必填:否
+     * 类型:int
+     * 描述:
+     *  转账成功的笔数。当批次状态为“PROCESSING”(转账中)时,转账成功笔数随时可能变化
+     * 示例值:199
+     * 
+ */ + @SerializedName("success_num") + private Integer successNum; + + /** + *
+     * 字段名:转账失败金额
+     * 变量名:fail_amount
+     * 是否必填:否
+     * 类型:int
+     * 描述:
+     *  转账失败的金额,单位为分
+     * 示例值:100000
+     * 
+ */ + @SerializedName("fail_amount") + private Integer failAmount; + + /** + *
+     * 字段名:转账失败笔数
+     * 变量名:fail_num
+     * 是否必填:否
+     * 类型:int
+     * 描述:
+     *  转账失败的笔数
+     * 示例值:1
+     * 
+ */ + @SerializedName("fail_num") + private Integer failNum; + } + + /** + * The type Transfer detail. + */ + @Data + @Accessors(chain = true) + public class TransferDetail implements Serializable { + /** + *
+     * 字段名:微信明细单号
+     * 变量名:detail_id
+     * 是否必填:是
+     * 类型:string[1,64]
+     * 描述:
+     *  微信支付系统内部区分转账批次单下不同转账明细单的唯一标识
+     * 示例值:1040000071100999991182020050700019500100
+     * 
+ */ + @SerializedName("detail_id") + private String detailId; + + /** + *
+     * 字段名:商家明细单号
+     * 变量名:out_detail_no
+     * 是否必填:是
+     * 类型:string[1,32]
+     * 描述:
+     *  商户系统内部区分转账批次单下不同转账明细单的唯一标识
+     * 示例值:x23zy545Bd5436
+     * 
+ */ + @SerializedName("out_detail_no") + private String outDetailNo; + + /** + *
+     * 字段名:明细状态
+     * 变量名:detail_status
+     * 是否必填:是
+     * 类型:string[1,32]
+     * 描述:
+     *  枚举值:
+     * PROCESSING:转账中。正在处理中,转账结果尚未明确
+     * SUCCESS:转账成功
+     * FAIL:转账失败。需要确认失败原因后,再决定是否重新发起对该笔明细单的转账(并非整个转账批次单)
+     * 示例值:SUCCESS
+     * 
+ */ + @SerializedName("detail_status") + private String detailStatus; + } +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/DetailElectronicBillRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/DetailElectronicBillRequest.java new file mode 100644 index 000000000..adfc8585f --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/DetailElectronicBillRequest.java @@ -0,0 +1,71 @@ +package com.github.binarywang.wxpay.bean.merchanttransfer; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * The type Detail electronic bill request. + * + * @author glz + * @date 2022-6-11 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class DetailElectronicBillRequest implements Serializable { + private static final long serialVersionUID = 716155129313310192L; + /** + *
+   * 字段名:受理类型
+   * 变量名:accept_type
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   * query电子回单受理类型:
+   * BATCH_TRANSFER:批量转账明细电子回单
+   * TRANSFER_TO_POCKET:企业付款至零钱电子回单
+   * TRANSFER_TO_BANK:企业付款至银行卡电子回单
+   * 示例值:BATCH_TRANSFER
+   * 
+ */ + @SerializedName("accept_type") + private String acceptType; + + /** + *
+   * 字段名:商家转账批次单号
+   * 变量名:out_batch_no
+   * 是否必填:否
+   * 类型:string[5,32]
+   * 描述:
+   * query需要电子回单的批量转账明细单所在的转账批次单号,该单号为商户申请转账时生成的商户单号。受理类型为BATCH_TRANSFER时该单号必填,否则该单号留空。
+   * 示例值:GD2021011610162610BBdkkIwcu3
+   * 
+ */ + @SerializedName("out_batch_no") + private String outBatchNo; + + /** + *
+   * 字段名:商家转账明细单号
+   * 变量名:out_detail_no
+   * 是否必填:是
+   * 类型:string[5,32]
+   * 描述:
+   * query该单号为商户申请转账时生成的商家转账明细单号。
+   * 1.受理类型为BATCH_TRANSFER时填写商家批量转账明细单号。
+   * 2. 受理类型为TRANSFER_TO_POCKET或TRANSFER_TO_BANK时填写商家转账单号。
+   * 示例值:mx0911231610162610v4CNkO4HAf
+   * 
+ */ + @SerializedName("out_detail_no") + private String outDetailNo; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/DetailElectronicBillResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/DetailElectronicBillResult.java new file mode 100644 index 000000000..3199a3ed0 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/DetailElectronicBillResult.java @@ -0,0 +1,143 @@ +package com.github.binarywang.wxpay.bean.merchanttransfer; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * 查询转账明细电子回单受理结果响应实体 + * + * @author glz + * @date 2022-6-11 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class DetailElectronicBillResult implements Serializable { + private static final long serialVersionUID = -6544648835213399159L; + /** + *
+   * 字段名:受理类型
+   * 变量名:accept_type
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  电子回单受理类型:
+   * BATCH_TRANSFER:批量转账明细电子回单
+   * TRANSFER_TO_POCKET:企业付款至零钱电子回单
+   * TRANSFER_TO_BANK:企业付款至银行卡电子回单
+   * 示例值:BATCH_TRANSFER
+   * 
+ */ + @SerializedName("accept_type") + private String acceptType; + + /** + *
+   * 字段名:商家转账批次单号
+   * 变量名:out_batch_no
+   * 是否必填:否
+   * 类型:string[5,32]
+   * 描述:
+   *  需要电子回单的批量转账明细单所在的转账批次单号,该单号为商户申请转账时生成的商户单号。受理类型为BATCH_TRANSFER时该单号必填,否则该单号留空。
+   * 示例值:GD2021011610162610BBdkkIwcu3
+   * 
+ */ + @SerializedName("out_batch_no") + private String outBatchNo; + + /** + *
+   * 字段名:商家转账明细单号
+   * 变量名:out_detail_no
+   * 是否必填:是
+   * 类型:string[5,32]
+   * 描述:
+   *  该单号为商户申请转账时生成的商家转账明细单号。
+   * 1.受理类型为BATCH_TRANSFER时填写商家批量转账明细单号。
+   * 2. 受理类型为TRANSFER_TO_POCKET或TRANSFER_TO_BANK时填写商家转账单号。
+   * 示例值:mx0911231610162610v4CNkO4HAf
+   * 
+ */ + @SerializedName("out_detail_no") + private String outDetailNo; + + /** + *
+   * 字段名:电子回单受理单号
+   * 变量名:signature_no
+   * 是否必填:是
+   * 类型:string[3,256]
+   * 描述:
+   *  电子回单受理单号,受理单据的唯一标识
+   * 示例值:1050000010509999485212020110200058820001
+   * 
+ */ + @SerializedName("signature_no") + private String signatureNo; + + /** + *
+   * 字段名:电子回单状态
+   * 变量名:signature_status
+   * 是否必填:否
+   * 类型:string[1,10]
+   * 描述:
+   *  枚举值:
+   * ACCEPTED:已受理,电子签章已受理成功
+   * FINISHED:已完成。电子签章已处理完成
+   * 示例值:ACCEPTED
+   * 
+ */ + @SerializedName("signature_status") + private String signatureStatus; + + /** + *
+   * 字段名:电子回单文件的hash方法
+   * 变量名:hash_type
+   * 是否必填:否
+   * 类型:string[1,20]
+   * 描述:
+   *  电子回单文件的hash方法,回单状态为:FINISHED时返回
+   * 示例值:SHA256
+   * 
+ */ + @SerializedName("hash_type") + private String hashType; + + /** + *
+   * 字段名:电子回单文件的hash值
+   * 变量名:hash_value
+   * 是否必填:否
+   * 类型:string[3,1000]
+   * 描述:
+   *  电子回单文件的hash值,用于下载之后验证文件的完整、正确性,回单状态为:FINISHED时返回
+   * 示例值:DE731F35146A0BEFADE5DB9D1E468D96C01CA8898119C674FEE9F11F4DBE5529
+   * 
+ */ + @SerializedName("hash_value") + private String hashValue; + + /** + *
+   * 字段名:电子回单文件的下载地址
+   * 变量名:download_url
+   * 是否必填:否
+   * 类型:string[10,3000]
+   * 描述:
+   *  电子回单文件的下载地址,回单状态为:FINISHED时返回。URL有效时长为10分钟,10分钟后需要重新去获取下载地址(但不需要走受理)
+   * 示例值:https://api.mch.weixin.qq.com/v3/billdownload/file?token=xxx
+   * 
+ */ + @SerializedName("download_url") + private String downloadUrl; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/DetailsQueryResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/DetailsQueryResult.java new file mode 100644 index 000000000..b7bca954c --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/DetailsQueryResult.java @@ -0,0 +1,242 @@ +package com.github.binarywang.wxpay.bean.merchanttransfer; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * 微信明细单号查询明细单 响应实体、 + * + * @author glz + * @date 2022-6-11 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class DetailsQueryResult implements Serializable { + private static final long serialVersionUID = -6900642921137234815L; + /** + *
+   * 字段名:商户号
+   * 变量名:mchid
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  微信支付分配的商户号
+   * 示例值:1900001109
+   * 
+ */ + @SerializedName("mchid") + private String mchid; + + /** + *
+   * 字段名:商家批次单号
+   * 变量名:out_batch_no
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  商户系统内部的商家批次单号,在商户系统内部唯一
+   * 示例值:plfk2020042013
+   * 
+ */ + @SerializedName("out_batch_no") + private String outBatchNo; + + /** + *
+   * 字段名:微信批次单号
+   * 变量名:batch_id
+   * 是否必填:是
+   * 类型:string[1,64]
+   * 描述:
+   *  微信批次单号,微信商家转账系统返回的唯一标识
+   * 示例值:1030000071100999991182020050700019480001
+   * 
+ */ + @SerializedName("batch_id") + private String batchId; + + /** + *
+   * 字段名:直连商户的appid
+   * 变量名:appid
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  申请商户号的appid或商户号绑定的appid(企业号corpid即为此appid)
+   * 示例值:wxf636efh567hg4356
+   * 
+ */ + @SerializedName("appid") + private String appid; + + /** + *
+   * 字段名:商家明细单号
+   * 变量名:out_detail_no
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  商户系统内部区分转账批次单下不同转账明细单的唯一标识
+   * 示例值:x23zy545Bd5436
+   * 
+ */ + @SerializedName("out_detail_no") + private String outDetailNo; + + /** + *
+   * 字段名:微信明细单号
+   * 变量名:detail_id
+   * 是否必填:是
+   * 类型:string[1,64]
+   * 描述:
+   *  微信支付系统内部区分转账批次单下不同转账明细单的唯一标识
+   * 示例值:1040000071100999991182020050700019500100
+   * 
+ */ + @SerializedName("detail_id") + private String detailId; + + /** + *
+   * 字段名:明细状态
+   * 变量名:detail_status
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  枚举值:
+   * PROCESSING:转账中。正在处理中,转账结果尚未明确
+   * SUCCESS:转账成功
+   * FAIL:转账失败。需要确认失败原因后,再决定是否重新发起对该笔明细单的转账(并非整个转账批次单)
+   * 示例值:SUCCESS
+   * 
+ */ + @SerializedName("detail_status") + private String detailStatus; + + /** + *
+   * 字段名:转账金额
+   * 变量名:transfer_amount
+   * 是否必填:是
+   * 类型:int
+   * 描述:
+   *  转账金额单位为分
+   * 示例值:200000
+   * 
+ */ + @SerializedName("transfer_amount") + private Integer transferAmount; + + /** + *
+   * 字段名:转账备注
+   * 变量名:transfer_remark
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  单条转账备注(微信用户会收到该备注),UTF8编码,最多允许32个字符
+   * 示例值:2020年4月报销
+   * 
+ */ + @SerializedName("transfer_remark") + private String transferRemark; + + /** + *
+   * 字段名:明细失败原因
+   * 变量名:fail_reason
+   * 是否必填:否
+   * 类型:string[1,64]
+   * 描述:
+   *  如果转账失败则有失败原因
+   * ACCOUNT_FROZEN:账户冻结
+   * REAL_NAME_CHECK_FAIL:用户未实名
+   * NAME_NOT_CORRECT:用户姓名校验失败
+   * OPENID_INVALID:Openid校验失败
+   * TRANSFER_QUOTA_EXCEED:超过用户单笔收款额度
+   * DAY_RECEIVED_QUOTA_EXCEED:超过用户单日收款额度
+   * MONTH_RECEIVED_QUOTA_EXCEED:超过用户单月收款额度
+   * DAY_RECEIVED_COUNT_EXCEED:超过用户单日收款次数
+   * PRODUCT_AUTH_CHECK_FAIL:产品权限校验失败
+   * OVERDUE_CLOSE:转账关闭
+   * ID_CARD_NOT_CORRECT:用户身份证校验失败
+   * ACCOUNT_NOT_EXIST:用户账户不存在
+   * TRANSFER_RISK:转账存在风险
+   * REALNAME_ACCOUNT_RECEIVED_QUOTA_EXCEED:用户账户收款受限,请引导用户在微信支付查看详情
+   * RECEIVE_ACCOUNT_NOT_PERMMIT:未配置该用户为转账收款人
+   * PAYER_ACCOUNT_ABNORMAL:商户账户付款受限,可前往商户平台-违约记录获取解除功能限制指引
+   * PAYEE_ACCOUNT_ABNORMAL:用户账户收款异常,请引导用户完善其在微信支付的身份信息以继续收款
+   * 示例值:ACCOUNT_FROZEN
+   * 
+ */ + @SerializedName("fail_reason") + private String failReason; + + /** + *
+   * 字段名:用户在直连商户应用下的用户标示
+   * 变量名:openid
+   * 是否必填:是
+   * 类型:string[1,128]
+   * 描述:
+   *  用户在直连商户appid下的唯一标识
+   * 示例值:o-MYE42l80oelYMDE34nYD456Xoy
+   * 
+ */ + @SerializedName("openid") + private String openid; + + /** + *
+   * 字段名:收款用户姓名
+   * 变量名:user_name
+   * 是否必填:否
+   * 类型:string[1,1024]
+   * 描述:
+   *  1、商户转账时传入了收款用户姓名、查询时会返回收款用户姓名;
+   * 2、收款方姓名采用标准RSA算法,公钥由微信侧提供
+   * 3、 该字段需进行加密处理,加密方法详见敏感信息加密说明。(提醒:必须在HTTP头中上送Wechatpay-Serial)
+   * 示例值:757b340b45ebef5467rter35gf464344v3542sdf4t6re4tb4f54ty45t4yyry45
+   * 
+ */ + @SerializedName("user_name") + private String userName; + + /** + *
+   * 字段名:转账发起时间
+   * 变量名:initiate_time
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  转账发起的时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss.sss+TIMEZONE,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss.sss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35.120+08:00表示北京时间2015年05月20日13点29分35秒
+   * 示例值:2015-05-20T13:29:35.120+08:00
+   * 
+ */ + @SerializedName("initiate_time") + private String initiateTime; + + /** + *
+   * 字段名:明细更新时间
+   * 变量名:update_time
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  明细最后一次状态变更的时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss.sss+TIMEZONE,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss.sss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35.120+08:00表示北京时间2015年05月20日13点29分35秒
+   * 示例值:2015-05-20T13:29:35.120+08:00
+   * 
+ */ + @SerializedName("update_time") + private String updateTime; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/ElectronicBillApplyRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/ElectronicBillApplyRequest.java new file mode 100644 index 000000000..66ca59e4b --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/ElectronicBillApplyRequest.java @@ -0,0 +1,38 @@ +package com.github.binarywang.wxpay.bean.merchanttransfer; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * The type Electronic bill apply request. + * + * @author glz + * @date 2022-6-11 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class ElectronicBillApplyRequest implements Serializable { + private static final long serialVersionUID = -2121536206019844928L; + /** + *
+   * 字段名:商家批次单号
+   * 变量名:out_batch_no
+   * 是否必填:是
+   * 类型:string[5,32]
+   * 描述:
+   *  body商户系统内部的商家批次单号,在商户系统内部唯一。需要电子回单的批次单号
+   * 示例值:plfk2020042013
+   * 
+ */ + @SerializedName("out_batch_no") + private String outBatchNo; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/ElectronicBillResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/ElectronicBillResult.java new file mode 100644 index 000000000..699f66c3c --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/ElectronicBillResult.java @@ -0,0 +1,138 @@ +package com.github.binarywang.wxpay.bean.merchanttransfer; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * The type Electronic bill result. + * + * @author glz + * @date 2022-6-11 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class ElectronicBillResult implements Serializable { + private static final long serialVersionUID = 7528245102572829190L; + /** + *
+   * 字段名:商家批次单号
+   * 变量名:out_batch_no
+   * 是否必填:是
+   * 类型:string[5,32]
+   * 描述:
+   *  body商户系统内部的商家批次单号,在商户系统内部唯一。需要电子回单的批次单号
+   * 示例值:plfk2020042013
+   * 
+ */ + @SerializedName("out_batch_no") + private String outBatchNo; + + /** + *
+   * 字段名:电子回单申请单号
+   * 变量名:signature_no
+   * 是否必填:是
+   * 类型:string[3,45]
+   * 描述:
+   *  电子回单申请单号,申请单据的唯一标识
+   * 示例值:1050000010509999485212020110200058820001
+   * 
+ */ + @SerializedName("signature_no") + private String signatureNo; + + /** + *
+   * 字段名:电子回单状态
+   * 变量名:signature_status
+   * 是否必填:否
+   * 类型:string[1,10]
+   * 描述:
+   *  枚举值:
+   * ACCEPTED:已受理,电子签章已受理成功
+   * FINISHED:已完成。电子签章已处理完成
+   * 示例值:ACCEPTED
+   * 
+ */ + @SerializedName("signature_status") + private String signatureStatus; + + /** + *
+   * 字段名:电子回单文件的hash方法
+   * 变量名:hash_type
+   * 是否必填:否
+   * 类型:string[1,20]
+   * 描述:
+   *  电子回单文件的hash方法,回单状态为:FINISHED时返回。
+   * 示例值:SHA256
+   * 
+ */ + @SerializedName("hash_type") + private String hashType; + + /** + *
+   * 字段名:电子回单文件的hash值
+   * 变量名:hash_value
+   * 是否必填:否
+   * 类型:string[3,1000]
+   * 描述:
+   *  电子回单文件的hash值,用于下载之后验证文件的完整、正确性,回单状态为:FINISHED时返回。
+   * 示例值:DE731F35146A0BEFADE5DB9D1E468D96C01CA8898119C674FEE9F11F4DBE5529
+   * 
+ */ + @SerializedName("hash_value") + private String hashValue; + + /** + *
+   * 字段名:电子回单文件的下载地址
+   * 变量名:download_url
+   * 是否必填:否
+   * 类型:string[10,3000]
+   * 描述:
+   *  电子回单文件的下载地址,回单状态为:FINISHED时返回。URL有效时长为10分钟,10分钟后需要重新去获取下载地址(但不需要走受理)
+   * 示例值:https://api.mch.weixin.qq.com/v3/billdownload/file?token=xxx
+   * 
+ */ + @SerializedName("download_url") + private String downloadUrl; + + /** + *
+   * 字段名:创建时间
+   * 变量名:create_time
+   * 是否必填:否
+   * 类型:string[1,32]
+   * 描述:
+   *  电子签章单创建时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss.sss+TIMEZONE,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss.sss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35.120+08:00表示北京时间2015年05月20日13点29分35秒
+   * 示例值:2020-05-20T13:29:35.120+08:00
+   * 
+ */ + @SerializedName("create_time") + private String createTime; + + /** + *
+   * 字段名:更新时间
+   * 变量名:update_time
+   * 是否必填:否
+   * 类型:string[1,32]
+   * 描述:
+   *  电子签章单最近一次状态变更的时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss.sss+TIMEZONE,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss.sss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35.120+08:00表示北京时间2015年05月20日13点29分35秒
+   * 示例值:2020-05-21T13:29:35.120+08:00
+   * 
+ */ + @SerializedName("update_time") + private String updateTime; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/MerchantBatchesQueryRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/MerchantBatchesQueryRequest.java new file mode 100644 index 000000000..a123db230 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/MerchantBatchesQueryRequest.java @@ -0,0 +1,99 @@ +package com.github.binarywang.wxpay.bean.merchanttransfer; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * The type Merchant batches query request. + * + * @author glz + * @date 2022-6-11 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class MerchantBatchesQueryRequest implements Serializable { + private static final long serialVersionUID = 7074459219428697275L; + /** + *
+   * 字段名:商家批次单号
+   * 变量名:out_batch_no
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  path商户系统内部的商家批次单号,要求此参数只能由数字、大小写字母组成,在商户系统内部唯一
+   * 示例值:plfk2020042013
+   * 
+ */ + @SerializedName("out_batch_no") + private String outBatchNo; + + /** + *
+   * 字段名:是否查询转账明细单
+   * 变量名:need_query_detail
+   * 是否必填:是
+   * 类型:boolean
+   * 描述:
+   *  query枚举值:
+   * true:是;
+   * false:否,默认否。
+   * 商户可选择是否查询指定状态的转账明细单,当转账批次单状态为“FINISHED”(已完成)时,才会返回满足条件的转账明细单
+   * 示例值:true
+   * 
+ */ + @SerializedName("need_query_detail") + private Boolean needQueryDetail; + + /** + *
+   * 字段名:请求资源起始位置
+   * 变量名:offset
+   * 是否必填:否
+   * 类型:int
+   * 描述:
+   *  query该次请求资源的起始位置,从0开始,默认值为0
+   * 
+ */ + @SerializedName("offset") + private Integer offset; + + /** + *
+   * 字段名:最大资源条数
+   * 变量名:limit
+   * 是否必填:否
+   * 类型:int
+   * 描述:
+   *  query该次请求可返回的最大明细条数,最小20条,最大100条,不传则默认20条。不足20条按实际条数返回
+   * 示例值:20
+   * 
+ */ + @SerializedName("limit") + private Integer limit; + + /** + *
+   * 字段名:明细状态
+   * 变量名:detail_status
+   * 是否必填:否
+   * 类型:string[1,32]
+   * 描述:
+   *  query查询指定状态的转账明细单,当need_query_detail为true时,该字段必填
+   * ALL:全部。需要同时查询转账成功和转账失败的明细单
+   * SUCCESS:转账成功。只查询转账成功的明细单
+   * FAIL:转账失败。只查询转账失败的明细单
+   * 示例值:FAIL
+   * 
+ */ + @SerializedName("detail_status") + private String detailStatus; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/MerchantDetailsQueryRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/MerchantDetailsQueryRequest.java new file mode 100644 index 000000000..d9ae599c3 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/MerchantDetailsQueryRequest.java @@ -0,0 +1,52 @@ +package com.github.binarywang.wxpay.bean.merchanttransfer; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * The type Merchant details query request. + * + * @author glz + * @date 2022-6-11 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class MerchantDetailsQueryRequest implements Serializable { + private static final long serialVersionUID = 3167548999175561804L; + /** + *
+   * 字段名:商家明细单号
+   * 变量名:out_detail_no
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   * path商户系统内部区分转账批次单下不同转账明细单的唯一标识,要求此参数只能由数字、大小写字母组成
+   * 示例值:x23zy545Bd5436
+   * 
+ */ + @SerializedName("out_detail_no") + private String outDetailNo; + + /** + *
+   * 字段名:商家批次单号
+   * 变量名:out_batch_no
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  path商户系统内部的商家批次单号,要求此参数只能由数字、大小写字母组成,在商户系统内部唯一
+   * 示例值:plfk2020042013
+   * 
+ */ + @SerializedName("out_batch_no") + private String outBatchNo; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/TransferCreateRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/TransferCreateRequest.java new file mode 100644 index 000000000..946f0d67d --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/TransferCreateRequest.java @@ -0,0 +1,208 @@ +package com.github.binarywang.wxpay.bean.merchanttransfer; + +import com.github.binarywang.wxpay.v3.SpecEncrypt; +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.List; + +/** + * The type Transfer create request. + * + * @author glz + * @date 2022-5-26 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class TransferCreateRequest implements Serializable { + private static final long serialVersionUID = -6865437704112740902L; + /** + *
+   * 字段名:直连商户的appid
+   * 变量名:appid
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  申请商户号的appid或商户号绑定的appid(企业号corpid即为此appid)
+   * 示例值:wxf636efh567hg4356
+   * 
+ */ + @SerializedName("appid") + private String appid; + + /** + *
+   * 字段名:商家批次单号
+   * 变量名:out_batch_no
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  path商户系统内部的商家批次单号,要求此参数只能由数字、大小写字母组成,在商户系统内部唯一
+   * 示例值:plfk2020042013
+   * 
+ */ + @SerializedName("out_batch_no") + private String outBatchNo; + + /** + *
+   * 字段名:批次名称
+   * 变量名:batch_name
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  该笔批量转账的名称
+   * 示例值:2019年1月深圳分部报销单
+   * 
+ */ + @SerializedName("batch_name") + private String batchName; + + /** + *
+   * 字段名:批次备注
+   * 变量名:batch_remark
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  转账说明,UTF8编码,最多允许32个字符
+   * 示例值:2019年1月深圳分部报销单
+   * 
+ */ + @SerializedName("batch_remark") + private String batchRemark; + + /** + *
+   * 字段名:转账总金额
+   * 变量名:total_amount
+   * 是否必填:是
+   * 类型:int
+   * 描述:
+   *  转账金额单位为分
+   * 示例值:4000000
+   * 
+ */ + @SerializedName("total_amount") + private Integer totalAmount; + + /** + *
+   * 字段名:转账总笔数
+   * 变量名:total_num
+   * 是否必填:是
+   * 类型:int
+   * 描述:
+   *  一个转账批次单最多发起三千笔转账
+   * 示例值:200
+   * 
+ */ + @SerializedName("total_num") + private Integer totalNum; + + /** + *
+   * 字段名:转账明细单列表
+   * 变量名:transfer_detail_list
+   * 是否必填:否
+   * 类型:array
+   * 描述:
+   *  body发起批量转账的明细列表,最多三千笔
+   * 
+ */ + @SerializedName("transfer_detail_list") + @SpecEncrypt + private List transferDetailList; + + + /** + * The type Transfer detail list. + */ + @Data + @Accessors(chain = true) + public static class TransferDetailList implements Serializable { + + /** + *
+     * 字段名:商家明细单号
+     * 变量名:out_detail_no
+     * 是否必填:是
+     * 类型:string[1,32]
+     * 描述:
+     *  商户系统内部区分转账批次单下不同转账明细单的唯一标识
+     * 示例值:x23zy545Bd5436
+     * 
+ */ + @SerializedName("out_detail_no") + private String outDetailNo; + + /** + *
+     * 字段名:转账金额
+     * 变量名:transfer_amount
+     * 是否必填:是
+     * 类型:int
+     * 描述:
+     *  转账金额单位为分
+     * 示例值:200000
+     * 
+ */ + @SerializedName("transfer_amount") + private Integer transferAmount; + + /** + *
+     * 字段名:转账备注
+     * 变量名:transfer_remark
+     * 是否必填:是
+     * 类型:string[1,32]
+     * 描述:
+     *  单条转账备注(微信用户会收到该备注),UTF8编码,最多允许32个字符
+     * 示例值:2020年4月报销
+     * 
+ */ + @SerializedName("transfer_remark") + private String transferRemark; + + /** + *
+     * 字段名:用户在直连商户应用下的用户标示
+     * 变量名:openid
+     * 是否必填:是
+     * 类型:string[1,128]
+     * 描述:
+     *  用户在直连商户appid下的唯一标识
+     * 示例值:o-MYE42l80oelYMDE34nYD456Xoy
+     * 
+ */ + @SerializedName("openid") + private String openid; + + /** + *
+     * 字段名:收款用户姓名
+     * 变量名:user_name
+     * 是否必填:否
+     * 类型:string[1,1024]
+     * 描述:
+     *  1、商户转账时传入了收款用户姓名、查询时会返回收款用户姓名;
+     * 2、收款方姓名采用标准RSA算法,公钥由微信侧提供
+     * 3、 该字段需进行加密处理,加密方法详见敏感信息加密说明。(提醒:必须在HTTP头中上送Wechatpay-Serial)
+     * 示例值:757b340b45ebef5467rter35gf464344v3542sdf4t6re4tb4f54ty45t4yyry45
+     * 
+ */ + @SerializedName("user_name") + @SpecEncrypt + private String userName; + } +} + + diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/TransferCreateResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/TransferCreateResult.java new file mode 100644 index 000000000..e5b057a79 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/TransferCreateResult.java @@ -0,0 +1,66 @@ +package com.github.binarywang.wxpay.bean.merchanttransfer; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * The type Transfer create result. + * + * @author glz + * @date 2022-6-11 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class TransferCreateResult implements Serializable { + private static final long serialVersionUID = 586974090302358983L; + /** + *
+   * 字段名:商家批次单号
+   * 变量名:out_batch_no
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  商户系统内部的商家批次单号,在商户系统内部唯一
+   * 示例值:plfk2020042013
+   * 
+ */ + @SerializedName("out_batch_no") + private String outBatchNo; + + /** + *
+   * 字段名:微信批次单号
+   * 变量名:batch_id
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  微信批次单号,微信商家转账系统返回的唯一标识
+   * 示例值:1030000071100999991182020050700019480001
+   * 
+ */ + @SerializedName("batch_id") + private String batchId; + + /** + *
+   * 字段名:批次创建时间
+   * 变量名:create_time
+   * 是否必填:否
+   * 类型:string[1,32]
+   * 描述:
+   *  批次受理成功时返回,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss.sss+TIMEZONE,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss.sss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35.120+08:00表示北京时间2015年05月20日13点29分35秒
+   * 示例值:2015-05-20T13:29:35.120+08:00
+   * 
+ */ + @SerializedName("create_time") + private String createTime; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/WxBatchesQueryRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/WxBatchesQueryRequest.java new file mode 100644 index 000000000..1cf4697f4 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/WxBatchesQueryRequest.java @@ -0,0 +1,99 @@ +package com.github.binarywang.wxpay.bean.merchanttransfer; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * The type Wx batches query request. + * + * @author glz + * @date 2022-6-11 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class WxBatchesQueryRequest implements Serializable { + private static final long serialVersionUID = 1030840820271586649L; + /** + *
+   * 字段名:微信批次单号
+   * 变量名:batch_id
+   * 是否必填:是
+   * 类型:string[1,64]
+   * 描述:
+   *  path微信批次单号,微信商家转账系统返回的唯一标识
+   * 示例值:1030000071100999991182020050700019480001
+   * 
+ */ + @SerializedName("batch_id") + private String batchId; + + /** + *
+   * 字段名:是否查询转账明细单
+   * 变量名:need_query_detail
+   * 是否必填:是
+   * 类型:boolean
+   * 描述:
+   *  query枚举值:
+   * true:是;
+   * false:否,默认否。
+   * 商户可选择是否查询指定状态的转账明细单,当转账批次单状态为“FINISHED”(已完成)时,才会返回满足条件的转账明细单
+   * 示例值:true
+   * 
+ */ + @SerializedName("need_query_detail") + private Boolean needQueryDetail; + + /** + *
+   * 字段名:请求资源起始位置
+   * 变量名:offset
+   * 是否必填:否
+   * 类型:int
+   * 描述:
+   *  query该次请求资源的起始位置,从0开始,默认值为0
+   * 
+ */ + @SerializedName("offset") + private Integer offset; + + /** + *
+   * 字段名:最大资源条数
+   * 变量名:limit
+   * 是否必填:否
+   * 类型:int
+   * 描述:
+   *  query该次请求可返回的最大明细条数,最小20条,最大100条,不传则默认20条。不足20条按实际条数返回
+   * 示例值:20
+   * 
+ */ + @SerializedName("limit") + private Integer limit; + + /** + *
+   * 字段名:明细状态
+   * 变量名:detail_status
+   * 是否必填:否
+   * 类型:string[1,32]
+   * 描述:
+   *  query查询指定状态的转账明细单,当need_query_detail为true时,该字段必填
+   * ALL:全部。需要同时查询转账成功和转账失败的明细单
+   * SUCCESS:转账成功。只查询转账成功的明细单
+   * FAIL:转账失败。只查询转账失败的明细单
+   * 示例值:FAIL
+   * 
+ */ + @SerializedName("detail_status") + private String detailStatus; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/WxDetailsQueryRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/WxDetailsQueryRequest.java new file mode 100644 index 000000000..6216bed53 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/WxDetailsQueryRequest.java @@ -0,0 +1,53 @@ +package com.github.binarywang.wxpay.bean.merchanttransfer; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * The type Wx details query request. + * + * @author glz + * @date 2022-6-11 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class WxDetailsQueryRequest implements Serializable { + private static final long serialVersionUID = 4869511970509348272L; + + /** + *
+   * 字段名:微信批次单号
+   * 变量名:batch_id
+   * 是否必填:是
+   * 类型:string[1,64]
+   * 描述:
+   *  path微信批次单号,微信商家转账系统返回的唯一标识
+   * 示例值:1030000071100999991182020050700019480001
+   * 
+ */ + @SerializedName("batch_id") + private String batchId; + + /** + *
+   * 字段名:微信明细单号
+   * 变量名:detail_id
+   * 是否必填:是
+   * 类型:string[1,64]
+   * 描述:
+   *  path微信支付系统内部区分转账批次单下不同转账明细单的唯一标识
+   * 示例值:1040000071100999991182020050700019500100
+   * 
+ */ + @SerializedName("detail_id") + private String detailId; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/SignatureHeader.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/SignatureHeader.java index d010637a8..daa6d6e72 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/SignatureHeader.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/SignatureHeader.java @@ -1,5 +1,7 @@ package com.github.binarywang.wxpay.bean.notify; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; @@ -10,7 +12,9 @@ * 文档地址: https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_1.shtml */ @Data +@Builder @NoArgsConstructor +@AllArgsConstructor public class SignatureHeader implements Serializable { private static final long serialVersionUID = -1L; /** diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxPayNotifyV3Response.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxPayNotifyV3Response.java new file mode 100644 index 000000000..c947a9ddc --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxPayNotifyV3Response.java @@ -0,0 +1,50 @@ +package com.github.binarywang.wxpay.bean.notify; + +import com.google.gson.Gson; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 微信支付订单和退款的异步通知,V3版本共用的响应类. + * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_11.shtml + * + * @author Wang_Wong + * @date 2022-08-15 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class WxPayNotifyV3Response { + + private static final transient String SUCCESS = "SUCCESS"; + private static final transient String FAIL = "FAIL"; + + private String code; + private String message; + + /** + * 返回成功 + * + * @param msg + * @return + */ + public static String success(String msg) { + WxPayNotifyV3Response response = new WxPayNotifyV3Response(SUCCESS, msg); + return new Gson().toJson(response); + } + + /** + * 返回失败 + * + * @param msg 返回信息,如非空,为错误原因 + * @return + */ + public static String fail(String msg) { + WxPayNotifyV3Response response = new WxPayNotifyV3Response(FAIL, msg); + return new Gson().toJson(response); + } + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxPayRefundNotifyV3Result.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxPayRefundNotifyV3Result.java index 961dbaa11..976e7e269 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxPayRefundNotifyV3Result.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxPayRefundNotifyV3Result.java @@ -184,7 +184,7 @@ public static class Amount implements Serializable { *
*/ @SerializedName(value = "refund") - private String refund; + private Integer refund; /** *
      * 字段名:用户支付金额
@@ -210,6 +210,6 @@ public static class Amount implements Serializable {
      * 
*/ @SerializedName(value = "payer_refund") - private String payerRefund; + private Integer payerRefund; } } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/payscore/WxPartnerPayScoreRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/payscore/WxPartnerPayScoreRequest.java new file mode 100644 index 000000000..8948d3d4c --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/payscore/WxPartnerPayScoreRequest.java @@ -0,0 +1,39 @@ +package com.github.binarywang.wxpay.bean.payscore; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; +import lombok.experimental.SuperBuilder; +import me.chanjar.weixin.common.util.json.WxGsonBuilder; + +/** + * @author hallkk + * @date 2022/05/18 + */ +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class WxPartnerPayScoreRequest extends WxPayScoreRequest { + private static final long serialVersionUID = 6269843192878112955L; + + public String toJson() { + return WxGsonBuilder.create().toJson(this); + } + + @SerializedName("sub_appid") + private String subAppid; + + @SerializedName("sub_mchid") + private String subMchid; + + @SerializedName("out_apply_no") + private String outApplyNo; + + @SerializedName("result_notify_url") + private String resultNotifyUrl; + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/payscore/WxPartnerPayScoreResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/payscore/WxPartnerPayScoreResult.java new file mode 100644 index 000000000..d8a350efe --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/payscore/WxPartnerPayScoreResult.java @@ -0,0 +1,42 @@ +package com.github.binarywang.wxpay.bean.payscore; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; +import me.chanjar.weixin.common.util.json.WxGsonBuilder; + +/** + * @author hallkk + * @date 2022/05/18 + */ +@Data +@NoArgsConstructor +public class WxPartnerPayScoreResult extends WxPayScoreResult { + private static final long serialVersionUID = 718267574622164410L; + + public static WxPartnerPayScoreResult fromJson(String json) { + return WxGsonBuilder.create().fromJson(json, WxPartnerPayScoreResult.class); + } + + @SerializedName("sub_appid") + private String subAppid; + + @SerializedName("sub_mchid") + private String subMchid; + + @SerializedName("sub_openid") + private String subOpenId; + + @SerializedName("out_apply_no") + private String outApplyNo; + + @SerializedName("result_notify_url") + private String resultNotifyUrl; + + @SerializedName("apply_state") + private String applyState; + + @SerializedName("reject_reason") + private String rejectReason; + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/payscore/WxPayScoreRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/payscore/WxPayScoreRequest.java index 0f4b92a7b..295b7000e 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/payscore/WxPayScoreRequest.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/payscore/WxPayScoreRequest.java @@ -10,6 +10,7 @@ import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; +import lombok.experimental.SuperBuilder; import me.chanjar.weixin.common.util.json.WxGsonBuilder; /** @@ -17,7 +18,7 @@ * @date 2020/5/12 16:36 */ @Data -@Builder +@SuperBuilder @NoArgsConstructor @AllArgsConstructor @Accessors(chain = true) @@ -82,6 +83,6 @@ public String toJson() { @SerializedName("detail") private Detail detail; @SerializedName("authorization_code") - private String authorizationCode; + private String authorizationCode; } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/payscore/WxPayScoreResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/payscore/WxPayScoreResult.java index 266440d21..713e5d314 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/payscore/WxPayScoreResult.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/payscore/WxPayScoreResult.java @@ -85,21 +85,23 @@ public static WxPayScoreResult fromJson(String json) { @SerializedName("payScoreSignInfo") private Map payScoreSignInfo; + @SerializedName("openid") + private String openid; + @SerializedName("apply_permissions_token") - private String applyPermissionsToken; + private String applyPermissionsToken; @SerializedName("authorization_code") - private String authorizationCode; + private String authorizationCode; @SerializedName("authorization_state") - private String authorizationState; + private String authorizationState; @SerializedName("cancel_authorization_time") - private String cancelAuthorizationTime; + private String cancelAuthorizationTime; @SerializedName("authorization_success_time") - private String authorizationSuccessTime; - + private String authorizationSuccessTime; /** * 收款信息 diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingNotifyData.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingNotifyData.java new file mode 100644 index 000000000..6d47183f2 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingNotifyData.java @@ -0,0 +1,142 @@ +package com.github.binarywang.wxpay.bean.profitsharingV3; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * + * 微信V3接口 + * 通用通知实体 + * + * @author yuanbo + * @create 2022-04-26-21:33 PM + */ +@Data +@NoArgsConstructor +public class ProfitSharingNotifyData implements Serializable{ + + + private static final long serialVersionUID = 4242383310854692441L; + + /** + *
+   * 字段名:通知ID
+   * 是否必填:是
+   * 描述:通知的唯一ID
+   * 
+ */ + @SerializedName("id") + private String id; + + /** + *
+   * 字段名:通知创建时间
+   * 是否必填:是
+   * 描述:通知创建的时间,Rfc3339标准
+   * 
+ */ + @SerializedName("create_time") + private String createTime; + + /** + *
+   * 字段名:通知数据类型
+   * 是否必填:是
+   * 描述:通知的资源数据类型
+   * 
+ */ + @SerializedName("resource_type") + private String resourceType; + + /** + *
+   * 字段名:通知类型
+   * 是否必填:是
+   * 描述:通知的类型
+   * 
+ */ + @SerializedName("event_type") + private String eventType; + + /** + *
+   * 字段名:通知数据
+   * 是否必填:是
+   * 描述:通知资源数据
+   * 
+ */ + @SerializedName("resource") + private Resource resource; + + /** + *
+   * 字段名:通知简要说明
+   * 是否必填:是
+   * 描述:通知简要说明
+   * 
+ */ + @SerializedName("summary") + private String summary; + + @Data + @NoArgsConstructor + public static class Resource implements Serializable { + + private static final long serialVersionUID = 8530711804335261449L; + + + /** + *
+     * 字段名:加密算法类型
+     * 是否必填:是
+     * 描述:对分账结果数据进行加密的加密算法,目前只支持AEAD_AES_256_GCM
+     * 
+ */ + @SerializedName("algorithm") + private String algorithm; + + + /** + *
+     * 字段名:加密前的对象类型
+     * 是否必填:是
+     * 描述:加密前的对象类型,分账动账通知的类型为profitsharing
+     * 
+ */ + @SerializedName("original_type") + private String originalType; + + /** + *
+     * 字段名:数据密文
+     * 是否必填:是
+     * 描述:Base64编码后的分账结果数据密文
+     * 
+ */ + @SerializedName("ciphertext") + private String cipherText; + + /** + *
+     * 字段名:随机串
+     * 是否必填:是
+     * 描述:加密使用的随机串
+     * 
+ */ + @SerializedName("nonce") + private String nonce; + + /** + *
+     * 字段名:附加数据
+     * 是否必填:否
+     * 描述:附加数据
+     * 
+ */ + @SerializedName("associated_data") + private String associatedData; + } +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingNotifyResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingNotifyResult.java new file mode 100644 index 000000000..06c00101c --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingNotifyResult.java @@ -0,0 +1,130 @@ +package com.github.binarywang.wxpay.bean.profitsharingV3; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * + * 微信V3接口 + * 分账动账通知解密后数据实体 + * + * @author yuanbo + * @create 2022-04-26-21:08 PM + */ +@Data +@NoArgsConstructor +public class ProfitSharingNotifyResult implements Serializable { + + + private static final long serialVersionUID = -2875006651351414624L; + + /** + *
+   * 字段名:直连商户号
+   * 是否必填:是
+   * 描述:直连模式分账发起和出资商户
+   * 
+ */ + @SerializedName("mchid") + private String mchId; + + /** + *
+   * 字段名:微信订单号
+   * 是否必填:是
+   * 描述:微信支付订单号
+   * 
+ */ + @SerializedName("transaction_id") + private String transactionId; + + /** + *
+   * 字段名:微信分账/回退单号
+   * 是否必填:是
+   * 描述:微信分账/回退单号
+   * 
+ */ + @SerializedName("order_id") + private String orderId; + + /** + *
+   * 字段名:商户分账/回退单号
+   * 是否必填:是
+   * 描述:分账方系统内部的分账/回退单号
+   * 
+ */ + @SerializedName("out_order_no") + private String outOrderNo; + + /** + *
+   * 字段名:分账接收方
+   * 是否必填:是
+   * 描述:分账接收方对象
+   * 
+ */ + @SerializedName("receiver") + private Receiver receiver; + + /** + *
+   * 字段名:成功时间
+   * 是否必填:是
+   * 描述:成功时间,Rfc3339标准
+   * 
+ */ + @SerializedName("success_time") + private String successTime; + + @Data + @NoArgsConstructor + public static class Receiver implements Serializable { + + private static final long serialVersionUID = -931070141604645363L; + + /** + *
+     * 字段名:分账接收方类型
+     * 是否必填:是
+     * 描述:MERCHANT_ID:商户号(mch_id或者sub_mch_id)
+     * 
+ */ + @SerializedName("type") + private String type; + + /** + *
+     * 字段名:分账接收方账号
+     * 是否必填:是
+     * 描述:申请本功能商户号
+     * 
+ */ + @SerializedName("account") + private String account; + + /** + *
+     * 字段名:分账动账金额
+     * 是否必填:是
+     * 描述:分账动账金额,单位为分,只能为整数
+     * 
+ */ + @SerializedName("amount") + private Integer amount; + + /** + *
+     * 字段名:分账/回退描述
+     * 是否必填:是
+     * 描述:分账/回退描述
+     * 
+ */ + @SerializedName("description") + private String description; + } +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingReceiver.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingReceiver.java index cbdeeba28..01017a8ee 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingReceiver.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingReceiver.java @@ -23,6 +23,17 @@ public class ProfitSharingReceiver implements Serializable { private static final long serialVersionUID = -4391888575149767840L; + + /** + *
+   * 字段名:子商户号
+   * 是否必填:是
+   * 描述:微信支付分配的子商户号,即分账的出资商户号。
+   * 
+ */ + @SerializedName("sub_mchid") + private String subMchId; + /** *
    * 字段名:应用ID
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingRequest.java
index 78122bfbf..da3b1b2bd 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingRequest.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingRequest.java
@@ -23,6 +23,16 @@
 public class ProfitSharingRequest implements Serializable {
   private static final long serialVersionUID = 3644929701624280800L;
 
+  /**
+   * 
+   * 字段名:子商户号
+   * 是否必填:是
+   * 描述:微信支付分配的子商户号,即分账的出资商户号。
+   * 
+ */ + @SerializedName("sub_mchid") + private String subMchId; + /** *
    * 字段名:应用ID
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingResult.java
index 892d31773..536ddd3c6 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingResult.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingResult.java
@@ -18,6 +18,16 @@
 public class ProfitSharingResult implements Serializable {
   private static final long serialVersionUID = -6201692412535987502L;
 
+  /**
+   * 
+   * 字段名:子商户号
+   * 是否必填:是
+   * 描述:微信支付分配的子商户号,即分账的出资商户号。
+   * 
+ */ + @SerializedName("sub_mchid") + private String subMchId; + /** *
    * 字段名:微信订单号
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingReturnRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingReturnRequest.java
index 31e26775f..a880e7c7b 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingReturnRequest.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingReturnRequest.java
@@ -22,6 +22,16 @@
 public class ProfitSharingReturnRequest implements Serializable {
   private static final long serialVersionUID = -2175582517588397426L;
 
+  /**
+   * 
+   * 字段名:子商户号
+   * 是否必填:是
+   * 描述:分账回退的接收商户,对应原分账出资的分账方商户,填写微信支付分配的商户号
+   * 
+ */ + @SerializedName("sub_mchid") + private String subMchId; + /** *
    * 字段名:微信分账单号
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingReturnResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingReturnResult.java
index 6e08a9a41..756dba672 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingReturnResult.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingReturnResult.java
@@ -16,6 +16,16 @@
 public class ProfitSharingReturnResult implements Serializable {
   private static final long serialVersionUID = -2175582517588397426L;
 
+  /**
+   * 
+   * 字段名:子商户号
+   * 是否必填:是
+   * 描述:分账回退的接收商户,对应原分账出资的分账方商户,填写微信支付分配的商户号
+   * 
+ */ + @SerializedName("sub_mchid") + private String subMchId; + /** *
    * 字段名:微信分账单号
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingUnfreezeRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingUnfreezeRequest.java
index c79b9b638..0005c6933 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingUnfreezeRequest.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingUnfreezeRequest.java
@@ -22,6 +22,16 @@
 public class ProfitSharingUnfreezeRequest implements Serializable {
   private static final long serialVersionUID = 6835471990040104843L;
 
+  /**
+   * 
+   * 字段名:子商户号
+   * 是否必填:是
+   * 描述:微信支付分配的子商户号,即分账的出资商户号。
+   * 
+ */ + @SerializedName("sub_mchid") + private String subMchId; + /** *
    * 字段名:微信订单号
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingUnfreezeResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingUnfreezeResult.java
index 0e67eee4c..160b0b450 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingUnfreezeResult.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharingV3/ProfitSharingUnfreezeResult.java
@@ -4,6 +4,7 @@
 import lombok.Data;
 
 import java.io.Serializable;
+import java.util.List;
 
 /**
  * 微信V3接口
@@ -46,7 +47,6 @@ public class ProfitSharingUnfreezeResult implements Serializable {
   @SerializedName("order_id")
   private String orderId;
 
-
   /**
    * 
    * 字段名:分账单状态
@@ -59,6 +59,12 @@ public class ProfitSharingUnfreezeResult implements Serializable {
   @SerializedName("state")
   private String state;
 
+  /**
+   * 分账接收方列表
+   */
+  @SerializedName("receivers")
+  private List receivers;
+
   @Data
   public static class Receiver implements Serializable {
     private static final long serialVersionUID = 4240983048700956806L;
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPreWithholdRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPreWithholdRequest.java
index ed806afec..bc9032433 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPreWithholdRequest.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPreWithholdRequest.java
@@ -28,7 +28,7 @@ public class WxPreWithholdRequest implements Serializable {
    * 委托代扣协议ID
    */
   @SerializedName(value = "contract_id")
-  private String contractId;
+  private transient String contractId;
 
   /**
    * 直连商户号
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxH5EntrustResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxH5EntrustResult.java
index 3cd8daad7..e39e71f86 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxH5EntrustResult.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxH5EntrustResult.java
@@ -19,6 +19,7 @@
 @Data
 @AllArgsConstructor
 @NoArgsConstructor
+@XStreamAlias("xml")
 public class WxH5EntrustResult extends BaseWxPayResult implements Serializable {
 
   private static final long serialVersionUID = 1L;
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayEntrustResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayEntrustResult.java
index 2cd0e3588..417eb8566 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayEntrustResult.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayEntrustResult.java
@@ -28,6 +28,7 @@
 @Data
 @AllArgsConstructor
 @NoArgsConstructor
+@XStreamAlias("xml")
 public class WxPayEntrustResult extends BaseWxPayResult implements Serializable {
 
   private static final long serialVersionUID = 1L;
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/QueryTransferBatchesRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/QueryTransferBatchesRequest.java
new file mode 100644
index 000000000..48401ce9c
--- /dev/null
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/QueryTransferBatchesRequest.java
@@ -0,0 +1,50 @@
+package com.github.binarywang.wxpay.bean.transfer;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * 查询微信批次单号查询批次单API参数
+ *
+ * @author zhongjun
+ * @date 2022/6/17
+ **/
+@Data
+@Builder(builderMethodName = "newBuilder")
+@NoArgsConstructor
+@AllArgsConstructor
+public class QueryTransferBatchesRequest implements Serializable {
+  private static final long serialVersionUID = -2175582517588397426L;
+
+  /**
+   * 微信批次单号
+   */
+  private String batchId;
+
+  /**
+   * 是否查询转账明细单
+   */
+  private Boolean needQueryDetail;
+
+  private Integer offset;
+
+  private Integer limit;
+
+  /**
+   * 明细状态
+   * 查询指定状态的转账明细单,当need_query_detail为true时,该字段必填
+   * ALL:全部。需要同时查询转账成功和转账失败的明细单
+   * SUCCESS:转账成功。只查询转账成功的明细单
+   * FAIL:转账失败。只查询转账失败的明细单
+   */
+  private String detailStatus;
+
+  /**
+   * 商家批次单号
+   */
+  private String outBatchNo;
+}
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/QueryTransferBatchesResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/QueryTransferBatchesResult.java
new file mode 100644
index 000000000..59a2f30fc
--- /dev/null
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/QueryTransferBatchesResult.java
@@ -0,0 +1,101 @@
+package com.github.binarywang.wxpay.bean.transfer;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 查询微信批次单号查询批次单API响应
+ *
+ * @author zhongjun
+ * @date 2022/6/17
+ **/
+@Data
+@NoArgsConstructor
+public class QueryTransferBatchesResult implements Serializable {
+  private static final long serialVersionUID = -2175582517588397426L;
+
+  @SerializedName("offset")
+  private Integer offset;
+
+  @SerializedName("limit")
+  private Integer limit;
+
+  @SerializedName("transfer_batch")
+  private TransferBatch transferBatch;
+
+  @SerializedName("transfer_detail_list")
+  private List transferDetailList;
+
+  @NoArgsConstructor
+  @Data
+  public static class TransferBatch {
+    @SerializedName("mchid")
+    private String mchid;
+
+    @SerializedName("out_batch_no")
+    private String outBatchNo;
+
+    @SerializedName("batch_id")
+    private String batchId;
+
+    @SerializedName("appid")
+    private String appid;
+
+    @SerializedName("batch_status")
+    private String batchStatus;
+
+    @SerializedName("batch_type")
+    private String batchType;
+
+    @SerializedName("batch_name")
+    private String batchName;
+
+    @SerializedName("batch_remark")
+    private String batchRemark;
+
+    @SerializedName("close_reason")
+    private String closeReason;
+
+    @SerializedName("total_amount")
+    private Integer totalAmount;
+
+    @SerializedName("total_num")
+    private Integer totalNum;
+
+    @SerializedName("create_time")
+    private String createTime;
+
+    @SerializedName("update_time")
+    private String updateTime;
+
+    @SerializedName("success_amount")
+    private Integer successAmount;
+
+    @SerializedName("success_num")
+    private Integer successNum;
+
+    @SerializedName("fail_amount")
+    private Integer failAmount;
+
+    @SerializedName("fail_num")
+    private Integer failNum;
+  }
+
+  @NoArgsConstructor
+  @Data
+  public static class TransferDetail {
+
+    @SerializedName("detail_id")
+    private String detailId;
+
+    @SerializedName("out_detail_no")
+    private String outDetailNo;
+
+    @SerializedName("detail_status")
+    private String detailStatus;
+  }
+}
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/TransferBatchDetailResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/TransferBatchDetailResult.java
new file mode 100644
index 000000000..8b76e445e
--- /dev/null
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/TransferBatchDetailResult.java
@@ -0,0 +1,60 @@
+package com.github.binarywang.wxpay.bean.transfer;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * 微信明细单号查询明细单API
+ *
+ * @author zhongjun
+ */
+@NoArgsConstructor
+@Data
+public class TransferBatchDetailResult implements Serializable {
+  private static final long serialVersionUID = -2175582517588397426L;
+
+  @SerializedName("mchid")
+  private String mchid;
+
+  @SerializedName("out_batch_no")
+  private String outBatchNo;
+
+  @SerializedName("batch_id")
+  private String batchId;
+
+  @SerializedName("appid")
+  private String appid;
+
+  @SerializedName("out_detail_no")
+  private String outDetailNo;
+
+  @SerializedName("detail_id")
+  private String detailId;
+
+  @SerializedName("detail_status")
+  private String detailStatus;
+
+  @SerializedName("transfer_amount")
+  private Integer transferAmount;
+
+  @SerializedName("transfer_remark")
+  private String transferRemark;
+
+  @SerializedName("fail_reason")
+  private String failReason;
+
+  @SerializedName("openid")
+  private String openid;
+
+  @SerializedName("user_name")
+  private String userName;
+
+  @SerializedName("initiate_time")
+  private String initiateTime;
+
+  @SerializedName("update_time")
+  private String updateTime;
+}
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/TransferBatchesRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/TransferBatchesRequest.java
new file mode 100644
index 000000000..c2188c611
--- /dev/null
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/TransferBatchesRequest.java
@@ -0,0 +1,107 @@
+package com.github.binarywang.wxpay.bean.transfer;
+
+import com.github.binarywang.wxpay.v3.SpecEncrypt;
+import com.google.gson.annotations.SerializedName;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 发起商家转账API参数
+ *
+ * @author zhongjun
+ * @date 2022/6/17
+ **/
+@Data
+@Builder(builderMethodName = "newBuilder")
+@NoArgsConstructor
+@AllArgsConstructor
+public class TransferBatchesRequest implements Serializable {
+  private static final long serialVersionUID = -2175582517588397426L;
+
+  /**
+   * 直连商户的appid
+   */
+  @SerializedName("appid")
+  private String appid;
+
+  /**
+   * 商家批次单号
+   */
+  @SerializedName("out_batch_no")
+  private String outBatchNo;
+
+  /**
+   * 批次名称
+   */
+  @SerializedName("batch_name")
+  private String batchName;
+
+  /**
+   * 批次备注
+   */
+  @SerializedName("batch_remark")
+  private String batchRemark;
+
+  /**
+   * 转账总金额
+   */
+  @SerializedName("total_amount")
+  private Integer totalAmount;
+
+  /**
+   * 转账总笔数
+   */
+  @SerializedName("total_num")
+  private Integer totalNum;
+
+  /**
+   * 转账明细列表
+   */
+  @SpecEncrypt
+  @SerializedName("transfer_detail_list")
+  private List transferDetailList;
+
+
+  @Data
+  @Builder(builderMethodName = "newBuilder")
+  @AllArgsConstructor
+  @NoArgsConstructor
+  public static class TransferDetail {
+
+    /**
+     * 商家明细单号
+     */
+    @SerializedName("out_detail_no")
+    private String outDetailNo;
+
+    /**
+     * 转账金额
+     */
+    @SerializedName("transfer_amount")
+    private Integer transferAmount;
+
+    /**
+     * 转账备注
+     */
+    @SerializedName("transfer_remark")
+    private String transferRemark;
+
+    /**
+     * 用户在直连商户应用下的用户标示
+     */
+    @SerializedName("openid")
+    private String openid;
+
+    /**
+     * 收款用户姓名
+     */
+    @SpecEncrypt
+    @SerializedName("user_name")
+    private String userName;
+  }
+}
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/TransferBatchesResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/TransferBatchesResult.java
new file mode 100644
index 000000000..70b9a279d
--- /dev/null
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/TransferBatchesResult.java
@@ -0,0 +1,37 @@
+package com.github.binarywang.wxpay.bean.transfer;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * 商家转账结果
+ *
+ * @author zhongjun
+ * @date 2022/6/17
+ **/
+@Data
+@NoArgsConstructor
+public class TransferBatchesResult implements Serializable {
+  private static final long serialVersionUID = -2175582517588397426L;
+
+  /**
+   * 商家批次单号
+   */
+  @SerializedName("out_batch_no")
+  private String outBatchNo;
+
+  /**
+   * 微信批次单号
+   */
+  @SerializedName("batch_id")
+  private String batchId;
+
+  /**
+   * 批次创建时间
+   */
+  @SerializedName("create_time")
+  private String createTime;
+}
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/config/WxPayConfig.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/config/WxPayConfig.java
index 59733944a..b94620ee9 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/config/WxPayConfig.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/config/WxPayConfig.java
@@ -26,6 +26,7 @@
 import java.security.KeyStore;
 import java.security.PrivateKey;
 import java.security.cert.X509Certificate;
+import java.util.Base64;
 import java.util.Collections;
 
 /**
@@ -101,15 +102,28 @@ public class WxPayConfig {
    */
   private String signType;
   private SSLContext sslContext;
+  /**
+   * p12证书base64编码
+   */
+  private String keyString;
   /**
    * p12证书文件的绝对路径或者以classpath:开头的类路径.
    */
   private String keyPath;
 
+  /**
+   * apiclient_key.pem证书base64编码
+   */
+  private String privateKeyString;
   /**
    * apiclient_key.pem证书文件的绝对路径或者以classpath:开头的类路径.
    */
   private String privateKeyPath;
+
+  /**
+   * apiclient_cert.pem证书base64编码
+   */
+  private String privateCertString;
   /**
    * apiclient_cert.pem证书文件的绝对路径或者以classpath:开头的类路径.
    */
@@ -222,7 +236,7 @@ public SSLContext initSSLContext() throws WxPayException {
       throw new WxPayException("请确保商户号mchId已设置");
     }
 
-    InputStream inputStream = this.loadConfigInputStream(this.getKeyPath(), this.keyContent, "p12证书");
+    InputStream inputStream = this.loadConfigInputStream(this.keyString, this.getKeyPath(), this.keyContent, "p12证书");
 
     try {
       KeyStore keystore = KeyStore.getInstance("PKCS12");
@@ -245,7 +259,9 @@ public SSLContext initSSLContext() throws WxPayException {
    * @author doger.wang
    **/
   public CloseableHttpClient initApiV3HttpClient() throws WxPayException {
+    val privateKeyString = this.getPrivateKeyString();
     val privateKeyPath = this.getPrivateKeyPath();
+    val privateCertString = this.getPrivateCertString();
     val privateCertPath = this.getPrivateCertPath();
     val serialNo = this.getCertSerialNo();
     val apiV3Key = this.getApiV3Key();
@@ -253,8 +269,8 @@ public CloseableHttpClient initApiV3HttpClient() throws WxPayException {
       throw new WxPayException("请确保apiV3Key值已设置");
     }
 
-    InputStream keyInputStream = this.loadConfigInputStream(privateKeyPath, this.privateKeyContent, "privateKeyPath");
-    InputStream certInputStream = this.loadConfigInputStream(privateCertPath, this.privateCertContent, "privateCertPath");
+    InputStream keyInputStream = this.loadConfigInputStream(privateKeyString, privateKeyPath, this.privateKeyContent, "privateKeyPath");
+    InputStream certInputStream = this.loadConfigInputStream(privateCertString, privateCertPath, this.privateCertContent, "privateCertPath");
     try {
       PrivateKey merchantPrivateKey = PemUtils.loadPrivateKey(keyInputStream);
       X509Certificate certificate = PemUtils.loadCertificate(certInputStream);
@@ -298,10 +314,13 @@ private WxPayHttpProxy getWxPayHttpProxy() {
     return null;
   }
 
-  private InputStream loadConfigInputStream(String configPath, byte[] configContent, String fileName) throws WxPayException {
+  private InputStream loadConfigInputStream(String configString, String configPath, byte[] configContent, String fileName) throws WxPayException {
     InputStream inputStream;
     if (configContent != null) {
       inputStream = new ByteArrayInputStream(configContent);
+    } else if(StringUtils.isNotEmpty(configString)) {
+      configContent = Base64.getDecoder().decode(configString);
+      inputStream = new ByteArrayInputStream(configContent);
     } else {
       if (StringUtils.isBlank(configPath)) {
         throw new WxPayException("请确保证书文件地址【" + fileName + "】或者内容已配置");
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java
index fbc499fed..ffd17efe4 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java
@@ -311,6 +311,7 @@ public static class RefundStatus {
     public static final String SUCCESS = "SUCCESS";
 
     /**
+     * v2
      * 退款关闭.
      */
     public static final String REFUND_CLOSE = "REFUNDCLOSE";
@@ -321,10 +322,23 @@ public static class RefundStatus {
     public static final String PROCESSING = "PROCESSING";
 
     /**
+     * v2
      * 退款异常.
      * 退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败,可前往商户平台(pay.weixin.qq.com)-交易中心,手动处理此笔退款。
      */
     public static final String CHANGE = "CHANGE";
+
+    /**
+     * v3
+     * 退款关闭
+     */
+    public static final String CLOSED = "CLOSED";
+
+    /**
+     * v3
+     * 退款异常
+     */
+    public static final String ABNORMAL = "ABNORMAL";
   }
 
   public static class ReceiverType {
@@ -345,4 +359,5 @@ public static class ReceiverType {
      */
     public static final String PERSONAL_SUB_OPENID = "PERSONAL_SUB_OPENID";
   }
+
 }
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/BankService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/BankService.java
new file mode 100644
index 000000000..095510d4f
--- /dev/null
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/BankService.java
@@ -0,0 +1,121 @@
+package com.github.binarywang.wxpay.service;
+
+import com.github.binarywang.wxpay.bean.bank.*;
+import com.github.binarywang.wxpay.exception.WxPayException;
+
+/**
+ * 
+ * 微信支付-银行组件
+ * 
+ * + * @author zhongjun + **/ +public interface BankService { + /** + *
+   *
+   * 获取对私银行卡号开户银行
+   *
+   * 请求方式:GET(HTTPS)
+   * 请求地址:https://api.mch.weixin.qq.com/v3/capital/capitallhh/banks/search-banks-by-bank-account
+   *
+   * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter11_2_1.shtml
+   * 
+ * + * @param accountNumber 银行卡号 该字段需进行加密处理,加密方法详见敏感信息加密说明。(提醒:必须在HTTP头中上送Wechatpay-Serial) + * @return BankAccountResult 对私银行卡号开户银行信息 + * @throws WxPayException . + */ + BankAccountResult searchBanksByBankAccount(String accountNumber) throws WxPayException; + + /** + *
+   *
+   * 查询支持个人业务的银行列表
+   *
+   * 请求方式:GET(HTTPS)
+   * 请求地址:https://api.mch.weixin.qq.com/v3/capital/capitallhh/banks/personal-banking
+   *
+   * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter11_2_2.shtml
+   * 
+ * + * @param offset 本次查询偏移量 + * @param limit 本次请求最大查询条数,最大值为200 + * @return PersonalBankingResult 支持个人业务的银行列表信息 + * @throws WxPayException . + */ + BankingResult personalBanking(Integer offset, Integer limit) throws WxPayException; + + /** + *
+   *
+   * 支持对公业务的银行列表
+   *
+   * 请求方式:GET(HTTPS)
+   * 请求地址:https://api.mch.weixin.qq.com/v3/capital/capitallhh/banks/corporate-banking
+   *
+   * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter11_2_3.shtml
+   * 
+ * + * @param offset 本次查询偏移量 + * @param limit 本次请求最大查询条数,最大值为200 + * @return BankingResult 支持对公业务的银行列表信息 + * @throws WxPayException . + */ + BankingResult corporateBanking(Integer offset, Integer limit) throws WxPayException; + + /** + *
+   *
+   * 查询省份列表API
+   * 通过本接口获取省份列表数据(不包含中国港澳台地区),可用于省份下的城市数据查询
+   *
+   * 请求方式:GET(HTTPS)
+   * 请求地址:https://api.mch.weixin.qq.com/v3/capital/capitallhh/areas/provinces
+   *
+   * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter11_2_4.shtml
+   * 
+ * + * @return ProvincesResult 省份列表信息 + * @throws WxPayException . + */ + ProvincesResult areasProvinces() throws WxPayException; + + /** + *
+   *
+   * 查询城市列表API
+   * 通过本接口根据省份编码获取省份下的城市列表信息,不包含中国港澳台地区城市信息,可用于支行数据过滤查询
+   *
+   * 请求方式:GET(HTTPS)
+   * 请求地址:https://api.mch.weixin.qq.com/v3/capital/capitallhh/areas/provinces/{province_code}/cities
+   *
+   * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter11_2_5.shtml
+   * 
+ * + * @return CitiesResult 城市列表信息 + * @throws WxPayException . + */ + CitiesResult areasCities(Integer provinceCode) throws WxPayException; + + /** + *
+   *
+   * 查询支行列表API
+   * 本接口可以用于根据银行别名编码(仅支持需要填写支行的银行别名编码)和城市编码过滤查询支行列表数据
+   *
+   * 请求方式:GET(HTTPS)
+   * 请求地址:https://api.mch.weixin.qq.com/v3/capital/capitallhh/banks/{bank_alias_code}/branches
+   *
+   * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter11_2_5.shtml
+   * 
+ * + * @param bankAliasCode 银行别名的编码,查询支行接口仅支持需要填写支行的银行别名编码。示例值:1000006247 + * @param cityCode 城市编码,唯一标识一座城市,用于结合银行别名编码查询支行列表。示例值:536 + * @param offset 非负整数,表示该次请求资源的起始位置,从0开始计数。调用方选填,默认为0。offset为20,limit为100时,查询第21-120条数据 + * @param limit 非0非负的整数,该次请求可返回的最大资源条数。示例值:200 + * @return BankBranchesResult 城市列表信息 + * @throws WxPayException . + */ + BankBranchesResult bankBranches(String bankAliasCode, Integer cityCode, Integer offset, Integer limit) throws WxPayException; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/ComplaintService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/ComplaintService.java index bd6a2e346..1ed2b09df 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/ComplaintService.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/ComplaintService.java @@ -1,9 +1,13 @@ package com.github.binarywang.wxpay.service; import com.github.binarywang.wxpay.bean.complaint.*; +import com.github.binarywang.wxpay.bean.media.ImageUploadResult; import com.github.binarywang.wxpay.exception.WxPayException; import javax.crypto.BadPaddingException; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; /** *
@@ -129,4 +133,31 @@ public interface ComplaintService {
    */
   void complete(CompleteRequest request) throws WxPayException;
 
+  /**
+   * 
+   * 商户上传反馈图片API
+   * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter10_2_10.shtml
+   * 接口链接:https://api.mch.weixin.qq.com/v3/merchant-service/images/upload
+   * 
+ * + * @param imageFile 需要上传的图片文件 + * @return ImageUploadResult 微信返回的媒体文件标识Id。示例值:BB04A5DEEFEA18D4F2554C1EDD3B610B.bmp + * @throws WxPayException the wx pay exception + */ + ImageUploadResult uploadResponseImage(File imageFile) throws WxPayException, IOException; + + /** + *
+   * 商户上传反馈图片API
+   * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter10_2_10.shtml
+   * 接口链接:https://api.mch.weixin.qq.com/v3/merchant-service/images/upload
+   * 
+ * + * @param inputStream 需要上传的图片文件流 + * @param fileName 需要上传的图片文件名 + * @return ImageUploadResult 微信返回的媒体文件标识Id。示例值:BB04A5DEEFEA18D4F2554C1EDD3B610B.bmp + * @throws WxPayException the wx pay exception + */ + ImageUploadResult uploadResponseImage(InputStream inputStream, String fileName) throws WxPayException, IOException; + } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/CustomDeclarationService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/CustomDeclarationService.java new file mode 100644 index 000000000..98f55d51d --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/CustomDeclarationService.java @@ -0,0 +1,80 @@ +package com.github.binarywang.wxpay.service; + +import com.github.binarywang.wxpay.bean.customs.*; +import com.github.binarywang.wxpay.exception.WxPayException; + +/** + *
+ * 微信支付 支付报关 API.
+ * Created by xifengzhu on 2022/05/05.
+ * 
+ * + * @author xifengzhu + */ +public interface CustomDeclarationService { + + /** + * The constant DECLARATION_BASE_URL. + */ + String DECLARATION_BASE_URL = "https://apihk.mch.weixin.qq.com/global/v3/customs"; + + /** + *
+   * 报关API
+   * 文档地址: ...
+   * 
+ * + * @param request the request + * @return 返回数据 declaration result + * @throws WxPayException the wx pay exception + */ + DeclarationResult declare(DeclarationRequest request) throws WxPayException; + + /** + *
+   * 报关查询API
+   * 文档地址: ...
+   * 
+ * + * @param request the request + * @return 返回数据 declaration query result + * @throws WxPayException the wx pay exception + */ + DeclarationQueryResult query(DeclarationQueryRequest request) throws WxPayException; + + /** + *
+   * 身份信息校验API
+   * 文档地址: ...
+   * 
+ * + * @param request the request + * @return 返回数据 verify certification result + * @throws WxPayException the wx pay exception + */ + VerifyCertificateResult verifyCertificate(VerifyCertificateRequest request) throws WxPayException; + + /** + *
+   * 报关信息修改API
+   * 文档地址: ...
+   * 
+ * + * @param request the request + * @return 返回数据 declaration result + * @throws WxPayException the wx pay exception + */ + DeclarationResult modify(DeclarationRequest request) throws WxPayException; + + /** + *
+   * 报关重推API
+   * 文档地址: ...
+   * 
+ * + * @param request the request + * @return 返回数据 redeclaration result + * @throws WxPayException the wx pay exception + */ + RedeclareResult redeclare(RedeclareRequest request) throws WxPayException; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/EcommerceService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/EcommerceService.java index 3f97b150a..044ae3936 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/EcommerceService.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/EcommerceService.java @@ -22,7 +22,7 @@ public interface EcommerceService { *
    * 二级商户进件API
    * 接口地址: https://api.mch.weixin.qq.com/v3/ecommerce/applyments/
-   * 文档地址: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/applyments/chapter3_1.shtml
+   * 文档地址: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_1_8.shtml
    *
    * 
* @@ -252,6 +252,18 @@ public interface EcommerceService { */ ProfitSharingResult queryProfitSharing(ProfitSharingQueryRequest request) throws WxPayException; + /** + *
+   * 查询订单剩余待分金额API
+   * 文档地址: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_4_9.shtml
+   * 
+ * + * @param request 查询订单剩余待分金额请求 + * @return 返回数据 profit sharing UnSplitAmount result + * @throws WxPayException the wx pay exception + */ + ProfitSharingOrdersUnSplitAmountResult queryProfitSharingOrdersUnsplitAmount(ProfitSharingOrdersUnSplitAmountRequest request) throws WxPayException; + /** *
    * 添加分账接收方API
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/MerchantTransferService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/MerchantTransferService.java
new file mode 100644
index 000000000..049253aca
--- /dev/null
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/MerchantTransferService.java
@@ -0,0 +1,150 @@
+package com.github.binarywang.wxpay.service;
+
+import com.github.binarywang.wxpay.bean.merchanttransfer.*;
+import com.github.binarywang.wxpay.exception.WxPayException;
+
+/**
+ * 商家转账到零钱(直联商户)
+ *
+ * @author glz
+ * @date 2022-6-11
+ */
+public interface MerchantTransferService {
+
+  /**
+   * 发起商家转账API
+   * 

+ * 适用对象:直连商户 + * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_1.shtml + * 请求URL:https://api.mch.weixin.qq.com/v3/transfer/batches + * 请求方式:POST + * 接口限频: 单个商户 50QPS,如果超过频率限制,会报错FREQUENCY_LIMITED,请降低频率请求。 + * 是否需要证书:是 + * + * @param request the request + * @return transfer create result + * @throws WxPayException the wx pay exception + */ + TransferCreateResult createTransfer(TransferCreateRequest request) throws WxPayException; + + /** + * 微信批次单号查询批次单API + *

+ * 适用对象:直连商户 + * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_2.shtml + * 请求URL:https://api.mch.weixin.qq.com/v3/transfer/batches/batch-id/{batch_id} + * 请求方式:GET + * 接口限频: 单个商户 50QPS,如果超过频率限制,会报错FREQUENCY_LIMITED,请降低频率请求。 + * + * @param request the request + * @return batches query result + * @throws WxPayException the wx pay exception + */ + BatchesQueryResult queryWxBatches(WxBatchesQueryRequest request) throws WxPayException; + + /** + * 微信明细单号查询明细单API + *

+ * 适用对象:直连商户 + * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_3.shtml + * 请求URL:https://api.mch.weixin.qq.com/v3/transfer/batches/batch-id/{batch_id}/details/detail-id/{detail_id} + * 请求方式:GET + * 接口限频: 单个商户 50QPS,如果超过频率限制,会报错FREQUENCY_LIMITED,请降低频率请求。 + * + * @param request the request + * @return details query result + * @throws WxPayException the wx pay exception + */ + DetailsQueryResult queryWxDetails(WxDetailsQueryRequest request) throws WxPayException; + + /** + * 商家批次单号查询批次单API + *

+ * 适用对象:直连商户 + * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_5.shtml + * 请求URL:https://api.mch.weixin.qq.com/v3/transfer/batches/out-batch-no/{out_batch_no} + * 请求方式:GET + * 接口限频: 单个商户 50QPS,如果超过频率限制,会报错FREQUENCY_LIMITED,请降低频率请求。 + * + * @param request the request + * @return batches query result + * @throws WxPayException the wx pay exception + */ + BatchesQueryResult queryMerchantBatches(MerchantBatchesQueryRequest request) throws WxPayException; + + /** + * 商家明细单号查询明细单API + *

+ * 适用对象:直连商户 + * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_6.shtml + * 请求URL:https://api.mch.weixin.qq.com/v3/transfer/batches/out-batch-no/{out_batch_no}/details/out-detail-no/{out_detail_no} + * 请求方式:GET + * 接口限频: 单个商户 50QPS,如果超过频率限制,会报错FREQUENCY_LIMITED,请降低频率请求。 + * + * @param request the request + * @return details query result + * @throws WxPayException the wx pay exception + */ + DetailsQueryResult queryMerchantDetails(MerchantDetailsQueryRequest request) throws WxPayException; + + /** + * 转账电子回单申请受理API + *

+ * 适用对象:直连商户 + * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_7.shtml + * 请求URL:https://api.mch.weixin.qq.com/v3/transfer/bill-receipt + * 请求方式:POST + * 接口限频: 单个商户 20QPS,如果超过频率限制,会报错FREQUENCY_LIMITED,请降低频率请求。 + * + * @param request the request + * @return electronic bill result + * @throws WxPayException the wx pay exception + */ + ElectronicBillResult applyElectronicBill(ElectronicBillApplyRequest request) throws WxPayException; + + /** + * 查询转账电子回单API + *

+ * 适用对象:直连商户 + * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_8.shtml + * 请求URL:https://api.mch.weixin.qq.com/v3/transfer/bill-receipt/{out_batch_no} + * 请求方式:GET + * + * @param outBatchNo the out batch no + * @return electronic bill result + * @throws WxPayException the wx pay exception + */ + ElectronicBillResult queryElectronicBill(String outBatchNo) throws WxPayException; + + /** + * 转账明细电子回单受理API + *

+ * 适用对象:直连商户 + * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_9.shtml + * 请求URL:https://api.mch.weixin.qq.com/v3/transfer-detail/electronic-receipts + * 请求方式:POST + * 接口限频: 单个商户 20QPS,如果超过频率限制,会报错FREQUENCY_LIMITED,请降低频率请求。 + * 前置条件:只支持受理最近30天内的转账明细单 + * + * @param request the request + * @return detail electronic bill result + * @throws WxPayException the wx pay exception + */ + DetailElectronicBillResult applyDetailElectronicBill(DetailElectronicBillRequest request) throws WxPayException; + + + /** + * 查询转账明细电子回单受理结果API + *

+ * 适用对象:直连商户 + * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_10.shtml + * 请求URL:https://api.mch.weixin.qq.com/v3/transfer-detail/electronic-receipts + * 请求方式:GET + * 前置条件:只支持查询最近90天内的转账明细单 + * + * @param request the request + * @return detail electronic bill result + * @throws WxPayException the wx pay exception + */ + DetailElectronicBillResult queryDetailElectronicBill(DetailElectronicBillRequest request) throws WxPayException; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/PartnerPayScoreService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/PartnerPayScoreService.java new file mode 100644 index 000000000..e55b83785 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/PartnerPayScoreService.java @@ -0,0 +1,277 @@ +package com.github.binarywang.wxpay.service; + +import com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader; +import com.github.binarywang.wxpay.bean.payscore.PayScoreNotifyData; +import com.github.binarywang.wxpay.bean.payscore.UserAuthorizationStatusNotifyResult; +import com.github.binarywang.wxpay.bean.payscore.WxPartnerPayScoreRequest; +import com.github.binarywang.wxpay.bean.payscore.WxPartnerPayScoreResult; +import com.github.binarywang.wxpay.exception.WxPayException; + +/** + *

+ *  服务商支付分相关服务类.
+ *   微信支付分是对个人的身份特质、支付行为、使用历史等情况的综合计算分值,旨在为用户提供更简单便捷的生活方式。
+ *   微信用户可以在具体应用场景中,开通微信支付分。开通后,用户可以在【微信—>钱包—>支付分】中查看分数和使用记录。
+ *   (即需在应用场景中使用过一次,钱包才会出现支付分入口)
+ *
+ * @author hallkk
+ * @date 2022/05/18
+ */
+public interface PartnerPayScoreService {
+
+
+  /**
+   * 
+   * 支付分商户预授权API
+   * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/payscore_partner/chapter5_1.shtml
+   * 接口链接:https://api.mch.weixin.qq.com/v3/payscore/partner/permissions
+   * 
+ * + * @param request 请求对象 + * @return WxPartnerPayScoreResult wx partner payscore result + * @throws WxPayException the wx pay exception + */ + WxPartnerPayScoreResult permissions(WxPartnerPayScoreRequest request) throws WxPayException; + + + /** + *
+   * 支付分查询与用户授权记录(授权协议号)API
+   * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/payscore_partner/chapter5_2.shtml
+   * 接口链接:https://api.mch.weixin.qq.com/v3/payscore/partner/permissions/authorization-code/{authorization_code}
+   * 
+ * + * @param serviceId + * @param subMchid + * @param authorizationCode + * @return WxPayScoreResult wx partner payscore result + * @throws WxPayException the wx pay exception + */ + WxPartnerPayScoreResult permissionsQueryByAuthorizationCode(String serviceId, String subMchid, + String authorizationCode) throws WxPayException; + + + /** + *
+   * 解除用户授权关系(授权协议号)API
+   * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/payscore_partner/chapter5_4.shtml
+   * 接口链接:https://api.mch.weixin.qq.com/v3/payscore/partner/permissions/authorization-code/{authorization_code}/terminate
+   * 
+ * + * @param serviceId + * @param subMchid + * @param authorizationCode + * @param reason + * @return WxPartnerPayScoreResult wx partner payscore result + * @throws WxPayException the wx pay exception + */ + WxPartnerPayScoreResult permissionsTerminateByAuthorizationCode(String serviceId, String subMchid, + String authorizationCode, String reason) throws WxPayException; + + + /** + *
+   * 支付分查询与用户授权记录(openid)API
+   * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/payscore_partner/chapter5_3.shtml
+   * 接口链接:https://api.mch.weixin.qq.com/v3/payscore/partner/permissions/search
+   * 
+ * + * @param serviceId + * @param subMchid + * @param subAppid + * @param openId + * @param subOpenid + * @return WxPayScoreResult wx partner payscore result + * @throws WxPayException the wx pay exception + */ + WxPartnerPayScoreResult permissionsQueryByOpenId(String serviceId, String appId, String subMchid, String subAppid, + String openId, String subOpenid) throws WxPayException; + + + /** + *
+   * 解除用户授权关系(openid)API
+   * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/payscore_partner/chapter5_5.shtml
+   * 接口链接:https://api.mch.weixin.qq.com/v3/payscore/partner/permissions/openid/{openid}/terminate
+   * 
+ * + * @param serviceId + * @param subMchid + * @param subAppid + * @param openId + * @param subOpenid + * @param reason + * @return WxPayScoreResult wx partner payscore result + * @throws WxPayException the wx pay exception + */ + WxPartnerPayScoreResult permissionsTerminateByOpenId(String serviceId, String appId, String subMchid, String subAppid, + String openId, String subOpenid, String reason) throws WxPayException; + + + /** + *
+   * 支付分创建订单API.
+   * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/payscore_partner/chapter3_1.shtml
+   * 接口链接:https://api.mch.weixin.qq.com/v3/payscore/partner/serviceorder
+   * 
+ * + * @param request 请求对象 + * @return WxPayScoreResult wx partner payscore result + * @throws WxPayException the wx pay exception + */ + WxPartnerPayScoreResult createServiceOrder(WxPartnerPayScoreRequest request) throws WxPayException; + + /** + *
+   * 支付分查询订单API.
+   * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/payscore_partner/chapter3_2.shtml
+   * 接口链接:https://api.mch.weixin.qq.com/v3/payscore/partner/serviceorder
+   * 
+ * + * @param serviceId + * @param subMchid + * @param outOrderNo the out order no + * @param queryId the query id + * @return the wx pay score result + * @throws WxPayException the wx pay exception + */ + WxPartnerPayScoreResult queryServiceOrder(String serviceId, String subMchid, + String outOrderNo, String queryId) throws WxPayException; + + /** + *
+   * 支付分取消订单API.
+   * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/payscore_partner/chapter3_3.shtml
+   * 接口链接:https://api.mch.weixin.qq.com/v3/payscore/partner/serviceorder/{out_order_no}/cancel
+   * 
+ *

+ * + * @param serviceId + * @param subMchid + * @param outOrderNo the out order no + * @param reason the reason + * @return com.github.binarywang.wxpay.bean.payscore.WxPayScoreResult wx pay score result + * @throws WxPayException the wx pay exception + */ + WxPartnerPayScoreResult cancelServiceOrder(String serviceId, String appId, String subMchid, + String outOrderNo, String reason) throws WxPayException; + + /** + *

+   * 支付分修改订单金额API.
+   * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/payscore_partner/chapter3_4.shtml
+   * 接口链接:https://api.mch.weixin.qq.com/v3/payscore/partner/serviceorder/{out_order_no}/modify
+   * 
+ *

+ * + * @param request the request + * @return the wx pay score result + * @throws WxPayException the wx pay exception + */ + WxPartnerPayScoreResult modifyServiceOrder(WxPartnerPayScoreRequest request) throws WxPayException; + + /** + *

+   * 支付分完结订单API.
+   * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/payscore_partner/chapter3_5.shtml
+   * 请求URL:https://api.mch.weixin.qq.com/v3/payscore/partner/serviceorder/{out_order_no}/complete
+   * 
+ * + * @param request the request + * @return the wx pay score result + * @throws WxPayException the wx pay exception + */ + void completeServiceOrder(WxPartnerPayScoreRequest request) throws WxPayException; + + /** + *
+   * 商户发起催收扣款API.
+   * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/payscore_partner/chapter3_6.shtml
+   * 请求URL:https://api.mch.weixin.qq.com/v3/payscore/partner/serviceorder/{out_order_no}/pay
+   *
+   * 
+ * + * @param serviceId + * @param subMchid + * @param outOrderNo the out order no + * @return the wx pay score result + * @throws WxPayException the wx pay exception + */ + WxPartnerPayScoreResult payServiceOrder(String serviceId, String appId, String subMchid, String outOrderNo) throws WxPayException; + + /** + *
+   * 支付分订单收款API.
+   * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/payscore_partner/chapter3_7.shtml
+   * 请求URL: https://api.mch.weixin.qq.com/v3/payscore/partner/serviceorder/{out_order_no}/sync
+   * 
+ * + * @param request the request + * @return the wx pay score result + * @throws WxPayException the wx pay exception + */ + WxPartnerPayScoreResult syncServiceOrder(WxPartnerPayScoreRequest request) throws WxPayException; + + /** + *
+   * 收付通子商户申请绑定支付分服务API.
+   * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/payscore_partner/chapter9_1.shtml
+   * 请求URL: https://api.mch.weixin.qq.com/v3/payscore/partner/service-account-applications
+   * 
+ * + * @param request the request + * @return the wx pay score result + * @throws WxPayException the wx pay exception + */ + WxPartnerPayScoreResult applyServiceAccount(WxPartnerPayScoreRequest request) throws WxPayException; + + /** + *
+   * 查询收付通子商户服务绑定结果API.
+   * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/payscore_partner/chapter9_2.shtml
+   * 请求URL: https://api.mch.weixin.qq.com/v3/payscore/partner/service-account-applications/{out_apply_no}
+   * 
+ * + * @param outApplyNo 商户申请绑定单号 + * @return the wx pay score result + * @throws WxPayException the wx pay exception + */ + WxPartnerPayScoreResult queryServiceAccountState(String outApplyNo) throws WxPayException; + + /** + *
+   * 授权/解除授权服务回调数据处理
+   * 文档地址: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/payscore/chapter4_4.shtml
+   * 
+ * + * @param notifyData 通知数据 + * @param header 通知头部数据,不传则表示不校验头 + * @return 解密后通知数据 return user authorization status notify result + * @throws WxPayException the wx pay exception + */ + UserAuthorizationStatusNotifyResult parseUserAuthorizationStatusNotifyResult(String notifyData, SignatureHeader header) throws WxPayException; + + /** + *
+   * 支付分回调内容解析方法
+   * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/payscore/chapter5_2.shtml
+   * 
+ * + * @param data the data + * @return the wx pay score result + */ + PayScoreNotifyData parseNotifyData(String data, SignatureHeader header) throws WxPayException; + + /** + *
+   * 支付分回调NotifyData解密resource
+   * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/payscore/chapter5_2.shtml
+   * 
+ * + * @param data the data + * @return the wx pay score result + * @throws WxPayException the wx pay exception + */ + WxPartnerPayScoreResult decryptNotifyDataResource(PayScoreNotifyData data) throws WxPayException; + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/ProfitSharingV3Service.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/ProfitSharingV3Service.java index fcb87063a..501e93397 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/ProfitSharingV3Service.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/ProfitSharingV3Service.java @@ -1,5 +1,6 @@ package com.github.binarywang.wxpay.service; +import com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader; import com.github.binarywang.wxpay.bean.profitsharingV3.*; import com.github.binarywang.wxpay.exception.WxPayException; @@ -161,4 +162,22 @@ public interface ProfitSharingV3Service { */ ProfitSharingReceiver deleteProfitSharingReceiver(ProfitSharingReceiver receiver) throws WxPayException; + + /** + *
+   * 分账动账通知
+   *
+   * 分账或分账回退成功后,微信会把相关变动结果发送给分账接收方(只支持商户)。
+   * 对后台通知交互时,如果微信收到应答不是成功或超时,微信认为通知失败,微信会通过一定的策略定期重新发起通知,尽可能提高通知的成功率,但微信不保证通知最终能成功。
+   * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter8_1_10.shtml
+   * 
+ * + * @param notifyData 分账通知实体 + * @param header 分账通知头 {@link SignatureHeader} + * @return {@link ProfitSharingNotifyData} 资源对象 + * @throws WxPayException the wx pay exception + * @see 微信文档 + */ + ProfitSharingNotifyData getProfitSharingNotifyData(String notifyData, SignatureHeader header) throws WxPayException; + } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/TransferService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/TransferService.java new file mode 100644 index 000000000..b2516ebe6 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/TransferService.java @@ -0,0 +1,102 @@ +package com.github.binarywang.wxpay.service; + +import com.github.binarywang.wxpay.bean.transfer.*; +import com.github.binarywang.wxpay.exception.WxPayException; + +/** + * 商家转账到零钱 + * + * @author zhongjun + * @date 2022/6/17 + **/ +public interface TransferService { + + /** + *
+   *
+   * 发起商家转账API
+   *
+   * 请求方式:POST(HTTPS)
+   * 请求地址:请求地址
+   *
+   * 文档地址:发起商家转账API
+   * 
+ * + * @param request 转账请求参数 + * @return TransferBatchesResult 转账结果 + * @throws WxPayException . + */ + TransferBatchesResult transferBatches(TransferBatchesRequest request) throws WxPayException; + + /** + *
+   *
+   * 微信批次单号查询批次单API
+   *
+   * 请求方式:GET(HTTPS)
+   * 请求地址:请求地址
+   *
+   * 文档地址:微信批次单号查询批次单API
+   * 
+ * + * @param request 查询请求参数 + * @return TransferBatchesResult 查询结果 + * @throws WxPayException . + */ + QueryTransferBatchesResult transferBatchesBatchId(QueryTransferBatchesRequest request) throws WxPayException; + + /** + *
+   *
+   * 微信明细单号查询明细单API
+   *
+   * 请求方式:GET(HTTPS)
+   * 请求地址:请求地址
+   *
+   * 文档地址:微信明细单号查询明细单API
+   * 
+ * + * @param batchId 微信批次单号 + * @param detailId 微信明细单号 + * @return TransferBatchDetailResult 查询结果 + * @throws WxPayException . + */ + TransferBatchDetailResult transferBatchesBatchIdDetail(String batchId, String detailId) throws WxPayException; + + /** + *
+   *
+   * 商家批次单号查询批次单API
+   *
+   * 请求方式:GET(HTTPS)
+   * 请求地址:请求地址
+   *
+   * 文档地址:商家批次单号查询批次单API
+   * 
+ * + * @param request 查询请求参数 + * @return TransferBatchesResult 查询结果 + * @throws WxPayException . + * @throws WxPayException . + */ + QueryTransferBatchesResult transferBatchesOutBatchNo(QueryTransferBatchesRequest request) throws WxPayException; + + /** + *
+   *
+   * 商家明细单号查询明细单API
+   *
+   * 请求方式:GET(HTTPS)
+   * 请求地址:请求地址
+   *
+   * 文档地址:商家明细单号查询明细单API
+   * 
+ * + * @param outBatchNo 商家明细单号 + * @param outDetailNo 商家批次单号 + * @return TransferBatchDetailResult 查询结果 + * @throws WxPayException . + */ + TransferBatchDetailResult transferBatchesOutBatchNoDetail(String outBatchNo, String outDetailNo) throws WxPayException; + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxEntrustPapService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxEntrustPapService.java index be76b34c4..b51f8dde1 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxEntrustPapService.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxEntrustPapService.java @@ -7,69 +7,64 @@ /** *
  *   微信签约代扣相关接口.
- *   https://pay.weixin.qq.com/wiki/doc/api/wxpay_v2/papay/chapter2_8.shtml
+ *   https://pay.weixin.qq.com/wiki/doc/api/wxpay_v2/papay/chapter2_8.shtml
  *  
* * @author chenliang - * @date 2021-08-02 4:50 下午 + * @date 2021 -08-02 4:50 下午 */ public interface WxEntrustPapService { /** - * *
    *   获取公众号纯签约链接,
-   *   详见:https://pay.weixin.qq.com/wiki/doc/api/wxpay_v2/papay/chapter3_1.shtml
+   *   详见:https://pay.weixin.qq.com/wiki/doc/api/wxpay_v2/papay/chapter3_1.shtml
    *   该接口返回一个签约链接,该链接只能在微信内打开
    * 
* - * @param wxMpEntrustRequest - * @return - * @throws WxPayException + * @param wxMpEntrustRequest the wx mp entrust request + * @return string + * @throws WxPayException the wx pay exception */ String mpSign(WxMpEntrustRequest wxMpEntrustRequest) throws WxPayException; /** - * *
    *   获取小程序纯签约参数json
-   *   详见:https://pay.weixin.qq.com/wiki/doc/api/wxpay_v2/papay/chapter3_3.shtml
+   *   详见:https://pay.weixin.qq.com/wiki/doc/api/wxpay_v2/papay/chapter3_3.shtml
    *   返回一个json 前端用来拉起一个新的签约小程序进行签约
    * 
* - * - * @param wxMaEntrustRequest - * @return - * @throws WxPayException + * @param wxMaEntrustRequest the wx ma entrust request + * @return string + * @throws WxPayException the wx pay exception */ String maSign(WxMaEntrustRequest wxMaEntrustRequest) throws WxPayException; /** - * *
    *   获取h5纯签约支付跳转链接
-   *   详见:https://pay.weixin.qq.com/wiki/doc/api/wxpay_v2/papay/chapter3_4.shtml
+   *   详见:https://pay.weixin.qq.com/wiki/doc/api/wxpay_v2/papay/chapter3_4.shtml
    *   返回一个签约链接  在浏览器请求链接拉起微信
    * 
* - * @param wxH5EntrustRequest - * @return - * @throws WxPayException + * @param wxH5EntrustRequest the wx h 5 entrust request + * @return wx h 5 entrust result + * @throws WxPayException the wx pay exception */ WxH5EntrustResult h5Sign(WxH5EntrustRequest wxH5EntrustRequest) throws WxPayException; /** - * *
    *   支付中签约
-   *   详见:https://pay.weixin.qq.com/wiki/doc/api/wxpay_v2/papay/chapter3_5.shtml
+   *   详见:https://pay.weixin.qq.com/wiki/doc/api/wxpay_v2/papay/chapter3_5.shtml
    *   请求微信 若微信内请求 需要构造json返回,
    *   若h5请求 直接使用mweb_url 链接即可拉起微信
    * 
* - * @param wxPayEntrustRequest - * @return - * @throws WxPayException + * @param wxPayEntrustRequest the wx pay entrust request + * @return wx pay entrust result + * @throws WxPayException the wx pay exception */ WxPayEntrustResult paySign(WxPayEntrustRequest wxPayEntrustRequest) throws WxPayException; @@ -77,7 +72,7 @@ public interface WxEntrustPapService { * 申请扣款 *
    *   申请扣款
-   *   详见:https://pay.weixin.qq.com/wiki/doc/api/wxpay_v2/papay/chapter3_8.shtml
+   *   详见:https://pay.weixin.qq.com/wiki/doc/api/wxpay_v2/papay/chapter3_8.shtml
    *   请求微信发起委托扣款,扣款额度和次数由使用的签约模板限制,
    *   该扣款接口是立即扣款 无延时 扣款前无消息通知。
    *
@@ -85,9 +80,9 @@ public interface WxEntrustPapService {
    *   从用户签约成功时间开始算,商户在12小时内发起的扣款,会被立即执行,无延迟。商户超过12小时以后发起的扣款,都按24小时扣费规则执行
    * 
* - * @param wxWithholdRequest - * @return - * @throws WxPayException + * @param wxWithholdRequest the wx withhold request + * @return wx withhold result + * @throws WxPayException the wx pay exception */ WxWithholdResult withhold(WxWithholdRequest wxWithholdRequest) throws WxPayException; @@ -95,16 +90,16 @@ public interface WxEntrustPapService { * 预扣费通知 *
    *   预扣费接口
-   *   详见:https://pay.weixin.qq.com/wiki/doc/api/wxpay_v2/papay/chapter3_10.shtml
+   *   详见:https://pay.weixin.qq.com/wiki/doc/api/wxpay_v2/papay/chapter3_10.shtml
    *   商户进行委托代扣扣费前需要在可通知时间段内调用「预扣费通知」的接口为用户发送扣费提醒,
    *   并设定扣费持续天数和预计扣费金额,经过扣费等待期后,在可扣费期内可发起扣费,扣款金额不能高于预计扣费金额,
    *   扣费失败可主动发起重试扣费(重试次数由其他规则限制),直到扣费成功,或者可扣费期结束。
    *   商户只能在北京时间每天 6:00~22:00调用「预扣费通知」
    * 
* - * @param wxPreWithholdRequest - * @return - * @throws WxPayException + * @param wxPreWithholdRequest the wx pre withhold request + * @return string + * @throws WxPayException the wx pay exception */ String preWithhold(WxPreWithholdRequest wxPreWithholdRequest) throws WxPayException; @@ -112,13 +107,13 @@ public interface WxEntrustPapService { * 签约状态查询 *
    *   签约状态查询
-   *   详见:https://pay.weixin.qq.com/wiki/doc/api/wxpay_v2/papay/chapter3_7.shtml
+   *   详见:https://pay.weixin.qq.com/wiki/doc/api/wxpay_v2/papay/chapter3_7.shtml
    *   查询签约关系接口提供单笔签约关系查询。
    * 
* - * @param wxSignQueryRequest - * @return - * @throws WxPayException + * @param wxSignQueryRequest the wx sign query request + * @return wx sign query result + * @throws WxPayException the wx pay exception */ WxSignQueryResult querySign(WxSignQueryRequest wxSignQueryRequest) throws WxPayException; @@ -127,31 +122,30 @@ public interface WxEntrustPapService { * 申请解约 *
    *   申请解约
-   *   详见:https://pay.weixin.qq.com/wiki/doc/api/wxpay_v2/papay/chapter3_9.shtml
+   *   详见:https://pay.weixin.qq.com/wiki/doc/api/wxpay_v2/papay/chapter3_9.shtml
    *   商户与用户的签约关系有误或者商户主动要求与用户解除之前的签约协议时可调用此接口完成解约。
    *   商户可以在商户后台(pay.weixin.qq.com)设置解约回调地址,当发生解约关系的时候,微信服务器会向此地址通知解约信息,内容与签约返回一致
    * 
* - * @param wxTerminatedContractRequest - * @return - * @throws WxPayException + * @param wxTerminatedContractRequest the wx terminated contract request + * @return wx termination contract result + * @throws WxPayException the wx pay exception */ WxTerminationContractResult terminationContract(WxTerminatedContractRequest wxTerminatedContractRequest) throws WxPayException; /** - * *
    *   查询代扣订单
-   *   详见:https://pay.weixin.qq.com/wiki/doc/api/wxpay_v2/papay/chapter4_5.shtml
+   *   详见:https://pay.weixin.qq.com/wiki/doc/api/wxpay_v2/papay/chapter4_5.shtml
    *   该接口仅提供微信扣款服务申请扣款接口创建的订单进行查询,商户可以通过该接口主动查询微信代扣订单状态,完成下一步的业务逻辑。
    *   ACCEPT等待扣款:为24小时延时扣费场景下独有的,当没有达到24小时前一直是这种状态;
    *   NOTPAY未支付:系统已经启动扣款流程,这个状态只是瞬间状态,很快会进入终态(SUCCESS、PAY_FAIL)
    *
    * 
* - * @param wxWithholdOrderQueryRequest - * @return - * @throws WxPayException + * @param wxWithholdOrderQueryRequest the wx withhold order query request + * @return wx withhold order query result + * @throws WxPayException the wx pay exception */ WxWithholdOrderQueryResult papOrderQuery(WxWithholdOrderQueryRequest wxWithholdOrderQueryRequest) throws WxPayException; } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java index 3f98c3d2c..bf95d5593 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java @@ -35,17 +35,17 @@ public interface WxPayService { String getPayBaseUrl(); /** - * Map里 加入新的 {@link WxPayConfig},适用于动态添加新的微信公众号配置. + * Map里 加入新的 {@link WxPayConfig},适用于动态添加新的微信商户配置. * - * @param mchId 商户号id + * @param mchId 商户id * @param wxPayConfig 新的微信配置 */ void addConfig(String mchId, WxPayConfig wxPayConfig); /** - * 从 Map中 移除 {@link String mchId} 所对应的 {@link WxPayConfig},适用于动态移除微信公众号配置. + * 从 Map中 移除 {@link String mchId} 所对应的 {@link WxPayConfig},适用于动态移除微信商户配置. * - * @param mchId 对应公众号的标识 + * @param mchId 对应商户的标识 */ void removeConfig(String mchId); @@ -66,17 +66,17 @@ public interface WxPayService { void setMultiConfig(Map wxPayConfigs, String defaultMchId); /** - * 进行相应的公众号切换. + * 进行相应的商户切换. * - * @param mchId 公众号标识 + * @param mchId 商户标识 * @return 切换是否成功 boolean */ boolean switchover(String mchId); /** - * 进行相应的公众号切换. + * 进行相应的商户切换. * - * @param mchId 公众号标识 + * @param mchId 商户标识 * @return 切换成功 ,则返回当前对象,方便链式调用,否则抛出异常 */ WxPayService switchoverTo(String mchId); @@ -164,6 +164,17 @@ public interface WxPayService { */ String getV3(String url) throws WxPayException; + /** + * 发送get请求,得到响应字符串. + *

+ * 部分字段会包含敏感信息,所以在提交前需要在请求头中会包含"Wechatpay-Serial"信息 + * + * @param url 请求地址 + * @return 返回请求结果字符串 string + * @throws WxPayException the wx pay exception + */ + String getV3WithWechatPaySerial(String url) throws WxPayException; + /** * 发送下载 V3请求,得到响应流. * @@ -176,8 +187,8 @@ public interface WxPayService { /** * 发送put V3请求,得到响应字符串. * - * @param url 请求地址 - * @param url 请求数据 + * @param url 请求地址 + * @param requestStr 请求数据 * @return 返回请求结果字符串 string * @throws WxPayException the wx pay exception */ @@ -194,6 +205,7 @@ public interface WxPayService { /** * 获取微信签约代扣服务类 + * * @return entrust service */ WxEntrustPapService getWxEntrustPapService(); @@ -229,7 +241,7 @@ public interface WxPayService { /** * 获取分账服务类. *

- * V3接口 {@link WxPayService#getProfitSharingV3Service()} + * V3接口 {@link WxPayService#getProfitSharingV3Service()} *

* * @return the ent pay service @@ -292,6 +304,13 @@ public interface WxPayService { */ MarketingBusiFavorService getMarketingBusiFavorService(); + /** + * 获取商家转账到零钱服务类 + * + * @return the merchant transfer service + */ + MerchantTransferService getMerchantTransferService(); + /** * 设置企业付款服务类,允许开发者自定义实现类. * @@ -341,7 +360,7 @@ public interface WxPayService { /** *
    * 查询订单
-   * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_2.shtml
+   * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_2.shtml
    * 商户可以通过查询订单接口主动查询订单状态,完成下一步的业务逻辑。查询订单状态可通过微信支付订单号或商户订单号两种方式查询
    * 注意:
    *  查询订单可通过微信支付订单号和商户订单号两种方式查询,两种查询方式返回结果相同
@@ -365,7 +384,7 @@ public interface WxPayService {
   /**
    * 
    * 查询订单
-   * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_2.shtml
+   * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_2.shtml
    * 商户可以通过查询订单接口主动查询订单状态,完成下一步的业务逻辑。查询订单状态可通过微信支付订单号或商户订单号两种方式查询
    * 注意:
    *  查询订单可通过微信支付订单号和商户订单号两种方式查询,两种查询方式返回结果相同
@@ -389,11 +408,11 @@ public interface WxPayService {
    * 
    * 合单查询订单API
    * 请求URL: https://api.mch.weixin.qq.com/v3/combine-transactions/out-trade-no/{combine_out_trade_no}
-   * 文档地址: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter5_1_11.shtml
+   * 文档地址: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter5_1_11.shtml
    * 
* * @param combineOutTradeNo 合单商户订单号 - * @return 合单支付订单信息 + * @return 合单支付订单信息 combine query result * @throws WxPayException the wx pay exception */ CombineQueryResult queryCombine(String combineOutTradeNo) throws WxPayException; @@ -472,7 +491,7 @@ public interface WxPayService { *
    * 合单关闭订单API
    * 请求URL: https://api.mch.weixin.qq.com/v3/combine-transactions/out-trade-no/{combine_out_trade_no}/close
-   * 文档地址: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter5_1_12.shtml
+   * 文档地址: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter5_1_12.shtml
    * 
* * @param request 请求对象 @@ -498,7 +517,7 @@ public interface WxPayService { * @param request 统一下单请求参数,设定的 tradeType 及配置里的 tradeType 将被忽略,转而使用 specificTradeType * @return 返回 {@link WxPayConstants.TradeType.Specific} 指定的类 * @throws WxPayException the wx pay exception - * @see WxPayService#createOrder(WxPayUnifiedOrderRequest) WxPayService#createOrder(WxPayUnifiedOrderRequest) + * @see WxPayService#createOrder(WxPayUnifiedOrderRequest) WxPayService#createOrder(WxPayUnifiedOrderRequest)WxPayService#createOrder(WxPayUnifiedOrderRequest) */ T createOrder(WxPayConstants.TradeType.Specific specificTradeType, WxPayUnifiedOrderRequest request) throws WxPayException; @@ -516,8 +535,9 @@ public interface WxPayService { /** * 调用统一下单接口,并组装生成支付所需参数对象. * - * @param 请使用{@link com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result}里的内部类或字段 - * @param request 统一下单请求参数 + * @param 请使用{@link com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result}里的内部类或字段 + * @param tradeType the trade type + * @param request 统一下单请求参数 * @return 返回 {@link com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result}里的内部类或字段 * @throws WxPayException the wx pay exception */ @@ -526,7 +546,8 @@ public interface WxPayService { /** * 在发起微信支付前,需要调用统一下单接口,获取"预支付交易会话标识" * - * @param request 请求对象,注意一些参数如appid、mchid等不用设置,方法内会自动从配置对象中获取到(前提是对应配置中已经设置) + * @param tradeType the trade type + * @param request 请求对象,注意一些参数如appid、mchid等不用设置,方法内会自动从配置对象中获取到(前提是对应配置中已经设置) * @return the wx pay unified order result * @throws WxPayException the wx pay exception */ @@ -540,7 +561,7 @@ public interface WxPayService { * https://api.mch.weixin.qq.com/v3/combine-transactions/h5 * https://api.mch.weixin.qq.com/v3/combine-transactions/jsapi * https://api.mch.weixin.qq.com/v3/combine-transactions/native - * 文档地址: https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_9_3.shtml + * 文档地址: https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_9_3.shtml *
* * @param tradeType 支付方式 @@ -558,9 +579,10 @@ public interface WxPayService { * https://api.mch.weixin.qq.com/v3/combine-transactions/h5 * https://api.mch.weixin.qq.com/v3/combine-transactions/jsapi * https://api.mch.weixin.qq.com/v3/combine-transactions/native - * 文档地址: https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_9_3.shtml + * 文档地址: https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_9_3.shtml *
* + * @param the type parameter * @param tradeType 支付方式 * @param request 请求对象 * @return 调起支付需要的参数 t @@ -597,7 +619,7 @@ public interface WxPayService { /** *
    * 微信支付-申请退款.
-   * 详见 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
+   * 详见 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
    * 接口链接:https://api.mch.weixin.qq.com/secapi/pay/refund
    * 
* @@ -610,7 +632,7 @@ public interface WxPayService { /** *
    * 申请退款API(支持单品).
-   * 详见 https://pay.weixin.qq.com/wiki/doc/api/danpin.php?chapter=9_103&index=3
+   * 详见 https://pay.weixin.qq.com/wiki/doc/api/danpin.php?chapter=9_103&index=3
    *
    * 应用场景
    * 当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付款退还给买家,微信支付将在收到退款请求并且验证成功之后,按照退款规则将支付款按原路退到买家帐号上。
@@ -637,7 +659,7 @@ public interface WxPayService {
   /**
    * 
    * 申请退款API(支持单品).
-   * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_9.shtml
+   * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_9.shtml
    *
    * 应用场景
    * 当交易发生之后一年内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付金额退还给买家,微信支付将在收到退款请求并且验证成功之后,将支付款按原路退还至买家账号上。
@@ -667,7 +689,7 @@ public interface WxPayService {
    * 应用场景:
    *  提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,用零钱支付的退款20分钟内到账,
    *  银行卡支付的退款3个工作日后重新查询退款状态。
-   * 详见 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_5
+   * 详见 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_5
    * 接口链接:https://api.mch.weixin.qq.com/pay/refundquery
    * 
* 以下四个参数四选一 @@ -688,7 +710,7 @@ WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, Stri * 应用场景: * 提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,用零钱支付的退款20分钟内到账, * 银行卡支付的退款3个工作日后重新查询退款状态。 - * 详见 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_5 + * 详见 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_5 * 接口链接:https://api.mch.weixin.qq.com/pay/refundquery *
* @@ -712,7 +734,7 @@ WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, Stri * 接口地址 * https://api.mch.weixin.qq.com/pay/refundqueryv2 * https://api2.mch.weixin.qq.com/pay/refundqueryv2(备用域名)见跨城冗灾方案 - * 详见 https://pay.weixin.qq.com/wiki/doc/api/danpin.php?chapter=9_104&index=4 + * 详见 https://pay.weixin.qq.com/wiki/doc/api/danpin.php?chapter=9_104&index=4 *
* * @param request 微信退款单号 @@ -726,7 +748,7 @@ WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, Stri * 微信支付-查询退款 * 应用场景: * 提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,建议在提交退款申请后1分钟发起查询退款状态,一般来说零钱支付的退款5分钟内到账,银行卡支付的退款1-3个工作日到账。 - * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_10.shtml + * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_10.shtml * 接口链接:https://api.mch.weixin.qq.com/v3/refund/domestic/refunds/{out_refund_no} *
* @@ -741,7 +763,7 @@ WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, Stri * 微信支付-查询退款 * 应用场景: * 提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,建议在提交退款申请后1分钟发起查询退款状态,一般来说零钱支付的退款5分钟内到账,银行卡支付的退款1-3个工作日到账。 - * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_10.shtml + * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_10.shtml * 接口链接:https://api.mch.weixin.qq.com/v3/refund/domestic/refunds/{out_refund_no} *
* @@ -786,7 +808,7 @@ WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, Stri /** *
    * 合单支付通知回调数据处理
-   * 文档地址: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter5_1_13.shtml
+   * 文档地址: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter5_1_13.shtml
    * 
* * @param notifyData 通知数据 @@ -844,7 +866,7 @@ WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, Stri * 二维码中的内容为链接,形式为: * weixin://wxpay/bizpayurl?sign=XXXXX&appid=XXXXX&mch_id=XXXXX&product_id=XXXXXX&time_stamp=XXXXXX&nonce_str=XXXXX * 其中XXXXX为商户需要填写的内容,商户将该链接生成二维码,如需要打印发布二维码,需要采用此格式。商户可调用第三方库生成二维码图片。 - * 文档详见: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4 + * 文档详见: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4 *
* * @param productId 产品Id @@ -860,7 +882,7 @@ WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, Stri * 二维码中的内容为链接,形式为: * weixin://wxpay/bizpayurl?sign=XXXXX&appid=XXXXX&mch_id=XXXXX&product_id=XXXXXX&time_stamp=XXXXXX&nonce_str=XXXXX * 其中XXXXX为商户需要填写的内容,商户将该链接生成二维码,如需要打印发布二维码,需要采用此格式。商户可调用第三方库生成二维码图片。 - * 文档详见: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4 + * 文档详见: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4 *
* * @param productId 产品Id @@ -873,7 +895,7 @@ WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, Stri * 扫码支付模式二生成二维码的方法. * 对应链接格式:weixin://wxpay/bizpayurl?sr=XXXXX。请商户调用第三方库将code_url生成二维码图片。 * 该模式链接较短,生成的二维码打印到结账小票上的识别率较高。 - * 文档详见: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5 + * 文档详见: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5 *
* * @param codeUrl 微信返回的交易会话的二维码链接 @@ -890,7 +912,7 @@ WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, Stri * 商户在调用微信支付提供的相关接口时,会得到微信支付返回的相关信息以及获得整个接口的响应时间。 * 为提高整体的服务水平,协助商户一起提高服务质量,微信支付提供了相关接口调用耗时和返回信息的主动上报接口, * 微信支付可以根据商户侧上报的数据进一步优化网络部署,完善服务监控,和商户更好的协作为用户提供更好的业务体验。 - * 接口地址: https://api.mch.weixin.qq.com/payitil/report + * 接口地址: https://api.mch.weixin.qq.com/payitil/report * 是否需要证书:不需要 *
* @@ -908,7 +930,7 @@ WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, Stri * 2、微信在次日9点启动生成前一天的对账单,建议商户10点后再获取; * 3、对账单中涉及金额的字段单位为“元”。 * 4、对账单接口只能下载三个月以内的账单。 - * 接口链接:https://api.mch.weixin.qq.com/pay/downloadbill + * 接口链接:https://api.mch.weixin.qq.com/pay/downloadbill * 详情请见: 下载对账单 *
* @@ -1027,7 +1049,7 @@ WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, Stri * • 微信侧未成功下单的交易不会出现在对账单中。支付成功后撤销的交易会出现在对账单中,跟原支付单订单号一致; * • 对账单中涉及金额的字段单位为“元”; * • 对账单接口只能下载三个月以内的账单。 - * 接口链接:https://api.mch.weixin.qq.com/v3/bill/tradebill + * 接口链接:https://api.mch.weixin.qq.com/v3/bill/tradebill * 详情请见: 申请交易账单 *
* @@ -1044,7 +1066,7 @@ WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, Stri * 注意: * • 资金账单中的数据反映的是商户微信支付账户资金变动情况; * • 对账单中涉及金额的字段单位为“元”。 - * 接口链接:https://api.mch.weixin.qq.com/v3/bill/fundflowbill + * 接口链接:https://api.mch.weixin.qq.com/v3/bill/fundflowbill * 详情请见: 申请资金账单 *
* @@ -1075,12 +1097,12 @@ WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, Stri /** *
    * 提交付款码支付.
-   * 文档地址:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_10&index=1
+   * 文档地址:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_10&index=1
    * 应用场景:
    * 收银员使用扫码设备读取微信用户刷卡授权码以后,二维码或条码信息传送至商户收银台,由商户收银台或者商户后台调用该接口发起支付。
    * 提醒1:提交支付请求后微信会同步返回支付结果。当返回结果为“系统错误”时,商户系统等待5秒后调用【查询订单API】,查询支付实际交易结果;当返回结果为“USERPAYING”时,商户系统可设置间隔时间(建议10秒)重新查询支付结果,直到支付成功或超时(建议30秒);
    * 提醒2:在调用查询接口返回后,如果交易状况不明晰,请调用【撤销订单API】,此时如果交易失败则关闭订单,该单不能再支付成功;如果交易成功,则将扣款退回到用户账户。当撤销无返回或错误时,请再次调用。注意:请勿扣款后立即调用【撤销订单API】,建议至少15秒后再调用。撤销订单API需要双向证书。
-   * 接口地址:   https://api.mch.weixin.qq.com/pay/micropay
+   * 接口地址:   https://api.mch.weixin.qq.com/pay/micropay
    * 是否需要证书:不需要。
    * 
* @@ -1114,10 +1136,10 @@ WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, Stri *
    *  转换短链接.
    *  文档地址:
-   *     https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_9&index=8
+   *     https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_9&index=8
    *  应用场景:
    *     该接口主要用于扫码原生支付模式一中的二维码链接转成短链接(weixin://wxpay/s/XXXXXX),减小二维码数据量,提升扫描速度和精确度。
-   *  接口地址:https://api.mch.weixin.qq.com/tools/shorturl
+   *  接口地址:https://api.mch.weixin.qq.com/tools/shorturl
    *  是否需要证书:否
    * 
* @@ -1135,7 +1157,7 @@ WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, Stri * @param longUrl 需要被压缩的网址 * @return the string * @throws WxPayException the wx pay exception - * @see WxPayService#shorturl(WxPayShorturlRequest) WxPayService#shorturl(WxPayShorturlRequest)WxPayService#shorturl(WxPayShorturlRequest) + * @see WxPayService#shorturl(WxPayShorturlRequest) WxPayService#shorturl(WxPayShorturlRequest)WxPayService#shorturl(WxPayShorturlRequest)WxPayService#shorturl(WxPayShorturlRequest) */ String shorturl(String longUrl) throws WxPayException; @@ -1144,7 +1166,7 @@ WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, Stri * 授权码查询OPENID接口. * 通过授权码查询公众号Openid,调用查询后,该授权码只能由此商户号发起扣款,直至授权码更新。 * 文档地址: - * https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_13&index=9 + * https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_13&index=9 * 接口链接: * https://api.mch.weixin.qq.com/tools/authcodetoopenid * @@ -1163,7 +1185,7 @@ WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, Stri * @param authCode 授权码 * @return openid string * @throws WxPayException the wx pay exception - * @see WxPayService#authcode2Openid(WxPayAuthcode2OpenidRequest) WxPayService#authcode2Openid(WxPayAuthcode2OpenidRequest)WxPayService#authcode2Openid(WxPayAuthcode2OpenidRequest) + * @see WxPayService#authcode2Openid(WxPayAuthcode2OpenidRequest) WxPayService#authcode2Openid(WxPayAuthcode2OpenidRequest)WxPayService#authcode2Openid(WxPayAuthcode2OpenidRequest)WxPayService#authcode2Openid(WxPayAuthcode2OpenidRequest) */ String authcode2Openid(String authCode) throws WxPayException; @@ -1333,4 +1355,19 @@ WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, Stri * @return the complaints service */ ComplaintService getComplaintsService(); + + + /** + * 获取银行组件服务 + * + * @return 银行组件服务 + */ + BankService getBankService(); + + /** + * 获取商家转账到零钱服务类. + * + * @return the transfers service + */ + TransferService getTransferService(); } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BankServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BankServiceImpl.java new file mode 100644 index 000000000..623a787d9 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BankServiceImpl.java @@ -0,0 +1,68 @@ +package com.github.binarywang.wxpay.service.impl; + +import com.github.binarywang.wxpay.bean.bank.*; +import com.github.binarywang.wxpay.exception.WxPayException; +import com.github.binarywang.wxpay.service.BankService; +import com.github.binarywang.wxpay.service.WxPayService; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import lombok.RequiredArgsConstructor; + +/** + * 微信支付-银行组件 + * + * @author zhongjun + **/ +@RequiredArgsConstructor +public class BankServiceImpl implements BankService { + private final WxPayService payService; + private static final Gson GSON = new GsonBuilder().create(); + + @Override + public BankAccountResult searchBanksByBankAccount(String accountNumber) throws WxPayException { + String url = String.format("%s/v3/capital/capitallhh/banks/search-banks-by-bank-account?account_number=%s", this.payService.getPayBaseUrl(), accountNumber); + String response = payService.getV3WithWechatPaySerial(url); + return GSON.fromJson(response, BankAccountResult.class); + } + + @Override + public BankingResult personalBanking(Integer offset, Integer limit) throws WxPayException { + offset = offset == null ? 0 : offset; + limit = limit == null ? 200 : limit; + String url = String.format("%s/v3/capital/capitallhh/banks/personal-banking?offset=%s&limit=%s", this.payService.getPayBaseUrl(), offset, limit); + String response = payService.getV3(url); + return GSON.fromJson(response, BankingResult.class); + } + + @Override + public BankingResult corporateBanking(Integer offset, Integer limit) throws WxPayException { + offset = offset == null ? 0 : offset; + limit = limit == null ? 200 : limit; + String url = String.format("%s/v3/capital/capitallhh/banks/corporate-banking?offset=%s&limit=%s", this.payService.getPayBaseUrl(), offset, limit); + String response = payService.getV3(url); + return GSON.fromJson(response, BankingResult.class); + } + + @Override + public ProvincesResult areasProvinces() throws WxPayException { + String url = String.format("%s/v3/capital/capitallhh/areas/provinces", this.payService.getPayBaseUrl()); + String response = payService.getV3WithWechatPaySerial(url); + return GSON.fromJson(response, ProvincesResult.class); + } + + @Override + public CitiesResult areasCities(Integer provinceCode) throws WxPayException { + String url = String.format("%s/v3/capital/capitallhh/areas/provinces/%s/cities", this.payService.getPayBaseUrl(), provinceCode); + String response = payService.getV3WithWechatPaySerial(url); + return GSON.fromJson(response, CitiesResult.class); + } + + @Override + public BankBranchesResult bankBranches(String bankAliasCode, Integer cityCode, Integer offset, Integer limit) throws WxPayException { + offset = offset == null ? 0 : offset; + limit = limit == null ? 200 : limit; + String url = String.format("%s/v3/capital/capitallhh/banks/%s/branches?city_code=%s&offset=%s&limit=%s", this.payService.getPayBaseUrl(), bankAliasCode, cityCode, offset, limit); + String response = payService.getV3(url); + return GSON.fromJson(response, BankBranchesResult.class); + } +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java index 128a7362d..f88165c72 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java @@ -27,6 +27,8 @@ import com.google.common.collect.Maps; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import lombok.Getter; +import lombok.Setter; import me.chanjar.weixin.common.error.WxRuntimeException; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; @@ -63,98 +65,63 @@ public abstract class BaseWxPayServiceImpl implements WxPayService { static ThreadLocal wxApiData = new ThreadLocal<>(); + + @Setter + @Getter private EntPayService entPayService = new EntPayServiceImpl(this); + + @Getter private final ProfitSharingService profitSharingService = new ProfitSharingServiceImpl(this); + + @Getter private final ProfitSharingV3Service profitSharingV3Service = new ProfitSharingV3ServiceImpl(this); - private final RedpackService redpackService = new RedpackServiceImpl(this); - private final PayScoreService payScoreService = new PayScoreServiceImpl(this); - private final EcommerceService ecommerceService = new EcommerceServiceImpl(this); - private final BusinessCircleService businessCircleService = new BusinessCircleServiceImpl(this); - private final MerchantMediaService merchantMediaService = new MerchantMediaServiceImpl(this); - private final MarketingMediaService marketingMediaService = new MarketingMediaServiceImpl(this); - private final MarketingFavorService marketingFavorService = new MarketingFavorServiceImpl(this); - private final MarketingBusiFavorService marketingBusiFavorService = new MarketingBusiFavorServiceImpl(this); - private final WxEntrustPapService wxEntrustPapService = new WxEntrustPapServiceImpl(this); - private final PartnerTransferService partnerTransferService = new PartnerTransferServiceImpl(this); - private final PayrollService payrollService = new PayrollServiceImpl(this); - private final ComplaintService complaintsService = new ComplaintServiceImpl(this); - protected Map configMap; + @Getter + private final RedpackService redpackService = new RedpackServiceImpl(this); - @Override - public EntPayService getEntPayService() { - return entPayService; - } + @Getter + private final PayScoreService payScoreService = new PayScoreServiceImpl(this); - @Override - public ProfitSharingService getProfitSharingService() { - return profitSharingService; - } + @Getter + private final EcommerceService ecommerceService = new EcommerceServiceImpl(this); - @Override - public ProfitSharingV3Service getProfitSharingV3Service() { - return profitSharingV3Service; - } + @Getter + private final BusinessCircleService businessCircleService = new BusinessCircleServiceImpl(this); - @Override - public PayScoreService getPayScoreService() { - return payScoreService; - } + @Getter + private final MerchantMediaService merchantMediaService = new MerchantMediaServiceImpl(this); - @Override - public RedpackService getRedpackService() { - return this.redpackService; - } + @Getter + private final MarketingMediaService marketingMediaService = new MarketingMediaServiceImpl(this); - @Override - public EcommerceService getEcommerceService() { - return ecommerceService; - } + @Getter + private final MarketingFavorService marketingFavorService = new MarketingFavorServiceImpl(this); - @Override - public BusinessCircleService getBusinessCircleService() { - return this.businessCircleService; - } + @Getter + private final MarketingBusiFavorService marketingBusiFavorService = new MarketingBusiFavorServiceImpl(this); - @Override - public MerchantMediaService getMerchantMediaService() { - return this.merchantMediaService; - } + @Getter + private final WxEntrustPapService wxEntrustPapService = new WxEntrustPapServiceImpl(this); - @Override - public MarketingMediaService getMarketingMediaService() { - return this.marketingMediaService; - } + @Getter + private final PartnerTransferService partnerTransferService = new PartnerTransferServiceImpl(this); - @Override - public MarketingFavorService getMarketingFavorService() { - return this.marketingFavorService; - } + @Getter + private final PayrollService payrollService = new PayrollServiceImpl(this); - @Override - public MarketingBusiFavorService getMarketingBusiFavorService() { - return this.marketingBusiFavorService; - } + @Getter + private final ComplaintService complaintsService = new ComplaintServiceImpl(this); - @Override - public void setEntPayService(EntPayService entPayService) { - this.entPayService = entPayService; - } + @Getter + private final BankService bankService = new BankServiceImpl(this); - @Override - public WxEntrustPapService getWxEntrustPapService() { - return wxEntrustPapService; - } + @Getter + private final TransferService transferService = new TransferServiceImpl(this); - @Override - public PartnerTransferService getPartnerTransferService() { - return partnerTransferService; - } + @Getter + private final MerchantTransferService merchantTransferService = new MerchantTransferServiceImpl(this); - @Override - public PayrollService getPayrollService() { - return payrollService; - } + protected Map configMap; @Override public WxPayConfig getConfig() { @@ -344,9 +311,10 @@ public WxPayOrderNotifyResult parseOrderNotifyResult(String xmlData, String sign if (result.getSignType() != null) { // 如果解析的通知对象中signType有值,则使用它进行验签 signType = result.getSignType(); - } else if (this.getConfig().getSignType() != null) { + } else if (configMap.get(result.getMchId()).getSignType() != null) { // 如果配置中signType有值,则使用它进行验签 - signType = this.getConfig().getSignType(); + signType = configMap.get(result.getMchId()).getSignType(); + this.switchover(result.getMchId()); } } @@ -429,6 +397,7 @@ public WxPayRefundNotifyResult parseRefundNotifyResult(String xmlData) throws Wx WxPayRefundNotifyResult result; if (XmlConfig.fastMode) { result = BaseWxPayResult.fromXML(xmlData, WxPayRefundNotifyResult.class); + this.switchover(result.getMchId()); result.decryptReqInfo(this.getConfig().getMchKey()); } else { result = WxPayRefundNotifyResult.fromXML(xmlData, this.getConfig().getMchKey()); @@ -464,12 +433,13 @@ public WxPayRefundNotifyV3Result parseRefundNotifyV3Result(String notifyData, Si } @Override - public WxScanPayNotifyResult parseScanPayNotifyResult(String xmlData, String signType) throws WxPayException { + public WxScanPayNotifyResult parseScanPayNotifyResult(String xmlData, @Deprecated String signType) throws WxPayException { try { log.debug("扫码支付回调通知请求参数:{}", xmlData); WxScanPayNotifyResult result = BaseWxPayResult.fromXML(xmlData, WxScanPayNotifyResult.class); + this.switchover(result.getMchId()); log.debug("扫码支付回调通知解析后的对象:{}", result); - result.checkResult(this, signType, false); + result.checkResult(this, this.getConfig().getSignType(), false); return result; } catch (WxPayException e) { throw e; @@ -480,8 +450,8 @@ public WxScanPayNotifyResult parseScanPayNotifyResult(String xmlData, String sig @Override public WxScanPayNotifyResult parseScanPayNotifyResult(String xmlData) throws WxPayException { - final String signType = this.getConfig().getSignType(); - return this.parseScanPayNotifyResult(xmlData, signType); +// final String signType = this.getConfig().getSignType(); + return this.parseScanPayNotifyResult(xmlData, null); } @Override @@ -1261,4 +1231,13 @@ public ComplaintService getComplaintsService() { return complaintsService; } + @Override + public BankService getBankService() { + return bankService; + } + + @Override + public TransferService getTransferService() { + return transferService; + } } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/ComplaintServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/ComplaintServiceImpl.java index d269a8f90..51d9609c4 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/ComplaintServiceImpl.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/ComplaintServiceImpl.java @@ -1,15 +1,20 @@ package com.github.binarywang.wxpay.service.impl; import com.github.binarywang.wxpay.bean.complaint.*; +import com.github.binarywang.wxpay.bean.media.ImageUploadResult; import com.github.binarywang.wxpay.exception.WxPayException; import com.github.binarywang.wxpay.service.ComplaintService; import com.github.binarywang.wxpay.service.WxPayService; +import com.github.binarywang.wxpay.v3.WechatPayUploadHttpPost; import com.github.binarywang.wxpay.v3.util.RsaCryptoUtil; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import lombok.RequiredArgsConstructor; +import org.apache.commons.codec.digest.DigestUtils; import javax.crypto.BadPaddingException; +import java.io.*; +import java.net.URI; import java.util.List; /** @@ -34,7 +39,7 @@ public ComplaintResult queryComplaints(ComplaintRequest request) throws WxPayExc List data = complaintResult.getData(); for (ComplaintDetailResult complaintDetailResult : data) { // 对手机号进行解密操作 - if(complaintDetailResult.getPayerPhone() != null) { + if (complaintDetailResult.getPayerPhone() != null) { String payerPhone = RsaCryptoUtil.decryptOAEP(complaintDetailResult.getPayerPhone(), this.payService.getConfig().getPrivateKey()); complaintDetailResult.setPayerPhone(payerPhone); } @@ -49,7 +54,7 @@ public ComplaintDetailResult getComplaint(ComplaintDetailRequest request) throws String response = this.payService.getV3(url); ComplaintDetailResult result = GSON.fromJson(response, ComplaintDetailResult.class); // 对手机号进行解密操作 - if(result.getPayerPhone() != null) { + if (result.getPayerPhone() != null) { String payerPhone = RsaCryptoUtil.decryptOAEP(result.getPayerPhone(), this.payService.getConfig().getPrivateKey()); result.setPayerPhone(payerPhone); } @@ -107,4 +112,41 @@ public void complete(CompleteRequest request) throws WxPayException { this.payService.postV3(url, GSON.toJson(request)); } + @Override + public ImageUploadResult uploadResponseImage(File imageFile) throws WxPayException, IOException { + String url = String.format("%s/v3/merchant-service/images/upload", this.payService.getPayBaseUrl()); + + try (FileInputStream s1 = new FileInputStream(imageFile)) { + String sha256 = DigestUtils.sha256Hex(s1); + try (InputStream s2 = new FileInputStream(imageFile)) { + WechatPayUploadHttpPost request = new WechatPayUploadHttpPost.Builder(URI.create(url)) + .withImage(imageFile.getName(), sha256, s2) + .build(); + String result = this.payService.postV3(url, request); + return ImageUploadResult.fromJson(result); + } + } + } + + @Override + public ImageUploadResult uploadResponseImage(InputStream inputStream, String fileName) throws WxPayException, IOException { + String url = String.format("%s/v3/merchant-service/images/upload", this.payService.getPayBaseUrl()); + try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) { + //文件大小不能超过2M + byte[] buffer = new byte[2048]; + int len; + while ((len = inputStream.read(buffer)) > -1) { + bos.write(buffer, 0, len); + } + bos.flush(); + byte[] data = bos.toByteArray(); + String sha256 = DigestUtils.sha256Hex(data); + WechatPayUploadHttpPost request = new WechatPayUploadHttpPost.Builder(URI.create(url)) + .withImage(fileName, sha256, new ByteArrayInputStream(data)) + .build(); + String result = this.payService.postV3(url, request); + return ImageUploadResult.fromJson(result); + } + } + } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/CustomDeclarationServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/CustomDeclarationServiceImpl.java new file mode 100644 index 000000000..d25ed7c0a --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/CustomDeclarationServiceImpl.java @@ -0,0 +1,110 @@ +package com.github.binarywang.wxpay.service.impl; + +import com.github.binarywang.wxpay.bean.customs.*; +import com.github.binarywang.wxpay.exception.WxPayException; +import com.github.binarywang.wxpay.service.CustomDeclarationService; +import com.github.binarywang.wxpay.service.WxPayService; +import com.github.binarywang.wxpay.v3.util.RsaCryptoUtil; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import lombok.RequiredArgsConstructor; +import me.chanjar.weixin.common.error.WxRuntimeException; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import java.nio.charset.StandardCharsets; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.X509Certificate; +import java.util.Base64; + +/** + *
+ * 支付报关 实现.
+ * Created by xifengzhu on 2022/05/05.
+ * 
+ * + * @author xifengzhu + */ +@RequiredArgsConstructor +public class CustomDeclarationServiceImpl implements CustomDeclarationService { + private static final Gson GSON = new GsonBuilder().create(); + private final WxPayService payService; + + @Override + public DeclarationResult declare(DeclarationRequest request) throws WxPayException { + String response = this.payService.postV3(DECLARATION_BASE_URL.concat("/orders"), GSON.toJson(request)); + return GSON.fromJson(response, DeclarationResult.class); + } + + @Override + public DeclarationQueryResult query(DeclarationQueryRequest request) throws WxPayException { + String url = String.format("%s/orders?appid=%s&mchid=%s&order_type=%s&order_no=%s&customs=%s&offset=%s&limit=%s", + DECLARATION_BASE_URL, + request.getAppid(), + request.getMchid(), + request.getOrderType(), + request.getOrderNo(), + request.getCustoms(), + request.getOffset(), + request.getLimit() + ); + String result = this.payService.getV3(url); + return GSON.fromJson(result, DeclarationQueryResult.class); + } + + @Override + public VerifyCertificateResult verifyCertificate(VerifyCertificateRequest request) throws WxPayException { + this.encryptFields(request); + String response = this.payService.postV3WithWechatpaySerial(DECLARATION_BASE_URL.concat("/verify-certificate"), GSON.toJson(request)); + return GSON.fromJson(response, VerifyCertificateResult.class); + } + + @Override + public DeclarationResult modify(DeclarationRequest request) throws WxPayException { + String response = this.payService.patchV3(DECLARATION_BASE_URL.concat("/orders"), GSON.toJson(request)); + return GSON.fromJson(response, DeclarationResult.class); + } + + @Override + public RedeclareResult redeclare(RedeclareRequest request) throws WxPayException { + String response = this.payService.postV3(DECLARATION_BASE_URL.concat("/redeclare"), GSON.toJson(request)); + return GSON.fromJson(response, RedeclareResult.class); + } + + private void encryptFields(VerifyCertificateRequest request) throws WxPayException { + try { + request.setCertificateId(encryptOAEP(request.getCertificateId())); + request.setCertificateName(encryptOAEP(request.getCertificateName())); + } catch (Exception e) { + throw new WxPayException("敏感信息加密失败", e); + } + } + + private X509Certificate getValidCertificate() { + return this.payService.getConfig().getVerifier().getValidCertificate(); + } + + private String encryptOAEP(String message) + throws IllegalBlockSizeException { + X509Certificate certificate = getValidCertificate(); + try { + // 身份信息校验 RSA 加密,填充方案使用 `RSAES-PKCS1-v1_5` + // https://pay.weixin.qq.com/wiki/doc/api/wxpay/ch/declarecustom_ch/chapter3_2.shtml + Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); + cipher.init(Cipher.ENCRYPT_MODE, certificate.getPublicKey()); + + byte[] data = message.getBytes(StandardCharsets.UTF_8); + byte[] ciphertext = cipher.doFinal(data); + return Base64.getEncoder().encodeToString(ciphertext); + } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { + throw new WxRuntimeException("当前Java环境不支持RSA v1.5/OAEP", e); + } catch (InvalidKeyException e) { + throw new IllegalArgumentException("无效的证书", e); + } catch (IllegalBlockSizeException | BadPaddingException e) { + throw new IllegalBlockSizeException("加密原串的长度不能超过214字节"); + } + } +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/EcommerceServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/EcommerceServiceImpl.java index 4f13618f3..27a34a9e2 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/EcommerceServiceImpl.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/EcommerceServiceImpl.java @@ -12,17 +12,23 @@ import com.google.common.base.CaseFormat; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import org.apache.commons.lang3.StringUtils; import lombok.RequiredArgsConstructor; -import org.apache.commons.beanutils.BeanMap; +import org.apache.commons.lang3.StringUtils; +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; import java.io.IOException; import java.io.InputStream; -import java.net.URI; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.nio.charset.StandardCharsets; import java.security.GeneralSecurityException; +import java.text.DateFormat; import java.util.Iterator; import java.util.Map; +import java.util.LinkedHashMap; import java.util.Objects; import java.util.Set; @@ -30,6 +36,11 @@ public class EcommerceServiceImpl implements EcommerceService { private static final Gson GSON = new GsonBuilder().create(); + + // https://stackoverflow.com/questions/6873020/gson-date-format + // gson default date format not match, so custom DateFormat + // detail DateFormat: FULL,LONG,SHORT,MEDIUM + private static final Gson GSON_CUSTOM = new GsonBuilder().setDateFormat(DateFormat.FULL, DateFormat.FULL).create(); private final WxPayService payService; @Override @@ -71,7 +82,7 @@ public T combineTransactions(TradeTypeEnum tradeType, CombineTransactionsReq @Override public CombineTransactionsNotifyResult parseCombineNotifyResult(String notifyData, SignatureHeader header) throws WxPayException { - if(Objects.nonNull(header) && !this.verifyNotifySign(header, notifyData)){ + if (Objects.nonNull(header) && !this.verifyNotifySign(header, notifyData)) { throw new WxPayException("非法请求,头部信息验证失败"); } NotifyResponse response = GSON.fromJson(notifyData, NotifyResponse.class); @@ -81,7 +92,7 @@ public CombineTransactionsNotifyResult parseCombineNotifyResult(String notifyDat String nonce = resource.getNonce(); String apiV3Key = this.payService.getConfig().getApiV3Key(); try { - String result = AesUtils.decryptToString(associatedData, nonce,cipherText, apiV3Key); + String result = AesUtils.decryptToString(associatedData, nonce, cipherText, apiV3Key); CombineTransactionsResult transactionsResult = GSON.fromJson(result, CombineTransactionsResult.class); CombineTransactionsNotifyResult notifyResult = new CombineTransactionsNotifyResult(); @@ -110,13 +121,14 @@ public TransactionsResult partner(TradeTypeEnum tradeType, PartnerTransactionsRe @Override public T partnerTransactions(TradeTypeEnum tradeType, PartnerTransactionsRequest request) throws WxPayException { TransactionsResult result = this.partner(tradeType, request); - return result.getPayInfo(tradeType, request.getSpAppid(), + String appId = request.getSubAppid() != null ? request.getSubAppid() : request.getSpAppid(); + return result.getPayInfo(tradeType, appId, request.getSpMchid(), payService.getConfig().getPrivateKey()); } @Override public PartnerTransactionsNotifyResult parsePartnerNotifyResult(String notifyData, SignatureHeader header) throws WxPayException { - if(Objects.nonNull(header) && !this.verifyNotifySign(header, notifyData)){ + if (Objects.nonNull(header) && !this.verifyNotifySign(header, notifyData)) { throw new WxPayException("非法请求,头部信息验证失败"); } NotifyResponse response = GSON.fromJson(notifyData, NotifyResponse.class); @@ -126,7 +138,7 @@ public PartnerTransactionsNotifyResult parsePartnerNotifyResult(String notifyDat String nonce = resource.getNonce(); String apiV3Key = this.payService.getConfig().getApiV3Key(); try { - String result = AesUtils.decryptToString(associatedData, nonce,cipherText, apiV3Key); + String result = AesUtils.decryptToString(associatedData, nonce, cipherText, apiV3Key); PartnerTransactionsResult transactionsResult = GSON.fromJson(result, PartnerTransactionsResult.class); PartnerTransactionsNotifyResult notifyResult = new PartnerTransactionsNotifyResult(); @@ -199,6 +211,14 @@ public ProfitSharingResult queryProfitSharing(ProfitSharingQueryRequest request) return GSON.fromJson(response, ProfitSharingResult.class); } + @Override + public ProfitSharingOrdersUnSplitAmountResult queryProfitSharingOrdersUnsplitAmount(ProfitSharingOrdersUnSplitAmountRequest request) throws WxPayException { + String url = String.format("%s/v3/ecommerce/profitsharing/orders/%s/amounts", + this.payService.getPayBaseUrl(), request.getTransactionId()); + String response = this.payService.getV3(url); + return GSON.fromJson(response, ProfitSharingOrdersUnSplitAmountResult.class); + } + @Override public ProfitSharingReceiverResult addReceivers(ProfitSharingReceiverRequest request) throws WxPayException { String url = String.format("%s/v3/ecommerce/profitsharing/receivers/add", this.payService.getPayBaseUrl()); @@ -268,7 +288,7 @@ public RefundQueryResult queryRefundByOutRefundNo(String subMchid, String outRef @Override public RefundNotifyResult parseRefundNotifyResult(String notifyData, SignatureHeader header) throws WxPayException { - if(Objects.nonNull(header) && !this.verifyNotifySign(header, notifyData)){ + if (Objects.nonNull(header) && !this.verifyNotifySign(header, notifyData)) { throw new WxPayException("非法请求,头部信息验证失败"); } NotifyResponse response = GSON.fromJson(notifyData, NotifyResponse.class); @@ -278,7 +298,7 @@ public RefundNotifyResult parseRefundNotifyResult(String notifyData, SignatureHe String nonce = resource.getNonce(); String apiV3Key = this.payService.getConfig().getApiV3Key(); try { - String result = AesUtils.decryptToString(associatedData, nonce,cipherText, apiV3Key); + String result = AesUtils.decryptToString(associatedData, nonce, cipherText, apiV3Key); RefundNotifyResult notifyResult = GSON.fromJson(result, RefundNotifyResult.class); notifyResult.setRawData(response); return notifyResult; @@ -350,8 +370,9 @@ public InputStream downloadBill(String url) throws WxPayException { /** * 校验通知签名 + * * @param header 通知头信息 - * @param data 通知数据 + * @param data 通知数据 * @return true:校验通过 false:校验不通过 */ private boolean verifyNotifySign(SignatureHeader header, String data) { @@ -365,17 +386,18 @@ private boolean verifyNotifySign(SignatureHeader header, String data) { /** * 对象拼接到url + * * @param o 转换对象 - * @return 拼接好的string + * @return 拼接好的string */ private String parseURLPair(Object o) { - Map map = new BeanMap(o); + Map map = getObjectToMap(o); Set> set = map.entrySet(); Iterator> it = set.iterator(); StringBuilder sb = new StringBuilder(); while (it.hasNext()) { Map.Entry e = it.next(); - if ( !"class".equals(e.getKey()) && e.getValue() != null) { + if (!"class".equals(e.getKey()) && e.getValue() != null) { sb.append(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, String.valueOf(e.getKey()))) .append("=").append(e.getValue()).append("&"); } @@ -383,5 +405,27 @@ private String parseURLPair(Object o) { return sb.deleteCharAt(sb.length() - 1).toString(); } - + public static Map getObjectToMap(Object obj) { + try { + Map result = new LinkedHashMap<>(); + final Class beanClass = obj.getClass(); + final BeanInfo beanInfo = Introspector.getBeanInfo(beanClass); + final PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); + if (propertyDescriptors != null) { + for (final PropertyDescriptor propertyDescriptor : propertyDescriptors) { + if (propertyDescriptor != null) { + final String name = propertyDescriptor.getName(); + final Method readMethod = propertyDescriptor.getReadMethod(); + if (readMethod != null) { + result.put(name, readMethod.invoke(obj)); + } + } + } + } + return result; + } catch (IllegalAccessException | IntrospectionException | InvocationTargetException ignored) { + return null; + } } + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/MerchantTransferServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/MerchantTransferServiceImpl.java new file mode 100644 index 000000000..0a6317e3a --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/MerchantTransferServiceImpl.java @@ -0,0 +1,118 @@ +package com.github.binarywang.wxpay.service.impl; + +import com.github.binarywang.wxpay.bean.merchanttransfer.*; +import com.github.binarywang.wxpay.exception.WxPayException; +import com.github.binarywang.wxpay.service.MerchantTransferService; +import com.github.binarywang.wxpay.service.WxPayService; +import com.github.binarywang.wxpay.v3.util.RsaCryptoUtil; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @author glz + * @date 2022/6/11 + */ +@Slf4j +@RequiredArgsConstructor +public class MerchantTransferServiceImpl implements MerchantTransferService { + private static final Gson GSON = (new GsonBuilder()).create(); + + private final WxPayService wxPayService; + + + @Override + public TransferCreateResult createTransfer(TransferCreateRequest request) throws WxPayException { + request.setAppid(this.wxPayService.getConfig().getAppId()); + String url = String.format("%s/v3/transfer/batches", this.wxPayService.getPayBaseUrl()); + RsaCryptoUtil.encryptFields(request, this.wxPayService.getConfig().getVerifier().getValidCertificate()); + + String response = wxPayService.postV3WithWechatpaySerial(url,GSON.toJson(request)); + return GSON.fromJson(response, TransferCreateResult.class); + } + + @Override + public BatchesQueryResult queryWxBatches(WxBatchesQueryRequest request) throws WxPayException { + String url = String.format("%s/v3/transfer/batches/batch-id/%s?need_query_detail=%b", this.wxPayService.getPayBaseUrl(), request.getBatchId(), request.getNeedQueryDetail()); + + if(request.getOffset()!=null){ + url = String.format("%s&offset=%d",url,request.getOffset()); + } + if(request.getLimit()!=null){ + url = String.format("%s&limit=%d",url,request.getLimit()); + } + if(request.getDetailStatus()!=null && request.getDetailStatus().length()!=0){ + url = String.format("%s&detail_status=%s",url,request.getDetailStatus()); + } + + String response = wxPayService.getV3(url); + return GSON.fromJson(response, BatchesQueryResult.class); + } + + @Override + public DetailsQueryResult queryWxDetails(WxDetailsQueryRequest request) throws WxPayException { + String url = String.format("%s/v3/transfer/batches/batch-id/%s/details/detail-id/%s",this.wxPayService.getPayBaseUrl(),request.getBatchId(),request.getDetailId()); + String response = wxPayService.getV3(url); + return GSON.fromJson(response, DetailsQueryResult.class); + } + + @Override + public BatchesQueryResult queryMerchantBatches(MerchantBatchesQueryRequest request) throws WxPayException { + String url = String.format("%s/v3/transfer/batches/out-batch-no/%s?need_query_detail=%b", this.wxPayService.getPayBaseUrl(), request.getOutBatchNo(),request.getNeedQueryDetail()); + + if(request.getOffset()!=null){ + url = String.format("%s&offset=%d",url,request.getOffset()); + } + if(request.getLimit()!=null){ + url = String.format("%s&limit=%d",url,request.getLimit()); + } + if(request.getDetailStatus()!=null && request.getDetailStatus().length()!=0){ + url = String.format("%s&detail_status=%s",url,request.getDetailStatus()); + } + + String response = wxPayService.getV3(url); + return GSON.fromJson(response, BatchesQueryResult.class); + } + + @Override + public DetailsQueryResult queryMerchantDetails(MerchantDetailsQueryRequest request) throws WxPayException { + String url = String.format("%s/v3/transfer/batches/out-batch-no/%s/details/out-detail-no/%s",this.wxPayService.getPayBaseUrl(),request.getOutBatchNo(),request.getOutDetailNo()); + String response = wxPayService.getV3(url); + return GSON.fromJson(response, DetailsQueryResult.class); + } + + @Override + public ElectronicBillResult applyElectronicBill(ElectronicBillApplyRequest request) throws WxPayException { + String url = String.format("%s/v3/transfer/bill-receipt",this.wxPayService.getPayBaseUrl()); + String response = wxPayService.postV3(url,GSON.toJson(request)); + return GSON.fromJson(response, ElectronicBillResult.class); + } + + @Override + public ElectronicBillResult queryElectronicBill(String outBatchNo) throws WxPayException { + String url = String.format("%s/v3/transfer/bill-receipt/%s",this.wxPayService.getPayBaseUrl(),outBatchNo); + String response = wxPayService.getV3(url); + return GSON.fromJson(response, ElectronicBillResult.class); + } + + @Override + public DetailElectronicBillResult applyDetailElectronicBill(DetailElectronicBillRequest request) throws WxPayException { + String url = String.format("%s/v3/transfer-detail/electronic-receipts",this.wxPayService.getPayBaseUrl()); + String response = wxPayService.postV3(url,GSON.toJson(request)); + return GSON.fromJson(response, DetailElectronicBillResult.class); + } + + @Override + public DetailElectronicBillResult queryDetailElectronicBill(DetailElectronicBillRequest request) throws WxPayException { + String url = String.format("%s/v3/transfer-detail/electronic-receipts?accept_type=%s&out_detail_no=%s", this.wxPayService.getPayBaseUrl(), request.getAcceptType(),request.getOutDetailNo()); + + if(request.getOutBatchNo()!=null && request.getOutBatchNo().length()!=0){ + url = String.format("%s&out_batch_no=%s",url,request.getOutBatchNo()); + } + + String response = wxPayService.getV3(url); + return GSON.fromJson(response, DetailElectronicBillResult.class); + } + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/PartnerPayScoreServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/PartnerPayScoreServiceImpl.java new file mode 100644 index 000000000..48ea1b2f6 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/PartnerPayScoreServiceImpl.java @@ -0,0 +1,341 @@ +package com.github.binarywang.wxpay.service.impl; + +import com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader; +import com.github.binarywang.wxpay.bean.payscore.PayScoreNotifyData; +import com.github.binarywang.wxpay.bean.payscore.UserAuthorizationStatusNotifyResult; +import com.github.binarywang.wxpay.bean.payscore.WxPartnerPayScoreRequest; +import com.github.binarywang.wxpay.bean.payscore.WxPartnerPayScoreResult; +import com.github.binarywang.wxpay.config.WxPayConfig; +import com.github.binarywang.wxpay.exception.WxPayException; +import com.github.binarywang.wxpay.service.PartnerPayScoreService; +import com.github.binarywang.wxpay.service.WxPayService; +import com.github.binarywang.wxpay.v3.util.AesUtils; +import com.google.common.collect.Maps; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import lombok.RequiredArgsConstructor; +import me.chanjar.weixin.common.util.json.WxGsonBuilder; +import org.apache.commons.lang3.StringUtils; +import org.apache.http.client.utils.URIBuilder; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; +import java.security.GeneralSecurityException; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * @author hallkk + * @date 2022/05/18 + */ +@RequiredArgsConstructor +public class PartnerPayScoreServiceImpl implements PartnerPayScoreService { + private static final Gson GSON = new GsonBuilder().create(); + private final WxPayService payService; + + @Override + public WxPartnerPayScoreResult permissions(WxPartnerPayScoreRequest request) throws WxPayException { + String url = this.payService.getPayBaseUrl() + "/v3/payscore/partner/permissions"; + request.setAppid(request.getAppid()); + request.setServiceId(request.getServiceId()); + WxPayConfig config = this.payService.getConfig(); + String permissionNotifyUrl = config.getPayScorePermissionNotifyUrl(); + if (StringUtils.isBlank(permissionNotifyUrl)) { + throw new WxPayException("授权回调地址未配置"); + } + String authorizationCode = request.getAuthorizationCode(); + if (StringUtils.isBlank(authorizationCode)) { + throw new WxPayException("authorizationCode不允许为空"); + } + request.setNotifyUrl(permissionNotifyUrl); + String result = this.payService.postV3(url, request.toJson()); + return WxPartnerPayScoreResult.fromJson(result); + } + + @Override + public WxPartnerPayScoreResult permissionsQueryByAuthorizationCode(String serviceId, String subMchid, String authorizationCode) + throws WxPayException { + if (StringUtils.isBlank(authorizationCode)) { + throw new WxPayException("authorizationCode不允许为空"); + } + String url = String.format("%s/v3/payscore/partner/permissions/authorization-code/%s", this.payService.getPayBaseUrl(), authorizationCode); + URIBuilder uriBuilder; + try { + uriBuilder = new URIBuilder(url); + } catch (URISyntaxException e) { + throw new WxPayException("未知异常!", e); + } + + uriBuilder.setParameter("service_id", serviceId); + uriBuilder.setParameter("sub_mchid", subMchid); + try { + String result = payService.getV3(uriBuilder.build().toString()); + return WxPartnerPayScoreResult.fromJson(result); + } catch (URISyntaxException e) { + throw new WxPayException("未知异常!", e); + } + } + + @Override + public WxPartnerPayScoreResult permissionsTerminateByAuthorizationCode(String serviceId, String subMchid, + String authorizationCode, String reason) throws WxPayException { + if (StringUtils.isBlank(authorizationCode)) { + throw new WxPayException("authorizationCode不允许为空"); + } + String url = String.format( + "%s/v3/payscore/partner/permissions/authorization-code/%s/terminate", + this.payService.getPayBaseUrl(), + authorizationCode + ); + Map map = new HashMap<>(4); + map.put("service_id", serviceId); + map.put("sub_mchid", subMchid); + map.put("reason", reason); + String result = payService.postV3(url, WxGsonBuilder.create().toJson(map)); + return WxPartnerPayScoreResult.fromJson(result); + } + + @Override + public WxPartnerPayScoreResult permissionsQueryByOpenId(String serviceId, String appId, String subMchid, + String subAppid, String openId, String subOpenid) throws WxPayException { + if (StringUtils.isAllEmpty(openId, subOpenid) || !StringUtils.isAnyEmpty(openId, subOpenid)) { + throw new WxPayException("open_id,sub_openid不允许都填写或都不填写"); + } + if (StringUtils.isBlank(subMchid)) { + throw new WxPayException("sub_mchid不允许都为空"); + } + String url = String.format("%s/v3/payscore/partner/permissions/openid/%s", this.payService.getPayBaseUrl(), openId); + URIBuilder uriBuilder; + try { + uriBuilder = new URIBuilder(url); + } catch (URISyntaxException e) { + throw new WxPayException("未知异常!", e); + } + + uriBuilder.setParameter("appid", appId); + uriBuilder.setParameter("service_id", serviceId); + uriBuilder.setParameter("sub_mchid", subMchid); + uriBuilder.setParameter("sub_appid", subAppid); + uriBuilder.setParameter("openid", openId); + uriBuilder.setParameter("sub_openid", subOpenid); + + if (StringUtils.isNotEmpty(openId)) { + uriBuilder.setParameter("openid", openId); + } + if (StringUtils.isNotEmpty(subOpenid)) { + uriBuilder.setParameter("sub_openid", subOpenid); + } + + try { + String result = payService.getV3(uriBuilder.build().toString()); + return WxPartnerPayScoreResult.fromJson(result); + } catch (URISyntaxException e) { + throw new WxPayException("未知异常!", e); + } + } + + @Override + public WxPartnerPayScoreResult permissionsTerminateByOpenId(String serviceId, String appId, String subMchid, String subAppid, String openId, String subOpenid, String reason) throws WxPayException { + if (StringUtils.isAllEmpty(openId, subOpenid) || !StringUtils.isAnyEmpty(openId, subOpenid)) { + throw new WxPayException("open_id,sub_openid不允许都填写或都不填写"); + } + String url = String.format("%s/v3/payscore/partner/permissions/openid/%s/terminate", this.payService.getPayBaseUrl(), openId); + Map map = new HashMap<>(4); + map.put("appid", appId); + map.put("sub_appid", subAppid); + map.put("service_id", serviceId); + if (StringUtils.isNotEmpty(openId)) { + map.put("openid", openId); + } + if (StringUtils.isNotEmpty(subOpenid)) { + map.put("sub_openid", subOpenid); + } + map.put("sub_mchid", subMchid); + map.put("reason", reason); + String result = payService.postV3(url, WxGsonBuilder.create().toJson(map)); + return WxPartnerPayScoreResult.fromJson(result); + } + + @Override + public WxPartnerPayScoreResult createServiceOrder(WxPartnerPayScoreRequest request) throws WxPayException { + String url = this.payService.getPayBaseUrl() + "/v3/payscore/partner/serviceorder"; + + WxPayConfig config = this.payService.getConfig(); + request.setNotifyUrl(config.getPayScoreNotifyUrl()); + String result = this.payService.postV3(url, request.toJson()); + + return WxPartnerPayScoreResult.fromJson(result); + } + + @Override + public WxPartnerPayScoreResult queryServiceOrder(String serviceId, String subMchid, String outOrderNo, + String queryId) throws WxPayException { + String url = this.payService.getPayBaseUrl() + "/v3/payscore/partner/serviceorder"; + + URIBuilder uriBuilder; + try { + uriBuilder = new URIBuilder(url); + } catch (URISyntaxException e) { + throw new WxPayException("未知异常!", e); + } + uriBuilder.setParameter("service_id", serviceId); + uriBuilder.setParameter("sub_mchid", subMchid); + if (StringUtils.isAllEmpty(outOrderNo, queryId) || !StringUtils.isAnyEmpty(outOrderNo, queryId)) { + throw new WxPayException("out_order_no,query_id不允许都填写或都不填写"); + } + if (StringUtils.isNotEmpty(outOrderNo)) { + uriBuilder.setParameter("out_order_no", outOrderNo); + } + if (StringUtils.isNotEmpty(queryId)) { + uriBuilder.setParameter("query_id", queryId); + } + + try { + String result = payService.getV3(uriBuilder.build().toString()); + return WxPartnerPayScoreResult.fromJson(result); + } catch (URISyntaxException e) { + throw new WxPayException("未知异常!", e); + } + } + + @Override + public WxPartnerPayScoreResult cancelServiceOrder(String serviceId, String appId, String subMchid, String outOrderNo, String reason) throws WxPayException { + String url = String.format("%s/v3/payscore/partner/serviceorder/%s/cancel", this.payService.getPayBaseUrl(), outOrderNo); + Map map = new HashMap<>(4); + map.put("appid", appId); + map.put("service_id", serviceId); + map.put("sub_mchid", subMchid); + map.put("reason", reason); + if (StringUtils.isAnyEmpty(appId, serviceId, subMchid, reason)) { + throw new WxPayException("appid, service_id, sub_mchid, reason都不能为空"); + } + String result = payService.postV3(url, WxGsonBuilder.create().toJson(map)); + return WxPartnerPayScoreResult.fromJson(result); + } + + @Override + public WxPartnerPayScoreResult modifyServiceOrder(WxPartnerPayScoreRequest request) throws WxPayException { + String outOrderNo = request.getOutOrderNo(); + String url = String.format("%s/v3/payscore/partner/serviceorder/%s/modify", this.payService.getPayBaseUrl(), outOrderNo); + request.setAppid(this.payService.getConfig().getAppId()); + request.setOutOrderNo(null); + String result = payService.postV3(url, request.toJson()); + return WxPartnerPayScoreResult.fromJson(result); + } + + @Override + public void completeServiceOrder(WxPartnerPayScoreRequest request) throws WxPayException { + String outOrderNo = request.getOutOrderNo(); + String url = String.format("%s/v3/payscore/partner/serviceorder/%s/complete", this.payService.getPayBaseUrl(), outOrderNo); + request.setAppid(request.getAppid()); + request.setServiceId(request.getServiceId()); + request.setOutOrderNo(null); + request.setSubMchid(request.getSubMchid()); + this.payService.postV3(url, request.toJson()); + } + + @Override + public WxPartnerPayScoreResult payServiceOrder(String serviceId, String appId, String subMchid, String outOrderNo) throws WxPayException { + String url = String.format("%s/v3/payscore/partner/serviceorder/%s/pay", this.payService.getPayBaseUrl(), outOrderNo); + Map map = new HashMap<>(3); + map.put("appid", appId); + map.put("service_id", serviceId); + map.put("sub_mchid", subMchid); + if (StringUtils.isAnyEmpty(appId, serviceId, subMchid)) { + throw new WxPayException("appid, service_id, sub_mchid都不能为空"); + } + String result = payService.postV3(url, WxGsonBuilder.create().toJson(map)); + return WxPartnerPayScoreResult.fromJson(result); + } + + @Override + public WxPartnerPayScoreResult syncServiceOrder(WxPartnerPayScoreRequest request) throws WxPayException { + String outOrderNo = request.getOutOrderNo(); + String url = String.format("%s/v3/payscore/partner/serviceorder/%s/sync", this.payService.getPayBaseUrl(), outOrderNo); + request.setAppid(this.payService.getConfig().getAppId()); + request.setOutOrderNo(null); + String result = payService.postV3(url, request.toJson()); + return WxPartnerPayScoreResult.fromJson(result); + } + + @Override + public WxPartnerPayScoreResult applyServiceAccount(WxPartnerPayScoreRequest request) throws WxPayException { + String url = String.format("%s/v3/payscore/partner/service-account-applications", this.payService.getPayBaseUrl()); + Map params = Maps.newHashMap(); + params.put("service_id", request.getServiceId()); + params.put("appid", request.getAppid()); + params.put("sub_mchid", request.getSubMchid()); + params.put("sub_appid", request.getSubAppid()); + params.put("out_apply_no", request.getOutApplyNo()); + params.put("result_notify_url", request.getResultNotifyUrl()); + + String result = payService.postV3(url, WxGsonBuilder.create().toJson(params)); + return WxPartnerPayScoreResult.fromJson(result); + + } + + @Override + public WxPartnerPayScoreResult queryServiceAccountState(String outApplyNo) throws WxPayException { + String url = String.format("%s/v3/payscore/partner/service-account-applications/%s", this.payService.getPayBaseUrl(), outApplyNo); + String result = payService.getV3(url); + return WxPartnerPayScoreResult.fromJson(result); + } + + @Override + public UserAuthorizationStatusNotifyResult parseUserAuthorizationStatusNotifyResult(String notifyData, SignatureHeader header) throws WxPayException { + PayScoreNotifyData response = parseNotifyData(notifyData, header); + PayScoreNotifyData.Resource resource = response.getResource(); + String cipherText = resource.getCipherText(); + String associatedData = resource.getAssociatedData(); + String nonce = resource.getNonce(); + String apiV3Key = this.payService.getConfig().getApiV3Key(); + try { + String result = AesUtils.decryptToString(associatedData, nonce, cipherText, apiV3Key); + UserAuthorizationStatusNotifyResult notifyResult = GSON.fromJson(result, UserAuthorizationStatusNotifyResult.class); + notifyResult.setRawData(response); + return notifyResult; + } catch (GeneralSecurityException | IOException e) { + throw new WxPayException("解析报文异常!", e); + } + } + + @Override + public PayScoreNotifyData parseNotifyData(String data, SignatureHeader header) throws WxPayException { + if (Objects.nonNull(header) && !this.verifyNotifySign(header, data)) { + throw new WxPayException("非法请求,头部信息验证失败"); + } + return GSON.fromJson(data, PayScoreNotifyData.class); + } + + @Override + public WxPartnerPayScoreResult decryptNotifyDataResource(PayScoreNotifyData data) throws WxPayException { + PayScoreNotifyData.Resource resource = data.getResource(); + String cipherText = resource.getCipherText(); + String associatedData = resource.getAssociatedData(); + String nonce = resource.getNonce(); + String apiV3Key = this.payService.getConfig().getApiV3Key(); + try { + return WxPartnerPayScoreResult.fromJson(AesUtils.decryptToString(associatedData, nonce, cipherText, apiV3Key)); + } catch (GeneralSecurityException | IOException e) { + throw new WxPayException("解析报文异常!", e); + } + } + + /** + * 校验通知签名 + * + * @param header 通知头信息 + * @param data 通知数据 + * @return true:校验通过 false:校验不通过 + */ + private boolean verifyNotifySign(SignatureHeader header, String data) { + String beforeSign = String.format("%s\n%s\n%s\n", header.getTimeStamp(), header.getNonce(), data); + return this.payService.getConfig().getVerifier().verify( + header.getSerialNo(), + beforeSign.getBytes(StandardCharsets.UTF_8), + header.getSigned() + ); + } +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/PartnerTransferServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/PartnerTransferServiceImpl.java index 1a8a28f84..8e2a372a5 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/PartnerTransferServiceImpl.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/PartnerTransferServiceImpl.java @@ -78,7 +78,7 @@ public BatchNumberResult queryBatchByBatchId(BatchNumberRequest request) throws if (request.getLimit() == null || request.getLimit() <= 0) { request.setLimit(20); } - String query = String.format("?need_query_detail=true&detail_status=ALL&offset=%s&limit=%s", request.getNeedQueryDetail(), request.getOffset(), request.getLimit()); + String query = String.format("?need_query_detail=%s&detail_status=ALL&offset=%s&limit=%s", request.getNeedQueryDetail(), request.getOffset(), request.getLimit()); if (StringUtil.isNotBlank(request.getDetailStatus())){ query += "&detail_status="+request.getDetailStatus(); } @@ -107,7 +107,7 @@ public BatchNumberResult queryBatchByOutBatchNo(MerchantBatchRequest request) th if (request.getLimit() == null || request.getLimit() <= 0) { request.setLimit(20); } - String query = String.format("?need_query_detail=true&offset=%s&limit=%s", request.getNeedQueryDetail(), request.getOffset(), request.getLimit()); + String query = String.format("?need_query_detail=%s&offset=%s&limit=%s", request.getNeedQueryDetail(), request.getOffset(), request.getLimit()); if (StringUtil.isNotBlank(request.getDetailStatus())){ query += "&detail_status="+request.getDetailStatus(); } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/ProfitSharingV3ServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/ProfitSharingV3ServiceImpl.java index 539836de1..92d724177 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/ProfitSharingV3ServiceImpl.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/ProfitSharingV3ServiceImpl.java @@ -1,15 +1,24 @@ package com.github.binarywang.wxpay.service.impl; +import com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader; import com.github.binarywang.wxpay.bean.profitsharingV3.*; +import com.github.binarywang.wxpay.config.WxPayConfig; import com.github.binarywang.wxpay.exception.WxPayException; import com.github.binarywang.wxpay.service.ProfitSharingV3Service; import com.github.binarywang.wxpay.service.WxPayService; +import com.github.binarywang.wxpay.v3.auth.Verifier; +import com.github.binarywang.wxpay.v3.util.AesUtils; import com.github.binarywang.wxpay.v3.util.RsaCryptoUtil; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.security.GeneralSecurityException; +import java.util.Objects; + /** * 微信支付V3-资金应用-分账Service * @@ -82,4 +91,48 @@ public ProfitSharingReceiver deleteProfitSharingReceiver(ProfitSharingReceiver r String result = this.payService.postV3WithWechatpaySerial(url, GSON.toJson(request)); return GSON.fromJson(result, ProfitSharingReceiver.class); } + + @Override + public ProfitSharingNotifyData getProfitSharingNotifyData(String notifyData, SignatureHeader header) throws WxPayException { + ProfitSharingNotifyData response = parseNotifyData(notifyData, header); + ProfitSharingNotifyData.Resource resource = response.getResource(); + String cipherText = resource.getCipherText(); + String associatedData = resource.getAssociatedData(); + String nonce = resource.getNonce(); + String apiV3Key = this.payService.getConfig().getApiV3Key(); + try { + String result = AesUtils.decryptToString(associatedData, nonce, cipherText, apiV3Key); + ProfitSharingNotifyData notifyResult = GSON.fromJson(result, ProfitSharingNotifyData.class); + return notifyResult; + } catch (GeneralSecurityException | IOException e) { + throw new WxPayException("解析报文异常!", e); + } + } + + private ProfitSharingNotifyData parseNotifyData(String data, SignatureHeader header) throws WxPayException { + if (Objects.nonNull(header) && !this.verifyNotifySign(header, data)) { + throw new WxPayException("非法请求,头部信息验证失败"); + } + return GSON.fromJson(data, ProfitSharingNotifyData.class); + } + + /** + * 校验通知签名 + * + * @param header 通知头信息 + * @param data 通知数据 + * @return true:校验通过 false:校验不通过 + */ + private boolean verifyNotifySign(SignatureHeader header, String data) throws WxPayException { + String beforeSign = String.format("%s\n%s\n%s\n", + header.getTimeStamp(), + header.getNonce(), + data); + Verifier verifier = this.payService.getConfig().getVerifier(); + if (verifier == null) { + throw new WxPayException("证书检验对象为空"); + } + return verifier.verify(header.getSerialNo(), + beforeSign.getBytes(StandardCharsets.UTF_8), header.getSigned()); + } } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/TransferServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/TransferServiceImpl.java new file mode 100644 index 000000000..82882b42f --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/TransferServiceImpl.java @@ -0,0 +1,68 @@ +package com.github.binarywang.wxpay.service.impl; + +import com.github.binarywang.wxpay.bean.transfer.*; +import com.github.binarywang.wxpay.exception.WxPayException; +import com.github.binarywang.wxpay.service.TransferService; +import com.github.binarywang.wxpay.service.WxPayService; +import com.github.binarywang.wxpay.v3.util.RsaCryptoUtil; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import lombok.RequiredArgsConstructor; + +import java.security.cert.X509Certificate; +import java.util.List; + +/** + * 商家转账到零钱 + * + * @author zhongjun + * @date 2022/6/17 + **/ +@RequiredArgsConstructor +public class TransferServiceImpl implements TransferService { + + private static final Gson GSON = new GsonBuilder().create(); + private final WxPayService payService; + + @Override + public TransferBatchesResult transferBatches(TransferBatchesRequest request) throws WxPayException { + String url = String.format("%s/v3/transfer/batches", this.payService.getPayBaseUrl()); + List transferDetailList = request.getTransferDetailList(); + X509Certificate validCertificate = this.payService.getConfig().getVerifier().getValidCertificate(); + for (TransferBatchesRequest.TransferDetail detail : transferDetailList) { + RsaCryptoUtil.encryptFields(detail, validCertificate); + } + String result = this.payService.postV3WithWechatpaySerial(url, GSON.toJson(request)); + return GSON.fromJson(result, TransferBatchesResult.class); + } + + @Override + public QueryTransferBatchesResult transferBatchesBatchId(QueryTransferBatchesRequest request) throws WxPayException { + String url = String.format("%s/v3/transfer/batches/batch-id/%s?need_query_detail=%s&offset=%s&limit=%s&detail_status=%s", + this.payService.getPayBaseUrl(), request.getBatchId(), request.getNeedQueryDetail(), request.getOffset(), request.getLimit(), request.getDetailStatus()); + String result = this.payService.getV3(url); + return GSON.fromJson(result, QueryTransferBatchesResult.class); + } + + @Override + public TransferBatchDetailResult transferBatchesBatchIdDetail(String batchId, String detailId) throws WxPayException { + String url = String.format("%s/v3/transfer/batches/batch-id/%s/details/detail-id/%s", this.payService.getPayBaseUrl(), batchId, detailId); + String result = this.payService.getV3(url); + return GSON.fromJson(result, TransferBatchDetailResult.class); + } + + @Override + public QueryTransferBatchesResult transferBatchesOutBatchNo(QueryTransferBatchesRequest request) throws WxPayException { + String url = String.format("%s/v3/transfer/batches/out-batch-no/%s?need_query_detail=%s&offset=%s&limit=%s&detail_status=%s", + this.payService.getPayBaseUrl(), request.getOutBatchNo(), request.getNeedQueryDetail(), request.getOffset(), request.getLimit(), request.getDetailStatus()); + String result = this.payService.getV3(url); + return GSON.fromJson(result, QueryTransferBatchesResult.class); + } + + @Override + public TransferBatchDetailResult transferBatchesOutBatchNoDetail(String outBatchNo, String outDetailNo) throws WxPayException { + String url = String.format("%s/v3/transfer/batches/out-batch-no/%s/details/out-detail-no/%s", this.payService.getPayBaseUrl(), outBatchNo, outDetailNo); + String result = this.payService.getV3(url); + return GSON.fromJson(result, TransferBatchDetailResult.class); + } +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxEntrustPapServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxEntrustPapServiceImpl.java index 7555425a8..7a2c0f450 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxEntrustPapServiceImpl.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxEntrustPapServiceImpl.java @@ -48,6 +48,8 @@ public String maSign(WxMaEntrustRequest wxMaEntrustRequest) throws WxPayExceptio @Override public WxH5EntrustResult h5Sign(WxH5EntrustRequest wxH5EntrustRequest) throws WxPayException { wxH5EntrustRequest.checkAndSign(payService.getConfig()); + // 微信最新接口signType不能参与签名,否则报错:签约参数签名校验错误 + wxH5EntrustRequest.setSignType(null); String sign = SignUtils.createSign(wxH5EntrustRequest, WxPayConstants.SignType.HMAC_SHA256, payService.getConfig().getMchKey(), null); /** diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceApacheHttpImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceApacheHttpImpl.java index e70813fc3..47f78c88e 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceApacheHttpImpl.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceApacheHttpImpl.java @@ -241,7 +241,17 @@ public String getV3(String url) throws WxPayException { HttpGet httpGet = new HttpGet(url); httpGet.addHeader("Accept", "application/json"); httpGet.addHeader("Content-Type", "application/json"); - return this.requestV3(url.toString(), httpGet); + return this.requestV3(url, httpGet); + } + + @Override + public String getV3WithWechatPaySerial(String url) throws WxPayException { + HttpGet httpGet = new HttpGet(url); + httpGet.addHeader("Accept", "application/json"); + httpGet.addHeader("Content-Type", "application/json"); + String serialNumber = getConfig().getVerifier().getValidCertificate().getSerialNumber().toString(16).toUpperCase(); + httpGet.addHeader("Wechatpay-Serial", serialNumber); + return this.requestV3(url, httpGet); } @Override diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceJoddHttpImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceJoddHttpImpl.java index 29521d493..5e6d23eac 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceJoddHttpImpl.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceJoddHttpImpl.java @@ -91,6 +91,11 @@ public String getV3(String url) throws WxPayException { return null; } + @Override + public String getV3WithWechatPaySerial(String url) throws WxPayException { + return null; + } + @Override public InputStream downloadV3(String url) throws WxPayException { return null; diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/v3/auth/AutoUpdateCertificatesVerifier.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/v3/auth/AutoUpdateCertificatesVerifier.java index ca8b30bc8..f5219e500 100755 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/v3/auth/AutoUpdateCertificatesVerifier.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/v3/auth/AutoUpdateCertificatesVerifier.java @@ -123,7 +123,7 @@ public boolean verify(String serialNumber, byte[] message, String signature) { * 检查证书是否在有效期内,如果不在有效期内则进行更新 */ private void checkAndAutoUpdateCert() { - if (instant == null || instant.plus(minutesInterval, ChronoUnit.MINUTES).compareTo(Instant.now()) >= 0) { + if (instant == null || instant.plus(minutesInterval, ChronoUnit.MINUTES).compareTo(Instant.now()) <= 0) { if (lock.tryLock()) { try { autoUpdateCert(); diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/v3/util/AesUtils.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/v3/util/AesUtils.java index 2c8c40252..b4a97ba88 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/v3/util/AesUtils.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/v3/util/AesUtils.java @@ -1,7 +1,5 @@ package com.github.binarywang.wxpay.v3.util; -import com.google.common.base.CharMatcher; -import com.google.common.io.BaseEncoding; import org.apache.commons.lang3.StringUtils; import javax.crypto.Cipher; @@ -10,6 +8,7 @@ import javax.crypto.spec.GCMParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.security.GeneralSecurityException; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; @@ -58,7 +57,7 @@ public static byte[] decryptToByte(byte[] associatedData, byte[] nonce, byte[] c } public String decryptToString(byte[] associatedData, byte[] nonce, String ciphertext) - throws GeneralSecurityException, IOException { + throws GeneralSecurityException, IOException { try { Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); @@ -68,7 +67,7 @@ public String decryptToString(byte[] associatedData, byte[] nonce, String cipher cipher.init(Cipher.DECRYPT_MODE, key, spec); cipher.updateAAD(associatedData); - return new String(cipher.doFinal(BaseEncoding.base64().decode(CharMatcher.whitespace().removeFrom(ciphertext))), "utf-8"); + return new String(cipher.doFinal(Base64.getDecoder().decode(StringUtils.remove(ciphertext, " "))), StandardCharsets.UTF_8); } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { throw new IllegalStateException(e); } catch (InvalidKeyException | InvalidAlgorithmParameterException e) { @@ -76,7 +75,7 @@ public String decryptToString(byte[] associatedData, byte[] nonce, String cipher } } - public static String decryptToString(String associatedData, String nonce, String ciphertext,String apiV3Key) + public static String decryptToString(String associatedData, String nonce, String ciphertext, String apiV3Key) throws GeneralSecurityException, IOException { try { Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); @@ -87,7 +86,7 @@ public static String decryptToString(String associatedData, String nonce, String cipher.init(Cipher.DECRYPT_MODE, key, spec); cipher.updateAAD(associatedData.getBytes()); - return new String(cipher.doFinal(Base64.getDecoder().decode(ciphertext)), "utf-8"); + return new String(cipher.doFinal(Base64.getDecoder().decode(ciphertext)), StandardCharsets.UTF_8); } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { throw new IllegalStateException(e); } catch (InvalidKeyException | InvalidAlgorithmParameterException e) { @@ -116,9 +115,9 @@ public static String createSign(Map map, String mchKey) { public static String HMACSHA256(String data, String key) { try { Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); - SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256"); + SecretKeySpec secret_key = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256"); sha256_HMAC.init(secret_key); - byte[] array = sha256_HMAC.doFinal(data.getBytes("UTF-8")); + byte[] array = sha256_HMAC.doFinal(data.getBytes(StandardCharsets.UTF_8)); StringBuilder sb = new StringBuilder(); for (byte item : array) { sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3)); diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/v3/util/PemUtils.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/v3/util/PemUtils.java index c039ccb63..1983fb338 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/v3/util/PemUtils.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/v3/util/PemUtils.java @@ -47,7 +47,7 @@ public static PrivateKey loadPrivateKey(InputStream inputStream) { public static X509Certificate loadCertificate(InputStream inputStream) { try { - CertificateFactory cf = CertificateFactory.getInstance("X509"); + CertificateFactory cf = CertificateFactory.getInstance("X.509"); X509Certificate cert = (X509Certificate) cf.generateCertificate(inputStream); cert.checkValidity(); return cert; diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/v3/util/RsaCryptoUtil.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/v3/util/RsaCryptoUtil.java index 295303740..d8fe3b35b 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/v3/util/RsaCryptoUtil.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/v3/util/RsaCryptoUtil.java @@ -47,7 +47,7 @@ private static void encryptField(Object encryptObject, X509Certificate certifica Object oldValue = field.get(encryptObject); if (oldValue != null) { String oldStr = (String) oldValue; - if (!oldStr.trim().equals("'")) { + if (!"".equals(oldStr.trim())) { field.set(encryptObject, encryptOAEP(oldStr, certificate)); } } diff --git a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/notify/WxPayNotifyResponseTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/notify/WxPayNotifyResponseTest.java index 60be34e35..1245c0a15 100644 --- a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/notify/WxPayNotifyResponseTest.java +++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/notify/WxPayNotifyResponseTest.java @@ -1,5 +1,6 @@ package com.github.binarywang.wxpay.bean.notify; +import lombok.extern.slf4j.Slf4j; import org.testng.annotations.Test; import static org.assertj.core.api.Assertions.assertThat; @@ -10,8 +11,12 @@ * @author Binary Wang * @date 2019-06-30 */ +@Slf4j public class WxPayNotifyResponseTest { + /** + * V2版本 + */ @Test public void testSuccess() { final String result = WxPayNotifyResponse.success("OK"); @@ -38,4 +43,23 @@ public void testFailResp() { "" + ""); } + + /** + * V3版本 + * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_5.shtml + */ + @Test + public void testV3Fail() { + final String result = WxPayNotifyV3Response.fail("失败"); + log.info(result); + assertThat(result).isNotEmpty(); + } + + @Test + public void testV3Success() { + final String result = WxPayNotifyV3Response.success("成功"); + log.info(result); + assertThat(result).isNotEmpty(); + } + } diff --git a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/config/WxPayConfigTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/config/WxPayConfigTest.java index 8b5a621b8..5a506e72f 100644 --- a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/config/WxPayConfigTest.java +++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/config/WxPayConfigTest.java @@ -37,4 +37,11 @@ public void testInitSSLContext() throws Exception { public void testHashCode() { payConfig.hashCode(); } + + @Test + public void testInitSSLContext_base64() throws Exception { + payConfig.setMchId("123"); + payConfig.setKeyString("MIIKmgIBAzCCCmQGCS..."); + payConfig.initSSLContext(); + } } diff --git a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/ComplaintServiceImplTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/ComplaintServiceImplTest.java index 6014924fd..f4607116e 100644 --- a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/ComplaintServiceImplTest.java +++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/ComplaintServiceImplTest.java @@ -1,8 +1,7 @@ package com.github.binarywang.wxpay.service.impl; import com.github.binarywang.wxpay.bean.complaint.*; -import com.github.binarywang.wxpay.bean.profitsharing.*; -import com.github.binarywang.wxpay.constant.WxPayConstants; +import com.github.binarywang.wxpay.bean.media.ImageUploadResult; import com.github.binarywang.wxpay.exception.WxPayException; import com.github.binarywang.wxpay.service.WxPayService; import com.github.binarywang.wxpay.testbase.ApiTestModule; @@ -13,6 +12,8 @@ import org.testng.annotations.Test; import javax.crypto.BadPaddingException; +import java.io.File; +import java.io.IOException; /** *
@@ -152,4 +153,21 @@ public void testComplete() throws WxPayException {
     this.payService.getComplaintsService().complete(request);
   }
 
+  /**
+   *  商户上传反馈图片API
+   * @throws WxPayException
+   * @throws IOException
+   */
+  @Test
+  public  void testUploadResponseImage() throws WxPayException, IOException {
+    String filePath="你的图片文件的路径地址";
+//    String filePath="WxJava/images/banners/wiki.jpg";
+
+    File file = new File(filePath);
+
+    ImageUploadResult imageUploadResult = this.payService.getComplaintsService().uploadResponseImage(file);
+    imageUploadResult.getMediaId();
+
+  }
+
 }
diff --git a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/CustomDeclarationServiceImplTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/CustomDeclarationServiceImplTest.java
new file mode 100644
index 000000000..6a219ee2f
--- /dev/null
+++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/CustomDeclarationServiceImplTest.java
@@ -0,0 +1,74 @@
+package com.github.binarywang.wxpay.service.impl;
+
+import com.github.binarywang.wxpay.bean.customs.*;
+import com.github.binarywang.wxpay.exception.WxPayException;
+import com.github.binarywang.wxpay.service.CustomDeclarationService;
+import com.github.binarywang.wxpay.service.WxPayService;
+import com.github.binarywang.wxpay.testbase.ApiTestModule;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.inject.Inject;
+import lombok.extern.slf4j.Slf4j;
+import org.testng.annotations.Guice;
+import org.testng.annotations.Test;
+
+@Slf4j
+@Test
+@Guice(modules = ApiTestModule.class)
+public class CustomDeclarationServiceImplTest {
+  private static final Gson GSON = new GsonBuilder().create();
+  @Inject
+  private WxPayService wxPayService;
+
+  @Test
+  public void testDeclare() throws WxPayException {
+    CustomDeclarationService customDeclarationService = new CustomDeclarationServiceImpl(wxPayService);
+    String requestParamStr = "{\"appid\":\"wx4275b35dac8f1bde\",\"mchid\":\"1623887211\",\"out_trade_no\":\"schiff32205031811186126779176\",\"transaction_id\":\"4200001480202205035540107159\",\"customs\":\"NINGBO\",\"merchant_customs_no\":\"4401230148\"}";
+    DeclarationRequest request = GSON.fromJson(requestParamStr, DeclarationRequest.class);
+
+    DeclarationResult result = customDeclarationService.declare(request);
+    System.out.println("result = " + result);
+  }
+
+  @Test
+  public void testQuery() throws WxPayException {
+    CustomDeclarationService customDeclarationService = new CustomDeclarationServiceImpl(wxPayService);
+    String requestParamStr = "{\"appid\":\"wx4275b35dac8f1bde\",\"mchid\":\"1623887211\",\"order_type\":\"transaction_id\",\"order_no\":\"4200001480202205035540107159\",\"customs\":\"NINGBO\",\"offset\":\"0\",\"limit\":\"20\"}";
+    DeclarationQueryRequest request = GSON.fromJson(requestParamStr, DeclarationQueryRequest.class);
+
+    DeclarationQueryResult result = customDeclarationService.query(request);
+    System.out.println("result = " + result);
+  }
+
+  @Test
+  public void testVerifyCertificate() throws WxPayException {
+    CustomDeclarationService customDeclarationService = new CustomDeclarationServiceImpl(wxPayService);
+    String requestParamStr = "{\"appid\":\"wx4275b35dac8f1bde\",\"mchid\":\"1623887211\",\"out_trade_no\":\"schiff32205031811186126779176\",\"transaction_id\":\"4200001480202205035540107159\",\"customs\":\"NINGBO\",\"merchant_customs_no\":\"4401230148\",\"certificate_type\":\"IDCARD\",\"certificate_id\":\"430223199101264838\",\"certificate_name\":\"易株强\"}";
+    VerifyCertificateRequest request = GSON.fromJson(requestParamStr, VerifyCertificateRequest.class);
+
+    VerifyCertificateResult result = customDeclarationService.verifyCertificate(request);
+    System.out.println("result = " + result);
+  }
+
+  @Test
+  public void testModify() throws WxPayException {
+    CustomDeclarationService customDeclarationService = new CustomDeclarationServiceImpl(wxPayService);
+
+    String requestParamStr = "{\"appid\":\"wx4275b35dac8f1bde\",\"mchid\":\"1623887211\",\"out_trade_no\":\"schiff32205031811186126779176\",\"transaction_id\":\"4200001480202205035540107159\",\"customs\":\"NINGBO\",\"merchant_customs_no\":\"4401230148\"}";
+
+    DeclarationRequest request = GSON.fromJson(requestParamStr, DeclarationRequest.class);
+
+    DeclarationResult result = customDeclarationService.modify(request);
+    System.out.println("result = " + result);
+  }
+
+  @Test
+  public void testRedeclare() throws WxPayException {
+    CustomDeclarationService customDeclarationService = new CustomDeclarationServiceImpl(wxPayService);
+    String requestParamStr = "{\"appid\":\"wx4275b35dac8f1bde\",\"mchid\":\"1623887211\",\"out_trade_no\":\"schiff32205031811186126779176\",\"transaction_id\":\"4200001480202205035540107159\",\"customs\":\"NINGBO\",\"merchant_customs_no\":\"4401230148\"}";
+    RedeclareRequest request = GSON.fromJson(requestParamStr, RedeclareRequest.class);
+
+    RedeclareResult result = customDeclarationService.redeclare(request);
+    System.out.println("result = " + result);
+  }
+}
diff --git a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/MerchantTransferServiceImplTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/MerchantTransferServiceImplTest.java
new file mode 100644
index 000000000..fd7eb66c9
--- /dev/null
+++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/MerchantTransferServiceImplTest.java
@@ -0,0 +1,110 @@
+package com.github.binarywang.wxpay.service.impl;
+
+import com.github.binarywang.wxpay.bean.merchanttransfer.*;
+import com.github.binarywang.wxpay.exception.WxPayException;
+import com.github.binarywang.wxpay.service.WxPayService;
+import com.github.binarywang.wxpay.testbase.ApiTestModule;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.inject.Inject;
+import lombok.extern.slf4j.Slf4j;
+import org.testng.annotations.Guice;
+import org.testng.annotations.Test;
+
+/**
+ * 商家转账到零钱(直连商户)
+ * @author glz
+ * @date 2022/6/11
+ */
+@Slf4j
+@Test
+@Guice(modules = ApiTestModule.class)
+public class MerchantTransferServiceImplTest {
+
+  @Inject
+  private WxPayService wxPayService;
+
+  private static final Gson GSON = new GsonBuilder().create();
+
+  @Test
+  public void createTransfer() throws WxPayException {
+    String requestParamStr = "{\"out_batch_no\":\"p11lfk2020042013\",\"batch_name\":\"xxx\",\"batch_remark\":\"xxx\",\"total_amount\":30,\"total_num\":1,\"transfer_detail_list\":[{\"out_detail_no\":\"x23zy545Bd5436\",\"transfer_amount\":30,\"transfer_remark\":\"5586提款\",\"openid\":\"or1b65DLMUir7F-_vLwKlutmm3qw\",\"user_name\":\"xxx\"}]}";
+
+    TransferCreateRequest request = GSON.fromJson(requestParamStr, TransferCreateRequest.class);
+    TransferCreateResult result = wxPayService.getMerchantTransferService().createTransfer(request);
+    log.info(result.toString());
+  }
+
+  @Test
+  public void queryWxBatches() throws WxPayException {
+    String requestParamStr = "{\"batch_id\":\"xxx\",\"need_query_detail\":true,\"offset\":0,\"limit\":20,\"detail_status\":\"ALL\"}";
+
+    WxBatchesQueryRequest request = GSON.fromJson(requestParamStr, WxBatchesQueryRequest.class);
+    log.info("request:{}",request);
+    BatchesQueryResult result = wxPayService.getMerchantTransferService().queryWxBatches(request);
+    log.info(result.toString());
+  }
+
+  @Test
+  public void queryWxDetails() throws WxPayException {
+    String requestParamStr = "{\"batch_id\":\"xxx\",\"detail_id\":\"xxx\"}";
+
+    WxDetailsQueryRequest request = GSON.fromJson(requestParamStr, WxDetailsQueryRequest.class);
+    DetailsQueryResult result = wxPayService.getMerchantTransferService().queryWxDetails(request);
+    log.info(result.toString());
+  }
+
+  @Test
+  public void queryMerchantBatches() throws WxPayException {
+    String requestParamStr = "{\"out_batch_no\":\"p11lfk2020042013\",\"need_query_detail\":true,\"offset\":0,\"limit\":20,\"detail_status\":\"ALL\"}";
+
+    MerchantBatchesQueryRequest request = GSON.fromJson(requestParamStr, MerchantBatchesQueryRequest.class);
+    BatchesQueryResult result = wxPayService.getMerchantTransferService().queryMerchantBatches(request);
+    log.info(result.toString());
+  }
+
+  @Test
+  public void queryMerchantDetails() throws WxPayException {
+    String requestParamStr = "{\"out_detail_no\":\"x23zy545Bd5436\",\"out_batch_no\":\"p11lfk2020042013\"}";
+
+    MerchantDetailsQueryRequest request = GSON.fromJson(requestParamStr, MerchantDetailsQueryRequest.class);
+    DetailsQueryResult result = wxPayService.getMerchantTransferService().queryMerchantDetails(request);
+    log.info(result.toString());
+  }
+
+  @Test
+  public void applyElectronicBill() throws WxPayException {
+    String requestParamStr = "{\"out_batch_no\":\"p11lfk2020042013\"}";
+
+    ElectronicBillApplyRequest request = GSON.fromJson(requestParamStr, ElectronicBillApplyRequest.class);
+    ElectronicBillResult result = wxPayService.getMerchantTransferService().applyElectronicBill(request);
+    log.info(result.toString());
+  }
+
+  @Test
+  public void queryElectronicBill() throws WxPayException {
+    String outBatchNo = "p11lfk2020042013";
+
+    ElectronicBillResult result = wxPayService.getMerchantTransferService().queryElectronicBill(outBatchNo);
+    log.info(result.toString());
+  }
+
+  @Test
+  public void applyDetailElectronicBill() throws WxPayException {
+    String requestParamStr = "{\"accept_type\":\"BATCH_TRANSFER\",\"out_batch_no\":\"p11lfk2020042013\",\"out_detail_no\":\"x23zy545Bd5436\"}";
+
+    DetailElectronicBillRequest request = GSON.fromJson(requestParamStr, DetailElectronicBillRequest.class);
+    DetailElectronicBillResult result = wxPayService.getMerchantTransferService().applyDetailElectronicBill(request);
+    log.info(result.toString());
+  }
+
+  @Test
+  public void queryDetailElectronicBill() throws WxPayException {
+    String requestParamStr = "{\"accept_type\":\"BATCH_TRANSFER\",\"out_batch_no\":\"p11lfk2020042013\",\"out_detail_no\":\"x23zy545Bd5436\"}";
+
+    DetailElectronicBillRequest request = GSON.fromJson(requestParamStr, DetailElectronicBillRequest.class);
+    DetailElectronicBillResult result = wxPayService.getMerchantTransferService().queryDetailElectronicBill(request);
+    log.info(result.toString());
+  }
+
+}
diff --git a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/ProfitSharingV3ServiceImplTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/ProfitSharingV3ServiceImplTest.java
new file mode 100644
index 000000000..398f1023f
--- /dev/null
+++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/ProfitSharingV3ServiceImplTest.java
@@ -0,0 +1,38 @@
+package com.github.binarywang.wxpay.service.impl;
+
+import com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader;
+import com.github.binarywang.wxpay.exception.WxPayException;
+import com.github.binarywang.wxpay.service.WxPayService;
+import com.github.binarywang.wxpay.testbase.ApiTestModule;
+import com.google.inject.Inject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.Guice;
+import org.testng.annotations.Test;
+
+/**
+ * 测试类
+ *
+ * @author yuanbo
+ * @create 2022-04-26-22:33 PM
+ */
+@Test
+@Guice(modules = ApiTestModule.class)
+public class ProfitSharingV3ServiceImplTest {
+
+  private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+  @Inject
+  private WxPayService payService;
+
+  @Test
+  public void testProfitSharingNotifyData() throws WxPayException {
+    SignatureHeader header = new SignatureHeader();
+    header.setSerialNo("Wechatpay-Serial");
+    header.setTimeStamp("Wechatpay-Timestamp");
+    header.setNonce("Wechatpay-Nonce");
+    header.setSigned("Wechatpay-Signature");
+    String data = "body";
+    this.logger.info(this.payService.getProfitSharingV3Service().getProfitSharingNotifyData(data,header).toString());
+  }
+}
diff --git a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/TransferServiceImplTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/TransferServiceImplTest.java
new file mode 100644
index 000000000..654276a27
--- /dev/null
+++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/TransferServiceImplTest.java
@@ -0,0 +1,76 @@
+package com.github.binarywang.wxpay.service.impl;
+
+import com.github.binarywang.wxpay.bean.transfer.QueryTransferBatchesRequest;
+import com.github.binarywang.wxpay.bean.transfer.TransferBatchesRequest;
+import com.github.binarywang.wxpay.exception.WxPayException;
+import com.github.binarywang.wxpay.service.WxPayService;
+import com.github.binarywang.wxpay.testbase.ApiTestModule;
+import com.google.inject.Inject;
+import lombok.extern.slf4j.Slf4j;
+import org.testng.annotations.Guice;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 获取商家转账到零钱服务类API测试
+ *
+ * @author zhongjun
+ * @date 2022/6/17
+ **/
+@Slf4j
+@Test
+@Guice(modules = ApiTestModule.class)
+public class TransferServiceImplTest {
+
+  @Inject
+  private WxPayService payService;
+
+  @Test
+  public void testTransferBatches() throws WxPayException {
+    List transferDetailList = new ArrayList<>();
+    transferDetailList.add(TransferBatchesRequest.TransferDetail.newBuilder()
+      .outDetailNo("1655447989156")
+      .transferAmount(100)
+      .transferRemark("测试转账")
+      .openid("oX_7Jzr9gSZz4X_Xc9-_7HGf8XzI")
+      .userName("测试用户").build());
+    TransferBatchesRequest batchesRequest = TransferBatchesRequest.newBuilder()
+      .appid("wxf636efh5xxxxx")
+      .outBatchNo("1655447999520")
+      .batchName("测试批次")
+      .batchRemark("测试批次备注")
+      .totalAmount(100)
+      .totalNum(1)
+      .transferDetailList(transferDetailList).build();
+    log.info("发起商家转账:{}", this.payService.getTransferService().transferBatches(batchesRequest));
+  }
+
+  @Test
+  public void testTransferBatchesBatchId() throws WxPayException {
+    log.info("微信批次单号查询批次单:{}", this.payService.getTransferService().transferBatchesBatchId(QueryTransferBatchesRequest.newBuilder()
+      .batchId("1655448154148")
+      .needQueryDetail(true)
+      .build()));
+
+  }
+
+  @Test
+  public void testTransferBatchesBatchIdDetail() throws WxPayException {
+    log.info("微信明细单号查询明细单:{}", this.payService.getTransferService().transferBatchesBatchIdDetail("1030000071100999991182020050700019480001", "1040000071100999991182020050700019500100"));
+  }
+
+  @Test
+  public void testTransferBatchesOutBatchNo() throws WxPayException {
+    log.info("商家批次单号查询批次单:{}", this.payService.getTransferService().transferBatchesOutBatchNo(QueryTransferBatchesRequest.newBuilder()
+      .outBatchNo("1655447999520")
+      .needQueryDetail(true)
+      .build()));
+  }
+
+  @Test
+  public void testTransferBatchesOutBatchNoDetail() throws WxPayException {
+    log.info("商家明细单号查询明细单:{}", this.payService.getTransferService().transferBatchesOutBatchNoDetail("1655447999520", "1655447989156"));
+  }
+}
diff --git a/weixin-java-pay/src/test/resources/test-config.sample.xml b/weixin-java-pay/src/test/resources/test-config.sample.xml
index 25ec4be05..9a299b8ac 100644
--- a/weixin-java-pay/src/test/resources/test-config.sample.xml
+++ b/weixin-java-pay/src/test/resources/test-config.sample.xml
@@ -1,21 +1,22 @@
 
   公众号appid
   微信商户平台ID
-  商户平台设置的API密钥
   
+    以下为官网文档所提供样例参数,仅供部分接口测试使用
+    wxd930ea5d5a258f4f
+    10000100
+    192006250b4c09247ec02edce69f6a2d
+-->
+  
+  商户平台设置的API密钥
   商户平台的证书文件地址
-  某个openId
 
-  
    apiV3 秘钥值.
   apiV3 证书序列号值
-  -->
+  apiclient_key.pem证书文件的绝对路径或者以classpath:开头的类路径.
+  apiclient_cert.pem证书文件的绝对路径或者以classpath:开头的类路径.
+
+  
+  某个openId
 
diff --git a/weixin-java-qidian/pom.xml b/weixin-java-qidian/pom.xml
index f0f2d05b1..c27a02b5e 100644
--- a/weixin-java-qidian/pom.xml
+++ b/weixin-java-qidian/pom.xml
@@ -7,7 +7,7 @@
   
     com.github.binarywang
     wx-java
-    4.3.0
+    4.4.0
   
 
   weixin-java-qidian