Compare commits

..

No commits in common. "main" and "v2.8.0" have entirely different histories.
main ... v2.8.0

2845 changed files with 50512 additions and 233789 deletions

7
.codeclimate.yml Normal file
View File

@ -0,0 +1,7 @@
engines:
fixme:
enabled: true
ratings:
paths: []
exclude_paths:
- "readme.md"

14
.editorconfig Normal file
View File

@ -0,0 +1,14 @@
# EditorConfig: http://editorconfig.org/
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false

269
.gitignore vendored
View File

@ -1,235 +1,52 @@
### Gradle ### *.class
.gradle test-output
build/
# Ignore Gradle GUI config # Mobile Tools for Java (J2ME)
gradle-app.setting .mtj.tmp/
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) # Package Files #
!gradle-wrapper.jar *.jar
*.war
*.ear
# Cache of project # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
.gradletasknamecache hs_err_pid*
# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 target
# gradle/wrapper/gradle-wrapper.properties bin
.project
.classpath
.settings
### Gradle Patch ### sw-pom.xml
*.iml
test-config.xml
.idea
/.gradle/
/gradle/
*.bat
/gradlew
**/build/ **/build/
### Intellij ### # OSX
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm # Icon must end with two \r
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 Icon
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### Intellij Patch ###
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
# *.iml
# modules.xml
# .idea/misc.xml
# *.ipr
# Sonarlint plugin
.idea/sonarlint
### Intellij+iml ### ._*
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm .DS_Store
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 .AppleDouble
.LSOverride
# User-specific stuff .DocumentRevisions-V100
.idea/**/workspace.xml .fseventsd
.idea/**/tasks.xml .Spotlight-V100
.idea/**/usage.statistics.xml .TemporaryItems
.idea/**/dictionaries .Trashes
.idea/**/shelf .VolumeIcon.icns
.AppleDB
# Generated files .AppleDesktop
.idea/**/contentModel.xml Network Trash Folder
Temporary Items
# Sensitive or high-churn files .apdisk
.idea/**/dataSources/ /.sonar/
.idea/**/dataSources.ids sonar-project.properties
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### Intellij+iml Patch ###
# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023
*.iml
modules.xml
.idea/misc.xml
*.ipr
### Maven ###
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
.mvn/wrapper/maven-wrapper.jar
.flattened-pom.xml
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### Intellij Patch ###
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
# *.iml
# modules.xml
# .idea/misc.xml
# *.ipr
# Sonarlint plugin
.idea/sonarlint

View File

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CheckStyle-IDEA" serialisationVersion="2">
<checkstyleVersion>10.22.0</checkstyleVersion>
<scanScope>JavaOnly</scanScope>
<copyLibs>true</copyLibs>
<option name="thirdPartyClasspath" />
<option name="activeLocationIds" />
<option name="locations">
<list>
<ConfigurationLocation id="bundled-sun-checks" type="BUNDLED" scope="All" description="Sun Checks">(bundled)</ConfigurationLocation>
<ConfigurationLocation id="bundled-google-checks" type="BUNDLED" scope="All" description="Google Checks">(bundled)</ConfigurationLocation>
</list>
</option>
</component>
</project>

18
.idea/compiler.xml generated
View File

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile name="Maven default annotation processors profile" enabled="true">
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<module name="wechat-j-open" />
<module name="wechat-j-pay" />
<module name="wechat-j-work" />
<module name="wechat-j-common" />
<module name="wechat-j-mp" />
<module name="wechat-j-oa" />
</profile>
</annotationProcessing>
</component>
</project>

19
.idea/encodings.xml generated
View File

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/common/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/common/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/mp/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/mp/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/oa/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/oa/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/open/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/open/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/pay/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/pay/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/work/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/work/src/main/resources" charset="UTF-8" />
</component>
</project>

View File

@ -1,30 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="ossez-repo-releases" />
<option name="name" value="iSharkFly Private Releases" />
<option name="url" value="https://repo.isharkfly.com/repository/isharkfly-maven-releases/" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="https://repo.isharkfly.com/repository/maven/" />
</remote-repository>
<remote-repository>
<option name="id" value="ossez-repo-snapshots" />
<option name="name" value="iSharkFly Private Snapshots" />
<option name="url" value="https://repo.isharkfly.com/repository/isharkfly-maven-snapshots/" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
</component>
</project>

6
.idea/vcs.xml generated
View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

27
.travis.yml Normal file
View File

@ -0,0 +1,27 @@
language: java
#sudo: false
#install: true
#addons:
# sonarcloud:
# token:
# secure: "834110c7191f97ecb226970c46dcaff8e681da5a"
jdk:
- oraclejdk8
script: "mvn clean package -Dmaven.test.skip=true"
#script:
# - mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent package sonar:sonar
branches:
only:
- develop
cache:
directories:
- '$HOME/.m2/repository'
# - '$HOME/.sonar/cache'
notifications:
email:
- binaryw@qq.com

214
LICENSE
View File

@ -1,21 +1,201 @@
MIT License Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
Copyright (c) 2023 OSSEZ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
Permission is hereby granted, free of charge, to any person obtaining a copy 1. Definitions.
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all "License" shall mean the terms and conditions for use, reproduction,
copies or substantial portions of the Software. and distribution as defined by Sections 1 through 9 of this document.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR "Licensor" shall mean the copyright owner or entity authorized by
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, the copyright owner that is granting the License.
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER "Legal Entity" shall mean the union of the acting entity and all
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, other entities that control, are controlled by, or are under common
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE control with that entity. For the purposes of this definition,
SOFTWARE. "control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) 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
(d) 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.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

150
README.md
View File

@ -1,150 +0,0 @@
# WeChat-J - 微信开发 Java SDK
<p align="center">
<a href="https://github.com/honeymoose">
<img height=85 src="https://avatars1.githubusercontent.com/u/45009982?s=200&v=4">
</a>
<br>This project builds by JDK 11 and OpenJ9 for JVM.
</p>
* [社区和讨论 (community)](https://www.ossez.com/tag/wechat)
WeChat-J 开发使用的库。
我们旨在提供一个初始化的开发框架,能够让应用在使用 Spring Boot 框架的基础上让你的微信公众号快速接入微信平台。
# 项目说明
我们在网上找了一些微信相关的 SDK要不就是缺少维护要不就是集成了非常多的功能因我们的公众号希望能够尽量的自动化处理所以我们在已有的基础上进行了一些修改和整合。
## 必要的准备
因微信开发 Java SDK 的开发其实并不非常复杂,主要是通过 HTTP 发送请求并且将获得的返回数据进行一些处理返回对象就可以了。
我们需要调用微信的 HTTP 接口,所以我们需要在 Java 中使用一个 Http 客户端,在当前我们的环境中,我们只使用 OkHttp 来进行实现。
在老的项目中,可能不少人会使用 Apache 的 HttpClient 来进行实现,但因为 OkHttp 广泛的被使用在安卓的手机上,所以使用 OkHttp
会更加简便。
* [Retrofit 是什么](https://www.ossez.com/t/retrofit/14302)
* [RxJava 是什么](https://www.ossez.com/t/rxjava/14305)
* [微信测试平台获得测试账号](https://www.ossez.com/t/topic/14281)
### Maven 和依赖
当前我们还没有把正式版发布到仓库中,我们还在使用 0.0.1-SNAPSHOT 版本进行内部测试。
最好的版本就是下载我们的源代码后 Fork 到你本地,然后直接使用 Maven 来进行编译。
#### 微信公众号WeChat Java Official Account
模块名wechat-j-oa
```xml
<dependency>
<groupId>com.ossez.wechat</groupId>
<artifactId>wechat-j-oa</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
```
#### 微信小程序WeChat Java Mini Programs
模块名wechat-j-mp
```xml
<dependency>
<groupId>com.ossez.wechat</groupId>
<artifactId>wechat-j-mp</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
```
#### 微信支付WeChat Java Pay
模块名wechat-j-pay
```xml
<dependency>
<groupId>com.ossez.wechat</groupId>
<artifactId>wechat-j-pay</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
```
#### 企业微信WeChat Java WeCom
模块名wechat-j-work
```xml
<dependency>
<groupId>com.ossez.wechat</groupId>
<artifactId>wechat-j-work</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
```
#### 微信开放平台WeChat Java Open
模块名wechat-j-open
```xml
<dependency>
<groupId>com.ossez.wechat</groupId>
<artifactId>wechat-j-open</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
```
### 其他内容
* 任何有关讨论,请访问 [社区](https://www.ossez.com/tag/wechat)您可以在这里提出功能需求Bug 修复,问题解答。
* 可以考虑使用 http://paste.ubuntu.com 来对你在提交问题的时候出现的为代码进行简化。
### 框架和案例
如果你想登记你的项目,请[访问这里](https://www.ossez.com/t/wechat-j-demo/14303)。
同时,我们也提供了一些开发框架,能够让你直接检出项目就可以直接对微信 SDK 进行接入和测试。
* [公众号 Spring Boot 测试程序](https://github.com/honeymoose/WeChat-Official-Account-Spring)
# 联系方式
请使用下面的联系方式和我们联系。
* [社区和讨论](https://www.ossez.com/tag/chat-gpt)
| 联系方式名称 | 联系方式 |
|------------------|-----------------------------------------------|
| 电子邮件Email | [yhu@ossez.com](mailto:yhu@ossez.com) |
| QQ 或微信WeChat | 103899765 |
| QQ 交流群 | 15186112 |
| 社区论坛 Community | https://www.ossez.com/c/computer-technology/7 |
# 公众平台
我们建议您通过社区论坛来和我们进行沟通,请关注我们公众平台上的账号
## 微信公众号
![](https://cdn.ossez.com/img/cwikius/cwikius-qr-wechat-search-w400.png)
## 头条号
我们也在头条号上创建了我们的公众号,请扫描下面的 QR 关注我们的头条号。
![](https://cdn.ossez.com/img/cwikius/cwikus-qr-toutiao.png)
## 知乎
请关注我们的知乎https://www.zhihu.com/people/huyuchengus
# License
[WeChat-J is licensed under the MIT License](https://src.ossez.com/honeymoose/WeChat-J/src/branch/main/LICENSE)

BIN
alipay_qrcode.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

View File

@ -1,186 +0,0 @@
<?xml version="1.0"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ossez.wechat</groupId>
<artifactId>wechat-j-common</artifactId>
<packaging>jar</packaging>
<parent>
<groupId>com.ossez.wechat</groupId>
<artifactId>wechat-j</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<name>WeChat Java Common</name>
<description>The module is common for all other package</description>
<dependencies>
<dependency>
<groupId>org.jodd</groupId>
<artifactId>jodd-http</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.36</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-guava</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.1.3</version>
<exclusions>
<exclusion>
<groupId>pull-parser</groupId>
<artifactId>pull-parser</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>com.github.jedis-lock</groupId>
<artifactId>jedis-lock</artifactId>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>src/test/resources/testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>native-image</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<annotationProcessors>
com.github.binarywang.wx.graal.GraalProcessor,lombok.launch.AnnotationProcessorHider$AnnotationProcessor,lombok.launch.AnnotationProcessorHider$ClaimingProcessor
</annotationProcessors>
<annotationProcessorPaths>
<path>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-graal</artifactId>
<version>${project.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@ -1,32 +0,0 @@
package com.ossez.wechat.common.api;
import com.ossez.wechat.common.model.WeChatAccessToken;
import com.ossez.wechat.common.model.WeChatApiDomainIp;
import com.ossez.wechat.common.model.req.NetworkCheck;
import com.ossez.wechat.common.model.req.QueryQuota;
import com.ossez.wechat.common.model.res.NetworkCheckResponse;
import com.ossez.wechat.common.model.res.QueryQuotaResponse;
import io.reactivex.Single;
import retrofit2.http.Body;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.Query;
public interface WeChatOfficialAccountApi {
@GET("/cgi-bin/token")
Single<WeChatAccessToken> getAccessToken(@Query("grant_type") String grantType, @Query("appid") String appId, @Query("secret") String secret);
@GET("/cgi-bin/get_api_domain_ip")
Single<WeChatApiDomainIp> getDomainIPs();
@POST("/cgi-bin/callback/check")
Single<NetworkCheckResponse> checkNetwork(@Body NetworkCheck request);
@POST("/cgi-bin/clear_quota")
Single<NetworkCheckResponse> clearQuota(@Body NetworkCheck request);
@POST("/cgi-bin/openapi/quota/get")
Single<QueryQuotaResponse> queryQuota(@Body QueryQuota request);
}

View File

@ -1,26 +0,0 @@
package com.ossez.wechat.common.api;
import com.ossez.wechat.common.model.WeChatAccessToken;
import com.ossez.wechat.common.model.WeChatApiDomainIp;
import com.ossez.wechat.common.model.WeChatOAuth2AccessToken;
import com.ossez.wechat.common.model.entity.WeChatOAuth2UserInfo;
import com.ossez.wechat.common.model.req.NetworkCheck;
import com.ossez.wechat.common.model.req.QueryQuota;
import com.ossez.wechat.common.model.res.NetworkCheckResponse;
import com.ossez.wechat.common.model.res.QueryQuotaResponse;
import io.reactivex.Single;
import retrofit2.http.Body;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.Query;
public interface WeChatOpenApi {
@GET("/sns/oauth2/access_token")
Single<WeChatOAuth2AccessToken> getAccessToken(@Query("grant_type") String grantType, @Query("appid") String appId, @Query("secret") String secret, @Query("code") String code);
@GET("/sns/userinfo")
Single<WeChatOAuth2UserInfo> getWeChatUserInfo(@Query("access_token") String accessToken, @Query("openid") String openId);
}

View File

@ -1,14 +0,0 @@
package com.ossez.wechat.common.api;
import com.ossez.wechat.common.exception.WxErrorException;
/**
* WxErrorException处理器.
*
* @author Daniel Qian
*/
public interface WxErrorExceptionHandler {
void handle(WxErrorException e);
}

View File

@ -1,97 +0,0 @@
package com.ossez.wechat.common.api;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* <pre>
* 默认消息重复检查器.
* 将每个消息id保存在内存里每隔5秒清理已经过期的消息id每个消息id的过期时间是15秒
* 替换类WxMessageInMemoryDuplicateCheckerSingleton
* </pre>
*
* @author Daniel Qian
*/
@Deprecated
public class WxMessageInMemoryDuplicateChecker implements WxMessageDuplicateChecker {
/**
* 一个消息ID在内存的过期时间15秒.
*/
private final Long timeToLive;
/**
* 每隔多少周期检查消息ID是否过期5秒.
*/
private final Long clearPeriod;
/**
* 消息id->消息时间戳的map.
*/
private final ConcurrentHashMap<String, Long> msgId2Timestamp = new ConcurrentHashMap<>();
/**
* 后台清理线程是否已经开启.
*/
private final AtomicBoolean backgroundProcessStarted = new AtomicBoolean(false);
/**
* 无参构造方法.
* <pre>
* 一个消息ID在内存的过期时间15秒
* 每隔多少周期检查消息ID是否过期5秒
* </pre>
*/
public WxMessageInMemoryDuplicateChecker() {
this.timeToLive = 15 * 1000L;
this.clearPeriod = 5 * 1000L;
}
/**
* 构造方法.
*
* @param timeToLive 一个消息ID在内存的过期时间毫秒
* @param clearPeriod 每隔多少周期检查消息ID是否过期毫秒
*/
public WxMessageInMemoryDuplicateChecker(Long timeToLive, Long clearPeriod) {
this.timeToLive = timeToLive;
this.clearPeriod = clearPeriod;
}
protected void checkBackgroundProcessStarted() {
if (this.backgroundProcessStarted.getAndSet(true)) {
return;
}
Thread t = new Thread(() -> {
try {
while (true) {
Thread.sleep(WxMessageInMemoryDuplicateChecker.this.clearPeriod);
Long now = System.currentTimeMillis();
for (Map.Entry<String, Long> entry :
WxMessageInMemoryDuplicateChecker.this.msgId2Timestamp.entrySet()) {
if (now - entry.getValue() > WxMessageInMemoryDuplicateChecker.this.timeToLive) {
WxMessageInMemoryDuplicateChecker.this.msgId2Timestamp.entrySet().remove(entry);
}
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
t.setDaemon(true);
t.start();
}
@Override
public boolean isDuplicate(String messageId) {
if (messageId == null) {
return false;
}
checkBackgroundProcessStarted();
Long timestamp = this.msgId2Timestamp.putIfAbsent(messageId, System.currentTimeMillis());
return timestamp != null;
}
}

View File

@ -1,91 +0,0 @@
package com.ossez.wechat.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
* <p>
* 消息去重记录消息ID首次出现时的时间戳
* 15S后定时任务触发时废除该记录消息ID
* </p>
* created on 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").setDaemon(true).build(), new ThreadPoolExecutor.AbortPolicy());
/**
* 消息id->消息时间戳的map.
*/
private static final ConcurrentHashMap<String, Long> 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;
}
}

View File

@ -1,15 +0,0 @@
package com.ossez.wechat.common.bean;
/**
* 包含toJson()方法的接口.
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
* created on 2020-10-05
*/
public interface ToJson {
/**
* 转换为json字符串
* @return json字符串
*/
String toJson();
}

View File

@ -1,40 +0,0 @@
package com.ossez.wechat.common.bean;
import java.io.Serializable;
import com.ossez.wechat.common.util.json.WxGsonBuilder;
import lombok.Data;
/**
* 卡券Api签名.
*
* @author YuJian
* @version 15/11/8
*/
@Data
public class WxCardApiSignature implements Serializable {
private static final long serialVersionUID = 158176707226975979L;
private String appId;
private String cardId;
private String cardType;
private String locationId;
private String code;
private String openId;
private Long timestamp;
private String nonceStr;
private String signature;
@Override
public String toString() {
return WxGsonBuilder.create().toJson(this);
}
}

View File

@ -1,32 +0,0 @@
package com.ossez.wechat.common.bean;
import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* jspai signature.
*
* @author Daniel Qian
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class WxJsapiSignature implements Serializable {
private static final long serialVersionUID = -1116808193154384804L;
private String appId;
private String nonceStr;
private long timestamp;
private String url;
private String signature;
}

View File

@ -1,42 +0,0 @@
package com.ossez.wechat.common.bean;
import com.ossez.wechat.common.util.json.WxGsonBuilder;
import lombok.Data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* 网络检测.
* @author billytomato
*/
@Data
public class WxNetCheckResult implements Serializable {
private static final long serialVersionUID = 6918924418847404172L;
private List<WxNetCheckDnsInfo> dnsInfos = new ArrayList<>();
private List<WxNetCheckPingInfo> pingInfos = new ArrayList<>();
public static WxNetCheckResult fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxNetCheckResult.class);
}
@Data
public static class WxNetCheckDnsInfo implements Serializable{
private static final long serialVersionUID = 82631178029516008L;
private String ip;
private String realOperator;
}
@Data
public static class WxNetCheckPingInfo implements Serializable{
private static final long serialVersionUID = -1871970825359178319L;
private String ip;
private String fromOperator;
private String packageLoss;
private String time;
}
}

View File

@ -1,69 +0,0 @@
package com.ossez.wechat.common.bean.imgproc;
import com.google.gson.annotations.SerializedName;
import com.ossez.wechat.common.util.json.WxGsonBuilder;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* @author Theo Nie
*/
@Data
public class WxImgProcAiCropResult implements Serializable {
private static final long serialVersionUID = -6470673963772979463L;
@SerializedName("img_size")
private ImgSize imgSize;
@SerializedName("results")
private List<Results> results;
@Override
public String toString() {
return WxGsonBuilder.create().toJson(this);
}
public static WxImgProcAiCropResult fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxImgProcAiCropResult.class);
}
@Data
public static class ImgSize implements Serializable {
private static final long serialVersionUID = -6470673963772979463L;
@SerializedName("w")
private int w;
@SerializedName("h")
private int h;
@Override
public String toString() {
return WxGsonBuilder.create().toJson(this);
}
}
@Data
public static class Results implements Serializable {
private static final long serialVersionUID = -6470673963772979463L;
@SerializedName("crop_left")
private int cropLeft;
@SerializedName("crop_top")
private int cropTop;
@SerializedName("crop_right")
private int cropRight;
@SerializedName("crop_bottom")
private int cropBottom;
@Override
public String toString() {
return WxGsonBuilder.create().toJson(this);
}
}
}

View File

@ -1,103 +0,0 @@
package com.ossez.wechat.common.bean.imgproc;
import com.google.gson.annotations.SerializedName;
import com.ossez.wechat.common.util.json.WxGsonBuilder;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 二维码/条码识别返回结果
*
* @author Theo Nie
*/
@Data
public class WxImgProcQrCodeResult implements Serializable {
private static final long serialVersionUID = -1194154790100866123L;
@SerializedName("img_size")
private ImgSize imgSize;
@SerializedName("code_results")
private List<CodeResults> codeResults;
@Data
public static class ImgSize implements Serializable {
private static final long serialVersionUID = -8847603245514017839L;
@SerializedName("w")
private int w;
@SerializedName("h")
private int h;
@Override
public String toString() {
return WxGsonBuilder.create().toJson(this);
}
}
@Data
public static class CodeResults implements Serializable {
private static final long serialVersionUID = -6138135951229076759L;
@SerializedName("type_name")
private String typeName;
@SerializedName("data")
private String data;
@SerializedName("pos")
private Pos pos;
@Override
public String toString() {
return WxGsonBuilder.create().toJson(this);
}
@Data
public static class Pos implements Serializable {
private static final long serialVersionUID = 7754894061212819602L;
@SerializedName("left_top")
private Coordinate leftTop;
@SerializedName("right_top")
private Coordinate rightTop;
@SerializedName("right_bottom")
private Coordinate rightBottom;
@SerializedName("left_bottom")
private Coordinate leftBottom;
@Override
public String toString() {
return WxGsonBuilder.create().toJson(this);
}
@Data
public static class Coordinate implements Serializable {
private static final long serialVersionUID = 8930443668927359677L;
@SerializedName("x")
private int x;
@SerializedName("y")
private int y;
@Override
public String toString() {
return WxGsonBuilder.create().toJson(this);
}
}
}
}
public static WxImgProcQrCodeResult fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxImgProcQrCodeResult.class);
}
@Override
public String toString() {
return WxGsonBuilder.create().toJson(this);
}
}

View File

@ -1,28 +0,0 @@
package com.ossez.wechat.common.bean.imgproc;
import com.google.gson.annotations.SerializedName;
import com.ossez.wechat.common.util.json.WxGsonBuilder;
import lombok.Data;
import java.io.Serializable;
/**
* 图片高清化返回结果
* @author Theo Nie
*/
@Data
public class WxImgProcSuperResolutionResult implements Serializable {
private static final long serialVersionUID = 8007440280170407021L;
@SerializedName("media_id")
private String mediaId;
@Override
public String toString() {
return WxGsonBuilder.create().toJson(this);
}
public static WxImgProcSuperResolutionResult fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxImgProcSuperResolutionResult.class);
}
}

View File

@ -1,29 +0,0 @@
package com.ossez.wechat.common.bean.ocr;
import com.google.gson.annotations.SerializedName;
import com.ossez.wechat.common.util.json.WxGsonBuilder;
import lombok.Data;
import java.io.Serializable;
/**
* 银行卡OCR识别结果
*
* @author Theo Nie
*/
@Data
public class WxOcrBankCardResult implements Serializable {
private static final long serialVersionUID = 554136620394204143L;
@SerializedName("number")
private String number;
@Override
public String toString() {
return WxGsonBuilder.create().toJson(this);
}
public static WxOcrBankCardResult fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxOcrBankCardResult.class);
}
}

View File

@ -1,108 +0,0 @@
package com.ossez.wechat.common.bean.ocr;
import com.google.gson.annotations.SerializedName;
import com.ossez.wechat.common.util.json.WxGsonBuilder;
import lombok.Data;
import java.io.Serializable;
/**
* @author Theo Nie
*/
@Data
public class WxOcrBizLicenseResult implements Serializable {
private static final long serialVersionUID = -5007671093920178291L;
/**
* 注册号
*/
@SerializedName("reg_num")
private String regNum;
/**
* 编号
*/
@SerializedName("serial")
private String serial;
/**
* 法定代表人姓名
*/
@SerializedName("legal_representative")
private String legalRepresentative;
/**
* 企业名称
*/
@SerializedName("enterprise_name")
private String enterpriseName;
/**
* 组成形式
*/
@SerializedName("type_of_organization")
private String typeOfOrganization;
/**
* 经营场所/企业住所
*/
@SerializedName("address")
private String address;
/**
* 公司类型
*/
@SerializedName("type_of_enterprise")
private String typeOfEnterprise;
/**
* 经营范围
*/
@SerializedName("business_scope")
private String businessScope;
/**
* 注册资本
*/
@SerializedName("registered_capital")
private String registeredCapital;
/**
* 实收资本
*/
@SerializedName("paid_in_capital")
private String paidInCapital;
/**
* 营业期限
*/
@SerializedName("valid_period")
private String validPeriod;
/**
* 注册日期/成立日期
*/
@SerializedName("registered_date")
private String registeredDate;
/**
* 营业执照位置
*/
@SerializedName("cert_position")
private CertPosition certPosition;
/**
* 图片大小
*/
@SerializedName("img_size")
private WxOcrImgSize imgSize;
public static WxOcrBizLicenseResult fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxOcrBizLicenseResult.class);
}
@Override
public String toString() {
return WxGsonBuilder.create().toJson(this);
}
@Data
public static class CertPosition implements Serializable {
private static final long serialVersionUID = 290286813344131863L;
@SerializedName("pos")
private WxOcrPos pos;
@Override
public String toString() {
return WxGsonBuilder.create().toJson(this);
}
}
}

View File

@ -1,45 +0,0 @@
package com.ossez.wechat.common.bean.ocr;
import com.google.gson.annotations.SerializedName;
import com.ossez.wechat.common.util.json.WxGsonBuilder;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* @author Theo Nie
*/
@Data
public class WxOcrCommResult implements Serializable {
private static final long serialVersionUID = 455833771627756440L;
@SerializedName("img_size")
private WxOcrImgSize imgSize;
@SerializedName("items")
private List<Items> items;
public static WxOcrCommResult fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxOcrCommResult.class);
}
@Override
public String toString() {
return WxGsonBuilder.create().toJson(this);
}
@Data
public static class Items implements Serializable {
private static final long serialVersionUID = 3066181677009102791L;
@SerializedName("text")
private String text;
@SerializedName("pos")
private WxOcrPos pos;
@Override
public String toString() {
return WxGsonBuilder.create().toJson(this);
}
}
}

View File

@ -1,80 +0,0 @@
package com.ossez.wechat.common.bean.ocr;
import com.google.gson.annotations.SerializedName;
import com.ossez.wechat.common.util.json.WxGsonBuilder;
import lombok.Data;
import java.io.Serializable;
/**
* @author Theo Nie
*/
@Data
public class WxOcrDrivingLicenseResult implements Serializable {
private static final long serialVersionUID = -6984670645802585738L;
/**
* 证号
*/
@SerializedName("id_num")
private String idNum;
/**
* 姓名
*/
@SerializedName("name")
private String name;
/**
* 性别
*/
@SerializedName("sex")
private String sex;
/**
* 国籍
*/
@SerializedName("nationality")
private String nationality;
/**
* 住址
*/
@SerializedName("address")
private String address;
/**
* 出生日期
*/
@SerializedName("birth_date")
private String birthDate;
/**
* 初次领证日期
*/
@SerializedName("issue_date")
private String issueDate;
/**
* 准驾车型
*/
@SerializedName("car_class")
private String carClass;
/**
* 有效期限起始日
*/
@SerializedName("valid_from")
private String validFrom;
/**
* 有效期限终止日
*/
@SerializedName("valid_to")
private String validTo;
/**
* 印章文字
*/
@SerializedName("official_seal")
private String officialSeal;
@Override
public String toString() {
return WxGsonBuilder.create().toJson(this);
}
public static WxOcrDrivingLicenseResult fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxOcrDrivingLicenseResult.class);
}
}

