Преглед изворни кода

# 368 增加 微信第三方平台 模块

* 增加 微信第三方平台 接口

* WxOpenXmlMessage 消息处理
master
007gzs пре 7 година
committed by Binary Wang
родитељ
комит
d52a55ff8d
31 измењених фајлова са 2302 додато и 381 уклоњено
  1. +387
    -381
      pom.xml
  2. +62
    -0
      weixin-java-open/README.md
  3. +97
    -0
      weixin-java-open/pom.xml
  4. +82
    -0
      weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenComponentService.java
  5. +106
    -0
      weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenConfigStorage.java
  6. +22
    -0
      weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenService.java
  7. +218
    -0
      weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenComponentServiceImpl.java
  8. +386
    -0
      weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenInMemoryConfigStorage.java
  9. +164
    -0
      weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenInRedisConfigStorage.java
  10. +49
    -0
      weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMpServiceImpl.java
  11. +63
    -0
      weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenServiceAbstractImpl.java
  12. +44
    -0
      weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenServiceApacheHttpClientImpl.java
  13. +8
    -0
      weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenServiceImpl.java
  14. +35
    -0
      weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/WxOpenAuthorizerAccessToken.java
  15. +35
    -0
      weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/WxOpenComponentAccessToken.java
  16. +18
    -0
      weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/WxOpenAuthorizationInfo.java
  17. +22
    -0
      weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/WxOpenAuthorizerInfo.java
  18. +100
    -0
      weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/message/WxOpenXmlMessage.java
  19. +16
    -0
      weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/result/WxOpenAuthorizerInfoResult.java
  20. +15
    -0
      weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/result/WxOpenAuthorizerOptionResult.java
  21. +14
    -0
      weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/result/WxOpenQueryAuthResult.java
  22. +28
    -0
      weixin-java-open/src/main/java/me/chanjar/weixin/open/util/WxOpenCryptUtil.java
  23. +45
    -0
      weixin-java-open/src/main/java/me/chanjar/weixin/open/util/json/WxOpenAuthorizationInfoGsonAdapter.java
  24. +21
    -0
      weixin-java-open/src/main/java/me/chanjar/weixin/open/util/json/WxOpenAuthorizerAccessTokenGsonAdapter.java
  25. +38
    -0
      weixin-java-open/src/main/java/me/chanjar/weixin/open/util/json/WxOpenAuthorizerInfoGsonAdapter.java
  26. +32
    -0
      weixin-java-open/src/main/java/me/chanjar/weixin/open/util/json/WxOpenAuthorizerInfoResultGsonAdapter.java
  27. +22
    -0
      weixin-java-open/src/main/java/me/chanjar/weixin/open/util/json/WxOpenAuthorizerOptionResultGsonAdapter.java
  28. +21
    -0
      weixin-java-open/src/main/java/me/chanjar/weixin/open/util/json/WxOpenComponentAccessTokenGsonAdapter.java
  29. +36
    -0
      weixin-java-open/src/main/java/me/chanjar/weixin/open/util/json/WxOpenGsonBuilder.java
  30. +26
    -0
      weixin-java-open/src/main/java/me/chanjar/weixin/open/util/json/WxOpenQueryAuthResultGsonAdapter.java
  31. +90
    -0
      weixin-java-open/src/main/java/me/chanjar/weixin/open/util/xml/XStreamTransformer.java

+ 387
- 381
pom.xml Прегледај датотеку

@@ -1,381 +1,387 @@
<?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.github.binarywang</groupId>
<artifactId>weixin-java-parent</artifactId>
<version>2.8.6.BETA</version>
<packaging>pom</packaging>
<name>WeiXin Java Tools - Parent</name>
<description>微信公众号、企业号上级POM</description>
<url>https://github.com/wechat-group/weixin-java-tools</url>

<licenses>
<license>
<name>The Apache License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
</license>
</licenses>

<developers>
<developer>
<name>Daniel Qian</name>
<email>chanjarster@gmail.com</email>
<url>https://github.com/chanjarster</url>
</developer>
<developer>
<name>Binary Wang</name>
<email>binarywang@gmail.com</email>
<url>https://github.com/binarywang</url>
</developer>
<developer>
<name>gaigeshen</name>
<email>gaigeshen@qq.com</email>
<url>https://github.com/gaigeshen</url>
</developer>
<developer>
<name>Liu Mingbo</name>
<email>liumingbo2008@gmail.com</email>
<url>https://github.com/FirenzesEagle</url>
</developer>
<developer>
<name>kakotor</name>
<email>kakotor@gmail.com</email>
<url>https://github.com/kakotor</url>
</developer>
<developer>
<name>xiong</name>
<email>zhaoxiong.tan@gmail.com</email>
<url>https://github.com/ZhaoxiongTan</url>
</developer>
<developer>
<name>LiuJunGuang</name>
<email>aimilin@yeah.net</email>
<url>https://github.com/aimilin6688</url>
</developer>
<developer>
<name>Eric.Tsai</name>
<email>xiaodong.cai.ks@gmail.com</email>
<url>https://github.com/iwareserictsai</url>
</developer>
<developer>
<name>withinthefog</name>
<email>withinthefog@gmail.com</email>
<url>https://github.com/withinthefog</url>
</developer>
<developer>
<name>Keung</name>
<email>dongfuqiang1988@163.com</email>
<url>https://github.com/johnnytung</url>
</developer>
<developer>
<name>Jonk</name>
<email>aimilin@yeah.net</email>
<url>https://github.com/aimilin6688</url>
</developer>
<developer>
<name>ecoolper</name>
<email>crskyp@gmail.com</email>
<url>https://github.com/crskyp</url>
</developer>
</developers>

<scm>
<connection>scm:git:https://github.com/wechat-group/weixin-java-tools.git</connection>
<developerConnection>scm:git:git@github.com:wechat-group/weixin-java-tools.git</developerConnection>
<url>https://github.com/wechat-group/weixin-java-tools</url>
</scm>

<modules>
<module>weixin-java-common</module>
<module>weixin-java-cp</module>
<module>weixin-java-mp</module>
<module>weixin-java-pay</module>
<module>weixin-java-miniapp</module>
<!--module>weixin-java-osgi</module-->
</modules>

<properties>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<downloadJavadocs>true</downloadJavadocs>
<downloadSources>true</downloadSources>
<httpclient.version>4.5</httpclient.version>
<jetty.version>9.3.0.RC0</jetty.version>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>qrcode-utils</artifactId>
<version>1.1</version>
</dependency>
<!-- 由于jodd-http较新的3.8版本需要jdk8,故而此处采用较低版本 -->
<dependency>
<groupId>org.jodd</groupId>
<artifactId>jodd-http</artifactId>
<version>3.7.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.7.0</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>${httpclient.version}</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>${httpclient.version}</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.5</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.24</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.9</version>
</dependency>
<!-- 由于guava较新的21.0版本需要jdk8,故而此处采用较低版本 -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>20.0</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.0</version>
</dependency>