View File

@ -1,133 +0,0 @@
package com.ossez.wechat.common.bean.ocr;
import com.google.gson.annotations.SerializedName;
import com.ossez.wechat.common.util.json.WxGsonBuilder;
import lombok.Data;
import java.io.Serializable;
/**
* @author Theo Nie
*/
@Data
public class WxOcrDrivingResult implements Serializable {
private static final long serialVersionUID = -7477484374200211303L;
/**
* 车牌号码
*/
@SerializedName("plate_num")
private String plateNum;
/**
* 车辆类型
*/
@SerializedName("vehicle_type")
private String vehicleType;
/**
* 所有人
*/
@SerializedName("owner")
private String owner;
/**
* 住址
*/
@SerializedName("addr")
private String addr;
/**
* 使用性质
*/
@SerializedName("use_character")
private String useCharacter;
/**
* 品牌型号
*/
@SerializedName("model")
private String model;
/**
* 车辆识别代码
*/
@SerializedName("vin")
private String vin;
/**
* 发动机号码
*/
@SerializedName("engine_num")
private String engineNum;
/**
* 注册日期
*/
@SerializedName("register_date")
private String registerDate;
/**
* 发证日期
*/
@SerializedName("issue_date")
private String issueDate;
/**
* 车牌号码
*/
@SerializedName("plate_num_b")
private String plateNumB;
/**
* 号牌
*/
@SerializedName("record")
private String record;
/**
* 核定载人数
*/
@SerializedName("passengers_num")
private String passengersNum;
/**
* 总质量
*/
@SerializedName("total_quality")
private String totalQuality;
/**
* 整备质量
*/
@SerializedName("prepare_quality")
private String prepareQuality;
/**
* 外廓尺寸
*/
@SerializedName("overall_size")
private String overallSize;
/**
* 卡片正面位置检测到卡片正面才会返回
*/
@SerializedName("card_position_front")
private CardPosition cardPositionFront;
/**
* 卡片反面位置检测到卡片反面才会返回
*/
@SerializedName("card_position_back")
private CardPosition cardPositionBack;
/**
* 图片大小
*/
@SerializedName("img_size")
private WxOcrImgSize imgSize;
@Data
public static class CardPosition implements Serializable {
private static final long serialVersionUID = 2884515165228160517L;
@SerializedName("pos")
private WxOcrPos pos;
@Override
public String toString() {
return WxGsonBuilder.create().toJson(this);
}
}
public static WxOcrDrivingResult fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxOcrDrivingResult.class);
}
@Override
public String toString() {
return WxGsonBuilder.create().toJson(this);
}
}

View File

@ -1,38 +0,0 @@
package com.ossez.wechat.common.bean.ocr;
import com.google.gson.annotations.SerializedName;
import com.ossez.wechat.common.util.json.WxGsonBuilder;
import lombok.Data;
import java.io.Serializable;
/**
* OCR身份证识别结果.
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
* created on 2019-06-23
*/
@Data
public class WxOcrIdCardResult implements Serializable {
private static final long serialVersionUID = 8184352486986729980L;
@SerializedName("type")
private String type;
@SerializedName("name")
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;
public static WxOcrIdCardResult fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxOcrIdCardResult.class);
}
}

View File

@ -1,25 +0,0 @@
package com.ossez.wechat.common.bean.ocr;
import com.google.gson.annotations.SerializedName;
import com.ossez.wechat.common.util.json.WxGsonBuilder;
import lombok.Data;
import java.io.Serializable;
/**
* @author Theo Nie
*/
@Data
public class WxOcrImgSize implements Serializable {
private static final long serialVersionUID = 5234409123551074168L;
@SerializedName("w")
private int w;
@SerializedName("h")
private int h;
@Override
public String toString() {
return WxGsonBuilder.create().toJson(this);
}
}

View File

@ -1,43 +0,0 @@
package com.ossez.wechat.common.bean.ocr;
import com.google.gson.annotations.SerializedName;
import com.ossez.wechat.common.util.json.WxGsonBuilder;
import lombok.Data;
import java.io.Serializable;
/**
* @author Theo Nie
*/
@Data
public class WxOcrPos implements Serializable {
private static final long serialVersionUID = 4204160206873907920L;
@SerializedName("left_top")
private Coordinate leftTop;
@SerializedName("right_top")
private Coordinate rightTop;
@SerializedName("right_bottom")
private Coordinate rightBottom;
@SerializedName("left_bottom")
private Coordinate leftBottom;
@Override
public String toString() {
return WxGsonBuilder.create().toJson(this);
}
@Data
public static class Coordinate implements Serializable {
private static final long serialVersionUID = 8675059935386304399L;
@SerializedName("x")
private int x;
@SerializedName("y")
private int y;
@Override
public String toString() {
return WxGsonBuilder.create().toJson(this);
}
}
}

View File

@ -1,31 +0,0 @@
package com.ossez.wechat.common.bean.result;
import java.io.Serializable;
import com.ossez.wechat.common.util.json.WxGsonBuilder;
import lombok.Data;
/**
*
* @author Daniel Qian
*/
@Data
public class WxMediaUploadResult implements Serializable {
private static final long serialVersionUID = 330834334738622341L;
private String url;
private String type;
private String mediaId;
private String thumbMediaId;
private long createdAt;
public static WxMediaUploadResult fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxMediaUploadResult.class);
}
@Override
public String toString() {
return WxGsonBuilder.create().toJson(this);
}
}

View File

@ -1,39 +0,0 @@
package com.ossez.wechat.common.bean.result;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.ossez.wechat.common.util.json.WxGsonBuilder;
import lombok.Data;
import java.io.Serializable;
@Data
public class WxMinishopImageUploadCustomizeResult implements Serializable {
private String errcode;
private String errmsg;
private WxMinishopPicFileCustomizeResult imgInfo;
public static WxMinishopImageUploadCustomizeResult fromJson(String json) {
JsonObject jsonObject = new JsonParser().parse(json).getAsJsonObject();
WxMinishopImageUploadCustomizeResult result = new WxMinishopImageUploadCustomizeResult();
result.setErrcode(jsonObject.get("errcode").getAsNumber().toString());
if (result.getErrcode().equals("0")) {
WxMinishopPicFileCustomizeResult picFileResult = new WxMinishopPicFileCustomizeResult();
JsonObject picObject = jsonObject.get("img_info").getAsJsonObject();
if (picObject.has("media_id")) {
picFileResult.setMediaId(picObject.get("media_id").getAsString());
}
if (picObject.has("temp_img_url")) {
picFileResult.setTempImgUrl(picObject.get("temp_img_url").getAsString());
}
result.setImgInfo(picFileResult);
}
return result;
}
@Override
public String toString() {
return WxGsonBuilder.create().toJson(this);
}
}

View File

@ -1,45 +0,0 @@
package com.ossez.wechat.common.bean.result;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.ossez.wechat.common.util.json.WxGsonBuilder;
import lombok.Data;
import java.io.Serializable;
@Data
public class WxMinishopImageUploadResult implements Serializable {
private static final long serialVersionUID = 330834334738622332L;
private String errcode;
private String errmsg;
private WxMinishopPicFileResult picFile;
public static WxMinishopImageUploadResult fromJson(String json) {
JsonObject jsonObject = new JsonParser().parse(json).getAsJsonObject();
WxMinishopImageUploadResult result = new WxMinishopImageUploadResult();
result.setErrcode(jsonObject.get("errcode").getAsNumber().toString());
if (result.getErrcode().equals("0")) {
WxMinishopPicFileResult picFileResult = new WxMinishopPicFileResult();
JsonObject picObject = jsonObject.get("pic_file").getAsJsonObject();
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);
}
return result;
}
@Override
public String toString() {
return WxGsonBuilder.create().toJson(this);
}
}

View File

@ -1,11 +0,0 @@
package com.ossez.wechat.common.bean.result;
import lombok.Data;
import java.io.Serializable;
@Data
public class WxMinishopPicFileCustomizeResult implements Serializable {
private String mediaId;
private String tempImgUrl;
}

View File

@ -1,12 +0,0 @@
package com.ossez.wechat.common.bean.result;
import lombok.Data;
import java.io.Serializable;
@Data
public class WxMinishopPicFileResult implements Serializable {
private String mediaId;
private String payMediaId;
private String tempImgUrl;
}

View File

@ -1,19 +0,0 @@
package com.ossez.wechat.common.bean.subscribemsg;
import lombok.Data;
import java.io.Serializable;
/**
* .
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
* created on 2021-01-27
*/
@Data
public class CategoryData implements Serializable {
private static final long serialVersionUID = -5935548352317679892L;
private int id;
private String name;
}

View File

@ -1,21 +0,0 @@
package com.ossez.wechat.common.bean.subscribemsg;
import lombok.Data;
import java.io.Serializable;
/**
* .
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
* created on 2021-01-27
*/
@Data
public class PubTemplateKeyword implements Serializable {
private static final long serialVersionUID = -1100641668859815647L;
private int kid;
private String name;
private String example;
private String rule;
}

View File

@ -1,36 +0,0 @@
package com.ossez.wechat.common.bean.subscribemsg;
import com.ossez.wechat.common.util.json.WxGsonBuilder;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* @author ArBing
*/
@Data
public class PubTemplateTitleListResult implements Serializable {
private static final long serialVersionUID = -7718911668757837527L;
private int count;
private List<TemplateItem> data;
public static PubTemplateTitleListResult fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, PubTemplateTitleListResult.class);
}
@Data
public static class TemplateItem implements Serializable {
private static final long serialVersionUID = 6888726696879905332L;
private Integer type;
private Integer tid;
private String categoryId;
private String title;
}
}

View File

@ -1,22 +0,0 @@
package com.ossez.wechat.common.bean.subscribemsg;
import lombok.Data;
import java.io.Serializable;
/**
* .
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
* created on 2021-01-27
*/
@Data
public class TemplateInfo implements Serializable {
private static final long serialVersionUID = 6971785763573992264L;
private String priTmplId;
private String title;
private String content;
private String example;
private int type;
}

View File

@ -1,227 +0,0 @@
package com.ossez.wechat.common.config;
import com.ossez.wechat.common.model.WeChatAccessToken;
import com.ossez.wechat.common.enums.TicketType;
import com.ossez.wechat.common.util.http.apache.ApacheHttpClientBuilder;
import java.io.File;
import java.util.concurrent.locks.Lock;
/**
* 微信客户端配置存储.
*
* @author chanjarster
*/
public interface ConfigStorage {
/**
* Gets access token.
*
* @return the access token
*/
String getAccessToken();
/**
* Gets access token lock.
*
* @return the access token lock
*/
Lock getAccessTokenLock();
/**
* Is access token expired boolean.
*
* @return the boolean
*/
boolean isAccessTokenExpired();
/**
* 强制将access token过期掉.
*/
void expireAccessToken();
/**
* 应该是线程安全的.
*
* @param accessToken 要更新的WxAccessToken对象
*/
void updateAccessToken(WeChatAccessToken accessToken);
/**
* 应该是线程安全的.
*
* @param accessToken 新的accessToken值
* @param expiresInSeconds 过期时间以秒为单位
*/
void updateAccessToken(String accessToken, int expiresInSeconds);
/**
* Gets ticket.
*
* @param type the type
* @return the ticket
*/
String getTicket(TicketType type);
/**
* Gets ticket lock.
*
* @param type the type
* @return the ticket lock
*/
Lock getTicketLock(TicketType type);
/**
* Is ticket expired boolean.
*
* @param type the type
* @return the boolean
*/
boolean isTicketExpired(TicketType type);
/**
* 强制将ticket过期掉.
*
* @param type the type
*/
void expireTicket(TicketType type);
/**
* 更新ticket.
* 应该是线程安全的
*
* @param type ticket类型
* @param ticket 新的ticket值
* @param expiresInSeconds 过期时间以秒为单位
*/
void updateTicket(TicketType type, String ticket, int expiresInSeconds);
String getOpenAppId();
String getOpenSecret();
/**
* Gets app id.
*
* @return the app id
*/
String getAppId();
/**
* Gets secret.
*
* @return the secret
*/
String getSecret();
/**
* Gets token.
*
* @return the token
*/
String getToken();
/**
* Gets aes key.
*
* @return the aes key
*/
String getAesKey();
/**
* Gets template id.
*
* @return the template id
*/
String getTemplateId();
/**
* Gets expires time.
*
* @return the expires time
*/
long getExpiresTime();
/**
* Gets oauth 2 redirect uri.
*
* @return the oauth 2 redirect uri
*/
String getOauth2redirectUri();
/**
* Gets http proxy host.
*
* @return the http proxy host
*/
String getHttpProxyHost();
/**
* Gets http proxy port.
*
* @return the http proxy port
*/
int getHttpProxyPort();
/**
* Gets http proxy username.
*
* @return the http proxy username
*/
String getHttpProxyUsername();
/**
* Gets http proxy password.
*
* @return the http proxy password
*/
String getHttpProxyPassword();
/**
* http 请求重试间隔
* <pre>
* {@link BaseWeChatOfficialAccountServiceImpl#setRetrySleepMillis(int)}
* </pre>
*/
int getRetrySleepMillis();
/**
* http 请求最大重试次数
* <pre>
* {@link BaseWeChatOfficialAccountServiceImpl#setMaxRetryTimes(int)}
* </pre>
*/
int getMaxRetryTimes();
/**
* Gets tmp dir file.
*
* @return the tmp dir file
*/
File getTmpDirFile();
/**
* http client builder.
*
* @return ApacheHttpClientBuilder apache http client builder
*/
ApacheHttpClientBuilder getApacheHttpClientBuilder();
/**
* 是否自动刷新token.
*
* @return the boolean
*/
boolean autoRefreshToken();
/**
* 得到微信接口地址域名部分的自定义设置信息.
*
* @return the host config
*/
WxMpHostConfig getHostConfig();
/**
* 设置微信接口地址域名部分的自定义设置信息.
*
* @param hostConfig host config
*/
void setHostConfig(WxMpHostConfig hostConfig);
}

View File

@ -1,194 +0,0 @@
package com.ossez.wechat.common.config;
import lombok.Data;
import com.ossez.wechat.common.model.WeChatAccessToken;
import com.ossez.wechat.common.enums.TicketType;
import com.ossez.wechat.common.util.http.apache.ApacheHttpClientBuilder;
import java.io.File;
import java.io.Serializable;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 基于内存的微信配置provider在实际生产环境中应该将这些配置持久化.
*
* @author chanjarster
*/
@Data
public class DefaultConfigStorage implements ConfigStorage, Serializable {
private static final long serialVersionUID = -6646519023303395185L;
protected volatile String openAppId;
protected volatile String openSecret;
protected volatile String appId;
protected volatile String secret;
protected volatile String token;
protected volatile String templateId;
protected volatile String accessToken;
protected volatile String aesKey;
protected volatile long expiresTime;
protected volatile String oauth2redirectUri;
protected volatile String httpProxyHost;
protected volatile int httpProxyPort;
protected volatile String httpProxyUsername;
protected volatile String httpProxyPassword;
protected volatile int retrySleepMillis = 1000;
protected volatile int maxRetryTimes = 5;
protected volatile String jsapiTicket;
protected volatile long jsapiTicketExpiresTime;
protected volatile String sdkTicket;
protected volatile long sdkTicketExpiresTime;
protected volatile String cardApiTicket;
protected volatile long cardApiTicketExpiresTime;
protected volatile Lock accessTokenLock = new ReentrantLock();
protected volatile Lock jsapiTicketLock = new ReentrantLock();
protected volatile Lock sdkTicketLock = new ReentrantLock();
protected volatile Lock cardApiTicketLock = new ReentrantLock();
protected volatile File tmpDirFile;
protected volatile ApacheHttpClientBuilder apacheHttpClientBuilder;
private WxMpHostConfig hostConfig = null;
@Override
public boolean isAccessTokenExpired() {
return System.currentTimeMillis() > this.expiresTime;
}
@Override
public synchronized void updateAccessToken(WeChatAccessToken accessToken) {
updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn());
}
@Override
public synchronized void updateAccessToken(String accessToken, int expiresInSeconds) {
this.accessToken = accessToken;
this.expiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L;
}
@Override
public void expireAccessToken() {
this.expiresTime = 0;
}
@Override
public String getTicket(TicketType type) {
switch (type) {
case SDK:
return this.sdkTicket;
case JSAPI:
return this.jsapiTicket;
case WX_CARD:
return this.cardApiTicket;
default:
return null;
}
}
public void setTicket(TicketType type, String ticket) {
switch (type) {
case JSAPI:
this.jsapiTicket = ticket;
break;
case WX_CARD:
this.cardApiTicket = ticket;
break;
case SDK:
this.sdkTicket = ticket;
break;
default:
}
}
@Override
public Lock getTicketLock(TicketType type) {
switch (type) {
case SDK:
return this.sdkTicketLock;
case JSAPI:
return this.jsapiTicketLock;
case WX_CARD:
return this.cardApiTicketLock;
default:
return null;
}
}
@Override
public boolean isTicketExpired(TicketType type) {
switch (type) {
case SDK:
return System.currentTimeMillis() > this.sdkTicketExpiresTime;
case JSAPI:
return System.currentTimeMillis() > this.jsapiTicketExpiresTime;
case WX_CARD:
return System.currentTimeMillis() > this.cardApiTicketExpiresTime;
default:
return false;
}
}
@Override
public synchronized void updateTicket(TicketType type, String ticket, int expiresInSeconds) {
switch (type) {
case JSAPI:
this.jsapiTicket = ticket;
// 预留200秒的时间
this.jsapiTicketExpiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L;
break;
case WX_CARD:
this.cardApiTicket = ticket;
// 预留200秒的时间
this.cardApiTicketExpiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L;
break;
case SDK:
this.sdkTicket = ticket;
// 预留200秒的时间
this.sdkTicketExpiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L;
break;
default:
}
}
@Override
public void expireTicket(TicketType type) {
switch (type) {
case JSAPI:
this.jsapiTicketExpiresTime = 0;
break;
case WX_CARD:
this.cardApiTicketExpiresTime = 0;
break;
case SDK:
this.sdkTicketExpiresTime = 0;
break;
default:
}
}
@Override
public boolean autoRefreshToken() {
return true;
}
@Override
public WxMpHostConfig getHostConfig() {
return this.hostConfig;
}
@Override
public void setHostConfig(WxMpHostConfig hostConfig) {
this.hostConfig = hostConfig;
}
}

View File

@ -1,45 +0,0 @@
package com.ossez.wechat.common.config;
import com.ossez.wechat.common.config.DefaultConfigStorage;
import lombok.Data;
import com.ossez.wechat.common.model.WeChatAccessToken;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author Brayden Wong
* created on 2021/1/16
* 提供accesstoken保存在concurrenthashmap中的实现支持高并发仅限于单机部署
*/
public class MapConfigStorage extends DefaultConfigStorage {
private static final long serialVersionUID = 5311395137835650104L;
private static final ConcurrentHashMap<String, String> CONCURRENT_HASH_MAP = new ConcurrentHashMap<>(1);
private static final String MAP_KEY = "access_token";
@Override
public String getAccessToken() {
return CONCURRENT_HASH_MAP.get(MAP_KEY);
}
@Override
public void setAccessToken(String accessToken) {
CONCURRENT_HASH_MAP.put(MAP_KEY, accessToken);
}
@Override
public void updateAccessToken(WeChatAccessToken accessToken) {
updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn());
}
@Override
public void updateAccessToken(String accessToken, int expiresInSeconds) {
CONCURRENT_HASH_MAP.put(MAP_KEY, accessToken);
this.expiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L;
}
}

View File

@ -1,98 +0,0 @@
package com.ossez.wechat.common.config;
import com.ossez.wechat.common.config.DefaultConfigStorage;
import lombok.Data;
import lombok.EqualsAndHashCode;
import com.ossez.wechat.common.enums.TicketType;
import com.ossez.wechat.common.redis.WxRedisOps;
import java.util.concurrent.TimeUnit;
/**
* 基于Redis的微信配置provider.
*
* <pre>
* 使用说明本实现仅供参考并不完整
* 比如为减少项目依赖未加入redis分布式锁的实现如有需要请自行实现
* </pre>
*
* @author nickwong
*/
public class RedisConfigStorage extends DefaultConfigStorage {
private static final long serialVersionUID = -988502871997239733L;
private static final String ACCESS_TOKEN_KEY_TPL = "%s:access_token:%s";
private static final String TICKET_KEY_TPL = "%s:ticket:key:%s:%s";
private static final String LOCK_KEY_TPL = "%s:lock:%s:";
private final WxRedisOps redisOps;
private final String keyPrefix;
private String accessTokenKey;
private String lockKey;
public RedisConfigStorage(WxRedisOps redisOps, String keyPrefix) {
this.redisOps = redisOps;
this.keyPrefix = keyPrefix;
}
/**
* 每个公众号生成独有的存储key.
*/
@Override
public void setAppId(String appId) {
super.setAppId(appId);
this.accessTokenKey = String.format(ACCESS_TOKEN_KEY_TPL, this.keyPrefix, appId);
this.lockKey = String.format(LOCK_KEY_TPL, this.keyPrefix, appId);
accessTokenLock = this.redisOps.getLock(lockKey.concat("accessTokenLock"));
jsapiTicketLock = this.redisOps.getLock(lockKey.concat("jsapiTicketLock"));
sdkTicketLock = this.redisOps.getLock(lockKey.concat("sdkTicketLock"));
cardApiTicketLock = this.redisOps.getLock(lockKey.concat("cardApiTicketLock"));
}
private String getTicketRedisKey(TicketType type) {
return String.format(TICKET_KEY_TPL, this.keyPrefix, appId, type.getCode());
}
@Override
public String getAccessToken() {
return redisOps.getValue(this.accessTokenKey);
}
@Override
public boolean isAccessTokenExpired() {
Long expire = redisOps.getExpire(this.accessTokenKey);
return expire == null || expire < 2;
}
@Override
public synchronized void updateAccessToken(String accessToken, int expiresInSeconds) {
redisOps.setValue(this.accessTokenKey, accessToken, expiresInSeconds - 200, TimeUnit.SECONDS);
}
@Override
public void expireAccessToken() {
redisOps.expire(this.accessTokenKey, 0, TimeUnit.SECONDS);
}
@Override
public String getTicket(TicketType type) {
return redisOps.getValue(this.getTicketRedisKey(type));
}
@Override
public boolean isTicketExpired(TicketType type) {
return redisOps.getExpire(this.getTicketRedisKey(type)) < 2;
}
@Override
public synchronized void updateTicket(TicketType type, String jsapiTicket, int expiresInSeconds) {
redisOps.setValue(this.getTicketRedisKey(type), jsapiTicket, expiresInSeconds - 200, TimeUnit.SECONDS);
}
@Override
public void expireTicket(TicketType type) {
redisOps.expire(this.getTicketRedisKey(type), 0, TimeUnit.SECONDS);
}
}

View File

@ -1,68 +0,0 @@
package com.ossez.wechat.common.config;
import com.ossez.wechat.common.constant.WeChatConstant;
/**
* 微信接口地址域名部分的自定义设置信息.
*/
public class WxMpHostConfig {
/**
* 对应于https://api.weixin.qq.com
*/
private String apiHost;
/**
* 对应于https://open.weixin.qq.com
*/
private String openHost;
/**
* 对应于https://mp.weixin.qq.com
*/
private String mpHost;
public static String buildUrl(WxMpHostConfig hostConfig, String prefix, String path) {
if (hostConfig == null) {
return prefix + path;
}
if (hostConfig.getApiHost() != null && prefix.equals(WeChatConstant.ENDPOINT_WECHAT)) {
return hostConfig.getApiHost() + path;
}
if (hostConfig.getMpHost() != null && prefix.equals(WeChatConstant.ENDPOINT_MP)) {
return hostConfig.getMpHost() + path;
}
if (hostConfig.getOpenHost() != null && prefix.equals(WeChatConstant.ENDPOINT_OPEN)) {
return hostConfig.getOpenHost() + path;
}
return prefix + path;
}
public String getApiHost() {
return apiHost;
}
public void setApiHost(String apiHost) {
this.apiHost = apiHost;
}
public String getOpenHost() {
return openHost;
}
public void setOpenHost(String openHost) {
this.openHost = openHost;
}
public String getMpHost() {
return mpHost;
}
public void setMpHost(String mpHost) {
this.mpHost = mpHost;
}
}

View File

@ -1,16 +0,0 @@
package com.ossez.wechat.common.constant;
import com.google.common.net.MediaType;
/**
* HttpClient send request the type constant.
* Because okHttp need to use MediaType to construct object, but if we use guava MediaType, the two package will get conflict
* at the same class.
* <p>
* So, we get MediaType String first before we convert to okHttp MediaType.
*
* @author YuCheng Hu
*/
public final class HttpClientMediaType {
public static final String APPLICATION_JSON = MediaType.JSON_UTF_8.toString();
}

View File

@ -1,154 +0,0 @@
package com.ossez.wechat.common.constant;
/**
* <pre>
* 微信公众号事件的相关常量
* Created by Binary Wang on 2017-5-10.
* </pre>
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
public class OfficialAccountEventConstants {
/**
* 门店审核事件.
*/
public static final String POI_CHECK_NOTIFY = "poi_check_notify";
/**
* 接收会员信息事件.
*/
public static final String SUBMIT_MEMBERCARD_USER_INFO = "submit_membercard_user_info";
/**
* 微信摇一摇周边>>摇一摇事件通知.
*/
public static final String SHAKEAROUND_USER_SHAKE = "ShakearoundUserShake";
/**
* 卡券相关事件.
*/
public static class Card {
public static final String CARD_PASS_CHECK = "card_pass_check";
public static final String CARD_NOT_PASS_CHECK = "card_not_pass_check";
public static final String USER_GET_CARD = "user_get_card";
public static final String USER_DEL_CARD = "user_del_card";
public static final String USER_CONSUME_CARD = "user_consume_card";
public static final String USER_PAY_FROM_PAY_CELL = "user_pay_from_pay_cell";
public static final String USER_VIEW_CARD = "user_view_card";
public static final String USER_ENTER_SESSION_FROM_CARD = "user_enter_session_from_card";
/**
* 卡券转赠事件.
*/
public static final String USER_GIFTING_CARD = "user_gifting_card";
/**
* 库存报警.
*/
public static final String CARD_SKU_REMIND = "card_sku_remind";
/**
* 会员卡内容更新事件.
*/
public static final String UPDATE_MEMBER_CARD = "update_member_card";
/**
* 券点流水详情事件.
*/
public static final String CARD_PAY_ORDER = "card_pay_order";
/**
* 用户购买礼品卡付款成功事件.
*/
public static final String GIFTCARD_PAY_DONE = "giftcard_pay_done";
/**
* 用户购买后赠送事件.
*/
public static final String GIFTCARD_SEND_TO_FRIEND = "giftcard_send_to_friend";
/**
* 用户领取礼品卡成功事件.
*/
public static final String GIFTCARD_USER_ACCEPT = "giftcard_user_accept";
}
/**
* 客服相关事件.
*/
public static class CustomerService {
/**
* 客服接入会话.
*/
public static final String KF_CREATE_SESSION = "kf_create_session";
/**
* 客服关闭会话.
*/
public static final String KF_CLOSE_SESSION = "kf_close_session";
/**
* 客服转接会话.
*/
public static final String KF_SWITCH_SESSION = "kf_switch_session";
}
/**
* 微信认证事件.
*/
public static class Qualification {
/**
* 资质认证成功.
*/
public static final String QUALIFICATION_VERIFY_SUCCESS = "qualification_verify_success";
/**
* 资质认证失败.
*/
public static final String QUALIFICATION_VERIFY_FAIL = "qualification_verify_fail";
/**
* 名称认证成功.
*/
public static final String NAMING_VERIFY_SUCCESS = "naming_verify_success";
/**
* 名称认证失败.
*/
public static final String NAMING_VERIFY_FAIL = "naming_verify_fail";
/**
* 年审通知.
*/
public static final String ANNUAL_RENEW = "annual_renew";
/**
* 认证过期失效通知.
*/
public static final String VERIFY_EXPIRED = "verify_expired";
}
/**
* 电子发票.
*/
public static class Invoice {
/**
* 用户授权事件.
*/
public static final String USER_AUTHORIZE_INVOICE = "user_authorize_invoice";
/**
* 统一开票接口-异步通知开票结果.
*/
public static final String CLOUD_INVOICE_INVOICERESULT_EVENT = "cloud_invoice_invoiceresult_event";
}
/**
* 对话助手相关事件
*/
public static class Guide {
/**
* 顾问邀请结果通知事件.
*/
public static final String GUIDE_INVITE_RESULT_EVENT = "guide_invite_result_event";
}
}

View File

@ -1,5 +0,0 @@
package com.ossez.wechat.common.constant;
public class WeChatApiParameter {
public static final String ACCESS_TOKEN_GRANT_TYPE_CLIENT_CREDENTIAL = "client_credential";
}

View File