<!-- 测试所用依赖 -->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.9.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>3.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.9.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${jetty.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>${jetty.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
<scope>compile</scope>
</dependency>
</dependencies>
</dependencyManagement>

<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>

<profiles>
<profile>
<id>doclint-java8-disable</id>
<activation>
<jdk>[1.8,)</jdk>
</activation>
<properties>
<javadoc.opts>-Xdoclint:none</javadoc.opts>
</properties>
</profile>

<profile>
<id>release</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9.1</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
<configuration>
<additionalparam>${javadoc.opts}</additionalparam>
<charset>UTF-8</charset>
<locale>zh_CN</locale>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>

<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.17</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</pluginManagement>

<plugins>
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.6.3</version>
<extensions>true</extensions>
<configuration>
<serverId>ossrh</serverId>
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
<autoReleaseAfterClose>true</autoReleaseAfterClose>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<autoVersionSubmodules>true</autoVersionSubmodules>
<useReleaseProfile>false</useReleaseProfile>
<releaseProfiles>release</releaseProfiles>
<goals>deploy</goals>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>2.17</version>
<configuration>
<configLocation>quality-checks/google_checks.xml</configLocation>
<includeTestSourceDirectory>true</includeTestSourceDirectory>
<consoleOutput>true</consoleOutput>
<failsOnError>true</failsOnError>
</configuration>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

</project>
<?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.github.binarywang</groupId>
<artifactId>weixin-java-parent</artifactId>
<version>2.8.6.BETA</version>
<packaging>pom</packaging>
<name>WeiXin Java Tools - Parent</name>
<description>微信公众号、企业号上级POM</description>
<url>https://github.com/wechat-group/weixin-java-tools</url>
<licenses>
<license>
<name>The Apache License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
</license>
</licenses>
<developers>
<developer>
<name>Daniel Qian</name>
<email>chanjarster@gmail.com</email>
<url>https://github.com/chanjarster</url>
</developer>
<developer>
<name>Binary Wang</name>
<email>binarywang@gmail.com</email>
<url>https://github.com/binarywang</url>
</developer>
<developer>
<name>gaigeshen</name>
<email>gaigeshen@qq.com</email>
<url>https://github.com/gaigeshen</url>
</developer>
<developer>
<name>Liu Mingbo</name>
<email>liumingbo2008@gmail.com</email>
<url>https://github.com/FirenzesEagle</url>
</developer>
<developer>
<name>kakotor</name>
<email>kakotor@gmail.com</email>
<url>https://github.com/kakotor</url>
</developer>
<developer>
<name>xiong</name>
<email>zhaoxiong.tan@gmail.com</email>
<url>https://github.com/ZhaoxiongTan</url>
</developer>
<developer>
<name>LiuJunGuang</name>
<email>aimilin@yeah.net</email>
<url>https://github.com/aimilin6688</url>
</developer>
<developer>
<name>Eric.Tsai</name>
<email>xiaodong.cai.ks@gmail.com</email>
<url>https://github.com/iwareserictsai</url>
</developer>
<developer>
<name>withinthefog</name>
<email>withinthefog@gmail.com</email>
<url>https://github.com/withinthefog</url>
</developer>
<developer>
<name>Keung</name>
<email>dongfuqiang1988@163.com</email>
<url>https://github.com/johnnytung</url>
</developer>
<developer>
<name>Jonk</name>
<email>aimilin@yeah.net</email>
<url>https://github.com/aimilin6688</url>
</developer>
<developer>
<name>ecoolper</name>
<email>crskyp@gmail.com</email>
<url>https://github.com/crskyp</url>
</developer>
<developer>
<name>007</name>
<email>007gzs@gmail.com</email>
<url>https://github.com/007gzs</url>
</developer>
</developers>
<scm>
<connection>scm:git:https://github.com/wechat-group/weixin-java-tools.git</connection>
<developerConnection>scm:git:git@github.com:wechat-group/weixin-java-tools.git</developerConnection>
<url>https://github.com/wechat-group/weixin-java-tools</url>
</scm>
<modules>
<module>weixin-java-common</module>
<module>weixin-java-cp</module>
<module>weixin-java-mp</module>
<module>weixin-java-pay</module>
<module>weixin-java-miniapp</module>
<module>weixin-java-open</module>
<!--module>weixin-java-osgi</module-->
</modules>
<properties>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<downloadJavadocs>true</downloadJavadocs>
<downloadSources>true</downloadSources>
<httpclient.version>4.5</httpclient.version>
<jetty.version>9.3.0.RC0</jetty.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>qrcode-utils</artifactId>
<version>1.1</version>
</dependency>
<!-- 由于jodd-http较新的3.8版本需要jdk8,故而此处采用较低版本 -->
<dependency>
<groupId>org.jodd</groupId>
<artifactId>jodd-http</artifactId>
<version>3.7.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.7.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>${httpclient.version}</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>${httpclient.version}</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.5</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.24</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.9</version>
</dependency>
<!-- 由于guava较新的21.0版本需要jdk8,故而此处采用较低版本 -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>20.0</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.0</version>
</dependency>
<!-- 测试所用依赖 -->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.9.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>3.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.9.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${jetty.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>${jetty.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
<scope>compile</scope>
</dependency>
</dependencies>
</dependencyManagement>
<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<profiles>
<profile>
<id>doclint-java8-disable</id>
<activation>
<jdk>[1.8,)</jdk>
</activation>
<properties>
<javadoc.opts>-Xdoclint:none</javadoc.opts>
</properties>
</profile>
<profile>
<id>release</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9.1</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
<configuration>
<additionalparam>${javadoc.opts}</additionalparam>
<charset>UTF-8</charset>
<locale>zh_CN</locale>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.17</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.6.3</version>
<extensions>true</extensions>
<configuration>
<serverId>ossrh</serverId>
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
<autoReleaseAfterClose>true</autoReleaseAfterClose>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<autoVersionSubmodules>true</autoVersionSubmodules>
<useReleaseProfile>false</useReleaseProfile>
<releaseProfiles>release</releaseProfiles>
<goals>deploy</goals>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>2.17</version>
<configuration>
<configLocation>quality-checks/google_checks.xml</configLocation>
<includeTestSourceDirectory>true</includeTestSourceDirectory>
<consoleOutput>true</consoleOutput>
<failsOnError>true</failsOnError>
</configuration>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

+ 62
- 0
weixin-java-open/README.md Прегледај датотеку

@@ -0,0 +1,62 @@
消息机制未实现,下面为通知回调中设置的代码部分
```
@RestController
@RequestMapping("notify")
public class NotifyController extends WechatThridBaseController {
@Autowired
protected WxOpenServiceDemo wxOpenService;
@RequestMapping("receive_ticket")
public Object receiveTicket(@RequestBody(required = false) String requestBody, @RequestParam("timestamp") String timestamp,
@RequestParam("nonce") String nonce, @RequestParam("signature") String signature,
@RequestParam(name = "encrypt_type", required = false) String encType,
@RequestParam(name = "msg_signature", required = false) String msgSignature) {
this.logger.info(
"\n接收微信请求:[signature=[{}], encType=[{}], msgSignature=[{}],"
+ " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ",
signature, encType, msgSignature, timestamp, nonce, requestBody);

if (!StringUtils.equalsIgnoreCase("aes", encType) || !wxOpenService.getWxOpenComponentService().checkSignature(timestamp, nonce, signature)) {
throw new IllegalArgumentException("非法请求,可能属于伪造的请求!");
}

// aes加密的消息
WxOpenXmlMessage inMessage = WxOpenXmlMessage.fromEncryptedXml(requestBody, wxOpenService.getWxOpenConfigStorage(), timestamp, nonce, msgSignature);
this.logger.debug("\n消息解密后内容为:\n{} ", inMessage.toString());
String out = null;
try {
out = wxOpenService.getWxOpenComponentService().route(inMessage);
} catch (WxErrorException e) {
throw new ResponseException(ErrorCodeEnum.ERROR, e);
}

this.logger.debug("\n组装回复信息:{}", out);

return out;
}
@RequestMapping("{appId}/callback")
public Object callback(@RequestBody(required = false)String requestBody,
@PathVariable ("appId") String appId,
@RequestParam("signature") String signature,
@RequestParam("timestamp") String timestamp,
@RequestParam("nonce") String nonce,
@RequestParam("openid") String openid,
@RequestParam("encrypt_type") String encType,
@RequestParam("msg_signature") String msgSignature) {
this.logger.info(
"\n接收微信请求:[appId=[{}], openid=[{}], signature=[{}], encType=[{}], msgSignature=[{}],"
+ " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ",
appId, openid, signature, encType, msgSignature, timestamp, nonce, requestBody);
logger.info("query:"+getHttpServletRequest().getQueryString()+"\nbody:"+requestBody);
if (!StringUtils.equalsIgnoreCase("aes", encType) || !wxOpenService.getWxOpenComponentService().checkSignature(timestamp, nonce, signature)) {
throw new IllegalArgumentException("非法请求,可能属于伪造的请求!");
}

String out = "";
// aes加密的消息
WxMpXmlMessage inMessage = WxOpenXmlMessage.fromEncryptedMpXml(requestBody, wxOpenService.getWxOpenConfigStorage(), timestamp, nonce, msgSignature);
this.logger.debug("\n消息解密后内容为:\n{} ", inMessage.toString());
//wxOpenService.getWxOpenComponentService().getWxMpServiceByAppid(appId);
return out;
}
}
```

+ 97
- 0
weixin-java-open/pom.xml Прегледај датотеку

@@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8"?>
<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>
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-parent</artifactId>
<version>2.8.6.BETA</version>
</parent>
<artifactId>weixin-java-open</artifactId>
<name>WeiXin Java Tools - Open</name>
<description>微信开放平台Java SDK</description>
<developers>
<developer>
<name>007</name>
<email>007gzs@gmail.com</email>
<url>https://github.com/007gzs</url>
</developer>
</developers>
<dependencies>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>org.jodd</groupId>
<artifactId>jodd-http</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>test</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>


</project>

+ 82
- 0
weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenComponentService.java Прегледај датотеку

@@ -0,0 +1,82 @@
package me.chanjar.weixin.open.api;

import me.chanjar.weixin.common.bean.result.WxError;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.open.bean.message.WxOpenXmlMessage;
import me.chanjar.weixin.open.bean.result.WxOpenAuthorizerInfoResult;
import me.chanjar.weixin.open.bean.result.WxOpenAuthorizerOptionResult;
import me.chanjar.weixin.open.bean.result.WxOpenQueryAuthResult;

/**
* @author <a href="https://github.com/007gzs">007</a>
*/
public interface WxOpenComponentService {

String API_COMPONENT_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/component/api_component_token";
String API_CREATE_PREAUTHCODE_URL = "https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode";
String API_QUERY_AUTH_URL = "https://api.weixin.qq.com/cgi-bin/component/api_query_auth";
String API_AUTHORIZER_TOKEN_URL = "https://api.weixin.qq.com /cgi-bin/component/api_authorizer_token";
String API_GET_AUTHORIZER_INFO_URL = "https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_info";
String API_GET_AUTHORIZER_OPTION_URL = "https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_option";
String API_SET_AUTHORIZER_OPTION_URL = "https://api.weixin.qq.com/cgi-bin/component/ api_set_authorizer_option";


String COMPONENT_LOGIN_PAGE_URL = "https://mp.weixin.qq.com/cgi-bin/componentloginpage?component_appid=%s&pre_auth_code=%s&redirect_uri=%s";
String CONNECT_OAUTH2_AUTHORIZE_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s&component_appid=%s#wechat_redirect";

/**
* 用code换取oauth2的access token
*/
String OAUTH2_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&code=%s&grant_type=authorization_code&component_appid=%s";
/**
* 刷新oauth2的access token
*/
String OAUTH2_REFRESH_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=%s&grant_type=refresh_token&refresh_token=%s&component_appid==%s";
WxMpService getWxMpServiceByAppid(String appid);

WxOpenConfigStorage getWxOpenConfigStorage();

boolean checkSignature(String timestamp, String nonce, String signature);

String getComponentAccessToken(boolean forceRefresh) throws WxErrorException;

/**
* 获取用户授权页URL(来路URL和成功跳转URL 的域名都需要为三方平台设置的 登录授权的发起页域名)
*/
String getPreAuthUrl(String redirectURI) throws WxErrorException;

String route(WxOpenXmlMessage wxMessage) throws WxErrorException;

/**
* 使用授权码换取公众号或小程序的接口调用凭据和授权信息
*/
WxOpenQueryAuthResult getQueryAuth(String authorizationCode) throws WxErrorException;

/**
* 获取授权方的帐号基本信息
*/
WxOpenAuthorizerInfoResult getAuthorizerInfo(String authorizerAppid) throws WxErrorException;

/**
* 获取授权方的选项设置信息
*/
WxOpenAuthorizerOptionResult getAuthorizerOption(String authorizerAppid, String optionName) throws WxErrorException;

/**
* 设置授权方的选项信息
*/
WxError setAuthorizerOption(String authorizerAppid, String optionName, String optionValue) throws WxErrorException;

String getAuthorizerAccessToken(String appid, boolean forceRefresh) throws WxErrorException;

WxMpOAuth2AccessToken oauth2getAccessToken(String appid, String code) throws WxErrorException;

boolean checkSignature(String appId, String timestamp, String nonce, String signature);

WxMpOAuth2AccessToken oauth2refreshAccessToken(String appid, String refreshToken) throws WxErrorException;

String oauth2buildAuthorizationUrl(String appid, String redirectURI, String scope, String state);

}

+ 106
- 0
weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenConfigStorage.java Прегледај датотеку

@@ -0,0 +1,106 @@
package me.chanjar.weixin.open.api;

import me.chanjar.weixin.mp.api.WxMpConfigStorage;
import me.chanjar.weixin.open.bean.WxOpenAuthorizerAccessToken;
import me.chanjar.weixin.open.bean.WxOpenComponentAccessToken;

/**
* @author <a href="https://github.com/007gzs">007</a>
*/
public interface WxOpenConfigStorage {

void setComponentAppId(String componentAppId);

void setComponentAppSecret(String componentAppSecret);

void setComponentToken(String componentToken);

void setComponentAesKey(String componentAesKey);

String getComponentAppId();
String getComponentAppSecret();
String getComponentToken();
String getComponentAesKey();
String getComponentVerifyTicket();
void setComponentVerifyTicket(String componentVerifyTicket);
String getComponentAccessToken();
boolean isComponentAccessTokenExpired();
void updateComponentAccessTokent(WxOpenComponentAccessToken componentAccessToken);
WxMpConfigStorage getWxMpConfigStorage(String appId);
/**
* 应该是线程安全的
*
* @param componentAccessToken 新的accessToken值
* @param expiresInSeconds 过期时间,以秒为单位
*/
void updateComponentAccessTokent(String componentAccessToken, int expiresInSeconds);

/**
* 是否自动刷新token
*/
boolean autoRefreshToken();


String getAuthorizerRefreshToken(String appId);
void setAuthorizerRefreshToken(String appId, String authorizerRefreshToken);
String getAuthorizerAccessToken(String appId);


boolean isAuthorizerAccessTokenExpired(String appId);

/**
* 强制将access token过期掉
*/
void expireAuthorizerAccessToken(String appId);

/**
* 应该是线程安全的
*
* @param authorizerAccessToken 要更新的WxAccessToken对象
*/
void updateAuthorizerAccessToken(String appId, WxOpenAuthorizerAccessToken authorizerAccessToken);

/**
* 应该是线程安全的
*
* @param authorizerAccessToken 新的accessToken值
* @param expiresInSeconds 过期时间,以秒为单位
*/
void updateAuthorizerAccessToken(String appId, String authorizerAccessToken, int expiresInSeconds);

String getJsapiTicket(String appId);

boolean isJsapiTicketExpired(String appId);

/**
* 强制将jsapi ticket过期掉
*/
void expireJsapiTicket(String appId);

/**
* 应该是线程安全的
*
* @param jsapiTicket 新的jsapi ticket值
* @param expiresInSeconds 过期时间,以秒为单位
*/
void updateJsapiTicket(String appId, String jsapiTicket, int expiresInSeconds);

String getCardApiTicket(String appId);


boolean isCardApiTicketExpired(String appId);

/**
* 强制将卡券api ticket过期掉
*/
void expireCardApiTicket(String appId);

/**
* 应该是线程安全的
*
* @param cardApiTicket 新的cardApi ticket值
* @param expiresInSeconds 过期时间,以秒为单位
*/
void updateCardApiTicket(String appId, String cardApiTicket, int expiresInSeconds);

}

+ 22
- 0
weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenService.java Прегледај датотеку

@@ -0,0 +1,22 @@
package me.chanjar.weixin.open.api;

import me.chanjar.weixin.common.exception.WxErrorException;

/**
* @author <a href="https://github.com/007gzs">007</a>
*/
public interface WxOpenService {
WxOpenComponentService getWxOpenComponentService();
WxOpenConfigStorage getWxOpenConfigStorage();
void setWxOpenConfigStorage(WxOpenConfigStorage wxOpenConfigStorage);
/**
* 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的GET请求
*/
String get(String url, String queryParam) throws WxErrorException;

/**
* 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的POST请求
*/
String post(String url, String postData) throws WxErrorException;

}

+ 218
- 0
weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenComponentServiceImpl.java Прегледај датотеку

@@ -0,0 +1,218 @@
package me.chanjar.weixin.open.api.impl;

import com.google.gson.JsonObject;
import me.chanjar.weixin.common.bean.result.WxError;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.util.crypto.SHA1;
import me.chanjar.weixin.common.util.http.URIUtil;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.open.api.WxOpenComponentService;
import me.chanjar.weixin.open.api.WxOpenConfigStorage;
import me.chanjar.weixin.open.api.WxOpenService;
import me.chanjar.weixin.open.bean.WxOpenAuthorizerAccessToken;
import me.chanjar.weixin.open.bean.WxOpenComponentAccessToken;
import me.chanjar.weixin.open.bean.auth.WxOpenAuthorizationInfo;
import me.chanjar.weixin.open.bean.message.WxOpenXmlMessage;
import me.chanjar.weixin.open.bean.result.WxOpenAuthorizerInfoResult;
import me.chanjar.weixin.open.bean.result.WxOpenAuthorizerOptionResult;
import me.chanjar.weixin.open.bean.result.WxOpenQueryAuthResult;
import me.chanjar.weixin.open.util.json.WxOpenGsonBuilder;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

/**
* @author <a href="https://github.com/007gzs">007</a>
*/
public class WxOpenComponentServiceImpl implements WxOpenComponentService {
protected final Logger log = LoggerFactory.getLogger(this.getClass());
private WxOpenService wxOpenService;
private static final Map<String, WxMpService> wxOpenMpServiceMap = new Hashtable<>();

public WxOpenComponentServiceImpl(WxOpenService wxOpenService) {
this.wxOpenService = wxOpenService;
}

@Override
public WxMpService getWxMpServiceByAppid(String appId) {
WxMpService wxMpService = wxOpenMpServiceMap.get(appId);
if (wxMpService == null) {
synchronized (wxOpenMpServiceMap) {
wxMpService = wxOpenMpServiceMap.get(appId);
if (wxMpService == null) {
wxMpService = new WxOpenMpServiceImpl(this, appId, getWxOpenConfigStorage().getWxMpConfigStorage(appId));

wxOpenMpServiceMap.put(appId, wxMpService);
}
}
}
return wxMpService;
}

public WxOpenService getWxOpenService() {
return wxOpenService;
}

@Override
public WxOpenConfigStorage getWxOpenConfigStorage() {
return wxOpenService.getWxOpenConfigStorage();
}
@Override
public boolean checkSignature(String timestamp, String nonce, String signature) {
try {
return SHA1.gen(getWxOpenConfigStorage().getComponentToken(), timestamp, nonce)
.equals(signature);
} catch (Exception e) {
this.log.error("Checking signature failed, and the reason is :" + e.getMessage());
return false;
}
}
@Override
public String getComponentAccessToken(boolean forceRefresh) throws WxErrorException {

if (this.getWxOpenConfigStorage().isComponentAccessTokenExpired() || forceRefresh) {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("component_appid", getWxOpenConfigStorage().getComponentAppId());
jsonObject.addProperty("component_appsecret", getWxOpenConfigStorage().getComponentAppSecret());
jsonObject.addProperty("component_verify_ticket", getWxOpenConfigStorage().getComponentVerifyTicket());

String responseContent = this.getWxOpenService().post(API_COMPONENT_TOKEN_URL, jsonObject.toString());
WxOpenComponentAccessToken componentAccessToken = WxOpenComponentAccessToken.fromJson(responseContent);
getWxOpenConfigStorage().updateComponentAccessTokent(componentAccessToken);
}
return this.getWxOpenConfigStorage().getComponentAccessToken();
}

private String post(String uri, String postData) throws WxErrorException {
String componentAccessToken = getComponentAccessToken(false);
String uriWithComponentAccessToken = uri + (uri.contains("?") ? "&" : "?") + "component_access_token=" + componentAccessToken;
return getWxOpenService().post(uriWithComponentAccessToken, postData);
}

private String get(String uri) throws WxErrorException {
String componentAccessToken = getComponentAccessToken(false);
String uriWithComponentAccessToken = uri + (uri.contains("?") ? "&" : "?") + "component_access_token=" + componentAccessToken;
return getWxOpenService().get(uriWithComponentAccessToken, null);
}

@Override
public String getPreAuthUrl(String redirectURI) throws WxErrorException {

JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("component_appid", getWxOpenConfigStorage().getComponentAppId());
String responseContent = post(API_CREATE_PREAUTHCODE_URL, jsonObject.toString());
jsonObject = WxGsonBuilder.create().fromJson(responseContent, JsonObject.class);
return String.format(COMPONENT_LOGIN_PAGE_URL, getWxOpenConfigStorage().getComponentAppId(), jsonObject.get("pre_auth_code").getAsString(), URIUtil.encodeURIComponent(redirectURI));
}

@Override
public String route(final WxOpenXmlMessage wxMessage) throws WxErrorException {
if (wxMessage == null) {
throw new NullPointerException("message is empty");
}
if (StringUtils.equalsIgnoreCase(wxMessage.getInfoType(), "component_verify_ticket")) {
getWxOpenConfigStorage().setComponentVerifyTicket(wxMessage.getComponentVerifyTicket());
return "success";
}
//新增、跟新授权
if (StringUtils.equalsAnyIgnoreCase(wxMessage.getInfoType(), "authorized", "updateauthorized")) {
WxOpenQueryAuthResult queryAuth = wxOpenService.getWxOpenComponentService().getQueryAuth(wxMessage.getAuthorizationCode());
if (queryAuth == null || queryAuth.getAuthorizationInfo() == null || queryAuth.getAuthorizationInfo().getAuthorizerAppid() == null) {
throw new NullPointerException("getQueryAuth");
}
WxOpenAuthorizationInfo authorizationInfo = queryAuth.getAuthorizationInfo();
if (authorizationInfo.getAuthorizerAccessToken() != null) {
getWxOpenConfigStorage().updateAuthorizerAccessToken(authorizationInfo.getAuthorizerAppid(),
authorizationInfo.getAuthorizerAccessToken(), authorizationInfo.getExpiresIn());
}
if (authorizationInfo.getAuthorizerRefreshToken() != null) {
getWxOpenConfigStorage().setAuthorizerRefreshToken(authorizationInfo.getAuthorizerAppid(), authorizationInfo.getAuthorizerRefreshToken());
}
return "success";
}
return null;
}
@Override
public WxOpenQueryAuthResult getQueryAuth(String authorizationCode) throws WxErrorException {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("component_appid", getWxOpenConfigStorage().getComponentAppId());
jsonObject.addProperty("authorization_code", authorizationCode);
String responseContent = post(API_QUERY_AUTH_URL, jsonObject.toString());
return WxOpenGsonBuilder.create().fromJson(responseContent, WxOpenQueryAuthResult.class);
}
@Override
public WxOpenAuthorizerInfoResult getAuthorizerInfo(String authorizerAppid) throws WxErrorException {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("component_appid", getWxOpenConfigStorage().getComponentAppId());
jsonObject.addProperty("authorizer_appid", authorizerAppid);
String responseContent = post(API_GET_AUTHORIZER_INFO_URL, jsonObject.toString());
return WxOpenGsonBuilder.create().fromJson(responseContent, WxOpenAuthorizerInfoResult.class);
}

@Override
public WxOpenAuthorizerOptionResult getAuthorizerOption(String authorizerAppid, String optionName) throws WxErrorException {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("component_appid", getWxOpenConfigStorage().getComponentAppId());
jsonObject.addProperty("authorizer_appid", authorizerAppid);
jsonObject.addProperty("option_name", optionName);
String responseContent = post(API_GET_AUTHORIZER_OPTION_URL, jsonObject.toString());
return WxOpenGsonBuilder.create().fromJson(responseContent, WxOpenAuthorizerOptionResult.class);
}
@Override
public WxError setAuthorizerOption(String authorizerAppid, String optionName, String optionValue) throws WxErrorException {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("component_appid", getWxOpenConfigStorage().getComponentAppId());
jsonObject.addProperty("authorizer_appid", authorizerAppid);
jsonObject.addProperty("option_name", optionName);
jsonObject.addProperty("option_value", optionValue);
String responseContent = post(API_SET_AUTHORIZER_OPTION_URL, jsonObject.toString());
return WxGsonBuilder.create().fromJson(responseContent, WxError.class);
}

@Override
public String getAuthorizerAccessToken(String appId, boolean forceRefresh) throws WxErrorException {

if (this.getWxOpenConfigStorage().isAuthorizerAccessTokenExpired(appId) || forceRefresh) {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("component_appid", getWxOpenConfigStorage().getComponentAppId());
jsonObject.addProperty("authorizer_appid", appId);
jsonObject.addProperty("authorizer_refresh_token", getWxOpenConfigStorage().getAuthorizerRefreshToken(appId));
String responseContent = post(API_AUTHORIZER_TOKEN_URL, jsonObject.toString());

WxOpenAuthorizerAccessToken wxOpenAuthorizerAccessToken = WxOpenAuthorizerAccessToken.fromJson(responseContent);
getWxOpenConfigStorage().updateAuthorizerAccessToken(appId, wxOpenAuthorizerAccessToken);
}
return this.getWxOpenConfigStorage().getAuthorizerAccessToken(appId);
}

@Override
public WxMpOAuth2AccessToken oauth2getAccessToken(String appId, String code) throws WxErrorException {
String url = String.format(OAUTH2_ACCESS_TOKEN_URL, appId, code, getWxOpenConfigStorage().getComponentAppId());
String responseContent = get(url);
return WxMpOAuth2AccessToken.fromJson(responseContent);
}

@Override
public boolean checkSignature(String appid, String timestamp, String nonce, String signature) {
return false;
}

@Override
public WxMpOAuth2AccessToken oauth2refreshAccessToken(String appId, String refreshToken) throws WxErrorException {
String url = String.format(OAUTH2_REFRESH_TOKEN_URL, appId, refreshToken, getWxOpenConfigStorage().getComponentAppId());
String responseContent = get(url);
return WxMpOAuth2AccessToken.fromJson(responseContent);
}

@Override
public String oauth2buildAuthorizationUrl(String appId, String redirectURI, String scope, String state) {
return String.format(CONNECT_OAUTH2_AUTHORIZE_URL,
appId, URIUtil.encodeURIComponent(redirectURI), scope, StringUtils.trimToEmpty(state), getWxOpenConfigStorage().getComponentAppId());
}

}

+ 386
- 0
weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenInMemoryConfigStorage.java Прегледај датотеку

@@ -0,0 +1,386 @@
package me.chanjar.weixin.open.api.impl;


import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.common.util.ToStringUtils;
import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder;
import me.chanjar.weixin.mp.api.WxMpConfigStorage;
import me.chanjar.weixin.open.api.WxOpenConfigStorage;
import me.chanjar.weixin.open.bean.WxOpenAuthorizerAccessToken;
import me.chanjar.weixin.open.bean.WxOpenComponentAccessToken;

import java.io.File;
import java.util.Hashtable;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
* 基于内存的微信配置provider,在实际生产环境中应该将这些配置持久化
*
* @author <a href="https://github.com/007gzs">007</a>
*/
public class WxOpenInMemoryConfigStorage implements WxOpenConfigStorage {
private String componentAppId;
private String componentAppSecret;
private String componentToken;
private String componentAesKey;
private String componentVerifyTicket;
private String componentAccessToken;
private long componentExpiresTime;

private Map<String, Token> authorizerRefreshTokens = new Hashtable<>();
private Map<String, Token> authorizerAccessTokens = new Hashtable<>();
private Map<String, Token> jsapiTickets = new Hashtable<>();
private Map<String, Token> cardApiTickets = new Hashtable<>();

@Override
public void setComponentAppId(String componentAppId) {
this.componentAppId = componentAppId;
}
@Override
public void setComponentAppSecret(String componentAppSecret) {
this.componentAppSecret = componentAppSecret;
}
@Override
public void setComponentToken(String componentToken) {
this.componentToken = componentToken;
}
@Override
public void setComponentAesKey(String componentAesKey) {
this.componentAesKey = componentAesKey;
}

@Override
public String getComponentAppId() {
return componentAppId;
}

@Override
public String getComponentAppSecret() {
return componentAppSecret;
}

@Override
public String getComponentToken() {
return componentToken;
}

@Override
public String getComponentAesKey() {
return componentAesKey;
}

@Override
public String getComponentVerifyTicket() {
return componentVerifyTicket;
}

@Override
public void setComponentVerifyTicket(String componentVerifyTicket) {
this.componentVerifyTicket = componentVerifyTicket;
}

@Override
public String getComponentAccessToken() {
return componentAccessToken;
}

@Override
public boolean isComponentAccessTokenExpired() {
return System.currentTimeMillis() > componentExpiresTime;
}

@Override
public void updateComponentAccessTokent(WxOpenComponentAccessToken componentAccessToken) {
updateComponentAccessTokent(componentAccessToken.getComponentAccessToken(), componentAccessToken.getExpiresIn());
}

@Override
public WxMpConfigStorage getWxMpConfigStorage(String appId) {
return new WxOpenMpConfigStorage(this, appId);
}

@Override
public void updateComponentAccessTokent(String componentAccessToken, int expiresInSeconds) {
this.componentAccessToken = componentAccessToken;
this.componentExpiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L;
}

@Override
public boolean autoRefreshToken() {
return true;
}
private String getTokenString(Map<String, Token> map, String key){
Token token = map.get(key);
if(token == null || (token.expiresTime != null && System.currentTimeMillis() > token.expiresTime)){
return null;
}
return token.token;
}
private void expireToken(Map<String, Token> map, String key){
Token token = map.get(key);
if(token != null){
token.expiresTime = 0L;
}
}
private void updateToken(Map<String, Token> map, String key, String tokenString, Integer expiresInSeconds){
Token token = map.get(key);
if(token == null){
token = new Token();
map.put(key, token);
}
token.token = tokenString;
if(expiresInSeconds != null) {
token.expiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L;
}
}
@Override
public String getAuthorizerRefreshToken(String appId) {
return getTokenString(authorizerRefreshTokens, appId);
}

@Override
public void setAuthorizerRefreshToken(String appId, String authorizerRefreshToken) {
updateToken(authorizerRefreshTokens, appId, authorizerRefreshToken, null);
}

@Override
public String getAuthorizerAccessToken(String appId) {
return getTokenString(authorizerAccessTokens, appId);
}


@Override
public boolean isAuthorizerAccessTokenExpired(String appId) {
return getTokenString(authorizerAccessTokens, appId) == null;
}

@Override
public void expireAuthorizerAccessToken(String appId) {
expireToken(authorizerAccessTokens, appId);
}

@Override
public void updateAuthorizerAccessToken(String appId, WxOpenAuthorizerAccessToken authorizerAccessToken) {
updateAuthorizerAccessToken(appId, authorizerAccessToken.getAuthorizerAccessToken(), authorizerAccessToken.getExpiresIn());
}

@Override
public void updateAuthorizerAccessToken(String appId, String authorizerAccessToken, int expiresInSeconds) {
updateToken(authorizerAccessTokens, appId, authorizerAccessToken, expiresInSeconds);
}

@Override
public String getJsapiTicket(String appId) {
return getTokenString(jsapiTickets, appId);
}

@Override
public boolean isJsapiTicketExpired(String appId) {
return getTokenString(jsapiTickets, appId) == null;
}

@Override
public void expireJsapiTicket(String appId) {
expireToken(jsapiTickets, appId);
}

@Override
public void updateJsapiTicket(String appId, String jsapiTicket, int expiresInSeconds) {
updateToken(jsapiTickets, appId, jsapiTicket, expiresInSeconds);
}

@Override
public String getCardApiTicket(String appId) {
return getTokenString(cardApiTickets, appId);
}

@Override
public boolean isCardApiTicketExpired(String appId) {
return getTokenString(cardApiTickets, appId) == null;
}

@Override
public void expireCardApiTicket(String appId) {
expireToken(cardApiTickets, appId);
}

@Override
public void updateCardApiTicket(String appId, String cardApiTicket, int expiresInSeconds) {
updateToken(cardApiTickets, appId, cardApiTicket, expiresInSeconds);
}

private static class Token{
private String token;
private Long expiresTime;
}
private static class WxOpenMpConfigStorage implements WxMpConfigStorage{
private WxOpenConfigStorage wxOpenConfigStorage;
private String appId;
private WxOpenMpConfigStorage(WxOpenConfigStorage wxOpenConfigStorage, String appId){
this.wxOpenConfigStorage = wxOpenConfigStorage;
this.appId = appId;
}

private Lock accessTokenLock = new ReentrantLock();
private Lock jsapiTicketLock = new ReentrantLock();
private Lock cardApiTicketLock = new ReentrantLock();


@Override
public String getAccessToken() {
return wxOpenConfigStorage.getAuthorizerAccessToken(appId);
}

@Override
public Lock getAccessTokenLock() {
return this.accessTokenLock;
}

@Override
public boolean isAccessTokenExpired() {
return wxOpenConfigStorage.isAuthorizerAccessTokenExpired(appId);
}

@Override
public synchronized void updateAccessToken(WxAccessToken accessToken) {
updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn());
}

@Override
public synchronized void updateAccessToken(String accessToken, int expiresInSeconds) {
wxOpenConfigStorage.updateAuthorizerAccessToken(appId, accessToken, expiresInSeconds);
}

@Override
public void expireAccessToken() {
wxOpenConfigStorage.expireAuthorizerAccessToken(appId);
}

@Override
public String getJsapiTicket() {
return wxOpenConfigStorage.getJsapiTicket(appId);
}

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

@Override
public boolean isJsapiTicketExpired() {
return wxOpenConfigStorage.isJsapiTicketExpired(appId);
}

@Override
public synchronized void updateJsapiTicket(String jsapiTicket, int expiresInSeconds) {
wxOpenConfigStorage.updateJsapiTicket(appId, jsapiTicket, expiresInSeconds);
}

@Override
public void expireJsapiTicket() {
wxOpenConfigStorage.expireJsapiTicket(appId);
}

/**
* 卡券api_ticket
*/
@Override
public String getCardApiTicket() {
return wxOpenConfigStorage.getCardApiTicket(appId);
}

@Override
public Lock getCardApiTicketLock() {
return this.cardApiTicketLock;
}

@Override
public boolean isCardApiTicketExpired() {
return wxOpenConfigStorage.isCardApiTicketExpired(appId);
}

@Override
public synchronized void updateCardApiTicket(String cardApiTicket, int expiresInSeconds) {
wxOpenConfigStorage.updateCardApiTicket(appId, cardApiTicket, expiresInSeconds);
}

@Override
public void expireCardApiTicket() {
wxOpenConfigStorage.expireCardApiTicket(appId);
}

@Override
public String getAppId() {
return this.appId;
}

@Override
public String getSecret() {
return null;
}

@Override
public String getToken() {
return null;
}

@Override
public long getExpiresTime() {
return 0;
}


@Override
public String getAesKey() {
return null;
}

@Override
public String getOauth2redirectUri() {
return null;
}

@Override
public String getHttpProxyHost() {
return null;
}

@Override
public int getHttpProxyPort() {
return 0;
}

@Override
public String getHttpProxyUsername() {
return null;
}

@Override
public String getHttpProxyPassword() {
return null;
}

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

@Override
public File getTmpDirFile() {
return null;
}

@Override
public ApacheHttpClientBuilder getApacheHttpClientBuilder() {
return null;
}


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

+ 164
- 0
weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenInRedisConfigStorage.java Прегледај датотеку

@@ -0,0 +1,164 @@
package me.chanjar.weixin.open.api.impl;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

/**
* @author <a href="https://github.com/007gzs">007</a>
*/
public class WxOpenInRedisConfigStorage extends WxOpenInMemoryConfigStorage {

private final static String COMPONENT_VERIFY_TICKET_KEY = "wechat_component_verify_ticket:";
private final static String COMPONENT_ACCESS_TOKEN_KEY = "wechat_component_access_token:";

private final static String AUTHORIZER_REFRESH_TOKEN_KEY = "wechat_authorizer_refresh_token:";
private final static String AUTHORIZER_ACCESS_TOKEN_KEY = "wechat_authorizer_access_token:";
private final static String JSAPI_TICKET_KEY = "wechat_jsapi_ticket:";
private final static String CARD_API_TICKET_KEY = "wechat_card_api_ticket:";


protected final JedisPool jedisPool;
private String componentVerifyTicketKey;
private String componentAccessTokenKey;
private String authorizerRefreshTokenKey;
private String authorizerAccessTokenKey;
private String jsapiTicketKey;
private String cardApiTicket;
public WxOpenInRedisConfigStorage(JedisPool jedisPool) {
this.jedisPool = jedisPool;
}

@Override
public void setComponentAppId(String componentAppId) {
super.setComponentAppId(componentAppId);
componentVerifyTicketKey = COMPONENT_VERIFY_TICKET_KEY.concat(componentAppId);
componentAccessTokenKey = COMPONENT_ACCESS_TOKEN_KEY.concat(componentAppId);
authorizerRefreshTokenKey = AUTHORIZER_REFRESH_TOKEN_KEY.concat(componentAppId);
authorizerAccessTokenKey = AUTHORIZER_ACCESS_TOKEN_KEY.concat(componentAppId);
jsapiTicketKey = JSAPI_TICKET_KEY.concat(componentAppId);
cardApiTicket = CARD_API_TICKET_KEY.concat(componentAppId);
}
@Override
public String getComponentVerifyTicket(){
try(Jedis jedis = jedisPool.getResource()){
return jedis.get(componentVerifyTicketKey);
}
}
@Override
public void setComponentVerifyTicket(String componentVerifyTicket){
try(Jedis jedis = jedisPool.getResource()){
jedis.set(componentVerifyTicketKey, componentVerifyTicket);
}
}
@Override
public String getComponentAccessToken(){
try(Jedis jedis = jedisPool.getResource()){
return jedis.get(componentAccessTokenKey);
}
}
@Override
public boolean isComponentAccessTokenExpired(){
try(Jedis jedis = jedisPool.getResource()){
return jedis.ttl(componentAccessTokenKey) < 2;
}
}
@Override
public void updateComponentAccessTokent(String componentAccessToken, int expiresInSeconds){
try (Jedis jedis = this.jedisPool.getResource()) {
jedis.setex(componentAccessTokenKey, expiresInSeconds - 200, componentAccessToken);
}
}
private String getKey(String prefix, String appId){
return prefix.endsWith(":") ? prefix.concat(appId) : prefix.concat(":").concat(appId);
}

@Override
public String getAuthorizerRefreshToken(String appId){
try (Jedis jedis = this.jedisPool.getResource()) {
return jedis.get(getKey(authorizerRefreshTokenKey, appId));
}
}
@Override
public void setAuthorizerRefreshToken(String appId, String authorizerRefreshToken){
try (Jedis jedis = this.jedisPool.getResource()) {
jedis.set(getKey(authorizerRefreshTokenKey, appId), authorizerRefreshToken);
}
}
@Override
public String getAuthorizerAccessToken(String appId){
try (Jedis jedis = this.jedisPool.getResource()) {
return jedis.get(getKey(authorizerAccessTokenKey, appId));
}
}


@Override
public boolean isAuthorizerAccessTokenExpired(String appId){
try (Jedis jedis = this.jedisPool.getResource()) {
return jedis.ttl(getKey(authorizerAccessTokenKey, appId)) < 2;
}
}
@Override
public void expireAuthorizerAccessToken(String appId){
try (Jedis jedis = this.jedisPool.getResource()) {
jedis.expire(getKey(authorizerAccessTokenKey, appId), 0);
}
}
@Override
public void updateAuthorizerAccessToken(String appId, String authorizerAccessToken, int expiresInSeconds){
try (Jedis jedis = this.jedisPool.getResource()) {
jedis.setex(getKey(authorizerAccessTokenKey, appId), expiresInSeconds - 200, authorizerAccessToken);
}
}

@Override
public String getJsapiTicket(String appId){
try (Jedis jedis = this.jedisPool.getResource()) {
return jedis.get(getKey(jsapiTicketKey, appId));
}
}

@Override
public boolean isJsapiTicketExpired(String appId){
try (Jedis jedis = this.jedisPool.getResource()) {
return jedis.ttl(getKey(jsapiTicketKey, appId)) < 2;
}
}
@Override
public void expireJsapiTicket(String appId){
try (Jedis jedis = this.jedisPool.getResource()) {
jedis.expire(getKey(jsapiTicketKey, appId), 0);
}
}
@Override
public void updateJsapiTicket(String appId, String jsapiTicket, int expiresInSeconds){
try (Jedis jedis = this.jedisPool.getResource()) {
jedis.setex(getKey(jsapiTicketKey, appId), expiresInSeconds - 200, jsapiTicket);
}
}

@Override
public String getCardApiTicket(String appId){
try (Jedis jedis = this.jedisPool.getResource()) {
return jedis.get(getKey(jsapiTicketKey, appId));
}
}
@Override
public boolean isCardApiTicketExpired(String appId){
try (Jedis jedis = this.jedisPool.getResource()) {
return jedis.ttl(getKey(cardApiTicket, appId)) < 2;
}
}
@Override
public void expireCardApiTicket(String appId){
try (Jedis jedis = this.jedisPool.getResource()) {
jedis.expire(getKey(cardApiTicket, appId), 0);
}
}
@Override
public void updateCardApiTicket(String appId, String cardApiTicket, int expiresInSeconds){
try (Jedis jedis = this.jedisPool.getResource()) {
jedis.setex(getKey(cardApiTicket, appId), expiresInSeconds - 200, cardApiTicket);
}
}
}

+ 49
- 0
weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMpServiceImpl.java Прегледај датотеку

@@ -0,0 +1,49 @@
package me.chanjar.weixin.open.api.impl;

import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpConfigStorage;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.open.api.WxOpenComponentService;

/**
* @author <a href="https://github.com/007gzs">007</a>
*/
public class WxOpenMpServiceImpl extends WxMpServiceImpl {
private WxOpenComponentService wxOpenComponentService;
private WxMpConfigStorage wxMpConfigStorage;
private String appId;
public WxOpenMpServiceImpl(WxOpenComponentService wxOpenComponentService, String appId, WxMpConfigStorage wxMpConfigStorage){
this.wxOpenComponentService = wxOpenComponentService;
this.appId = appId;
this.wxMpConfigStorage = wxMpConfigStorage;
}
@Override
public WxMpConfigStorage getWxMpConfigStorage(){
return wxMpConfigStorage;
}
@Override
public String getAccessToken(boolean forceRefresh) throws WxErrorException {
return wxOpenComponentService.getAuthorizerAccessToken(appId, forceRefresh);
}

@Override
public WxMpOAuth2AccessToken oauth2getAccessToken(String code) throws WxErrorException {
return wxOpenComponentService.oauth2getAccessToken(appId, code);
}

// @Override
// public boolean checkSignature(String timestamp, String nonce, String signature) {
// return wxOpenComponentService.checkSignature(appId, timestamp, nonce, signature);
// }

@Override
public WxMpOAuth2AccessToken oauth2refreshAccessToken(String refreshToken) throws WxErrorException {
return wxOpenComponentService.oauth2refreshAccessToken(appId, refreshToken);
}

@Override
public String oauth2buildAuthorizationUrl(String redirectURI, String scope, String state) {
return wxOpenComponentService.oauth2buildAuthorizationUrl(appId, redirectURI, scope, state);
}
}

+ 63
- 0
weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenServiceAbstractImpl.java Прегледај датотеку

@@ -0,0 +1,63 @@
package me.chanjar.weixin.open.api.impl;

import me.chanjar.weixin.common.bean.result.WxError;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.util.http.RequestExecutor;
import me.chanjar.weixin.common.util.http.RequestHttp;
import me.chanjar.weixin.open.api.WxOpenComponentService;
import me.chanjar.weixin.open.api.WxOpenConfigStorage;
import me.chanjar.weixin.open.api.WxOpenService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

/**
* @author <a href="https://github.com/007gzs">007</a>
*/
public abstract class WxOpenServiceAbstractImpl<H, P> implements WxOpenService, RequestHttp<H, P> {
protected final Logger log = LoggerFactory.getLogger(this.getClass());
private WxOpenConfigStorage wxOpenConfigStorage;
protected WxOpenComponentService wxOpenComponentService = new WxOpenComponentServiceImpl(this);
@Override
public WxOpenComponentService getWxOpenComponentService() {
return wxOpenComponentService;
}
@Override
public WxOpenConfigStorage getWxOpenConfigStorage(){
return wxOpenConfigStorage;
}
public void setWxOpenConfigStorage(WxOpenConfigStorage wxOpenConfigStorage){
this.wxOpenConfigStorage = wxOpenConfigStorage;
}

protected synchronized <T, E> T execute(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException {
try {
T result = executor.execute(uri, data);
this.log.debug("\n【请求地址】: {}\n【请求参数】:{}\n【响应数据】:{}", uri, data, result);
return result;
} catch (WxErrorException e) {
WxError error = e.getError();
// /*
// * 发生以下情况时尝试刷新access_token
// * 40001 获取access_token时AppSecret错误,或者access_token无效
// * 42001 access_token超时
// * 40014 不合法的access_token,请开发者认真比对access_token的有效性(如是否过期),或查看是否正在为恰当的公众号调用接口
// */
// if (error.getErrorCode() == 42001 || error.getErrorCode() == 40001 || error.getErrorCode() == 40014) {
// // 强制设置wxCpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token
// this.configStorage.expireAccessToken();
// return execute(executor, uri, data);
// }

if (error.getErrorCode() != 0) {
this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", uri, data, error);
throw new WxErrorException(error, e);
}
return null;
} catch (IOException e) {
this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【异常信息】:{}", uri, data, e.getMessage());
throw new RuntimeException(e);
}
}
}

+ 44
- 0
weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenServiceApacheHttpClientImpl.java Прегледај датотеку

@@ -0,0 +1,44 @@
package me.chanjar.weixin.open.api.impl;

import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.util.http.HttpType;
import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor;
import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor;
import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder;
import org.apache.http.HttpHost;
import org.apache.http.impl.client.CloseableHttpClient;

/**
* apache-http方式实现
* @author <a href="https://github.com/007gzs">007</a>
*/
public class WxOpenServiceApacheHttpClientImpl extends WxOpenServiceAbstractImpl<CloseableHttpClient, HttpHost> {
private CloseableHttpClient httpClient = DefaultApacheHttpClientBuilder.get().build();
private HttpHost httpProxy = null;

@Override
public CloseableHttpClient getRequestHttpClient() {
return httpClient;
}

@Override
public HttpHost getRequestHttpProxy() {
return httpProxy;
}

@Override
public HttpType getRequestType() {
return HttpType.APACHE_HTTP;
}

@Override
public String get(String url, String queryParam) throws WxErrorException {
return execute(SimpleGetRequestExecutor.create(this), url, queryParam);
}

@Override
public String post(String url, String postData) throws WxErrorException {
return execute(SimplePostRequestExecutor.create(this), url, postData);
}

}

+ 8
- 0
weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenServiceImpl.java Прегледај датотеку

@@ -0,0 +1,8 @@
package me.chanjar.weixin.open.api.impl;

/**
* @author <a href="https://github.com/007gzs">007</a>
*/
public class WxOpenServiceImpl extends WxOpenServiceApacheHttpClientImpl {

}

+ 35
- 0
weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/WxOpenAuthorizerAccessToken.java Прегледај датотеку

@@ -0,0 +1,35 @@
package me.chanjar.weixin.open.bean;

import me.chanjar.weixin.open.util.json.WxOpenGsonBuilder;

import java.io.Serializable;

/**
* @author <a href="https://github.com/007gzs">007</a>
*/
public class WxOpenAuthorizerAccessToken implements Serializable{

private String authorizerAccessToken;

private int expiresIn = -1;

public static WxOpenAuthorizerAccessToken fromJson(String json) {
return WxOpenGsonBuilder.create().fromJson(json, WxOpenAuthorizerAccessToken.class);
}

public String getAuthorizerAccessToken() {
return authorizerAccessToken;
}

public void setAuthorizerAccessToken(String authorizerAccessToken) {
this.authorizerAccessToken = authorizerAccessToken;
}

public int getExpiresIn() {
return expiresIn;
}

public void setExpiresIn(int expiresIn) {
this.expiresIn = expiresIn;
}
}

+ 35
- 0
weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/WxOpenComponentAccessToken.java Прегледај датотеку

@@ -0,0 +1,35 @@
package me.chanjar.weixin.open.bean;

import me.chanjar.weixin.open.util.json.WxOpenGsonBuilder;

import java.io.Serializable;

/**
* @author <a href="https://github.com/007gzs">007</a>
*/
public class WxOpenComponentAccessToken implements Serializable{

private String componentAccessToken;

private int expiresIn = -1;

public static WxOpenComponentAccessToken fromJson(String json) {
return WxOpenGsonBuilder.create().fromJson(json, WxOpenComponentAccessToken.class);
}

public String getComponentAccessToken() {
return componentAccessToken;
}

public void setComponentAccessToken(String componentAccessToken) {
this.componentAccessToken = componentAccessToken;
}

public int getExpiresIn() {
return expiresIn;
}

public void setExpiresIn(int expiresIn) {
this.expiresIn = expiresIn;
}
}

+ 18
- 0
weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/WxOpenAuthorizationInfo.java Прегледај датотеку

@@ -0,0 +1,18 @@
package me.chanjar.weixin.open.bean.auth;

import lombok.Data;

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

/**
* @author <a href="https://github.com/007gzs">007</a>
*/
@Data
public class WxOpenAuthorizationInfo implements Serializable{
private String authorizerAppid;
private String authorizerAccessToken;
private int expiresIn;
private String authorizerRefreshToken;
private List<Integer> funcInfo;
}

+ 22
- 0
weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/WxOpenAuthorizerInfo.java Прегледај датотеку

@@ -0,0 +1,22 @@
package me.chanjar.weixin.open.bean.auth;

import lombok.Data;

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

/**
* @author <a href="https://github.com/007gzs">007</a>
*/
@Data
public class WxOpenAuthorizerInfo implements Serializable{
private String nickName;
private String headImg;
private Integer serviceTypeInfo;
private Integer verifyTypeInfo;
private String userName;
private String principalName;
private Map<String, Integer> businessInfo;
private String alias;
private String qrcodeUrl;
}

+ 100
- 0
weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/message/WxOpenXmlMessage.java Прегледај датотеку

@@ -0,0 +1,100 @@
package me.chanjar.weixin.open.bean.message;

import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import lombok.Data;
import me.chanjar.weixin.common.util.xml.XStreamCDataConverter;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.open.api.WxOpenConfigStorage;
import me.chanjar.weixin.open.util.WxOpenCryptUtil;
import me.chanjar.weixin.open.util.xml.XStreamTransformer;
import org.apache.commons.io.IOUtils;

import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;

/**
* @author <a href="https://github.com/007gzs">007</a>
*/
@XStreamAlias("xml")
@Data
public class WxOpenXmlMessage implements Serializable{
@XStreamAlias("AppId")
@XStreamConverter(value = XStreamCDataConverter.class)
private String appId;

@XStreamAlias("CreateTime")
private Long createTime;

@XStreamAlias("InfoType")
@XStreamConverter(value = XStreamCDataConverter.class)
private String infoType;

@XStreamAlias("ComponentVerifyTicket")
@XStreamConverter(value = XStreamCDataConverter.class)
private String componentVerifyTicket;

@XStreamAlias("AuthorizerAppid")
@XStreamConverter(value = XStreamCDataConverter.class)
private String authorizerAppid;

@XStreamAlias("AuthorizationCode")
@XStreamConverter(value = XStreamCDataConverter.class)
private String authorizationCode;

@XStreamAlias("AuthorizationCodeExpiredTime")
@XStreamConverter(value = XStreamCDataConverter.class)
private Long authorizationCodeExpiredTime;

@XStreamAlias("PreAuthCode")
@XStreamConverter(value = XStreamCDataConverter.class)
private String preAuthCode;

public static WxOpenXmlMessage fromXml(String xml) {
//修改微信变态的消息内容格式,方便解析
xml = xml.replace("</PicList><PicList>", "");
return XStreamTransformer.fromXml(WxOpenXmlMessage.class, xml);
}

public static WxOpenXmlMessage fromXml(InputStream is) {
return XStreamTransformer.fromXml(WxOpenXmlMessage.class, is);
}

/**
* 从加密字符串转换
*
* @param encryptedXml 密文
* @param wxOpenConfigStorage 配置存储器对象
* @param timestamp 时间戳
* @param nonce 随机串
* @param msgSignature 签名串
*/
public static WxOpenXmlMessage fromEncryptedXml(String encryptedXml,
WxOpenConfigStorage wxOpenConfigStorage, String timestamp, String nonce,
String msgSignature) {
WxOpenCryptUtil cryptUtil = new WxOpenCryptUtil(wxOpenConfigStorage);
String plainText = cryptUtil.decrypt(msgSignature, timestamp, nonce,
encryptedXml);
return fromXml(plainText);
}
public static WxMpXmlMessage fromEncryptedMpXml(String encryptedXml,
WxOpenConfigStorage wxOpenConfigStorage, String timestamp, String nonce,
String msgSignature) {
WxOpenCryptUtil cryptUtil = new WxOpenCryptUtil(wxOpenConfigStorage);
String plainText = cryptUtil.decrypt(msgSignature, timestamp, nonce,
encryptedXml);
return WxMpXmlMessage.fromXml(plainText);
}

public static WxOpenXmlMessage fromEncryptedXml(InputStream is,
WxOpenConfigStorage wxOpenConfigStorage, String timestamp, String nonce,
String msgSignature) {
try {
return fromEncryptedXml(IOUtils.toString(is, "UTF-8"), wxOpenConfigStorage,
timestamp, nonce, msgSignature);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

+ 16
- 0
weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/result/WxOpenAuthorizerInfoResult.java Прегледај датотеку

@@ -0,0 +1,16 @@
package me.chanjar.weixin.open.bean.result;

import lombok.Data;
import me.chanjar.weixin.open.bean.auth.WxOpenAuthorizationInfo;
import me.chanjar.weixin.open.bean.auth.WxOpenAuthorizerInfo;

import java.io.Serializable;

/**
* @author <a href="https://github.com/007gzs">007</a>
*/
@Data
public class WxOpenAuthorizerInfoResult implements Serializable{
private WxOpenAuthorizationInfo authorizationInfo;
private WxOpenAuthorizerInfo authorizerInfo;
}

+ 15
- 0
weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/result/WxOpenAuthorizerOptionResult.java Прегледај датотеку

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

import lombok.Data;

import java.io.Serializable;

/**
* @author <a href="https://github.com/007gzs">007</a>
*/
@Data
public class WxOpenAuthorizerOptionResult implements Serializable{
String authorizerAppid;
String optionName;
String optionValue;
}

+ 14
- 0
weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/result/WxOpenQueryAuthResult.java Прегледај датотеку

@@ -0,0 +1,14 @@
package me.chanjar.weixin.open.bean.result;

import lombok.Data;
import me.chanjar.weixin.open.bean.auth.WxOpenAuthorizationInfo;

import java.io.Serializable;

/**
* @author <a href="https://github.com/007gzs">007</a>
*/
@Data
public class WxOpenQueryAuthResult implements Serializable{
private WxOpenAuthorizationInfo authorizationInfo;
}

+ 28
- 0
weixin-java-open/src/main/java/me/chanjar/weixin/open/util/WxOpenCryptUtil.java Прегледај датотеку

@@ -0,0 +1,28 @@
package me.chanjar.weixin.open.util;

import me.chanjar.weixin.open.api.WxOpenConfigStorage;
import org.apache.commons.codec.binary.Base64;
/**
* @author <a href="https://github.com/007gzs">007</a>
*/
public class WxOpenCryptUtil extends me.chanjar.weixin.common.util.crypto.WxCryptUtil {
/**
* 构造函数
*
* @param wxOpenConfigStorage
*/
public WxOpenCryptUtil(WxOpenConfigStorage wxOpenConfigStorage) {
/*
* @param token 公众平台上,开发者设置的token
* @param encodingAesKey 公众平台上,开发者设置的EncodingAESKey
* @param appId 公众平台appid
*/
String encodingAesKey = wxOpenConfigStorage.getComponentAesKey();
String token = wxOpenConfigStorage.getComponentToken();
String appId = wxOpenConfigStorage.getComponentAppId();

this.token = token;
this.appidOrCorpid = appId;
this.aesKey = Base64.decodeBase64(encodingAesKey + "=");
}
}

+ 45
- 0
weixin-java-open/src/main/java/me/chanjar/weixin/open/util/json/WxOpenAuthorizationInfoGsonAdapter.java Прегледај датотеку

@@ -0,0 +1,45 @@
package me.chanjar.weixin.open.util.json;

import com.google.gson.*;
import me.chanjar.weixin.common.util.json.GsonHelper;
import me.chanjar.weixin.open.bean.auth.WxOpenAuthorizationInfo;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

/**
* @author <a href="https://github.com/007gzs">007</a>
*/
public class WxOpenAuthorizationInfoGsonAdapter implements JsonDeserializer<WxOpenAuthorizationInfo> {
@Override
public WxOpenAuthorizationInfo deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
WxOpenAuthorizationInfo authorizationInfo = new WxOpenAuthorizationInfo();
JsonObject jsonObject = jsonElement.getAsJsonObject();
authorizationInfo.setAuthorizerAppid(GsonHelper.getString(jsonObject, "authorizer_appid"));
authorizationInfo.setAuthorizerAccessToken(GsonHelper.getString(jsonObject, "authorizer_access_token"));
authorizationInfo.setExpiresIn(GsonHelper.getPrimitiveInteger(jsonObject, "expires_in"));
authorizationInfo.setAuthorizerRefreshToken(GsonHelper.getString(jsonObject, "authorizer_refresh_token"));
List<Integer> funcInfo = new ArrayList<>();
JsonArray jsonArray = GsonHelper.getAsJsonArray(jsonObject.get("func_info"));
if(jsonArray != null && !jsonArray.isJsonNull()){
for(int i = 0; i < jsonArray.size(); i++){
jsonObject = jsonArray.get(i).getAsJsonObject();
if(jsonObject == null || jsonObject.isJsonNull()){
continue;
}
jsonObject = jsonObject.getAsJsonObject("funcscope_category");
if(jsonObject == null || jsonObject.isJsonNull()){
continue;
}
Integer id = GsonHelper.getInteger(jsonObject, "id");
if(id == null) {
continue;
}
funcInfo.add(id);
}
}
authorizationInfo.setFuncInfo(funcInfo);
return authorizationInfo;
}
}

+ 21
- 0
weixin-java-open/src/main/java/me/chanjar/weixin/open/util/json/WxOpenAuthorizerAccessTokenGsonAdapter.java Прегледај датотеку

@@ -0,0 +1,21 @@
package me.chanjar.weixin.open.util.json;

import com.google.gson.*;
import me.chanjar.weixin.common.util.json.GsonHelper;
import me.chanjar.weixin.open.bean.WxOpenAuthorizerAccessToken;

import java.lang.reflect.Type;

/**
* @author <a href="https://github.com/007gzs">007</a>
*/
public class WxOpenAuthorizerAccessTokenGsonAdapter implements JsonDeserializer<WxOpenAuthorizerAccessToken> {
@Override
public WxOpenAuthorizerAccessToken deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
WxOpenAuthorizerAccessToken authorizerAccessToken = new WxOpenAuthorizerAccessToken();
JsonObject jsonObject = jsonElement.getAsJsonObject();
authorizerAccessToken.setAuthorizerAccessToken(GsonHelper.getString(jsonObject, "authorizer_access_token"));
authorizerAccessToken.setExpiresIn(GsonHelper.getPrimitiveInteger(jsonObject, "expires_in"));
return authorizerAccessToken;
}
}

+ 38
- 0
weixin-java-open/src/main/java/me/chanjar/weixin/open/util/json/WxOpenAuthorizerInfoGsonAdapter.java Прегледај датотеку

@@ -0,0 +1,38 @@
package me.chanjar.weixin.open.util.json;

import com.google.gson.*;
import com.google.gson.reflect.TypeToken;
import me.chanjar.weixin.common.util.json.GsonHelper;
import me.chanjar.weixin.open.bean.auth.WxOpenAuthorizerInfo;

import java.lang.reflect.Type;
import java.util.Map;

/**
* @author <a href="https://github.com/007gzs">007</a>
*/
public class WxOpenAuthorizerInfoGsonAdapter implements JsonDeserializer<WxOpenAuthorizerInfo> {
@Override
public WxOpenAuthorizerInfo deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
WxOpenAuthorizerInfo authorizationInfo = new WxOpenAuthorizerInfo();
JsonObject jsonObject = jsonElement.getAsJsonObject();

authorizationInfo.setNickName(GsonHelper.getString(jsonObject, "nick_name"));
authorizationInfo.setHeadImg(GsonHelper.getString(jsonObject, "head_img"));
authorizationInfo.setUserName(GsonHelper.getString(jsonObject, "user_name"));
authorizationInfo.setPrincipalName(GsonHelper.getString(jsonObject, "principal_name"));
authorizationInfo.setAlias(GsonHelper.getString(jsonObject, "alias"));
authorizationInfo.setQrcodeUrl(GsonHelper.getString(jsonObject, "qrcode_url"));
if(jsonObject.has("service_type_info")) {
authorizationInfo.setServiceTypeInfo(GsonHelper.getInteger(jsonObject.getAsJsonObject("service_type_info"), "id"));
}
if(jsonObject.has("verify_type_info")) {
authorizationInfo.setVerifyTypeInfo(GsonHelper.getInteger(jsonObject.getAsJsonObject("verify_type_info"), "id"));
}
Map<String, Integer> businessInfo = WxOpenGsonBuilder.create().fromJson(jsonObject.get("business_info"),
new TypeToken<Map<String, Integer>>() {
}.getType());
authorizationInfo.setBusinessInfo(businessInfo);
return authorizationInfo;
}
}

+ 32
- 0
weixin-java-open/src/main/java/me/chanjar/weixin/open/util/json/WxOpenAuthorizerInfoResultGsonAdapter.java Прегледај датотеку

@@ -0,0 +1,32 @@
package me.chanjar.weixin.open.util.json;

import com.google.gson.*;
import com.google.gson.reflect.TypeToken;
import me.chanjar.weixin.open.bean.auth.WxOpenAuthorizationInfo;
import me.chanjar.weixin.open.bean.auth.WxOpenAuthorizerInfo;
import me.chanjar.weixin.open.bean.result.WxOpenAuthorizerInfoResult;

import java.lang.reflect.Type;

/**
* @author <a href="https://github.com/007gzs">007</a>
*/
public class WxOpenAuthorizerInfoResultGsonAdapter implements JsonDeserializer<WxOpenAuthorizerInfoResult> {
@Override
public WxOpenAuthorizerInfoResult deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
WxOpenAuthorizerInfoResult authorizerInfoResult = new WxOpenAuthorizerInfoResult();
JsonObject jsonObject = jsonElement.getAsJsonObject();

WxOpenAuthorizationInfo authorizationInfo = WxOpenGsonBuilder.INSTANCE.create().fromJson(jsonObject.get("authorization_info"),
new TypeToken<WxOpenAuthorizationInfo>() {
}.getType());

authorizerInfoResult.setAuthorizationInfo(authorizationInfo);
WxOpenAuthorizerInfo authorizerInfo = WxOpenGsonBuilder.INSTANCE.create().fromJson(jsonObject.get("authorizer_info"),
new TypeToken<WxOpenAuthorizerInfo>() {
}.getType());

authorizerInfoResult.setAuthorizerInfo(authorizerInfo);
return authorizerInfoResult;
}
}

+ 22
- 0
weixin-java-open/src/main/java/me/chanjar/weixin/open/util/json/WxOpenAuthorizerOptionResultGsonAdapter.java Прегледај датотеку

@@ -0,0 +1,22 @@
package me.chanjar.weixin.open.util.json;

import com.google.gson.*;
import me.chanjar.weixin.common.util.json.GsonHelper;
import me.chanjar.weixin.open.bean.result.WxOpenAuthorizerOptionResult;

import java.lang.reflect.Type;

/**
* @author <a href="https://github.com/007gzs">007</a>
*/
public class WxOpenAuthorizerOptionResultGsonAdapter implements JsonDeserializer<WxOpenAuthorizerOptionResult> {
@Override
public WxOpenAuthorizerOptionResult deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
WxOpenAuthorizerOptionResult authorizerOptionResult = new WxOpenAuthorizerOptionResult();
JsonObject jsonObject = jsonElement.getAsJsonObject();
authorizerOptionResult.setAuthorizerAppid(GsonHelper.getString(jsonObject, "authorizer_appid"));
authorizerOptionResult.setOptionName(GsonHelper.getString(jsonObject, "option_name"));
authorizerOptionResult.setOptionValue(GsonHelper.getString(jsonObject, "option_value"));
return authorizerOptionResult;
}
}

+ 21
- 0
weixin-java-open/src/main/java/me/chanjar/weixin/open/util/json/WxOpenComponentAccessTokenGsonAdapter.java Прегледај датотеку

@@ -0,0 +1,21 @@
package me.chanjar.weixin.open.util.json;

import com.google.gson.*;
import me.chanjar.weixin.common.util.json.GsonHelper;
import me.chanjar.weixin.open.bean.WxOpenComponentAccessToken;

import java.lang.reflect.Type;

/**
* @author <a href="https://github.com/007gzs">007</a>
*/
public class WxOpenComponentAccessTokenGsonAdapter implements JsonDeserializer<WxOpenComponentAccessToken> {
@Override
public WxOpenComponentAccessToken deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
WxOpenComponentAccessToken componentAccessToken = new WxOpenComponentAccessToken();
JsonObject jsonObject = jsonElement.getAsJsonObject();
componentAccessToken.setComponentAccessToken(GsonHelper.getString(jsonObject, "component_access_token"));
componentAccessToken.setExpiresIn(GsonHelper.getPrimitiveInteger(jsonObject, "expires_in"));
return componentAccessToken;
}
}

+ 36
- 0
weixin-java-open/src/main/java/me/chanjar/weixin/open/util/json/WxOpenGsonBuilder.java Прегледај датотеку

@@ -0,0 +1,36 @@
package me.chanjar.weixin.open.util.json;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import me.chanjar.weixin.open.bean.WxOpenAuthorizerAccessToken;
import me.chanjar.weixin.open.bean.WxOpenComponentAccessToken;
import me.chanjar.weixin.open.bean.auth.WxOpenAuthorizationInfo;
import me.chanjar.weixin.open.bean.auth.WxOpenAuthorizerInfo;
import me.chanjar.weixin.open.bean.result.WxOpenAuthorizerInfoResult;
import me.chanjar.weixin.open.bean.result.WxOpenAuthorizerOptionResult;
import me.chanjar.weixin.open.bean.result.WxOpenQueryAuthResult;

/**
* @author <a href="https://github.com/007gzs">007</a>
*/
public class WxOpenGsonBuilder {

public static final GsonBuilder INSTANCE = new GsonBuilder();

static {
INSTANCE.disableHtmlEscaping();
INSTANCE.registerTypeAdapter(WxOpenComponentAccessToken.class, new WxOpenComponentAccessTokenGsonAdapter());
INSTANCE.registerTypeAdapter(WxOpenAuthorizerAccessToken.class, new WxOpenAuthorizerAccessTokenGsonAdapter());
INSTANCE.registerTypeAdapter(WxOpenAuthorizationInfo.class, new WxOpenAuthorizationInfoGsonAdapter());
INSTANCE.registerTypeAdapter(WxOpenAuthorizerInfo.class, new WxOpenAuthorizerInfoGsonAdapter());
INSTANCE.registerTypeAdapter(WxOpenQueryAuthResult.class, new WxOpenQueryAuthResultGsonAdapter());
INSTANCE.registerTypeAdapter(WxOpenAuthorizerInfoResult.class, new WxOpenAuthorizerInfoResultGsonAdapter());
INSTANCE.registerTypeAdapter(WxOpenAuthorizerOptionResult.class, new WxOpenAuthorizerOptionResultGsonAdapter());

}

public static Gson create() {
return INSTANCE.create();
}

}

+ 26
- 0
weixin-java-open/src/main/java/me/chanjar/weixin/open/util/json/WxOpenQueryAuthResultGsonAdapter.java Прегледај датотеку

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

import com.google.gson.*;
import com.google.gson.reflect.TypeToken;
import me.chanjar.weixin.open.bean.auth.WxOpenAuthorizationInfo;
import me.chanjar.weixin.open.bean.result.WxOpenQueryAuthResult;

import java.lang.reflect.Type;

/**
* @author <a href="https://github.com/007gzs">007</a>
*/
public class WxOpenQueryAuthResultGsonAdapter implements JsonDeserializer<WxOpenQueryAuthResult> {
@Override
public WxOpenQueryAuthResult deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
WxOpenQueryAuthResult queryAuthResult = new WxOpenQueryAuthResult();
JsonObject jsonObject = jsonElement.getAsJsonObject();

WxOpenAuthorizationInfo authorizationInfo = WxOpenGsonBuilder.INSTANCE.create().fromJson(jsonObject.get("authorization_info"),
new TypeToken<WxOpenAuthorizationInfo>() {
}.getType());

queryAuthResult.setAuthorizationInfo(authorizationInfo);
return queryAuthResult;
}
}

+ 90
- 0
weixin-java-open/src/main/java/me/chanjar/weixin/open/util/xml/XStreamTransformer.java Прегледај датотеку

@@ -0,0 +1,90 @@
package me.chanjar.weixin.open.util.xml;

import com.thoughtworks.xstream.XStream;
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
import me.chanjar.weixin.open.bean.message.WxOpenXmlMessage;

import java.io.InputStream;
import java.util.*;

/**
* @author <a href="https://github.com/007gzs">007</a>
*/
public class XStreamTransformer {
private static final Map<Class<?>, XStream> CLASS_2_XSTREAM_INSTANCE = new HashMap<>();

static {
registerClass(WxOpenXmlMessage.class);
}

/**
* xml -> pojo
*/
@SuppressWarnings("unchecked")
public static <T> T fromXml(Class<T> clazz, String xml) {
T object = (T) CLASS_2_XSTREAM_INSTANCE.get(clazz).fromXML(xml);
return object;
}

@SuppressWarnings("unchecked")
public static <T> T fromXml(Class<T> clazz, InputStream is) {
T object = (T) CLASS_2_XSTREAM_INSTANCE.get(clazz).fromXML(is);
return object;
}

/**
* pojo -> xml
*/
public static <T> String toXml(Class<T> clazz, T object) {
return CLASS_2_XSTREAM_INSTANCE.get(clazz).toXML(object);
}

/**
* 注册扩展消息的解析器
*
* @param clz 类型
* @param xStream xml解析器
*/
private static void register(Class<?> clz, XStream xStream) {
CLASS_2_XSTREAM_INSTANCE.put(clz, xStream);
}

/**
* 会自动注册该类及其子类
*
* @param clz 要注册的类
*/
private static void registerClass(Class<?> clz) {
XStream xstream = XStreamInitializer.getInstance();
xstream.setClassLoader(Thread.currentThread().getContextClassLoader());

xstream.processAnnotations(clz);
xstream.processAnnotations(getInnerClasses(clz));
if (clz.equals(WxOpenXmlMessage.class)) {
// 操蛋的微信,模板消息推送成功的消息是MsgID,其他消息推送过来是MsgId
xstream.aliasField("MsgID", WxOpenXmlMessage.class, "msgId");
}

register(clz, xstream);
}

private static Class<?>[] getInnerClasses(Class<?> clz) {
Class<?>[] innerClasses = clz.getClasses();
if (innerClasses == null) {
return null;
}

List<Class<?>> result = new ArrayList<>();
result.addAll(Arrays.asList(innerClasses));
for (Class<?> inner : innerClasses) {
Class<?>[] innerClz = getInnerClasses(inner);
if (innerClz == null) {
continue;
}

result.addAll(Arrays.asList(innerClz));
}

return result.toArray(new Class<?>[0]);
}
}

Loading…
Откажи
Сачувај