@ -1,556 +0,0 @@
package com.ossez.wechat.common.constant;
import com.ossez.wechat.common.enums.WeChatErrorCode;
import java.util.*;
/**
* The constant of WeChat
*
* @author YuCheng Hu
*/
public class WeChatConstant {
public static final String ENDPOINT_WECHAT = "https://api.weixin.qq.com";
public static final String ENDPOINT_MP = "https://mp.weixin.qq.com";
public static final String ENDPOINT_OPEN = "https://open.weixin.qq.com";
/**
* access_token 相关错误代码
* <pre>
* 发生以下情况时尝试刷新access_token
* 40001 获取access_token时AppSecret错误或者access_token无效
* 42001 access_token超时
* 40014 不合法的access_token请开发者认真比对access_token的有效性如是否过期或查看是否正在为恰当的公众号调用接口
* </pre>
*/
public static final EnumSet<WeChatErrorCode> ACCESS_TOKEN_ERROR_CODES_SET = EnumSet.of(WeChatErrorCode.CODE_40001, WeChatErrorCode.CODE_40014, WeChatErrorCode.CODE_42001);
@Deprecated
public static final List<Integer> ACCESS_TOKEN_ERROR_CODES = Arrays.asList(WeChatErrorCode.CODE_40001.getCode(),
WeChatErrorCode.CODE_40014.getCode(), WeChatErrorCode.CODE_42001.getCode());
/**
* 微信推送过来的消息的类型和发送给微信xml格式消息的消息类型.
*/
public static class XmlMsgType {
public static final String TEXT = "text";
public static final String IMAGE = "image";
public static final String VOICE = "voice";
public static final String SHORTVIDEO = "shortvideo";
public static final String VIDEO = "video";
public static final String NEWS = "news";
public static final String MUSIC = "music";
public static final String LOCATION = "location";
public static final String LINK = "link";
public static final String EVENT = "event";
public static final String DEVICE_TEXT = "device_text";
public static final String DEVICE_EVENT = "device_event";
public static final String DEVICE_STATUS = "device_status";
public static final String HARDWARE = "hardware";
public static final String TRANSFER_CUSTOMER_SERVICE = "transfer_customer_service";
public static final String UPDATE_TASKCARD = "update_taskcard";
public static final String UPDATE_BUTTON = "update_button";
}
/**
* 主动发送消息(即客服消息)的消息类型.
*/
public static class MsgType {
/**
* 消息类型:
* text(文本)
* image(图片)
* voice(语音)
* video(视频)
* music(音乐)
* news(图文消息 - 点击跳转到外链)
* mpnews(图文消息 - 点击跳转到图文消息页面)
* wxcard(卡券)
* miniprogrampage(小程序)
* markdown(目前仅支持markdown语法的子集微工作台原企业号不支持展示markdown消息)
* file(发送文件 - CP专用)
* textcard(文本卡片消息 - CP专用)
* wxcard(卡券消息)
*/
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 MUSIC = "music";
public static final String NEWS = "news";
public static final String MPNEWS = "mpnews";
public static final String MARKDOWN = "markdown";
public static final String FILE = "file";
public static final String TEXTCARD = "textcard";
public static final String WXCARD = "wxcard";
/**
* 转发到客服的消息.
*/
public static final String TRANSFER_CUSTOMER_SERVICE = "transfer_customer_service";
/**
* 小程序卡片(要求小程序与公众号已关联).
*/
public static final String MINIPROGRAMPAGE = "miniprogrampage";
/**
* 任务卡片消息.
*/
public static final String TASKCARD = "taskcard";
/**
* 菜单消息.
*/
public static final String MSGMENU = "msgmenu";
/**
* 小程序通知消息.
*/
public static final String MINIPROGRAM_NOTICE = "miniprogram_notice";
/**
* 模板卡片消息.
*/
public static final String TEMPLATE_CARD = "template_card";
/**
* 发送图文消息点击跳转到图文消息页面使用通过 发布 系列接口得到的 article_id(草稿箱功能上线后不再支持客服接口中带 media_id mpnews 类型的图文消息)
*/
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";
}
/**
* 企业微信模板卡片消息的卡片类型
*/
public static class TemplateCardType {
/**
* 文本通知型卡片
*/
public static final String TEXT_NOTICE = "text_notice";
/**
* 图文展示型卡片
*/
public static final String NEWS_NOTICE = "news_notice";
/**
* 按钮交互型卡片
*/
public static final String BUTTON_INTERACTION = "button_interaction";
/**
* 投票选择型卡片
*/
public static final String VOTE_INTERACTION = "vote_interaction";
/**
* 多项选择型卡片
*/
public static final String MULTIPLE_INTERACTION = "multiple_interaction";
}
/**
* 表示是否是保密消息0表示否1表示是默认0.
*/
public static class KefuMsgSafe {
public static final String NO = "0";
public static final String YES = "1";
}
/**
* 群发消息的消息类型.
*/
public static class MassMsgType {
public static final String MPNEWS = "mpnews";
public static final String TEXT = "text";
public static final String VOICE = "voice";
public static final String IMAGE = "image";
public static final String IMAGES = "images";
public static final String MPVIDEO = "mpvideo";
}
/**
* 群发消息后微信端推送给服务器的反馈消息.
*/
public static class MassMsgStatus {
public static final String SEND_SUCCESS = "send success";
public static final String SEND_FAIL = "send fail";
public static final String ERR_10001 = "err(10001)";
public static final String ERR_20001 = "err(20001)";
public static final String ERR_20004 = "err(20004)";
public static final String ERR_20002 = "err(20002)";
public static final String ERR_20006 = "err(20006)";
public static final String ERR_20008 = "err(20008)";
public static final String ERR_20013 = "err(20013)";
public static final String ERR_22000 = "err(22000)";
public static final String ERR_21000 = "err(21000)";
public static final String ERR_30001 = "err(30001)";
public static final String ERR_30002 = "err(30002)";
public static final String ERR_30003 = "err(30003)";
public static final String ERR_40001 = "err(40001)";
public static final String ERR_40002 = "err(40002)";
/**
* 群发反馈消息代码所对应的文字描述.
*/
public static final Map<String, String> STATUS_DESC = new HashMap<>();
static {
STATUS_DESC.put(SEND_SUCCESS, "发送成功");
STATUS_DESC.put(SEND_FAIL, "发送失败");
STATUS_DESC.put(ERR_10001, "涉嫌广告");
STATUS_DESC.put(ERR_20001, "涉嫌政治");
STATUS_DESC.put(ERR_20004, "涉嫌社会");
STATUS_DESC.put(ERR_20002, "涉嫌色情");
STATUS_DESC.put(ERR_20006, "涉嫌违法犯罪");
STATUS_DESC.put(ERR_20008, "涉嫌欺诈");
STATUS_DESC.put(ERR_20013, "涉嫌版权");
STATUS_DESC.put(ERR_22000, "涉嫌互推_互相宣传");
STATUS_DESC.put(ERR_21000, "涉嫌其他");
STATUS_DESC.put(ERR_30001, "原创校验出现系统错误且用户选择了被判为转载就不群发");
STATUS_DESC.put(ERR_30002, "原创校验被判定为不能群发");
STATUS_DESC.put(ERR_30003, "原创校验被判定为转载文且用户选择了被判为转载就不群发");
STATUS_DESC.put(ERR_40001, "管理员拒绝");
STATUS_DESC.put(ERR_40002, "管理员30分钟内无响应超时");
}
}
/**
* 微信端推送过来的事件类型.
*/
public static class EventType {
public static final String SUBSCRIBE = "subscribe";
public static final String UNSUBSCRIBE = "unsubscribe";
public static final String SCAN = "SCAN";
public static final String LOCATION = "LOCATION";
public static final String CLICK = "CLICK";
public static final String VIEW = "VIEW";
public static final String MASS_SEND_JOB_FINISH = "MASSSENDJOBFINISH";
/**
* 扫码推事件的事件推送
*/
public static final String SCANCODE_PUSH = "scancode_push";
/**
* 扫码推事件且弹出消息接收中提示框的事件推送.
*/
public static final String SCANCODE_WAITMSG = "scancode_waitmsg";
/**
* 弹出系统拍照发图的事件推送.
*/
public static final String PIC_SYSPHOTO = "pic_sysphoto";
/**
* 弹出拍照或者相册发图的事件推送.
*/
public static final String PIC_PHOTO_OR_ALBUM = "pic_photo_or_album";
/**
* 弹出微信相册发图器的事件推送.
*/
public static final String PIC_WEIXIN = "pic_weixin";
/**
* 弹出地理位置选择器的事件推送.
*/
public static final String LOCATION_SELECT = "location_select";
/**
* 授权用户资料变更事件
* 1 当部分用户的资料存在风险时平台会对用户资料进行清理并通过消息推送服务器通知最近30天授权过的公众号开发者我们建议开发者留意响应该事件及时主动更新或清理用户的头像及昵称降低风险
* 2 当用户撤回授权信息时平台会通过消息推送服务器通知给公众号开发者请开发者注意及时删除用户信息
*/
public static final String USER_INFO_MODIFIED = "user_info_modified";
/**
* 用户撤回授权事件
*/
public static final String USER_AUTHORIZATION_REVOKE = "user_authorization_revoke";
/**
* 群发模板回调事件
*/
public static final String TEMPLATE_SEND_JOB_FINISH = "TEMPLATESENDJOBFINISH";
/**
* 微信小店 订单付款通知.
*/
public static final String MERCHANT_ORDER = "merchant_order";
/**
* 卡券事件卡券通过审核
*/
public static final String CARD_PASS_CHECK = "card_pass_check";
/**
* 卡券事件卡券未通过审核
*/
public static final String CARD_NOT_PASS_CHECK = "card_not_pass_check";
/**
* 卡券事件用户领取卡券
*/
public static final String CARD_USER_GET_CARD = "user_get_card";
/**
* 卡券事件用户转赠卡券
*/
public static final String CARD_USER_GIFTING_CARD = "user_gifting_card";
/**
* 异步安全校验事件
*/
public static final String WXA_MEDIA_CHECK = "wxa_media_check";
/**
* 卡券事件用户核销卡券
*/
public static final String CARD_USER_CONSUME_CARD = "user_consume_card";
/**
* 卡券事件用户通过卡券的微信买单完成时推送
*/
public static final String CARD_USER_PAY_FROM_PAY_CELL = "user_pay_from_pay_cell";
/**
* 卡券事件用户提交会员卡开卡信息
*/
public static final String CARD_SUBMIT_MEMBERCARD_USER_INFO = "submit_membercard_user_info";
/**
* 卡券事件用户打开查看卡券
*/
public static final String CARD_USER_VIEW_CARD = "user_view_card";
/**
* 卡券事件用户删除卡券
*/
public static final String CARD_USER_DEL_CARD = "user_del_card";
/**
* 卡券事件用户在卡券里点击查看公众号进入会话时需要用户已经关注公众号
*/
public static final String CARD_USER_ENTER_SESSION_FROM_CARD = "user_enter_session_from_card";
/**
* 卡券事件当用户的会员卡积分余额发生变动时
*/
public static final String CARD_UPDATE_MEMBER_CARD = "update_member_card";
/**
* 卡券事件当某个card_id的初始库存数大于200且当前库存小于等于100时用户尝试领券会触发发送事件给商户事件每隔12h发送一次
*/
public static final String CARD_SKU_REMIND = "card_sku_remind";
/**
* 卡券事件当商户朋友的券券点发生变动时
*/
public static final String CARD_PAY_ORDER = "card_pay_order";
/**
* 小程序审核事件审核通过
*/
public static final String WEAPP_AUDIT_SUCCESS = "weapp_audit_success";
/**
* 小程序审核事件审核不通过
*/
public static final String WEAPP_AUDIT_FAIL = "weapp_audit_fail";
/**
* 小程序自定义交易组件支付通知
*/
public static final String OPEN_PRODUCT_ORDER_PAY = "open_product_order_pay";
/**
* 点击菜单跳转小程序的事件推送
*/
public static final String VIEW_MINIPROGRAM = "view_miniprogram";
/**
* 订阅通知事件用户操作订阅通知弹窗
*/
public static final String SUBSCRIBE_MSG_POPUP_EVENT = "subscribe_msg_popup_event";
/**
* 订阅通知事件用户管理订阅通知
*/
public static final String SUBSCRIBE_MSG_CHANGE_EVENT = "subscribe_msg_change_event";
/**
* 订阅通知事件发送订阅通知回调
*/
public static final String SUBSCRIBE_MSG_SENT_EVENT = "subscribe_msg_sent_event";
}
/**
* 上传多媒体临时素材文件的类型.
*/
public static class MediaFileType {
public static final String IMAGE = "image";
public static final String VOICE = "voice";
public static final String VIDEO = "video";
public static final String THUMB = "thumb";
public static final String FILE = "file";
}
/**
* 自定义菜单的按钮类型.
*/
public static class MenuButtonType {
/**
* 点击推事件.
*/
public static final String CLICK = "click";
/**
* 跳转URL.
*/
public static final String VIEW = "view";
/**
* 跳转到小程序.
*/
public static final String MINIPROGRAM = "miniprogram";
/**
* 扫码推事件.
*/
public static final String SCANCODE_PUSH = "scancode_push";
/**
* 扫码推事件且弹出消息接收中提示框.
*/
public static final String SCANCODE_WAITMSG = "scancode_waitmsg";
/**
* 弹出系统拍照发图.
*/
public static final String PIC_SYSPHOTO = "pic_sysphoto";
/**
* 弹出拍照或者相册发图.
*/
public static final String PIC_PHOTO_OR_ALBUM = "pic_photo_or_album";
/**
* 弹出微信相册发图器.
*/
public static final String PIC_WEIXIN = "pic_weixin";
/**
* 弹出地理位置选择器.
*/
public static final String LOCATION_SELECT = "location_select";
/**
* 下发消息除文本消息.
*/
public static final String MEDIA_ID = "media_id";
/**
* 跳转图文消息URL.
*/
public static final String VIEW_LIMITED = "view_limited";
}
/**
* oauth2网页授权的scope.
*/
public static class OAuth2Scope {
/**
* 不弹出授权页面直接跳转只能获取用户openid.
*/
public static final String SNSAPI_BASE = "snsapi_base";
/**
* 弹出授权页面可通过openid拿到昵称性别所在地并且即使在未关注的情况下只要用户授权也能获取其信息.
*/
public static final String SNSAPI_USERINFO = "snsapi_userinfo";
/**
* 手动授权,可获取成员的详细信息,包含手机邮箱只适用于企业微信或企业号.
*/
public static final String SNSAPI_PRIVATEINFO = "snsapi_privateinfo";
}
/**
* 网页应用登录授权作用域.
*/
public static class QrConnectScope {
public static final String SNSAPI_LOGIN = "snsapi_login";
}
/**
* 永久素材类型.
*/
public static class MaterialType {
public static final String NEWS = "news";
public static final String VOICE = "voice";
public static final String IMAGE = "image";
public static final String VIDEO = "video";
}
/**
* 网络检测入参.
*/
public static class NetCheckArgs {
public static final String ACTIONDNS = "dns";
public static final String ACTIONPING = "ping";
public static final String ACTIONALL = "all";
public static final String OPERATORUNICOM = "UNICOM";
public static final String OPERATORCHINANET = "CHINANET";
public static final String OPERATORCAP = "CAP";
public static final String OPERATORDEFAULT = "DEFAULT";
}
/**
* appId 类型
*/
public static class AppIdType {
/**
* 公众号appId类型
*/
public static final String MP_TYPE = "mp";
/**
* 小程序appId类型
*/
public static final String MINI_TYPE = "mini";
}
}

View File

@ -1,20 +0,0 @@
package com.ossez.wechat.common.enums;
/**
* The language for WeChat API can support
*
* @author YuCheng Hu
*/
public enum Language {
ZH_CN("zh_CN"), EN_US("en_US");
private String code;
Language(String code) {
this.code = code;
}
public String getCode() {
return code;
}
}

View File

@ -1,35 +0,0 @@
package com.ossez.wechat.common.enums;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* <pre>
* ticket类型枚举
* Created by Binary Wang on 2018/11/18.
* </pre>
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@Getter
@RequiredArgsConstructor
public enum TicketType {
/**
* jsapi
*/
JSAPI("jsapi"),
/**
* sdk
*/
SDK("2"),
/**
* 微信卡券
*/
WX_CARD("wx_card");
/**
* type代码
*/
private final String code;
}

View File

@ -1,207 +0,0 @@
package com.ossez.wechat.common.enums;
import com.google.common.collect.Maps;
import java.util.Map;
/**
* WeChat Error Code
* <pre>
* 微信公众平台全局返回码.
* 参考文档<a href="https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Global_Return_Code.html">公众平台全局返回码</a>
* </pre>
*
* @author YuCheng Hu
*/
public enum WeChatErrorCode {
CODE_1(-1, "系统繁忙,此时请开发者稍候再试"),
CODE_0(0, "请求成功"),
CODE_40001(40001, "获取 access_token 时 AppSecret 错误,或者 access_token 无效。请开发者认真比对 AppSecret 的正确性,或查看是否正在为恰当的公众号调用接口"),
CODE_40002(40002, "不合法的凭证类型"),
CODE_40003(40003, "不合法的 OpenID ,请开发者确认 OpenID (该用户)是否已关注公众号,或是否是其他公众号的 OpenID"),
CODE_40004(40004, "不合法的媒体文件类型"),
CODE_40005(40005, "不合法的文件类型"),
CODE_40006(40006, "不合法的文件大小"),
CODE_40007(40007, "不合法的媒体文件 id"),
CODE_40008(40008, "不合法的消息类型"),
CODE_40009(40009, "不合法的图片文件大小"),
CODE_40010(40010, "不合法的语音文件大小"),
CODE_40011(40011, "不合法的视频文件大小"),
CODE_40012(40012, "不合法的缩略图文件大小"),
CODE_40013(40013, "不合法的 AppID ,请开发者检查 AppID 的正确性,避免异常字符,注意大小写"),
CODE_40014(40014, "不合法的 access_token ,请开发者认真比对 access_token 的有效性(如是否过期),或查看是否正在为恰当的公众号调用接口"),
CODE_40015(40015, "不合法的菜单类型"),
CODE_40016(40016, "不合法的按钮个数"),
CODE_40017(40017, "不合法的按钮类型"),
CODE_40018(40018, "不合法的按钮名字长度"),
CODE_40019(40019, "不合法的按钮 KEY 长度"),
CODE_40020(40020, "不合法的按钮 URL 长度"),
CODE_40021(40021, "不合法的菜单版本号"),
CODE_40022(40022, "不合法的子菜单级数"),
CODE_40023(40023, "不合法的子菜单按钮个数"),
CODE_40024(40024, "不合法的子菜单按钮类型"),
CODE_40025(40025, "不合法的子菜单按钮名字长度"),
CODE_40026(40026, "不合法的子菜单按钮 KEY 长度"),
CODE_40027(40027, "不合法的子菜单按钮 URL 长度"),
CODE_40028(40028, "不合法的自定义菜单使用用户"),
CODE_40029(40029, "不合法的 oauth_code"),
CODE_40030(40030, "不合法的 refresh_token"),
CODE_40031(40031, "不合法的 openid 列表"),
CODE_40032(40032, "不合法的 openid 列表长度"),
CODE_40033(40033, "不合法的请求字符,不能包含\\uxxxx 格式的字符"),
CODE_40035(40035, "不合法的参数"),
CODE_40038(40038, "不合法的请求格式"),
CODE_40039(40039, "不合法的 URL 长度"),
CODE_40050(40050, "不合法的分组 id"),
CODE_40051(40051, "分组名字不合法"),
CODE_40060(40060, "删除单篇图文时,指定的 article_idx 不合法"),
CODE_40117(40117, "分组名字不合法"),
CODE_40118(40118, "media_id 大小不合法"),
CODE_40119(40119, "button 类型错误"),
CODE_40120(40120, "button 类型错误"),
CODE_40121(40121, "不合法的 media_id 类型"),
CODE_40132(40132, "微信号不合法"),
CODE_40137(40137, "不支持的图片格式"),
CODE_40155(40155, "请勿添加其他公众号的主页链接"),
CODE_40163(40163, "oauth_code已使用"),
CODE_41001(41001, "缺少 access_token 参数"),
CODE_41002(41002, "缺少 appid 参数"),
CODE_41003(41003, "缺少 refresh_token 参数"),
CODE_41004(41004, "缺少 secret 参数"),
CODE_41005(41005, "缺少多媒体文件数据"),
CODE_41006(41006, "缺少 media_id 参数"),
CODE_41007(41007, "缺少子菜单数据"),
CODE_41008(41008, "缺少 oauth code"),
CODE_41009(41009, "缺少 openid"),
CODE_42001(42001, "access_token 超时,请检查 access_token 的有效期,请参考基础支持 - 获取 access_token 中,对 access_token 的详细机制说明"),
CODE_42002(42002, "refresh_token 超时"),
CODE_42003(42003, "oauth_code 超时"),
CODE_42007(42007, "用户修改微信密码, accesstoken 和 refreshtoken 失效,需要重新授权"),
CODE_43001(43001, "需要 GET 请求"),
CODE_43002(43002, "需要 POST 请求"),
CODE_43003(43003, "需要 HTTPS 请求"),
CODE_43004(43004, "需要接收者关注"),
CODE_43005(43005, "需要好友关系"),
CODE_43019(43019, "需要将接收者从黑名单中移除"),
CODE_44001(44001, "多媒体文件为空"),
CODE_44002(44002, "POST 的数据包为空"),
CODE_44003(44003, "图文消息内容为空"),
CODE_44004(44004, "文本消息内容为空"),
CODE_45001(45001, "多媒体文件大小超过限制"),
CODE_45002(45002, "消息内容超过限制"),
CODE_45003(45003, "标题字段超过限制"),
CODE_45004(45004, "描述字段超过限制"),
CODE_45005(45005, "链接字段超过限制"),
CODE_45006(45006, "图片链接字段超过限制"),
CODE_45007(45007, "语音播放时间超过限制"),
CODE_45008(45008, "图文消息超过限制"),
CODE_45009(45009, "接口调用超过限制"),
CODE_45010(45010, "创建菜单个数超过限制"),
CODE_45011(45011, "API 调用太频繁,请稍候再试"),
CODE_45015(45015, "回复时间超过限制"),
CODE_45016(45016, "系统分组,不允许修改"),
CODE_45017(45017, "分组名字过长"),
CODE_45018(45018, "分组数量超过上限"),
CODE_45047(45047, "客服接口下行条数超过上限"),
CODE_45159(45159, "非法的tag_id"),
CODE_45065(45065, "相同 clientmsgid 已存在群发记录,返回数据中带有已存在的群发任务的 msgid"),
CODE_45066(45066, "相同 clientmsgid 重试速度过快请间隔1分钟重试"),
CODE_45067(45067, "clientmsgid 长度超过限制"),
CODE_46001(46001, "不存在媒体数据"),
CODE_46002(46002, "不存在的菜单版本"),
CODE_46003(46003, "不存在的菜单数据"),
CODE_46004(46004, "不存在的用户"),
CODE_47001(47001, "解析 JSON/XML 内容错误"),
CODE_48001(48001, "api 功能未授权,请确认公众号已获得该接口,可以在公众平台官网 - 开发者中心页中查看接口权限"),
CODE_48002(48002, "粉丝拒收消息(粉丝在公众号选项中,关闭了 “ 接收消息 ” "),
CODE_48004(48004, "api 接口被封禁,请登录 mp.weixin.qq.com 查看详情"),
CODE_48005(48005, "api 禁止删除被自动回复和自定义菜单引用的素材"),
CODE_48006(48006, "api 禁止清零调用次数,因为清零次数达到上限"),
CODE_48008(48008, "没有该类型消息的发送权限"),
CODE_50001(50001, "用户未授权该 api"),
CODE_50002(50002, "用户受限,可能是违规后接口被封禁"),
CODE_50005(50005, "用户未关注公众号"),
CODE_61451(61451, "参数错误 (invalid parameter)"),
CODE_61452(61452, "无效客服账号 (invalid kf_account)"),
CODE_61453(61453, "客服帐号已存在 (kf_account exsited)"),
CODE_61454(61454, "客服帐号名长度超过限制 ( 仅允许 10 个英文字符,不包括 @ 及 @ 后的公众号的微信号 )(invalid kf_acount length)"),
CODE_61455(61455, "客服帐号名包含非法字符 ( 仅允许英文 + 数字 )(illegal character in kf_account)"),
CODE_61456(61456, "客服帐号个数超过限制 (10 个客服账号 )(kf_account count exceeded)"),
CODE_61457(61457, "无效头像文件类型 (invalid file type)"),
CODE_61450(61450, "系统错误 (system error)"),
CODE_61500(61500, "日期格式错误"),
CODE_65301(65301, "不存在此 menuid 对应的个性化菜单"),
CODE_65302(65302, "没有相应的用户"),
CODE_65303(65303, "没有默认菜单,不能创建个性化菜单"),
CODE_65304(65304, "MatchRule 信息为空"),
CODE_65305(65305, "个性化菜单数量受限"),
CODE_65306(65306, "不支持个性化菜单的帐号"),
CODE_65307(65307, "个性化菜单信息为空"),
CODE_65308(65308, "包含没有响应类型的 button"),
CODE_65309(65309, "个性化菜单开关处于关闭状态"),
CODE_65310(65310, "填写了省份或城市信息,国家信息不能为空"),
CODE_65311(65311, "填写了城市信息,省份信息不能为空"),
CODE_65312(65312, "不合法的国家信息"),
CODE_65313(65313, "不合法的省份信息"),
CODE_65314(65314, "不合法的城市信息"),
CODE_65316(65316, "该公众号的菜单设置了过多的域名外跳(最多跳转到 3 个域名的链接)"),
CODE_65317(65317, "不合法的 URL"),
CODE_9001001(9001001, "POST 数据参数不合法"),
CODE_9001002(9001002, "远端服务不可用"),
CODE_9001003(9001003, "Ticket 不合法"),
CODE_9001004(9001004, "获取摇周边用户信息失败"),
CODE_9001005(9001005, "获取商户信息失败"),
CODE_9001006(9001006, "获取 OpenID 失败"),
CODE_9001007(9001007, "上传文件缺失"),
CODE_9001008(9001008, "上传素材的文件类型不合法"),
CODE_9001009(9001009, "上传素材的文件尺寸不合法"),
CODE_9001010(9001010, "上传失败"),
CODE_9001020(9001020, "帐号不合法"),
CODE_9001021(9001021, "已有设备激活率低于 50% ,不能新增设备"),
CODE_9001022(9001022, "设备申请数不合法,必须为大于 0 的数字"),
CODE_9001023(9001023, "已存在审核中的设备 ID 申请"),
CODE_9001024(9001024, "一次查询设备 ID 数量不能超过 50"),
CODE_9001025(9001025, "设备 ID 不合法"),
CODE_9001026(9001026, "页面 ID 不合法"),
CODE_9001027(9001027, "页面参数不合法"),
CODE_9001028(9001028, "一次删除页面 ID 数量不能超过 10"),
CODE_9001029(9001029, "页面已应用在设备中,请先解除应用关系再删除"),
CODE_9001030(9001030, "一次查询页面 ID 数量不能超过 50"),
CODE_9001032(9001032, "保存设备与页面的绑定关系参数错误"),
CODE_9001033(9001033, "门店 ID 不合法"),
CODE_9001034(9001034, "设备备注信息过长"),
CODE_9001035(9001035, "设备申请参数不合法"),
CODE_9001036(9001036, "查询起始值 begin 不合法"),
CODE_45083(45083, "设置的 speed 参数不在0到4的范围内"),
CODE_45084(45084, "没有设置 speed 参数");
private final int code;
private final String msg;
WeChatErrorCode(int code, String msg) {
this.code = code;
this.msg = msg;
}
public int getCode() {
return code;
}
public String getMsg() {
return msg;
}
static final Map<Integer, String> valueMap = Maps.newHashMap();
static {
for (WeChatErrorCode value : WeChatErrorCode.values()) {
valueMap.put(value.code, value.msg);
}
}
/**
* 通过错误代码查找其中文含义..
*/
public static String findMsgByCode(int code) {
return valueMap.getOrDefault(code, null);
}
}

View File

@ -1,12 +0,0 @@
package com.ossez.wechat.common.enums;
/**
* WeChat's Storage Category
*
* We provide implement for MEM(RAM) and REDIS
*
* @author YuCheng Hu
*/
public enum WeChatStorageCategory {
MEM, REDIS
}

View File

@ -1,25 +0,0 @@
package com.ossez.wechat.common.enums;
/**
* 微信卡券
*
* @author YuCheng
*/
public enum WxCardType {
MEMBER_CARD("MEMBER_CARD"),
GROUPON("GROUPON"),
CASH("CASH"),
DISCOUNT("DISCOUNT"),
GIFT("GIFT"),
GENERAL_COUPON("GENERAL_COUPON");
private String code;
WxCardType(String code) {
this.code = code;
}
public String getCode() {
return code;
}
}

View File

@ -1,32 +0,0 @@
package com.ossez.wechat.common.enums;
/**
* <pre>
* 微信类型枚举.
* Created by BinaryWang on 2018/5/14.
* </pre>
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
public enum WxType {
/**
* 企业微信.
*/
CP,
/**
* 微信公众号.
*/
MP,
/**
* 微信小程序.
*/
MiniApp,
/**
* 微信开放平台.
*/
Open,
/**
* 微信支付.
*/
Pay;
}

View File

@ -1,26 +0,0 @@
package com.ossez.wechat.common.exception;
/**
* @author Daniel Qian
*/
public class DataStructureException extends WxErrorException {
private static final long serialVersionUID = -6357149550353160810L;
private final WxError error;
private static final int DEFAULT_ERROR_CODE = -99;
public DataStructureException(String message) {
this(WxError.builder().errorCode(DEFAULT_ERROR_CODE).errorMsg(message).build());
}
public DataStructureException(WxError error) {
super(error.toString());
this.error = error;
}
public WxError getError() {
return this.error;
}
}

View File

@ -1,111 +0,0 @@
package com.ossez.wechat.common.exception;
import com.ossez.wechat.common.enums.WeChatErrorCode;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import com.ossez.wechat.common.enums.WxType;
import com.ossez.wechat.common.util.json.WxGsonBuilder;
import org.apache.commons.lang3.StringUtils;
import java.io.Serializable;
/**
* 微信错误码.
* 请阅读
* 公众平台<a href="https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Global_Return_Code.html">全局返回码说明</a>
* 企业微信<a href="https://work.weixin.qq.com/api/doc#10649">全局错误码</a>
*
* @author Daniel Qian & Binary Wang
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class WxError implements Serializable {
private static final long serialVersionUID = -2696724276555657960L;
/**
* 微信错误代码.
*/
private int errorCode;
/**
* 微信错误信息.
* 如果可以翻译为中文就为中文
*/
private String errorMsg;
/**
* 微信接口返回的错误原始信息英文.
*/
private String errorMsgEn;
private String json;
public WxError(int errorCode, String errorMsg) {
this.errorCode = errorCode;
this.errorMsg = errorMsg;
}
public static WxError fromJson(String json) {
return fromJson(json, null);
}
public static WxError fromJson(String json, WxType type) {
final WxError wxError = WxGsonBuilder.create().fromJson(json, WxError.class);
if (wxError.getErrorCode() == 0 || type == null) {
return wxError;
}
if (StringUtils.isNotEmpty(wxError.getErrorMsg())) {
wxError.setErrorMsgEn(wxError.getErrorMsg());
}
switch (type) {
case MP: {
final String msg = WeChatErrorCode.findMsgByCode(wxError.getErrorCode());
if (msg != null) {
wxError.setErrorMsg(msg);
}
break;
}
case CP: {
final String msg = WxCpErrorMsgEnum.findMsgByCode(wxError.getErrorCode());
if (msg != null) {
wxError.setErrorMsg(msg);
}
break;
}
case MiniApp: {
final String msg = WxMaErrorMsgEnum.findMsgByCode(wxError.getErrorCode());
if (msg != null) {
wxError.setErrorMsg(msg);
}
break;
}
case Open: {
final String msg = WxOpenErrorMsgEnum.findMsgByCode(wxError.getErrorCode());
if (msg != null) {
wxError.setErrorMsg(msg);
}
break;
}
default:
return wxError;
}
return wxError;
}
@Override
public String toString() {
if (this.json == null) {
return "错误代码:" + this.errorCode + ", 错误信息:" + this.errorMsg;
}
return "错误代码:" + this.errorCode + ", 错误信息:" + this.errorMsg + ",微信原始报文:" + this.json;
}
}

View File

@ -1,37 +0,0 @@
package com.ossez.wechat.common.exception;
import static com.ossez.wechat.common.exception.WxError.*;
/**
* @author Daniel Qian
*/
public class WxErrorException extends Exception {
private static final long serialVersionUID = -6357149550353160810L;
private final WxError error;
private static final int DEFAULT_ERROR_CODE = -99;
public WxErrorException(String message) {
this(WxError.builder().errorCode(DEFAULT_ERROR_CODE).errorMsg(message).build());
}
public WxErrorException(WxError error) {
super(error.toString());
this.error = error;
}
public WxErrorException(WxError error, Throwable cause) {
super(error.toString(), cause);
this.error = error;
}
public WxErrorException(Throwable cause) {
super(cause.getMessage(), cause);
this.error = WxError.builder().errorCode(DEFAULT_ERROR_CODE).errorMsg(cause.getMessage()).build();
}
public WxError getError() {
return this.error;
}
}

View File

@ -1,684 +0,0 @@
package com.ossez.wechat.common.exception;
import com.google.common.collect.Maps;
import lombok.Getter;
import java.util.Map;
/**
* 微信小程序错误码
*
* @author <a href="https://github.com/biggates">biggates</a>
*/
@Getter
public enum WxMaErrorMsgEnum {
/**
* <pre>
* 获取 access_token AppSecret 错误
* 或者 access_token 无效请开发者认真比对 AppSecret 的正确性或查看是否正在为恰当的小程序调用接口
* 对应操作<code>sendCustomerMessage</code>
* 对应地址
* POST https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN
* 参考文档地址 https://developers.weixin.qq.com/miniprogram/dev/api/open-api/customer-message/sendCustomerMessage.html
* </pre>
*/
CODE_40001(40001, "access_token 无效或 AppSecret 错误"),
/**
* <pre>
* 不合法的凭证类型
* 对应操作<code>sendCustomerMessage</code>
* 对应地址
* POST https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN
* 参考文档地址 https://developers.weixin.qq.com/miniprogram/dev/api/open-api/customer-message/sendCustomerMessage.html
* </pre>
*/
CODE_40002(40002, "不合法的凭证类型"),
/**
* <pre>
* touser不是正确的openid.
* 对应操作<code>sendCustomerMessage</code>, <code>sendUniformMessage</code>
* 对应地址
* POST https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN
* POST https://api.weixin.qq.com/cgi-bin/message/wxopen/template/uniform_send?access_token=ACCESS_TOKEN
* 参考文档地址 https://developers.weixin.qq.com/miniprogram/dev/api/open-api/customer-message/sendCustomerMessage.html
* https://developers.weixin.qq.com/miniprogram/dev/api/open-api/uniform-message/sendUniformMessage.html
* </pre>
*/
CODE_40003(40003, "openid 不正确"),
/**
* <pre>
* 无效媒体文件类型
* 对应操作<code>uploadTempMedia</code>
* 对应地址
* POST https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE
* 参考文档地址 https://developers.weixin.qq.com/miniprogram/dev/api/open-api/customer-message/uploadTempMedia.html
* </pre>
*/
CODE_40004(40004, "无效媒体文件类型"),
/**
* <pre>
* 无效媒体文件 ID.
* 对应操作<code>getTempMedia</code>
* 对应地址
* GET https://api.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID
* 参考文档地址 https://developers.weixin.qq.com/miniprogram/dev/api/open-api/customer-message/getTempMedia.html
* </pre>
*/
CODE_40007(40007, "无效媒体文件 ID"),
/**
* <pre>
* appid不正确或者不符合绑定关系要求.
* 对应操作<code>sendUniformMessage</code>
* 对应地址
* POST https://api.weixin.qq.com/cgi-bin/message/wxopen/template/uniform_send?access_token=ACCESS_TOKEN
* 参考文档地址 https://developers.weixin.qq.com/miniprogram/dev/api/open-api/uniform-message/sendUniformMessage.html
* </pre>
*/
CODE_40013(40013, "appid不正确或者不符合绑定关系要求"),
/**
* <pre>
* template_id 不正确.
* 对应操作<code>sendUniformMessage</code>, <code>sendTemplateMessage</code>
* 对应地址
* POST https://api.weixin.qq.com/cgi-bin/message/wxopen/template/uniform_send?access_token=ACCESS_TOKEN
* POST https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=ACCESS_TOKEN
* 参考文档地址 https://developers.weixin.qq.com/miniprogram/dev/api/open-api/uniform-message/sendUniformMessage.html
* https://developers.weixin.qq.com/miniprogram/dev/api/open-api/template-message/sendTemplateMessage.html
* </pre>
*/
CODE_40037(40037, "template_id 不正确"),
/**
* <pre>
* form_id不正确或者过期.
* 对应操作<code>sendUniformMessage</code>, <code>sendTemplateMessage</code>
* 对应地址
* POST https://api.weixin.qq.com/cgi-bin/message/wxopen/template/uniform_send?access_token=ACCESS_TOKEN
* POST https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=ACCESS_TOKEN
* 参考文档地址 https://developers.weixin.qq.com/miniprogram/dev/api/open-api/uniform-message/sendUniformMessage.html
* https://developers.weixin.qq.com/miniprogram/dev/api/open-api/template-message/sendTemplateMessage.html
* </pre>
*/
CODE_41028(41028, "form_id 不正确,或者过期"),
/**
* <pre>
* code template_id 不正确.
* 对应操作<code>code2Session</code>, <code>sendUniformMessage</code>, <code>sendTemplateMessage</code>
* 对应地址
* GET https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code
* POST https://api.weixin.qq.com/cgi-bin/message/wxopen/template/uniform_send?access_token=ACCESS_TOKEN
* POST https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=ACCESS_TOKEN
* 参考文档地址 https://developers.weixin.qq.com/miniprogram/dev/api/open-api/login/code2Session.html
* https://developers.weixin.qq.com/miniprogram/dev/api/open-api/uniform-message/sendUniformMessage.html
* https://developers.weixin.qq.com/miniprogram/dev/api/open-api/template-message/sendTemplateMessage.html
* </pre>
*/
CODE_41029(41029, "请求的参数不正确"),
/**
* <pre>
* form_id 已被使用或者所传page页面不存在或者小程序没有发布
* 对应操作<code>sendUniformMessage</coce>, <code>getWXACodeUnlimit</code>
* 对应地址
* POST https://api.weixin.qq.com/cgi-bin/message/wxopen/template/uniform_send?access_token=ACCESS_TOKEN
* POST https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=ACCESS_TOKEN
* 参考文档地址 https://developers.weixin.qq.com/miniprogram/dev/api/open-api/uniform-message/sendUniformMessage.html
* https://developers.weixin.qq.com/miniprogram/dev/api/open-api/qr-code/getWXACodeUnlimit.html
* </pre>
*/
CODE_41030(41030, "请求的参数不正确"),
/**
* <pre>
* 调用分钟频率受限.
* 对应操作<code>getWXACodeUnlimit</code>, <code>sendUniformMessage</code>, <code>sendTemplateMessage</code>
* 对应地址
* POST https://api.weixin.qq.com/cgi-bin/message/wxopen/template/uniform_send?access_token=ACCESS_TOKEN
* POST https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=ACCESS_TOKEN
* POST https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=ACCESS_TOKEN
* 参考文档地址 https://developers.weixin.qq.com/miniprogram/dev/api/open-api/uniform-message/sendUniformMessage.html
* https://developers.weixin.qq.com/miniprogram/dev/api/open-api/qr-code/getWXACodeUnlimit.html
* </pre>
*/
CODE_45009(45009, "调用分钟频率受限"),
/**
* <pre>
* 频率限制每个用户每分钟100次.
* 对应操作<code>code2Session</code>
* 对应地址
* GET https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code
* 参考文档地址 https://developers.weixin.qq.com/miniprogram/dev/api/open-api/login/code2Session.html
* </pre>
*/
CODE_45011(45011, "频率限制每个用户每分钟100次"),
/**
* <pre>
* 回复时间超过限制.
* 对应操作<code>sendCustomerMessage</code>
* 对应地址
* POST https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN
* 参考文档地址 https://developers.weixin.qq.com/miniprogram/dev/api/open-api/customer-message/sendCustomerMessage.html
* </pre>
*/
CODE_45015(45015, "回复时间超过限制"),
/**
* <pre>
* 接口调用超过限额 或生成码个数总和到达最大个数限制.
* 对应操作<code>createWXAQRCode</code>, <code>sendTemplateMessage</code>
* 对应地址
* POST https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token=ACCESS_TOKEN
* POST https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=ACCESS_TOKEN
* 参考文档地址 https://developers.weixin.qq.com/miniprogram/dev/api/open-api/qr-code/getWXACode.html
* https://developers.weixin.qq.com/miniprogram/dev/api/open-api/template-message/sendTemplateMessage.html
* </pre>
*/
CODE_45029(45029, "接口调用超过限额"),
/**
* <pre>
* 客服接口下行条数超过上限.
* 对应操作<code>sendCustomerMessage</code>
* 对应地址
* POST https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN
* 参考文档地址 https://developers.weixin.qq.com/miniprogram/dev/api/open-api/customer-message/sendCustomerMessage.html
* </pre>
*/
CODE_45047(45047, "客服接口下行条数超过上限"),
/**
* <pre>
* command字段取值不对
* 对应操作<code>customerTyping</code>
* 对应地址
* POST https://api.weixin.qq.com/cgi-bin/message/custom/typing?access_token=ACCESS_TOKEN
* 参考文档地址 https://developers.weixin.qq.com/miniprogram/dev/api/open-api/customer-message/customerTyping.html
* </pre>
*/
CODE_45072(45072, "command字段取值不对"),
/**
* <pre>
* 下发输入状态需要之前30秒内跟用户有过消息交互.
* 对应操作<code>customerTyping</code>
* 对应地址
* POST https://api.weixin.qq.com/cgi-bin/message/custom/typing?access_token=ACCESS_TOKEN
* 参考文档地址 https://developers.weixin.qq.com/miniprogram/dev/api/open-api/customer-message/customerTyping.html
*/
CODE_45080(45080, "下发输入状态需要之前30秒内跟用户有过消息交互"),
/**
* <pre>
* 已经在输入状态不可重复下发.
* 对应操作<code>customerTyping</code>
* 对应地址
* POST https://api.weixin.qq.com/cgi-bin/message/custom/typing?access_token=ACCESS_TOKEN
* 参考文档地址 https://developers.weixin.qq.com/miniprogram/dev/api/open-api/customer-message/customerTyping.html
* </pre>
*/
CODE_45081(45081, "已经在输入状态,不可重复下发"),
/**
* <pre>
* API 功能未授权请确认小程序已获得该接口.
* 对应操作<code>sendCustomerMessage</code>
* 对应地址
* POST https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN
* 参考文档地址 https://developers.weixin.qq.com/miniprogram/dev/api/open-api/customer-message/sendCustomerMessage.html
* </pre>
*/
CODE_48001(48001, "API 功能未授权"),
/**
* <pre>
* 内容含有违法违规内容.
* 对应操作<code>imgSecCheck</code>, <code>msgSecCheck</code>
* 对应地址
* POST https://api.weixin.qq.com/wxa/img_sec_check?access_token=ACCESS_TOKEN
* POST https://api.weixin.qq.com/wxa/msg_sec_check?access_token=ACCESS_TOKEN
* 参考文档地址 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/msgSecCheck.html
* </pre>
*/
CODE_87014(87014, "内容含有违法违规内容"),
/**
* 系统繁忙此时请开发者稍候再试.
*/
CODE_MINUS_1(-1, "系统繁忙,此时请开发者稍候再试"),
/**
* code 无效.
*/
CODE_40029(40029, "code 无效"),
/**
* access_token 过期.
*/
CODE_42001(42001, "access_token 过期"),
/**
* post 数据为空.
*/
CODE_44002(44002, "post 数据为空"),
/**
* post 数据中参数缺失.
*/
CODE_47001(47001, "post 数据中参数缺失"),
/**
* 参数 activity_id 错误.
*/
CODE_47501(47501, "参数 activity_id 错误"),
/**
* 参数 target_state 错误.
*/
CODE_47502(47502, "参数 target_state 错误"),
/**
* 参数 version_type 错误.
*/
CODE_47503(47503, "参数 version_type 错误"),
/**
* activity_id 过期.
*/
CODE_47504(47504, "activity_id 过期"),
/**
* 没有绑定开放平台帐号.
*/
CODE_89002(89002, "没有绑定开放平台帐号"),
/**
* 订单无效.
*/
CODE_89300(89300, "订单无效"),
/**
* 代小程序实现业务的错误码部分和小程序业务一致
* https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/Mini_Programs/Intro.html
*/
CODE_85060(85060, "无效的taskid"),
CODE_85027(85027, "身份证绑定管理员名额达到上限"),
CODE_85061(85061, "手机号绑定管理员名额达到上限"),
CODE_85026(85026, "微信号绑定管理员名额达到上限"),
CODE_85063(85063, "身份证黑名单"),
CODE_85062(85062, "手机号黑名单"),
CODE_85016(85016, "域名数量超过限制"),
CODE_85017(85017, "没有新增域名,请确认小程序已经添加了域名或该域名是否没有在第三方平台添加"),
CODE_85018(85018, "域名没有在第三方平台设置"),
CODE_89019(89019, "业务域名无更改,无需重复设置"),
CODE_89020(89020, "尚未设置小程序业务域名,请先在第三方平台中设置小程序业务域名后在调用本接口"),
CODE_89021(89021, "请求保存的域名不是第三方平台中已设置的小程序业务域名或子域名"),
CODE_89029(89029, "业务域名数量超过限制"),
CODE_89231(89231, "个人小程序不支持调用 setwebviewdomain 接口"),
CODE_91001(91001, "不是公众号快速创建的小程序"),
CODE_91002(91002, "小程序发布后不可改名"),
CODE_91003(91003, "改名状态不合法"),
CODE_91004(91004, "昵称不合法"),
CODE_91005(91005, "昵称 15 天主体保护"),
CODE_91006(91006, "昵称命中微信号"),
CODE_91007(91007, "昵称已被占用"),
CODE_91008(91008, "昵称命中 7 天侵权保护期"),
CODE_91009(91009, "需要提交材料"),
CODE_91010(91010, "其他错误"),
CODE_91011(91011, "查不到昵称修改审核单信息"),
CODE_91012(91012, "其他错误"),
CODE_91013(91013, "占用名字过多"),
CODE_91014(91014, "+号规则 同一类型关联名主体不一致"),
CODE_91015(91015, "原始名不同类型主体不一致"),
CODE_91016(91016, "名称占用者 ≥2"),
CODE_91017(91017, "+号规则 不同类型关联名主体不一致"),
CODE_40097(40097, "参数错误"),
CODE_41006(41006, "media_id 不能为空"),
CODE_46001(46001, "media_id 不存在"),
CODE_40009(40009, "图片尺寸太大"),
CODE_53202(53202, "本月头像修改次数已用完"),
CODE_53200(53200, "本月功能介绍修改次数已用完"),
CODE_53201(53201, "功能介绍内容命中黑名单关键字"),
CODE_85083(85083, "搜索标记位被封禁,无法修改"),
CODE_85084(85084, "非法的 status 值,只能填 0 或者 1"),
CODE_85013(85013, "无效的自定义配置"),
CODE_85014(85014, "无效的模版编号"),
CODE_85043(85043, "模版错误"),
CODE_85044(85044, "代码包超过大小限制"),
CODE_85045(85045, "ext_json 有不存在的路径"),
CODE_85046(85046, "tabBar 中缺少 path"),
CODE_85047(85047, "pages 字段为空"),
CODE_85048(85048, "ext_json 解析失败"),
CODE_80082(80082, "没有权限使用该插件"),
CODE_80067(80067, "找不到使用的插件"),
CODE_80066(80066, "非法的插件版本"),
CODE_86000(86000, "不是由第三方代小程序进行调用"),
CODE_86001(86001, "不存在第三方的已经提交的代码"),
CODE_85006(85006, "标签格式错误"),
CODE_85007(85007, "页面路径错误"),
CODE_85008(85008, "类目填写错误"),
CODE_85009(85009, "已经有正在审核的版本"),
CODE_85010(85010, "item_list 有项目为空"),
CODE_85011(85011, "标题填写错误"),
CODE_85023(85023, "审核列表填写的项目数不在 1-5 以内"),
CODE_85077(85077, "小程序类目信息失效(类目中含有官方下架的类目,请重新选择类目)"),
CODE_86002(86002, "小程序还未设置昵称、头像、简介。请先设置完后再重新提交"),
CODE_85085(85085, "近 7 天提交审核的小程序数量过多,请耐心等待审核完毕后再次提交"),
CODE_85086(85086, "提交代码审核之前需提前上传代码"),
CODE_85087(85087, "小程序已使用 api navigateToMiniProgram请声明跳转 appid 列表后再次提交"),
CODE_85012(85012, "无效的审核 id"),
CODE_87013(87013, "撤回次数达到上限每天5次每个月 10 次)"),
CODE_85019(85019, "没有审核版本"),
CODE_85020(85020, "审核状态未满足发布"),
CODE_87011(87011, "现网已经在灰度发布,不能进行版本回退"),
CODE_87012(87012, "该版本不能回退可能的原因1:无上一个线上版用于回退 2:此版本为已回退版本,不能回退 3:此版本为回退功能上线之前的版本,不能回退"),
CODE_85079(85079, "小程序没有线上版本,不能进行灰度"),
CODE_85080(85080, "小程序提交的审核未审核通过"),
CODE_85081(85081, "无效的发布比例"),
CODE_85082(85082, "当前的发布比例需要比之前设置的高"),
CODE_85021(85021, "状态不可变"),
CODE_85022(85022, "action 非法"),
CODE_89401(89401, "系统不稳定,请稍后再试,如多次失败请通过社区反馈"),
CODE_89402(89402, "该审核单不在待审核队列,请检查是否已提交审核或已审完"),
CODE_89403(89403, "本单属于平台不支持加急种类,请等待正常审核流程"),
CODE_89404(89404, "本单已加速成功,请勿重复提交"),
CODE_89405(89405, "本月加急额度不足,请提升提审质量以获取更多额度"),
CODE_85064(85064, "找不到模版/草稿"),
CODE_85065(85065, "模版库已满"),
/**
* 小程序订阅消息错误码
* https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.send.html
*/
CODE_43101(43101, "用户拒绝接受消息,如果用户之前曾经订阅过,则表示用户取消了订阅关系"),
CODE_47003(47003, "模板参数不准确可能为空或者不满足规则errmsg会提示具体是哪个字段出错"),
/**
* 小程序绑定体验者
*/
CODE_85001(85001, "微信号不存在或微信号设置为不可搜索"),
CODE_85002(85002, "小程序绑定的体验者数量达到上限"),
CODE_85003(85003, "微信号绑定的小程序体验者达到上限"),
CODE_85004(85004, "微信号已经绑定"),
/**
* 53010
* 名称格式不合法
*/
CODE_53010(53010, "名称格式不合法"),
/**
* 53011
* 名称检测命中频率限制
*/
CODE_53011(53011, "名称检测命中频率限制"),
/**
* 53012
* 禁止使用该名称
*/
CODE_53012(53012, "禁止使用该名称"),
/**
* 53013
* 公众号名称与已有公众号名称重复;小程序该名称与已有小程序名称重复
*/
CODE_53013(53013, "公众号:名称与已有公众号名称重复;小程序:该名称与已有小程序名称重复"),
/**
* 53014
* 公众号公众号已有{名称 A+}需与该帐号相同主体才可申请{名称 A};小程序小程序已有{名称 A+}需与该帐号相同主体才可申请{名称 A}
*/
CODE_53014(53014, "公众号:公众号已有{名称 A+}时,需与该帐号相同主体才可申请{名称 A};小程序:小程序已有{名称 A+}时,需与该帐号相同主体才可申请{名称 A}"),
/**
* 53015
* 公众号该名称与已有小程序名称重复需与该小程序帐号相同主体才可申请;小程序该名称与已有公众号名称重复需与该公众号帐号相同主体才可申请
*/
CODE_53015(53015, "公众号:该名称与已有小程序名称重复,需与该小程序帐号相同主体才可申请;小程序:该名称与已有公众号名称重复,需与该公众号帐号相同主体才可申请"),
/**
* 53016
* 公众号该名称与已有多个小程序名称重复暂不支持申请;小程序该名称与已有多个公众号名称重复暂不支持申请
*/
CODE_53016(53016, "公众号:该名称与已有多个小程序名称重复,暂不支持申请;小程序:该名称与已有多个公众号名称重复,暂不支持申请"),
/**
* 53017
* 公众号小程序已有{名称 A+}需与该帐号相同主体才可申请{名称 A};小程序公众号已有{名称 A+}需与该帐号相同主体才可申请{名称 A}
*/
CODE_53017(53017, "公众号:小程序已有{名称 A+}时,需与该帐号相同主体才可申请{名称 A};小程序:公众号已有{名称 A+}时,需与该帐号相同主体才可申请{名称 A}"),
/**
* 53018
* 名称命中微信号
*/
CODE_53018(53018, "名称命中微信号"),
/**
* 53019
* 名称在保护期内
*/
CODE_53019(53019, "名称在保护期内"),
/**
* 61070
* 法人姓名与微信号不一致 name, wechat name not in accordance
*/
CODE_61070(61070, "法人姓名与微信号不一致"),
/**
* 85015
* 该账号不是小程序账号
*/
CODE_85015(85015, "该账号不是小程序账号"),
/**
* 85066
* 链接错误
*/
CODE_85066(85066, "链接错误"),
/**
* 85068
* 测试链接不是子链接
*/
CODE_85068(85068, "测试链接不是子链接"),
/**
* 85069
* 校验文件失败
*/
CODE_85069(85069, "校验文件失败"),
/**
* 85070
* 个人类型小程序无法设置二维码规则
*/
CODE_85070(85070, "个人类型小程序无法设置二维码规则"),
/**
* 85071
* 已添加该链接请勿重复添加
*/
CODE_85071(85071, "已添加该链接,请勿重复添加"),
/**
* 85072
* 该链接已被占用
*/
CODE_85072(85072, "该链接已被占用"),
/**
* 85073
* 二维码规则已满
*/
CODE_85073(85073, "二维码规则已满"),
/**
* 85074
* 小程序未发布, 小程序必须先发布代码才可以发布二维码跳转规则
*/
CODE_85074(85074, "小程序未发布, 小程序必须先发布代码才可以发布二维码跳转规则"),
/**
* 85075
* 个人类型小程序无法设置二维码规则
*/
CODE_85075(85075, "个人类型小程序无法设置二维码规则"),
/**
* 86004
* 无效微信号 invalid wechat
*/
CODE_86004(86004, "无效微信号"),
/**
* 89247
* 内部错误 inner error
*/
CODE_89247(89247, "内部错误"),
/**
* 89248
* 企业代码类型无效请选择正确类型填写 invalid code_type type
*/
CODE_89248(89248, "企业代码类型无效,请选择正确类型填写"),
/**
* 89249
* 该主体已有任务执行中距上次任务 24h 后再试 task running
*/
CODE_89249(89249, "该主体已有任务执行中,距上次任务 24h 后再试"),
/**
* 89250
* 未找到该任务 task not found
*/
CODE_89250(89250, "未找到该任务"),
/**
* 89251
* 待法人人脸核身校验 legal person checking
*/
CODE_89251(89251, "待法人人脸核身校验"),
/**
* 89252
* 法人&企业信息一致性校验中 front checking
*/
CODE_89252(89252, "法人&企业信息一致性校验中"),
/**
* 89253
* 缺少参数 lack of some params
*/
CODE_89253(89253, "缺少参数s"),
/**
* 89254
* 第三方权限集不全补全权限集全网发布后生效 lack of some component rights
*/
CODE_89254(89254, "第三方权限集不全,补全权限集全网发布后生效"),
/**
* 89255
* code参数无效请检查code长度以及内容是否正确 code参数无效请检查code长度以及内容是否正确_
* 注意code_type的值不同需要传的code长度不一样 注意code_type的值不同需要传的code长度不一样 enterprise code_invalid invalid
*/
CODE_89255(89255, "code参数无效请检查code长度以及内容是否正确_注意code_type的值不同需要传的code长度不一样 注意code_type的值不同需要传的code长度不一样"),
// CODE_504002(-504002, "云函数未找到 Function not found"),
;
private final int code;
private final String msg;
WxMaErrorMsgEnum(int code, String msg) {
this.code = code;
this.msg = msg;
}
static final Map<Integer, String> valueMap = Maps.newHashMap();
static {
for (WxMaErrorMsgEnum value : WxMaErrorMsgEnum.values()) {
valueMap.put(value.code, value.msg);
}
}
/**
* 通过错误代码查找其中文含义.
*/
public static String findMsgByCode(int code) {
return valueMap.getOrDefault(code, null);
}
}

View File

@ -1,23 +0,0 @@
package com.ossez.wechat.common.exception;
/**
* WxJava专用的runtime exception.
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
* created on 2020-09-26
*/
public class WxRuntimeException extends RuntimeException {
private static final long serialVersionUID = 4881698471192264412L;
public WxRuntimeException(Throwable e) {
super(e);
}
public WxRuntimeException(String msg) {
super(msg);
}
public WxRuntimeException(String msg, Throwable e) {
super(msg, e);
}
}

View File

@ -1,44 +0,0 @@
package com.ossez.wechat.common.model;
import java.io.Serializable;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ossez.wechat.common.util.json.WxGsonBuilder;
import lombok.Data;
/**
* WeChatAccessToken Response Object
*
* @author YuCheng Hu
*/
public class WeChatAccessToken {
@JsonProperty("access_token")
private String accessToken;
@JsonProperty("expires_in")
private int expiresIn = -1;
public static WeChatAccessToken fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WeChatAccessToken.class);
}
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public int getExpiresIn() {
return expiresIn;
}
public void setExpiresIn(int expiresIn) {
this.expiresIn = expiresIn;
}
}

View File

@ -1,27 +0,0 @@
package com.ossez.wechat.common.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ossez.wechat.common.util.json.WxGsonBuilder;
import java.util.List;
/**
* WeChatAccessToken Response Object
*
* @author YuCheng Hu
*/
public class WeChatApiDomainIp {
@JsonProperty("ip_list")
private List<String> ipList;
public List<String> getIpList() {
return ipList;
}
public void setIpList(List<String> ipList) {
this.ipList = ipList;
}
}

View File

@ -1,16 +0,0 @@
package com.ossez.wechat.common.model;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
@Data
@Accessors(chain = true)
public class WeChatHost implements Serializable {
private static final long serialVersionUID = -7648920647310280817L;
private String apiHost;
private String openHost;
private String mpHost;
}

View File

@ -1,107 +0,0 @@
package com.ossez.wechat.common.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.gson.annotations.SerializedName;
import com.ossez.wechat.common.util.json.WxGsonBuilder;
import lombok.Data;
import java.io.Serializable;
/**
* https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842
*
* @author Daniel Qian
*/
public class WeChatOAuth2AccessToken implements Serializable {
private static final long serialVersionUID = 5755678830089329526L;
@JsonProperty("access_token")
private String accessToken;
@JsonProperty("expires_in")
private int expiresIn = -1;
@JsonProperty("refresh_token")
private String refreshToken;
@JsonProperty("openid")
private String openId;
@JsonProperty("scope")
private String scope;
@JsonProperty("is_snapshotuser")
private Integer snapshotUser;
/**
* https://mp.weixin.qq.com/cgi-bin/announce?action=getannouncement&announce_id=11513156443eZYea&version=&lang=zh_CN.
* 本接口在scope参数为snsapi_base时不再提供unionID字段
*/
@SerializedName("unionid")
private String unionId;
public static WeChatOAuth2AccessToken fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WeChatOAuth2AccessToken.class);
}
@Override
public String toString() {
return WxGsonBuilder.create().toJson(this);
}
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public int getExpiresIn() {
return expiresIn;
}
public void setExpiresIn(int expiresIn) {
this.expiresIn = expiresIn;
}
public String getRefreshToken() {
return refreshToken;
}
public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}
public String getOpenId() {
return openId;
}
public void setOpenId(String openId) {
this.openId = openId;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
public Integer getSnapshotUser() {
return snapshotUser;
}
public void setSnapshotUser(Integer snapshotUser) {
this.snapshotUser = snapshotUser;
}
public String getUnionId() {
return unionId;
}
public void setUnionId(String unionId) {
this.unionId = unionId;
}
}

View File

@ -1,34 +0,0 @@
package com.ossez.wechat.common.model;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* WeChatStatus Response Object
*
* @author YuCheng Hu
*/
public class WeChatStatus {
@JsonProperty("errcode")
private int errCode = 0;
@JsonProperty("errmsg")
private String errMsg;
public int getErrCode() {
return errCode;
}
public void setErrCode(int errCode) {
this.errCode = errCode;
}
public String getErrMsg() {
return errMsg;
}
public void setErrMsg(String errMsg) {
this.errMsg = errMsg;
}
}

View File

@ -1,129 +0,0 @@
package com.ossez.wechat.common.model.entity;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.gson.annotations.SerializedName;
import com.ossez.wechat.common.util.json.WxGsonBuilder;
import lombok.Data;
import java.io.Serializable;
/**
* oauth2用户个人信息.
* <pre>
* {
* "openid":"OPENID",
* "nickname":"NICKNAME",
* "sex":1,
* "province":"PROVINCE",
* "city":"CITY",
* "country":"COUNTRY",
* "headimgurl": "https://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0",
* "privilege":[
* "PRIVILEGE1",
* "PRIVILEGE2"
* ],
* "unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL"
*
* }
* </pre>
*
* @author YuCheng
*/
@Data
public class WeChatOAuth2UserInfo implements Serializable {
private static final long serialVersionUID = 3181943506448954725L;
@JsonProperty("openid")
private String openid;
@JsonProperty("nickname")
private String nickname;
@JsonProperty("sex")
private Integer sex;
@JsonProperty("city")
private String city;
@JsonProperty("province")
private String province;
@JsonProperty("country")
private String country;
@JsonProperty("headimgurl")
private String headImgUrl;
@JsonProperty("unionid")
private String unionId;
@JsonProperty("privilege")
private String[] privileges;
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getHeadImgUrl() {
return headImgUrl;
}
public void setHeadImgUrl(String headImgUrl) {
this.headImgUrl = headImgUrl;
}
public String getUnionId() {
return unionId;
}
public void setUnionId(String unionId) {
this.unionId = unionId;
}
public String[] getPrivileges() {
return privileges;
}
public void setPrivileges(String[] privileges) {
this.privileges = privileges;
}
}

View File

@ -1,31 +0,0 @@
package com.ossez.wechat.common.model.entity;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* WeChatAccessToken Response Object
*
* @author YuCheng Hu
*/
public class WeChatResponseStatus {
@JsonProperty("errcode")
private Integer errorCode;
@JsonProperty("errmsg")
private String errorMsg;
public Integer getErrorCode() {
return errorCode;
}
public void setErrorCode(Integer errorCode) {
this.errorCode = errorCode;
}
public String getErrorMsg() {
return errorMsg;
}
public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}
}

View File

@ -1,104 +0,0 @@
package com.ossez.wechat.common.model.entity;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.experimental.Accessors;
@Accessors(chain = true)
public class WeChatUser {
@JsonProperty(value = "openid", required = true)
private String openId;
@JsonProperty(required = true)
private String nickname;
private Integer sex;
private String language;
private String city;
private String province;
private String country;
@JsonProperty(value = "headimgurl")
private String headImgURL;
@JsonProperty(value = "unionid", required = true)
private String unionId;
public String getOpenId() {
return openId;
}
public void setOpenId(String openId) {
this.openId = openId;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getHeadImgURL() {
return headImgURL;
}
public void setHeadImgURL(String headImgURL) {
this.headImgURL = headImgURL;
}
public String getUnionId() {
return unionId;
}
public void setUnionId(String unionId) {
this.unionId = unionId;
}
}

View File

@ -1,43 +0,0 @@
package com.ossez.wechat.common.model.entity.builder;
import com.ossez.wechat.common.model.entity.menu.MenuButton;
import com.ossez.wechat.common.model.req.MenuRequest;
import java.util.List;
public class MenuButtonBuilder {
private List<MenuButton> subButtonList;
private String type;
private String name;
private String key;
private String url;
public MenuButtonBuilder setSubButtonList(List<MenuButton> subButtonList) {
this.subButtonList = subButtonList;
return this;
}
public MenuButtonBuilder setType(String type) {
this.type = type;
return this;
}
public MenuButtonBuilder setName(String name) {
this.name = name;
return this;
}
public MenuButtonBuilder setKey(String key) {
this.key = key;
return this;
}
public MenuButtonBuilder setUrl(String url) {
this.url = url;
return this;
}
public MenuButton createMenuButton() {
return new MenuButton(subButtonList, type, name, key, url);
}
}

View File

@ -1,40 +0,0 @@
package com.ossez.wechat.common.model.entity.menu;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.gson.annotations.SerializedName;
import com.ossez.wechat.common.model.req.MenuRequest;
import com.ossez.wechat.common.util.json.WxGsonBuilder;
import lombok.Data;
/**
* menu button.
*
* @author Daniel Qian
*/
@Data
public class MenuButton implements Serializable {
private static final long serialVersionUID = -1070939403109776555L;
public MenuButton(List<MenuButton> subButtonList, String type, String name, String key, String url) {
this.subButtonList = subButtonList;
this.type = type;
this.name = name;
this.key = key;
this.url = url;
}
@JsonProperty(value = "sub_button")
private List<MenuButton> subButtonList;
@JsonProperty("type")
private String type;
@JsonProperty("name")
private String name;
@JsonProperty("key")
private String key;
@JsonProperty("url")
private String url;
}

View File

@ -1,55 +0,0 @@
package com.ossez.wechat.common.model.entity.menu;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import com.ossez.wechat.common.util.json.WxGsonBuilder;
import lombok.Data;
/**
* 菜单公众号和企业号共用的.
*
* @author Daniel Qian
*/
@Data
public class WxMenu implements Serializable {
private static final long serialVersionUID = -7083914585539687746L;
private List<MenuButton> buttons = new ArrayList<>();
private WxMenuRule matchRule;
/**
* 要用 http://mp.weixin.qq.com/wiki/16/ff9b7b85220e1396ffa16794a9d95adc.html 格式来反序列化
* 相比 http://mp.weixin.qq.com/wiki/13/43de8269be54a0a6f64413e4dfa94f39.html 的格式外层多套了一个menu
*
* @param json
* @return
*/
public static WxMenu fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxMenu.class);
}
/**
* 要用 http://mp.weixin.qq.com/wiki/16/ff9b7b85220e1396ffa16794a9d95adc.html 格式来反序列化
* 相比 http://mp.weixin.qq.com/wiki/13/43de8269be54a0a6f64413e4dfa94f39.html 的格式外层多套了一个menu
*/
public static WxMenu fromJson(InputStream is) {
return WxGsonBuilder.create()
.fromJson(new InputStreamReader(is, StandardCharsets.UTF_8), WxMenu.class);
}
public String toJson() {
return WxGsonBuilder.create().toJson(this);
}
@Override
public String toString() {
return this.toJson();
}
}

View File

@ -1,35 +0,0 @@
package com.ossez.wechat.common.model.entity.menu;
import java.io.Serializable;
import com.google.gson.annotations.SerializedName;
import com.ossez.wechat.common.util.json.WxGsonBuilder;
import lombok.Data;
/**
* menu rule.
*
* @author Daniel Qian
*/
@Data
public class WxMenuRule implements Serializable {
private static final long serialVersionUID = -4587181819499286670L;
/**
* 变态的微信接口反序列化时这里反人类的使用和序列化时不一样的名字.
*/
@SerializedName(value = "tag_id", alternate = "group_id")
private String tagId;
private String sex;
private String country;
private String province;
private String city;
@SerializedName("client_platform_type")
private String clientPlatformType;
private String language;
@Override
public String toString() {
return WxGsonBuilder.create().toJson(this);
}
}

View File

@ -1,128 +0,0 @@
package com.ossez.wechat.common.model.req;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.gson.annotations.SerializedName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import java.io.Serializable;
/**
* CustomMessage
*
* @author YuCheng
*/
public class CustomMessage implements Serializable {
private static final long serialVersionUID = -9196732086954365246L;
@JsonProperty("touser")
private String toUser;
@JsonProperty("msgtype")
private String msgType;
@JsonProperty("text")
private KfText text;
@JsonProperty("image")
private KfImage image;
@JsonProperty("link")
private KfLink link;
@JsonProperty("miniprogrampage")
private KfMaPage maPage;
@Data
@AllArgsConstructor
public static class KfText implements Serializable {
private static final long serialVersionUID = 151122958720941270L;
private String content;
}
@Data
@AllArgsConstructor
public static class KfImage implements Serializable {
private static final long serialVersionUID = -5409342945117300782L;
@SerializedName("media_id")
private String mediaId;
}
@Data
@Builder
public static class KfLink implements Serializable {
private static final long serialVersionUID = -6728776817556127413L;
private String title;
private String description;
private String url;
@SerializedName("thumb_url")
private String thumbUrl;
}
@Data
@Builder
public static class KfMaPage implements Serializable {
private static final long serialVersionUID = -5633492281871634466L;
private String title;
@SerializedName("pagepath")
private String pagePath;
@SerializedName("thumb_media_id")
private String thumbMediaId;
}
public String getToUser() {
return toUser;
}
public void setToUser(String toUser) {
this.toUser = toUser;
}
public String getMsgType() {
return msgType;
}
public void setMsgType(String msgType) {
this.msgType = msgType;
}
public KfText getText() {
return text;
}
public void setText(KfText text) {
this.text = text;
}
public KfImage getImage() {
return image;
}
public void setImage(KfImage image) {
this.image = image;
}
public KfLink getLink() {
return link;
}
public void setLink(KfLink link) {
this.link = link;
}
public KfMaPage getMaPage() {
return maPage;
}
public void setMaPage(KfMaPage maPage) {
this.maPage = maPage;
}
}

View File

@ -1,40 +0,0 @@
package com.ossez.wechat.common.model.req;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.gson.annotations.SerializedName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import java.io.Serializable;
/**
* CustomMessage
*
* @author YuCheng
*/
public class DataCubeRequest implements Serializable {
private static final long serialVersionUID = -9196732086954365246L;
@JsonProperty(value = "begin_date", required = true)
private String beginDate;
@JsonProperty(value = "end_date", required = true)
private String endDate;
public String getBeginDate() {
return beginDate;
}
public void setBeginDate(String beginDate) {
this.beginDate = beginDate;
}
public String getEndDate() {
return endDate;
}
public void setEndDate(String endDate) {
this.endDate = endDate;
}
}

View File

@ -1,28 +0,0 @@
package com.ossez.wechat.common.model.req;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ossez.wechat.common.model.entity.menu.MenuButton;
import com.ossez.wechat.common.model.res.DataCubeArticle;
import java.io.Serializable;
import java.util.List;
/**
* CustomMessage
*
* @author YuCheng
*/
public class MenuRequest implements Serializable {
private static final long serialVersionUID = -9196732086954365246L;
@JsonProperty(value = "button", required = true)
private List<MenuButton> buttonList;
public List<MenuButton> getButtonList() {
return buttonList;
}
public void setButtonList(List<MenuButton> buttonList) {
this.buttonList = buttonList;
}
}

View File

@ -1,33 +0,0 @@
package com.ossez.wechat.common.model.req;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ossez.wechat.common.util.json.WxGsonBuilder;
import org.apache.commons.lang3.StringUtils;
/**
* WeChatAccessToken Response Object
*
* @author YuCheng Hu
*/
public class NetworkCheck {
@JsonProperty("action")
private String action = "all";
@JsonProperty("check_operator")
private String checkOperator = StringUtils.upperCase("DEFAULT");
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
public String getCheckOperator() {
return checkOperator;
}
public void setCheckOperator(String checkOperator) {
this.checkOperator = checkOperator;
}
}

View File

@ -1,22 +0,0 @@
package com.ossez.wechat.common.model.req;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.apache.commons.lang3.StringUtils;
/**
* WeChatAccessToken Response Object
*
* @author YuCheng Hu
*/
public class QueryQuota {
@JsonProperty("cgi_path")
private String cgiPath = "/cgi-bin/message/custom/send";
public String getCgiPath() {
return cgiPath;
}
public void setCgiPath(String cgiPath) {
this.cgiPath = cgiPath;
}
}

View File

@ -1,130 +0,0 @@
package com.ossez.wechat.common.model.res;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
/**
* UserSummaryResponse Object
*
* @author YuCheng Hu
*/
public class DataCubeArticle {
@JsonProperty("list")
private List<ArticleData> articleDataList;
public static class ArticleData {
@JsonProperty("ref_date")
private String refDate;
@JsonProperty("msgid")
private String msgId;
@JsonProperty("title")
private String title;
@JsonProperty("int_page_read_user")
private Long intPageReadUser;
@JsonProperty("ori_page_read_user")
private Long oriPageReadUser;
@JsonProperty("ori_page_read_count")
private Long oriPageReadCount;
@JsonProperty("share_user")
private Long shareUser;
@JsonProperty("shareCount")
private Long shareCount;
@JsonProperty("add_to_fav_user")
private Long addToFavUser;
@JsonProperty("add_to_fav_count")
private Long addToFavCount;
public String getRefDate() {
return refDate;
}
public void setRefDate(String refDate) {
this.refDate = refDate;
}
public String getMsgId() {
return msgId;
}
public void setMsgId(String msgId) {
this.msgId = msgId;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Long getIntPageReadUser() {
return intPageReadUser;
}
public void setIntPageReadUser(Long intPageReadUser) {
this.intPageReadUser = intPageReadUser;
}
public Long getOriPageReadUser() {
return oriPageReadUser;
}
public void setOriPageReadUser(Long oriPageReadUser) {
this.oriPageReadUser = oriPageReadUser;
}
public Long getOriPageReadCount() {
return oriPageReadCount;
}
public void setOriPageReadCount(Long oriPageReadCount) {
this.oriPageReadCount = oriPageReadCount;
}
public Long getShareUser() {
return shareUser;
}
public void setShareUser(Long shareUser) {
this.shareUser = shareUser;
}
public Long getShareCount() {
return shareCount;
}
public void setShareCount(Long shareCount) {
this.shareCount = shareCount;
}
public Long getAddToFavUser() {
return addToFavUser;
}
public void setAddToFavUser(Long addToFavUser) {
this.addToFavUser = addToFavUser;
}
public Long getAddToFavCount() {
return addToFavCount;
}
public void setAddToFavCount(Long addToFavCount) {
this.addToFavCount = addToFavCount;
}
}
public List<ArticleData> getArticleDataList() {
return articleDataList;
}
public void setArticleDataList(List<ArticleData> articleDataList) {
this.articleDataList = articleDataList;
}
}

View File

@ -1,78 +0,0 @@
package com.ossez.wechat.common.model.res;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
/**
* UserSummaryResponse Object
*
* @author YuCheng Hu
*/
public class DataCubeUser {
@JsonProperty("list")
private List<UserData> userDataList;
public static class UserData {
@JsonProperty("ref_date")
private String refDate;
@JsonProperty("user_source")
private Long userSource;
@JsonProperty("new_user")
private Long newUser;
@JsonProperty("cancel_user")
private Long cancelUser;
@JsonProperty("cumulate_user")
private Long cumulateUser;
public String getRefDate() {
return refDate;
}
public void setRefDate(String refDate) {
this.refDate = refDate;
}
public Long getUserSource() {
return userSource;
}
public void setUserSource(Long userSource) {
this.userSource = userSource;
}
public Long getNewUser() {
return newUser;
}
public void setNewUser(Long newUser) {
this.newUser = newUser;
}
public Long getCancelUser() {
return cancelUser;
}
public void setCancelUser(Long cancelUser) {
this.cancelUser = cancelUser;
}
public Long getCumulateUser() {
return cumulateUser;
}
public void setCumulateUser(Long cumulateUser) {
this.cumulateUser = cumulateUser;
}
}
public List<UserData> getUserDataList() {
return userDataList;
}
public void setUserDataList(List<UserData> userDataList) {
this.userDataList = userDataList;
}
}

View File

@ -1,35 +0,0 @@
package com.ossez.wechat.common.model.res;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ossez.wechat.common.api.WxMessageInMemoryDuplicateCheckerSingleton;
import org.apache.commons.lang3.StringUtils;
/**
* WeChatAccessToken Response Object
*
* @author YuCheng Hu
*/
public class NetworkCheckResponse {
@JsonProperty("dns")
private String dns;
@JsonProperty("ping")
private Ping ping;
private static class dns {
@JsonProperty("ip")
private String ip;
@JsonProperty("real_operator")
private String realOperator;
}
private static class Ping {
@JsonProperty("ip")
private String ip;
@JsonProperty("from_operator")
private String fromOperator;
@JsonProperty("package_loss")
private String packageLoss;
@JsonProperty("time")
private String time;
}
}

View File

@ -1,66 +0,0 @@
package com.ossez.wechat.common.model.res;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* WeChatAccessToken Response Object
*
* @author YuCheng Hu
*/
public class QueryQuotaResponse {
@JsonProperty("errcode")
private Integer errorCode;
@JsonProperty("errmsg")
private String errorMsg;
@JsonProperty("quota")
private Quota quota;
private static class Quota {
@JsonProperty("daily_limit")
private String dailyLimit;
@JsonProperty("used")
private String used;
@JsonProperty("remain")
private String remain;
public String getDailyLimit() {
return dailyLimit;
}
public void setDailyLimit(String dailyLimit) {
this.dailyLimit = dailyLimit;
}
public String getUsed() {
return used;
}
public void setUsed(String used) {
this.used = used;
}
public String getRemain() {
return remain;
}
public void setRemain(String remain) {
this.remain = remain;
}
}
public Integer getErrorCode() {
return errorCode;
}
public void setErrorCode(Integer errorCode) {
this.errorCode = errorCode;
}
public String getErrorMsg() {
return errorMsg;
}
public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}
}

View File

@ -1,37 +0,0 @@
package com.ossez.wechat.common.redis;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
/**
* 微信redis操作基本类
* <p>
* 非内置实现redis相关操作, 请实现该类
*/
public abstract class BaseWxRedisOps implements WxRedisOps {
@Override
public String getValue(String key) {
throw new UnsupportedOperationException();
}
@Override
public void setValue(String key, String value, int expire, TimeUnit timeUnit) {
throw new UnsupportedOperationException();
}
@Override
public Long getExpire(String key) {
throw new UnsupportedOperationException();
}
@Override
public void expire(String key, int expire, TimeUnit timeUnit) {
throw new UnsupportedOperationException();
}
@Override
public Lock getLock(String key) {
throw new UnsupportedOperationException();
}
}

View File

@ -1,44 +0,0 @@
package com.ossez.wechat.common.redis;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import com.ossez.wechat.common.util.locks.RedisTemplateSimpleDistributedLock;
import org.springframework.data.redis.core.StringRedisTemplate;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
@RequiredArgsConstructor
public class RedisTemplateWxRedisOps implements WxRedisOps {
private final StringRedisTemplate redisTemplate;
@Override
public String getValue(String key) {
return redisTemplate.opsForValue().get(key);
}
@Override
public void setValue(String key, String value, int expire, TimeUnit timeUnit) {
if (expire <= 0) {
redisTemplate.opsForValue().set(key, value);
} else {
redisTemplate.opsForValue().set(key, value, expire, timeUnit);
}
}
@Override
public Long getExpire(String key) {
return redisTemplate.getExpire(key);
}
@Override
public void expire(String key, int expire, TimeUnit timeUnit) {
redisTemplate.expire(key, expire, timeUnit);
}
@Override
public Lock getLock(@NonNull String key) {
return new RedisTemplateSimpleDistributedLock(redisTemplate, key, 60 * 1000);
}
}

View File

@ -1,47 +0,0 @@
package com.ossez.wechat.common.redis;
import lombok.RequiredArgsConstructor;
import org.redisson.api.RedissonClient;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
@RequiredArgsConstructor
public class RedissonWxRedisOps implements WxRedisOps {
private final RedissonClient redissonClient;
@Override
public String getValue(String key) {
Object value = redissonClient.getBucket(key).get();
return value == null ? null : value.toString();
}
@Override
public void setValue(String key, String value, int expire, TimeUnit timeUnit) {
if (expire <= 0) {
redissonClient.getBucket(key).set(value);
} else {
redissonClient.getBucket(key).set(value, expire, timeUnit);
}
}
@Override
public Long getExpire(String key) {
long expire = redissonClient.getBucket(key).remainTimeToLive();
if (expire > 0) {
expire = expire / 1000;
}
return expire;
}
@Override
public void expire(String key, int expire, TimeUnit timeUnit) {
redissonClient.getBucket(key).expire(expire, timeUnit);
}
@Override
public Lock getLock(String key) {
return redissonClient.getLock(key);
}
}

View File

@ -1,28 +0,0 @@
package com.ossez.wechat.common.redis;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
/**
* 微信Redis相关操作
* <p>
* 该接口不承诺稳定, 外部实现请继承{@link BaseWxRedisOps}
*
* @author Mario Luo
* @see BaseWxRedisOps 实现需要继承该类
* @see JedisWxRedisOps jedis实现
* @see RedissonWxRedisOps redisson实现
* @see RedisTemplateWxRedisOps redisTemplate实现
*/
public interface WxRedisOps {
String getValue(String key);
void setValue(String key, String value, int expire, TimeUnit timeUnit);
Long getExpire(String key);
void expire(String key, int expire, TimeUnit timeUnit);
Lock getLock(String key);
}

View File

@ -1,57 +0,0 @@
package com.ossez.wechat.common.requestexecuter.ocr;
import com.ossez.wechat.common.enums.WxType;
import com.ossez.wechat.common.exception.WxError;
import com.ossez.wechat.common.exception.WxErrorException;
import com.ossez.wechat.common.util.http.RequestHttp;
import com.ossez.wechat.common.util.http.apache.Utf8ResponseHandler;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import java.io.File;
import java.io.IOException;
/**
* .
*
* @author : zhayueran
* created on 2019/6/27 14:06
*/
public class OcrDiscernApacheHttpRequestExecutor extends OcrDiscernRequestExecutor<CloseableHttpClient, HttpHost> {
public OcrDiscernApacheHttpRequestExecutor(RequestHttp requestHttp) {
super(requestHttp);
}
@Override
public String execute(String uri, File file, WxType wxType) throws WxErrorException, IOException {
HttpPost httpPost = new HttpPost(uri);
if (requestHttp.getRequestHttpProxy() != null) {
RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build();
httpPost.setConfig(config);
}
if (file != null) {
HttpEntity entity = MultipartEntityBuilder
.create()
.addBinaryBody("file", file)
.setMode(HttpMultipartMode.RFC6532)
.build();
httpPost.setEntity(entity);
}
try (CloseableHttpResponse response = requestHttp.getRequestHttpClient().execute(httpPost)) {
String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
WxError error = WxError.fromJson(responseContent, wxType);
if (error.getErrorCode() != 0) {
throw new WxErrorException(error);
}
return responseContent;
} finally {
httpPost.releaseConnection();
}
}
}

View File

@ -1,38 +0,0 @@
package com.ossez.wechat.common.requestexecuter.ocr;
import com.ossez.wechat.common.enums.WxType;
import com.ossez.wechat.common.exception.WxErrorException;
import com.ossez.wechat.common.util.http.RequestExecutor;
import com.ossez.wechat.common.util.http.RequestHttp;
import com.ossez.wechat.common.util.http.ResponseHandler;
import java.io.File;
import java.io.IOException;
/**
* .
*
* @author zhayueran
* created on 2019/6/27 15:06
*/
public abstract class OcrDiscernRequestExecutor<H, P> implements RequestExecutor<String, File> {
protected RequestHttp<H, P> requestHttp;
public OcrDiscernRequestExecutor(RequestHttp requestHttp) {
this.requestHttp = requestHttp;
}
@Override
public void execute(String uri, File data, ResponseHandler<String> handler, WxType wxType) throws WxErrorException, IOException {
handler.handle(this.execute(uri, data, wxType));
}
public static RequestExecutor<String, File> create(RequestHttp requestHttp) {
switch (requestHttp.getRequestType()) {
case APACHE_HTTP:
return new OcrDiscernApacheHttpRequestExecutor(requestHttp);
default:
return null;
}
}
}

View File

@ -1,121 +0,0 @@
package com.ossez.wechat.common.service;
import com.ossez.wechat.common.exception.WxErrorException;
import com.ossez.wechat.common.bean.imgproc.WxImgProcAiCropResult;
import com.ossez.wechat.common.bean.imgproc.WxImgProcQrCodeResult;
import com.ossez.wechat.common.bean.imgproc.WxImgProcSuperResolutionResult;
import java.io.File;
/**
* 多项图像处理能力相关的API.
* https://developers.weixin.qq.com/doc/offiaccount/Intelligent_Interface/Img_Proc.html
*
* @author Theo Nie
*/
public interface WxImgProcService {
/**
* 二维码/条码识别接口
* 说明
* 1.图片支持使用img参数实时上传也支持使用img_url参数传送图片地址由微信后台下载图片进行识别
* 2.文件大小限制小于2M
* 3.支持条码二维码DataMatrix和PDF417的识别
* 4.二维码DataMatrix会返回位置坐标条码和PDF417暂不返回位置坐标
*
* @param imgUrl 图片url地址
* @return WxMpImgProcQrCodeResult
* @throws WxErrorException .
*/
WxImgProcQrCodeResult qrCode(String imgUrl) throws WxErrorException;
/**
* 二维码/条码识别接口
* 说明
* 1.图片支持使用img参数实时上传也支持使用img_url参数传送图片地址由微信后台下载图片进行识别
* 2.文件大小限制小于2M
* 3.支持条码二维码DataMatrix和PDF417的识别
* 4.二维码DataMatrix会返回位置坐标条码和PDF417暂不返回位置坐标
*
* @param imgFile 图片文件对象
* @return WxMpImgProcQrCodeResult
* @throws WxErrorException .
*/
WxImgProcQrCodeResult qrCode(File imgFile) throws WxErrorException;
/**
* 图片高清化接口
* 说明
* 1.图片支持使用img参数实时上传也支持使用img_url参数传送图片地址由微信后台下载图片进行识别
* 2.文件大小限制小于2M
* 3.目前支持将图片超分辨率高清化2倍即生成图片分辨率为原图2倍大小
* 返回的media_id有效期为3天期间可以通过获取临时素材接口获取图片二进制
*
* @param imgUrl 图片url地址
* @return WxMpImgProcSuperResolutionResult
* @throws WxErrorException .
*/
WxImgProcSuperResolutionResult superResolution(String imgUrl) throws WxErrorException;
/**
* 图片高清化接口
* 说明
* 1.图片支持使用img参数实时上传也支持使用img_url参数传送图片地址由微信后台下载图片进行识别
* 2.文件大小限制小于2M
* 3.目前支持将图片超分辨率高清化2倍即生成图片分辨率为原图2倍大小
* 返回的media_id有效期为3天期间可以通过获取临时素材接口获取图片二进制
*
* @param imgFile 图片文件对象
* @return WxMpImgProcSuperResolutionResult
* @throws WxErrorException .
*/
WxImgProcSuperResolutionResult superResolution(File imgFile) throws WxErrorException;
/**
* 图片智能裁剪接口
* 说明
* 1.图片支持使用img参数实时上传也支持使用img_url参数传送图片地址由微信后台下载图片进行识别
* 2.文件大小限制小于2M
* 3.该接口默认使用最佳宽高比
* @param imgUrl 图片url地址
* @return WxMpImgProcAiCropResult
* @throws WxErrorException .
*/
WxImgProcAiCropResult aiCrop(String imgUrl) throws WxErrorException;
/**
* 图片智能裁剪接口
* 说明
* 1.图片支持使用img参数实时上传也支持使用img_url参数传送图片地址由微信后台下载图片进行识别
* 2.文件大小限制小于2M
* @param imgUrl 图片url地址
* @param ratios 宽高比最多支持5个请以英文逗号分隔
* @return WxMpImgProcAiCropResult
* @throws WxErrorException .
*/
WxImgProcAiCropResult aiCrop(String imgUrl, String ratios) throws WxErrorException;
/**
* 图片智能裁剪接口
* 说明
* 1.图片支持使用img参数实时上传也支持使用img_url参数传送图片地址由微信后台下载图片进行识别
* 2.文件大小限制小于2M
* 3.该接口默认使用最佳宽高比
* @param imgFile 图片文件对象
* @return WxMpImgProcAiCropResult
* @throws WxErrorException .
*/
WxImgProcAiCropResult aiCrop(File imgFile) throws WxErrorException;
/**
* 图片智能裁剪接口
* 说明
* 1.图片支持使用img参数实时上传也支持使用img_url参数传送图片地址由微信后台下载图片进行识别
* 2.文件大小限制小于2M
* @param imgFile 图片文件对象
* @param ratios 宽高比最多支持5个请以英文逗号分隔
* @return WxMpImgProcAiCropResult
* @throws WxErrorException .
*/
WxImgProcAiCropResult aiCrop(File imgFile, String ratios) throws WxErrorException;
}

View File

@ -1,83 +0,0 @@
package com.ossez.wechat.common.service;
import com.ossez.wechat.common.model.entity.WeChatOAuth2UserInfo;
import com.ossez.wechat.common.model.WeChatOAuth2AccessToken;
import com.ossez.wechat.common.exception.WxErrorException;
/**
* oauth2 相关接口.
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
* created on 2020-08-08
*/
public interface WxOAuth2Service {
/**
* <pre>
* 构造oauth2授权的url连接.
* 详情请见: <a href="https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html">网页授权</a>
* </pre>
*
* @param redirectUri 用户授权完成后的重定向链接无需urlencode, 方法内会进行encode
* @param scope scope,静默:snsapi_base, 带信息授权:snsapi_userinfo
* @param state state
* @return url
*/
String buildAuthorizationUrl(String redirectUri, String scope, String state);
/**
* <pre>
* 用code换取oauth2的access token.
* 详情请见: <a href="https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html">网页授权获取用户基本信息</a>
* </pre>
*
* @param code code
* @return token对象
* @throws WxErrorException .
*/
WeChatOAuth2AccessToken getAccessToken(String code) throws WxErrorException;
/**
* 用code换取oauth2的access token.
*
* @param appId the appid
* @param appSecret the secret
* @param code code
* @return token对象
* @throws WxErrorException .
*/
WeChatOAuth2AccessToken getAccessToken(String appId, String appSecret, String code) throws WxErrorException;
/**
* <pre>
* 刷新oauth2的access token.
* </pre>
*
* @param refreshToken 刷新token
* @return 新的token对象
* @throws WxErrorException .
*/
WeChatOAuth2AccessToken refreshAccessToken(String refreshToken) throws WxErrorException;
/**
* <pre>
* 用oauth2获取用户信息, 当前面引导授权时的scope是snsapi_userinfo的时候才可以.
* </pre>
*
* @param oAuth2AccessToken token对象
* @param lang zh_CN, zh_TW, en
* @return 用户对象
* @throws WxErrorException .
*/
WeChatOAuth2UserInfo getUserInfo(WeChatOAuth2AccessToken oAuth2AccessToken, String lang) throws WxErrorException;
/**
* <pre>
* 验证oauth2的access token是否有效.
* </pre>
*
* @param oAuth2AccessToken token对象
* @return 是否有效
*/
boolean validateAccessToken(WeChatOAuth2AccessToken oAuth2AccessToken);
}

View File

@ -1,16 +0,0 @@
package com.ossez.wechat.common.service;
import lombok.AllArgsConstructor;
import lombok.experimental.Delegate;
/**
* 微信 oauth2服务 装饰器
*
* @author <a href="https://www.sacoc.cn">广州跨界</a>
*/
@AllArgsConstructor
public class WxOAuth2ServiceDecorator implements WxOAuth2Service {
@Delegate
private final WxOAuth2Service wxOAuth2Service;
}

View File

@ -1,131 +0,0 @@
package com.ossez.wechat.common.service;
import com.ossez.wechat.common.exception.WxErrorException;
import com.ossez.wechat.common.bean.ocr.WxOcrBankCardResult;
import com.ossez.wechat.common.bean.ocr.WxOcrBizLicenseResult;
import com.ossez.wechat.common.bean.ocr.WxOcrCommResult;
import com.ossez.wechat.common.bean.ocr.WxOcrDrivingLicenseResult;
import com.ossez.wechat.common.bean.ocr.WxOcrDrivingResult;
import com.ossez.wechat.common.bean.ocr.WxOcrIdCardResult;
import java.io.File;
/**
* 基于小程序或 H5 的身份证银行卡行驶证 OCR 识别.
* https://mp.weixin.qq.com/wiki?t=resource/res_main&id=21516712284rHWMX
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
* created on 2019-06-22
*/
public interface WxOcrService {
/**
* 身份证OCR识别接口.
*
* @param imgUrl 图片url地址
* @return WxMpOcrIdCardResult
* @throws WxErrorException .
*/
WxOcrIdCardResult idCard(String imgUrl) throws WxErrorException;
/**
* 身份证OCR识别接口.
*
* @param imgFile 图片文件对象
* @return WxMpOcrIdCardResult
* @throws WxErrorException .
*/
WxOcrIdCardResult idCard(File imgFile) throws WxErrorException;
/**
* 银行卡OCR识别接口
* 文件大小限制小于2M
* @param imgUrl 图片url地址
* @return WxMpOcrBankCardResult
* @throws WxErrorException .
*/
WxOcrBankCardResult bankCard(String imgUrl) throws WxErrorException;
/**
* 银行卡OCR识别接口
* 文件大小限制小于2M
* @param imgFile 图片文件对象
* @return WxMpOcrBankCardResult
* @throws WxErrorException .
*/
WxOcrBankCardResult bankCard(File imgFile) throws WxErrorException;
/**
* 行驶证OCR识别接口
* 文件大小限制小于2M
* @param imgUrl 图片url地址
* @return WxMpOcrDrivingResult
* @throws WxErrorException .
*/
WxOcrDrivingResult driving(String imgUrl) throws WxErrorException;
/**
* 行驶证OCR识别接口
* 文件大小限制小于2M
* @param imgFile 图片文件对象
* @return WxMpOcrDrivingResult
* @throws WxErrorException .
*/
WxOcrDrivingResult driving(File imgFile) throws WxErrorException;
/**
* 驾驶证OCR识别接口
* 文件大小限制小于2M
* @param imgUrl 图片url地址
* @return WxMpOcrDrivingLicenseResult
* @throws WxErrorException .
*/
WxOcrDrivingLicenseResult drivingLicense(String imgUrl) throws WxErrorException;
/**
* 驾驶证OCR识别接口
* 文件大小限制小于2M
* @param imgFile 图片文件对象
* @return WxMpOcrDrivingLicenseResult
* @throws WxErrorException .
*/
WxOcrDrivingLicenseResult drivingLicense(File imgFile) throws WxErrorException;
/**
* 营业执照OCR识别接口
* 文件大小限制小于2M
* @param imgUrl 图片url地址
* @return WxMpOcrBizLicenseResult
* @throws WxErrorException .
*/
WxOcrBizLicenseResult bizLicense(String imgUrl) throws WxErrorException;
/**
* 营业执照OCR识别接口
* 文件大小限制小于2M
* @param imgFile 图片文件对象
* @return WxMpOcrBizLicenseResult
* @throws WxErrorException .
*/
WxOcrBizLicenseResult bizLicense(File imgFile) throws WxErrorException;
/**
* 通用印刷体OCR识别接口
* 文件大小限制小于2M
* 适用于屏幕截图印刷体照片等场景
* @param imgUrl 图片url地址
* @return WxMpOcrCommResult
* @throws WxErrorException .
*/
WxOcrCommResult comm(String imgUrl) throws WxErrorException;
/**
* 通用印刷体OCR识别接口
* 文件大小限制小于2M
* 适用于屏幕截图印刷体照片等场景
* @param imgFile 图片文件对象
* @return WxMpOcrCommResult
* @throws WxErrorException .
*/
WxOcrCommResult comm(File imgFile) throws WxErrorException;
}

View File

@ -1,63 +0,0 @@
package com.ossez.wechat.common.service;
import com.google.gson.JsonObject;
import com.ossez.wechat.common.bean.ToJson;
import com.ossez.wechat.common.exception.WxErrorException;
/**
* 微信服务接口.
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
* created on 2020-04-25
*/
public interface WxService {
/**
* 当本Service没有实现某个API的时候可以用这个针对所有微信API中的GET请求.
*
* @param queryParam 参数
* @param url 请求接口地址
* @return 接口响应字符串
* @throws WxErrorException 异常
*/
String get(String url, String queryParam) throws WxErrorException;
/**
* 当本Service没有实现某个API的时候可以用这个针对所有微信API中的POST请求.
*
* @param postData 请求参数json值
* @param url 请求接口地址
* @return 接口响应字符串
* @throws WxErrorException 异常
*/
String post(String url, String postData) throws WxErrorException;
/**
* 当本Service没有实现某个API的时候可以用这个针对所有微信API中的POST请求.
*
* @param url 请求接口地址
* @param obj 请求对象
* @return 接口响应字符串
* @throws WxErrorException 异常
*/
String post(String url, Object obj) throws WxErrorException;
/**
* 当本Service没有实现某个API的时候可以用这个针对所有微信API中的POST请求.
*
* @param url 请求接口地址
* @param jsonObject 请求对象
* @return 接口响应字符串
* @throws WxErrorException 异常
*/
String post(String url, JsonObject jsonObject) throws WxErrorException;
/**
* 当本Service没有实现某个API的时候可以用这个针对所有微信API中的POST请求.
*
* @param url 请求接口地址
* @param obj 请求对象实现了ToJson接口
* @return 接口响应字符串
* @throws WxErrorException 异常
*/
String post(String url, ToJson obj) throws WxErrorException;
}

View File

@ -1,64 +0,0 @@
package com.ossez.wechat.common.util;
import com.google.common.collect.Lists;
import com.ossez.wechat.common.annotation.Required;
import com.ossez.wechat.common.exception.WxErrorException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* <pre>
* bean操作的一些工具类
* Created by Binary Wang on 2016-10-21.
* </pre>
*
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
*/
public class BeanUtils {
private static Logger log = LoggerFactory.getLogger(BeanUtils.class);
/**
* 检查bean里标记为@Required的field是否为空为空则抛异常
*
* @param bean 要检查的bean对象
*/
public static void checkRequiredFields(Object bean) throws WxErrorException {
List<String> requiredFields = Lists.newArrayList();
List<Field> fields = new ArrayList<>(Arrays.asList(bean.getClass().getDeclaredFields()));
fields.addAll(Arrays.asList(bean.getClass().getSuperclass().getDeclaredFields()));
for (Field field : fields) {
try {
boolean isAccessible = field.isAccessible();
field.setAccessible(true);
if (field.isAnnotationPresent(Required.class)) {
// 两种情况一种是值为null
// 另外一种情况是类型为字符串但是字符串内容为空的都认为是没有提供值
boolean isRequiredMissing = field.get(bean) == null
|| (field.get(bean) instanceof String
&& StringUtils.isBlank(field.get(bean).toString())
);
if (isRequiredMissing) {
requiredFields.add(field.getName());
}
}
field.setAccessible(isAccessible);
} catch (SecurityException | IllegalArgumentException | IllegalAccessException e) {
log.error(e.getMessage(), e);
}
}
if (!requiredFields.isEmpty()) {
String msg = String.format("必填字段【%s】必须提供值", requiredFields);
log.debug(msg);
throw new WxErrorException(msg);
}
}
}

View File

@ -1,25 +0,0 @@
package com.ossez.wechat.common.util;
import org.apache.commons.lang3.RegExUtils;
import org.apache.commons.lang3.StringUtils;
/**
* <pre>
* 数据处理工具类
* Created by BinaryWang on 2018/5/8.
* </pre>
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
public class DataUtils {
/**
* 将数据中包含的secret字符使用星号替换防止日志打印时被输出
*/
public static <E> E handleDataWithSecret(E data) {
E dataForLog = data;
if(data instanceof String && StringUtils.contains((String)data, "&secret=")){
dataForLog = (E) RegExUtils.replaceAll((String)data,"&secret=\\w+&","&secret=******&");
}
return dataForLog;
}
}

View File

@ -1,177 +0,0 @@
package com.ossez.wechat.common.util;
import lombok.Data;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementFilter;
import javax.tools.FileObject;
import javax.tools.StandardLocation;
import java.io.IOException;
import java.io.Writer;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
/**
* 目前仅仅处理@Data且必须在lombok自己的processor之前执行千万注意
*
* @author outersky
*/
@SupportedAnnotationTypes("lombok.Data")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class GraalProcessor extends AbstractProcessor {
private static final String REFLECTION_CONFIG_JSON = "reflection-config.json";
private static final String NATIVE_IMAGE_PROPERTIES = "native-image.properties";
private final SortedSet<String> classSet = new TreeSet<>();
private String shortestPackageName = null;
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
for (TypeElement annotatedClass : ElementFilter.typesIn(roundEnv.getElementsAnnotatedWith(Data.class))) {
registerClass(annotatedClass.getQualifiedName().toString());
handleSuperClass(annotatedClass);
}
//只有最后一轮才可以写文件否则文件会被重复打开报错
if (!roundEnv.processingOver()) {
return false;
}
// 如果没有文件要写跳过
if (classSet.isEmpty()) {
return false;
}
writeFiles();
//必须返回false以便让lombok能继续处理
return false;
}
/**
* 设置当前最短的package名称
*
* @param packageName 包名
*/
private void setShortestPackageName(String packageName) {
if (shortestPackageName == null) {
shortestPackageName = packageName;
} else if (packageName.length() < shortestPackageName.length()) {
shortestPackageName = packageName;
}
}
/**
* 更加完整的类名来获取package名称
*
* @param fullClassName 完整的类名
* @return package name
*/
private String getPackageName(String fullClassName) {
int last = fullClassName.lastIndexOf('.');
if (last == -1) {
return fullClassName;
}
return fullClassName.substring(0, last);
}
/**
* 保存文件
* META-INF/native-image/.../reflection-config.json
* META-INF/native-image/.../native-image.properties
*/
private void writeFiles() {
String basePackage = shortestPackageName;
String module;
if (basePackage.contains(".")) {
final int i = basePackage.lastIndexOf('.');
module = basePackage.substring(i + 1);
basePackage = basePackage.substring(0, i);
} else {
module = basePackage;
}
String path = "META-INF/native-image/" + basePackage + "/" + module + "/";
String reflectFile = path + REFLECTION_CONFIG_JSON;
String propsFile = path + NATIVE_IMAGE_PROPERTIES;
try {
FileObject fileObject = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", propsFile);
try (Writer writer = fileObject.openWriter();) {
writer.append("Args = -H:ReflectionConfigurationResources=${.}/" + REFLECTION_CONFIG_JSON);
}
} catch (IOException e) {
e.printStackTrace();
}
try {
FileObject fileObject = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", reflectFile);
try (Writer writer = fileObject.openWriter();) {
writer.write("[\n");
boolean first = true;
for (String name : classSet) {
if (first) {
first = false;
} else {
writer.write(",");
}
writer.write(assetGraalJsonElement(name));
writer.append('\n');
}
writer.write("]");
}
} catch (IOException e) {
e.printStackTrace();
}
}
private String assetGraalJsonElement(String className) {
return "{\n" +
" \"name\" : \"" + className + "\",\n" +
" \"allDeclaredFields\":true,\n" +
" \"allDeclaredMethods\":true,\n" +
" \"allDeclaredConstructors\":true,\n" +
" \"allPublicMethods\" : true\n" +
"}";
}
/**
* 登记一个class
*
* @param className 完整的类名
*/
private void registerClass(String className) {
classSet.add(className);
setShortestPackageName(getPackageName(className));
}
/**
* 获取一个类型的所有的父类并登记
*
* @param typeElement 类型元素
*/
private void handleSuperClass(TypeElement typeElement) {
TypeMirror superclass = typeElement.getSuperclass();
if (superclass.getKind() == TypeKind.DECLARED) {
TypeElement s = (TypeElement) ((DeclaredType) superclass).asElement();
String sName = s.toString();
// ignore java.**/javax.**
if (sName.startsWith("java.") || sName.startsWith("javax.")) {
return;
}
registerClass(sName);
handleSuperClass(s);
}
}
}

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