| @@ -55,16 +55,6 @@ | |||
| <artifactId>httpmime</artifactId> | |||
| <version>${httpclient.version}</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>javax.xml.bind</groupId> | |||
| <artifactId>jaxb-api</artifactId> | |||
| <version>2.2.7</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.sun.xml.bind</groupId> | |||
| <artifactId>jaxb-impl</artifactId> | |||
| <version>2.2.7</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.google.code.gson</groupId> | |||
| <artifactId>gson</artifactId> | |||
| @@ -1,229 +0,0 @@ | |||
| <?xml version="1.0"?> | |||
| <project | |||
| xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" | |||
| xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> | |||
| <modelVersion>4.0.0</modelVersion> | |||
| <groupId>me.chanjar</groupId> | |||
| <artifactId>weixin-java-parent</artifactId> | |||
| <version>1.0.5-SNAPSHOT</version> | |||
| <packaging>pom</packaging> | |||
| <name>WeiXin Java Tools - Parent</name> | |||
| <description>微信公众号、企业号上级POM</description> | |||
| <url>https://github.com/chanjarster/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> | |||
| </developer> | |||
| </developers> | |||
| <scm> | |||
| <connection>scm:git:https://github.com/chanjarster/weixin-java-tools.git</connection> | |||
| <developerConnection>scm:git:git@github.com:chanjarster/weixin-java-tools.git</developerConnection> | |||
| <url>https://github.com/chanjarster/weixin-java-tools</url> | |||
| </scm> | |||
| <modules> | |||
| <module>weixin-java-common</module> | |||
| <module>weixin-java-cp</module> | |||
| <module>weixin-java-mp</module> | |||
| </modules> | |||
| <properties> | |||
| <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | |||
| <downloadJavadocs>true</downloadJavadocs> | |||
| <downloadSources>true</downloadSources> | |||
| <httpclient.version>4.3.5</httpclient.version> | |||
| </properties> | |||
| <dependencies> | |||
| <dependency> | |||
| <groupId>org.apache.httpcomponents</groupId> | |||
| <artifactId>fluent-hc</artifactId> | |||
| <version>${httpclient.version}</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.apache.httpcomponents</groupId> | |||
| <artifactId>httpmime</artifactId> | |||
| <version>${httpclient.version}</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>javax.xml.bind</groupId> | |||
| <artifactId>jaxb-api</artifactId> | |||
| <version>2.2.7</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.sun.xml.bind</groupId> | |||
| <artifactId>jaxb-impl</artifactId> | |||
| <version>2.2.7</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.google.code.gson</groupId> | |||
| <artifactId>gson</artifactId> | |||
| <version>2.2.2</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>commons-codec</groupId> | |||
| <artifactId>commons-codec</artifactId> | |||
| <version>1.9</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>commons-io</groupId> | |||
| <artifactId>commons-io</artifactId> | |||
| <version>2.4</version> | |||
| </dependency> | |||
| </dependencies> | |||
| <dependencyManagement> | |||
| <dependencies> | |||
| <dependency> | |||
| <groupId>junit</groupId> | |||
| <artifactId>junit</artifactId> | |||
| <version>4.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.8.7</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>9.3.0.M0</version> | |||
| <scope>test</scope> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.eclipse.jetty</groupId> | |||
| <artifactId>jetty-servlet</artifactId> | |||
| <version>9.3.0.M0</version> | |||
| <scope>test</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>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> | |||
| <charset>UTF-8</charset> | |||
| <locale>zh_CN</locale> | |||
| </configuration> | |||
| </plugin> | |||
| <plugin> | |||
| <groupId>org.apache.maven.plugins</groupId> | |||
| <artifactId>maven-gpg-plugin</artifactId> | |||
| <version>1.5</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> | |||
| </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>false</autoReleaseAfterClose> | |||
| </configuration> | |||
| </plugin> | |||
| <plugin> | |||
| <groupId>org.apache.maven.plugins</groupId> | |||
| <artifactId>maven-release-plugin</artifactId> | |||
| <version>2.5</version> | |||
| <configuration> | |||
| <autoVersionSubmodules>true</autoVersionSubmodules> | |||
| <useReleaseProfile>false</useReleaseProfile> | |||
| <releaseProfiles>release</releaseProfiles> | |||
| <goals>deploy</goals> | |||
| </configuration> | |||
| </plugin> | |||
| </plugins> | |||
| </build> | |||
| </project> | |||
| @@ -1,68 +1,73 @@ | |||
| <?xml version="1.0"?> | |||
| <project | |||
| xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" | |||
| xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> | |||
| <modelVersion>4.0.0</modelVersion> | |||
| <parent> | |||
| <groupId>me.chanjar</groupId> | |||
| <artifactId>weixin-java-parent</artifactId> | |||
| <version>1.0.7-SNAPSHOT</version> | |||
| </parent> | |||
| xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" | |||
| xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> | |||
| <modelVersion>4.0.0</modelVersion> | |||
| <parent> | |||
| <groupId>me.chanjar</groupId> | |||
| <artifactId>weixin-java-parent</artifactId> | |||
| <version>1.0.7-SNAPSHOT</version> | |||
| </parent> | |||
| <artifactId>weixin-java-common</artifactId> | |||
| <name>WeiXin Java Tools - Common</name> | |||
| <description>微信公众号、企业号Java SDK Common</description> | |||
| <artifactId>weixin-java-common</artifactId> | |||
| <name>WeiXin Java Tools - Common</name> | |||
| <description>微信公众号、企业号Java SDK Common</description> | |||
| <dependencies> | |||
| <dependency> | |||
| <groupId>junit</groupId> | |||
| <artifactId>junit</artifactId> | |||
| <scope>test</scope> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.testng</groupId> | |||
| <artifactId>testng</artifactId> | |||
| <version>6.8.7</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>com.google.inject</groupId> | |||
| <artifactId>guice</artifactId> | |||
| <version>3.0</version> | |||
| <scope>test</scope> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.eclipse.jetty</groupId> | |||
| <artifactId>jetty-server</artifactId> | |||
| <version>9.3.0.M0</version> | |||
| <scope>test</scope> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.eclipse.jetty</groupId> | |||
| <artifactId>jetty-servlet</artifactId> | |||
| <version>9.3.0.M0</version> | |||
| <scope>test</scope> | |||
| </dependency> | |||
| </dependencies> | |||
| <dependencies> | |||
| <dependency> | |||
| <groupId>com.thoughtworks.xstream</groupId> | |||
| <artifactId>xstream</artifactId> | |||
| <version>1.4.7</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>junit</groupId> | |||
| <artifactId>junit</artifactId> | |||
| <scope>test</scope> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.testng</groupId> | |||
| <artifactId>testng</artifactId> | |||
| <version>6.8.7</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>com.google.inject</groupId> | |||
| <artifactId>guice</artifactId> | |||
| <version>3.0</version> | |||
| <scope>test</scope> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.eclipse.jetty</groupId> | |||
| <artifactId>jetty-server</artifactId> | |||
| <version>9.3.0.M0</version> | |||
| <scope>test</scope> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.eclipse.jetty</groupId> | |||
| <artifactId>jetty-servlet</artifactId> | |||
| <version>9.3.0.M0</version> | |||
| <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> | |||
| <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> | |||
| @@ -1,68 +0,0 @@ | |||
| <?xml version="1.0"?> | |||
| <project | |||
| xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" | |||
| xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> | |||
| <modelVersion>4.0.0</modelVersion> | |||
| <parent> | |||
| <groupId>me.chanjar</groupId> | |||
| <artifactId>weixin-java-parent</artifactId> | |||
| <version>1.0.5-SNAPSHOT</version> | |||
| </parent> | |||
| <artifactId>weixin-java-common</artifactId> | |||
| <name>WeiXin Java Tools - Common</name> | |||
| <description>微信公众号、企业号Java SDK Common</description> | |||
| <dependencies> | |||
| <dependency> | |||
| <groupId>junit</groupId> | |||
| <artifactId>junit</artifactId> | |||
| <scope>test</scope> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.testng</groupId> | |||
| <artifactId>testng</artifactId> | |||
| <version>6.8.7</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>com.google.inject</groupId> | |||
| <artifactId>guice</artifactId> | |||
| <version>3.0</version> | |||
| <scope>test</scope> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.eclipse.jetty</groupId> | |||
| <artifactId>jetty-server</artifactId> | |||
| <version>9.3.0.M0</version> | |||
| <scope>test</scope> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.eclipse.jetty</groupId> | |||
| <artifactId>jetty-servlet</artifactId> | |||
| <version>9.3.0.M0</version> | |||
| <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> | |||
| @@ -1,24 +0,0 @@ | |||
| package me.chanjar.weixin.common.util.xml; | |||
| import javax.xml.bind.annotation.adapters.XmlAdapter; | |||
| /** | |||
| * | |||
| * http://stackoverflow.com/questions/14193944/jaxb-marshalling-unmarshalling-with-cdata | |||
| * | |||
| * @author Daniel Qian | |||
| * | |||
| */ | |||
| public class AdapterCDATA extends XmlAdapter<String, String> { | |||
| @Override | |||
| public String marshal(String arg0) throws Exception { | |||
| return "<![CDATA[" + arg0 + "]]>"; | |||
| } | |||
| @Override | |||
| public String unmarshal(String arg0) throws Exception { | |||
| return arg0; | |||
| } | |||
| } | |||
| @@ -1,21 +0,0 @@ | |||
| package me.chanjar.weixin.common.util.xml; | |||
| import javax.xml.bind.annotation.adapters.XmlAdapter; | |||
| /** | |||
| * @author Daniel Qian | |||
| */ | |||
| public class MediaIdMarshaller extends XmlAdapter<String, String> { | |||
| @Override | |||
| public String marshal(String arg0) throws Exception { | |||
| return "<MediaId><![CDATA[" + arg0 + "]]></MediaId>"; | |||
| } | |||
| @Override | |||
| public String unmarshal(String arg0) throws Exception { | |||
| // do nothing | |||
| return arg0; | |||
| } | |||
| } | |||
| @@ -0,0 +1,15 @@ | |||
| package me.chanjar.weixin.common.util.xml; | |||
| import com.thoughtworks.xstream.converters.basic.StringConverter; | |||
| /** | |||
| * Created by qianjia on 15/1/19. | |||
| */ | |||
| public class XStreamCDataConverter extends StringConverter { | |||
| @Override | |||
| public String toString(Object obj) { | |||
| return "<![CDATA[" + super.toString(obj) + "]]>"; | |||
| } | |||
| } | |||
| @@ -0,0 +1,53 @@ | |||
| package me.chanjar.weixin.common.util.xml; | |||
| import com.thoughtworks.xstream.XStream; | |||
| import com.thoughtworks.xstream.converters.basic.DoubleConverter; | |||
| import com.thoughtworks.xstream.converters.basic.FloatConverter; | |||
| import com.thoughtworks.xstream.converters.basic.IntConverter; | |||
| import com.thoughtworks.xstream.core.util.QuickWriter; | |||
| import com.thoughtworks.xstream.io.HierarchicalStreamWriter; | |||
| import com.thoughtworks.xstream.io.xml.PrettyPrintWriter; | |||
| import com.thoughtworks.xstream.io.xml.XppDriver; | |||
| import com.thoughtworks.xstream.security.NoTypePermission; | |||
| import com.thoughtworks.xstream.security.NullPermission; | |||
| import com.thoughtworks.xstream.security.PrimitiveTypePermission; | |||
| import java.io.Writer; | |||
| /** | |||
| * Created by qianjia on 15/1/19. | |||
| */ | |||
| public class XStreamInitializer { | |||
| public static XStream getInstance() { | |||
| XStream xstream = new XStream(new XppDriver() { | |||
| @Override | |||
| public HierarchicalStreamWriter createWriter(Writer out) { | |||
| return new PrettyPrintWriter(out, getNameCoder()) { | |||
| protected String PREFIX_CDATA = "<![CDATA["; | |||
| protected String SUFFIX_CDATA = "]]>"; | |||
| protected String PREFIX_MEDIA_ID = "<MediaId>"; | |||
| protected String SUFFIX_MEDIA_ID = "</MediaId>"; | |||
| @Override | |||
| protected void writeText(QuickWriter writer, String text) { | |||
| if (text.startsWith(PREFIX_CDATA) && text.endsWith(SUFFIX_CDATA)) { | |||
| writer.write(text); | |||
| } else if (text.startsWith(PREFIX_MEDIA_ID) && text.endsWith(SUFFIX_MEDIA_ID)) { | |||
| writer.write(text); | |||
| } else { | |||
| super.writeText(writer, text); | |||
| } | |||
| } | |||
| }; | |||
| } | |||
| }); | |||
| xstream.ignoreUnknownElements(); | |||
| xstream.setMode(XStream.NO_REFERENCES); | |||
| xstream.addPermission(NullPermission.NULL); | |||
| xstream.addPermission(PrimitiveTypePermission.PRIMITIVES); | |||
| return xstream; | |||
| } | |||
| } | |||
| @@ -0,0 +1,11 @@ | |||
| package me.chanjar.weixin.common.util.xml; | |||
| /** | |||
| * Created by qianjia on 15/1/19. | |||
| */ | |||
| public class XStreamMediaIdConverter extends XStreamCDataConverter { | |||
| @Override | |||
| public String toString(Object obj) { | |||
| return "<MediaId>" + super.toString(obj) + "</MediaId>"; | |||
| } | |||
| } | |||
| @@ -1,73 +0,0 @@ | |||
| <?xml version="1.0"?> | |||
| <project | |||
| xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" | |||
| xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> | |||
| <modelVersion>4.0.0</modelVersion> | |||
| <parent> | |||
| <groupId>me.chanjar</groupId> | |||
| <artifactId>weixin-java-parent</artifactId> | |||
| <version>1.0.5-SNAPSHOT</version> | |||
| </parent> | |||
| <artifactId>weixin-java-cp</artifactId> | |||
| <name>WeiXin Java Tools - CP</name> | |||
| <description>微信企业号Java SDK</description> | |||
| <dependencies> | |||
| <dependency> | |||
| <groupId>me.chanjar</groupId> | |||
| <artifactId>weixin-java-common</artifactId> | |||
| <version>${project.version}</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>junit</groupId> | |||
| <artifactId>junit</artifactId> | |||
| <scope>test</scope> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.testng</groupId> | |||
| <artifactId>testng</artifactId> | |||
| <version>6.8.7</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>com.google.inject</groupId> | |||
| <artifactId>guice</artifactId> | |||
| <version>3.0</version> | |||
| <scope>test</scope> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.eclipse.jetty</groupId> | |||
| <artifactId>jetty-server</artifactId> | |||
| <version>9.3.0.M0</version> | |||
| <scope>test</scope> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.eclipse.jetty</groupId> | |||
| <artifactId>jetty-servlet</artifactId> | |||
| <version>9.3.0.M0</version> | |||
| <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> | |||
| @@ -1,10 +1,10 @@ | |||
| package me.chanjar.weixin.cp.api; | |||
| import java.util.Map; | |||
| import me.chanjar.weixin.cp.bean.WxCpXmlMessage; | |||
| import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage; | |||
| import java.util.Map; | |||
| /** | |||
| * 处理微信推送消息的处理器接口 | |||
| * @author Daniel Qian | |||
| @@ -1,9 +1,9 @@ | |||
| package me.chanjar.weixin.cp.api; | |||
| import java.util.Map; | |||
| import me.chanjar.weixin.cp.bean.WxCpXmlMessage; | |||
| import java.util.Map; | |||
| /** | |||
| * 微信消息拦截器,可以用来做验证 | |||
| * @author Daniel Qian | |||
| @@ -1,5 +1,8 @@ | |||
| package me.chanjar.weixin.cp.api; | |||
| import me.chanjar.weixin.cp.bean.WxCpXmlMessage; | |||
| import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage; | |||
| import java.util.ArrayList; | |||
| import java.util.HashMap; | |||
| import java.util.List; | |||
| @@ -8,9 +11,6 @@ import java.util.concurrent.ExecutorService; | |||
| import java.util.concurrent.Executors; | |||
| import java.util.regex.Pattern; | |||
| import me.chanjar.weixin.cp.bean.WxCpXmlMessage; | |||
| import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage; | |||
| /** | |||
| * <pre> | |||
| * 微信消息路由器,通过代码化的配置,把来自微信的消息交给handler处理 | |||
| @@ -1,17 +1,18 @@ | |||
| package me.chanjar.weixin.cp.api; | |||
| import java.io.File; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.util.List; | |||
| import me.chanjar.weixin.common.bean.WxMenu; | |||
| import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import me.chanjar.weixin.common.util.http.RequestExecutor; | |||
| import me.chanjar.weixin.cp.bean.*; | |||
| import me.chanjar.weixin.cp.bean.WxCpDepart; | |||
| import me.chanjar.weixin.cp.bean.WxCpMessage; | |||
| import me.chanjar.weixin.cp.bean.WxCpTag; | |||
| import me.chanjar.weixin.cp.bean.WxCpUser; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import java.io.File; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.util.List; | |||
| /** | |||
| * 微信API的Service | |||
| @@ -1,11 +1,11 @@ | |||
| package me.chanjar.weixin.cp.bean; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| import me.chanjar.weixin.cp.bean.messagebuilder.*; | |||
| import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| /** | |||
| * 消息 | |||
| * @author Daniel Qian | |||
| @@ -1,14 +1,13 @@ | |||
| package me.chanjar.weixin.cp.bean; | |||
| import me.chanjar.weixin.common.util.xml.AdapterCDATA; | |||
| import com.thoughtworks.xstream.annotations.XStreamAlias; | |||
| import com.thoughtworks.xstream.annotations.XStreamConverter; | |||
| import me.chanjar.weixin.common.util.xml.XStreamCDataConverter; | |||
| import me.chanjar.weixin.cp.api.WxCpConfigStorage; | |||
| import me.chanjar.weixin.cp.util.crypto.WxCpCryptUtil; | |||
| import me.chanjar.weixin.cp.util.xml.XmlTransformer; | |||
| import me.chanjar.weixin.cp.util.xml.XStreamTransformer; | |||
| import org.apache.commons.io.IOUtils; | |||
| import javax.xml.bind.JAXBException; | |||
| import javax.xml.bind.annotation.*; | |||
| import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.util.ArrayList; | |||
| @@ -25,103 +24,102 @@ import java.util.List; | |||
| * | |||
| * @author Daniel Qian | |||
| */ | |||
| @XmlRootElement(name = "xml") | |||
| @XmlAccessorType(XmlAccessType.FIELD) | |||
| @XStreamAlias("xml") | |||
| public class WxCpXmlMessage { | |||
| /////////////////////// | |||
| // 以下都是微信推送过来的消息的xml的element所对应的属性 | |||
| /////////////////////// | |||
| @XmlElement(name="AgentID") | |||
| @XStreamAlias("AgentID") | |||
| private Integer agentId; | |||
| @XmlElement(name = "ToUserName") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("ToUserName") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String toUserName; | |||
| @XmlElement(name = "FromUserName") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("FromUserName") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String fromUserName; | |||
| @XmlElement(name = "CreateTime") | |||
| @XStreamAlias("CreateTime") | |||
| private Long createTime; | |||
| @XmlElement(name = "MsgType") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("MsgType") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String msgType; | |||
| @XmlElement(name = "Content") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Content") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String content; | |||
| @XmlElement(name = "MsgId") | |||
| @XStreamAlias("MsgId") | |||
| private Long msgId; | |||
| @XmlElement(name = "PicUrl") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("PicUrl") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String picUrl; | |||
| @XmlElement(name = "MediaId") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("MediaId") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String mediaId; | |||
| @XmlElement(name = "Format") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Format") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String format; | |||
| @XmlElement(name = "ThumbMediaId") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("ThumbMediaId") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String thumbMediaId; | |||
| @XmlElement(name = "Location_X") | |||
| @XStreamAlias("Location_X") | |||
| private Double locationX; | |||
| @XmlElement(name = "Location_Y") | |||
| @XStreamAlias("Location_Y") | |||
| private Double locationY; | |||
| @XmlElement(name = "Scale") | |||
| @XStreamAlias("Scale") | |||
| private Double scale; | |||
| @XmlElement(name = "Label") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Label") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String label; | |||
| @XmlElement(name = "Title") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Title") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String title; | |||
| @XmlElement(name = "Description") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Description") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String description; | |||
| @XmlElement(name = "Url") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Url") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String url; | |||
| @XmlElement(name = "Event") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Event") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String event; | |||
| @XmlElement(name = "EventKey") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("EventKey") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String eventKey; | |||
| @XmlElement(name = "Ticket") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Ticket") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String ticket; | |||
| @XmlElement(name = "Latitude") | |||
| @XStreamAlias("Latitude") | |||
| private Double latitude; | |||
| @XmlElement(name = "Longitude") | |||
| @XStreamAlias("Longitude") | |||
| private Double longitude; | |||
| @XmlElement(name = "Precision") | |||
| @XStreamAlias("Precision") | |||
| private Double precision; | |||
| @XmlElement(name = "Recognition") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Recognition") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String recognition; | |||
| /////////////////////////////////////// | |||
| @@ -130,37 +128,37 @@ public class WxCpXmlMessage { | |||
| /** | |||
| * 群发的结果 | |||
| */ | |||
| @XmlElement(name = "Status") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Status") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String status; | |||
| /** | |||
| * group_id下粉丝数;或者openid_list中的粉丝数 | |||
| */ | |||
| @XmlElement(name = "TotalCount") | |||
| @XStreamAlias("TotalCount") | |||
| private Integer totalCount; | |||
| /** | |||
| * 过滤(过滤是指特定地区、性别的过滤、用户设置拒收的过滤,用户接收已超4条的过滤)后,准备发送的粉丝数,原则上,filterCount = sentCount + errorCount | |||
| */ | |||
| @XmlElement(name = "FilterCount") | |||
| @XStreamAlias("FilterCount") | |||
| private Integer filterCount; | |||
| /** | |||
| * 发送成功的粉丝数 | |||
| */ | |||
| @XmlElement(name = "SentCount") | |||
| @XStreamAlias("SentCount") | |||
| private Integer sentCount; | |||
| /** | |||
| * 发送失败的粉丝数 | |||
| */ | |||
| @XmlElement(name = "ErrorCount") | |||
| @XStreamAlias("ErrorCount") | |||
| private Integer errorCount; | |||
| @XmlElement(name = "ScanCodeInfo") | |||
| @XStreamAlias("ScanCodeInfo") | |||
| private ScanCodeInfo scanCodeInfo = new ScanCodeInfo(); | |||
| @XmlElement(name = "SendPicsInfo") | |||
| @XStreamAlias("SendPicsInfo") | |||
| private SendPicsInfo sendPicsInfo = new SendPicsInfo(); | |||
| @XmlElement(name = "SendLocationInfo") | |||
| @XStreamAlias("SendLocationInfo") | |||
| private SendLocationInfo sendLocationInfo = new SendLocationInfo(); | |||
| public Integer getAgentId() { | |||
| @@ -390,19 +388,11 @@ public class WxCpXmlMessage { | |||
| } | |||
| protected static WxCpXmlMessage fromXml(String xml) { | |||
| try { | |||
| return XmlTransformer.fromXml(WxCpXmlMessage.class, xml); | |||
| } catch (JAXBException e) { | |||
| throw new RuntimeException(e); | |||
| } | |||
| return XStreamTransformer.fromXml(WxCpXmlMessage.class, xml); | |||
| } | |||
| protected static WxCpXmlMessage fromXml(InputStream is) { | |||
| try { | |||
| return XmlTransformer.fromXml(WxCpXmlMessage.class, is); | |||
| } catch (JAXBException e) { | |||
| throw new RuntimeException(e); | |||
| } | |||
| return XStreamTransformer.fromXml(WxCpXmlMessage.class, is); | |||
| } | |||
| /** | |||
| @@ -499,16 +489,15 @@ public class WxCpXmlMessage { | |||
| this.sendLocationInfo = sendLocationInfo; | |||
| } | |||
| @XmlRootElement(name = "ScanCodeInfo") | |||
| @XmlAccessorType(XmlAccessType.FIELD) | |||
| @XStreamAlias("ScanCodeInfo") | |||
| public static class ScanCodeInfo { | |||
| @XmlElement(name = "ScanType") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("ScanType") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String scanType; | |||
| @XmlElement(name = "ScanResult") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("ScanResult") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String scanResult; | |||
| /** | |||
| @@ -538,15 +527,13 @@ public class WxCpXmlMessage { | |||
| } | |||
| @XmlRootElement(name = "SendPicsInfo") | |||
| @XmlAccessorType(XmlAccessType.FIELD) | |||
| @XStreamAlias("SendPicsInfo") | |||
| public static class SendPicsInfo { | |||
| @XmlElement(name = "Count") | |||
| @XStreamAlias("Count") | |||
| private Long count; | |||
| @XmlElementWrapper(name="PicList") | |||
| @XmlElement(name = "item") | |||
| @XStreamAlias("PicList") | |||
| protected final List<Item> picList = new ArrayList<Item>(); | |||
| public Long getCount() { | |||
| @@ -561,13 +548,11 @@ public class WxCpXmlMessage { | |||
| return picList; | |||
| } | |||
| @XmlRootElement(name = "item") | |||
| @XmlAccessorType(XmlAccessType.FIELD) | |||
| @XmlType(name = "WxXmlMessage.SendPicsInfo.Item") | |||
| @XStreamAlias("item") | |||
| public static class Item { | |||
| @XmlElement(name = "PicMd5Sum") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("PicMd5Sum") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String PicMd5Sum; | |||
| public String getPicMd5Sum() { | |||
| @@ -580,28 +565,27 @@ public class WxCpXmlMessage { | |||
| } | |||
| } | |||
| @XmlRootElement(name = "SendLocationInfo") | |||
| @XmlAccessorType(XmlAccessType.FIELD) | |||
| @XStreamAlias("SendLocationInfo") | |||
| public static class SendLocationInfo { | |||
| @XmlElement(name = "Location_X") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Location_X") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String locationX; | |||
| @XmlElement(name = "Location_Y") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Location_Y") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String locationY; | |||
| @XmlElement(name = "Scale") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Scale") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String scale; | |||
| @XmlElement(name = "Label") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Label") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String label; | |||
| @XmlElement(name = "Poiname") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Poiname") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String poiname; | |||
| public String getLocationX() { | |||
| @@ -1,20 +1,15 @@ | |||
| package me.chanjar.weixin.cp.bean; | |||
| import com.thoughtworks.xstream.annotations.XStreamAlias; | |||
| import com.thoughtworks.xstream.annotations.XStreamConverter; | |||
| import me.chanjar.weixin.common.api.WxConsts; | |||
| import me.chanjar.weixin.common.util.xml.MediaIdMarshaller; | |||
| import me.chanjar.weixin.common.util.xml.XStreamMediaIdConverter; | |||
| import javax.xml.bind.annotation.XmlAccessType; | |||
| import javax.xml.bind.annotation.XmlAccessorType; | |||
| import javax.xml.bind.annotation.XmlElement; | |||
| import javax.xml.bind.annotation.XmlRootElement; | |||
| import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; | |||
| @XmlRootElement(name = "xml") | |||
| @XmlAccessorType(XmlAccessType.FIELD) | |||
| @XStreamAlias("xml") | |||
| public class WxCpXmlOutImageMessage extends WxCpXmlOutMessage { | |||
| @XmlElement(name="Image") | |||
| @XmlJavaTypeAdapter(MediaIdMarshaller.class) | |||
| @XStreamAlias("Image") | |||
| @XStreamConverter(value=XStreamMediaIdConverter.class) | |||
| private String mediaId; | |||
| public WxCpXmlOutImageMessage() { | |||
| @@ -1,35 +1,29 @@ | |||
| package me.chanjar.weixin.cp.bean; | |||
| import me.chanjar.weixin.common.util.xml.AdapterCDATA; | |||
| import com.thoughtworks.xstream.annotations.XStreamAlias; | |||
| import com.thoughtworks.xstream.annotations.XStreamConverter; | |||
| import me.chanjar.weixin.common.util.xml.XStreamCDataConverter; | |||
| import me.chanjar.weixin.cp.api.WxCpConfigStorage; | |||
| import me.chanjar.weixin.cp.bean.outxmlbuilder.*; | |||
| import me.chanjar.weixin.cp.util.crypto.WxCpCryptUtil; | |||
| import me.chanjar.weixin.cp.util.xml.XmlTransformer; | |||
| import me.chanjar.weixin.cp.util.xml.XStreamTransformer; | |||
| import javax.xml.bind.JAXBException; | |||
| import javax.xml.bind.annotation.XmlAccessType; | |||
| import javax.xml.bind.annotation.XmlAccessorType; | |||
| import javax.xml.bind.annotation.XmlElement; | |||
| import javax.xml.bind.annotation.XmlRootElement; | |||
| import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; | |||
| @XStreamAlias("xml") | |||
| public abstract class WxCpXmlOutMessage { | |||
| @XmlRootElement(name = "xml") | |||
| @XmlAccessorType(XmlAccessType.FIELD) | |||
| public class WxCpXmlOutMessage { | |||
| @XmlElement(name="ToUserName") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("ToUserName") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| protected String toUserName; | |||
| @XmlElement(name="FromUserName") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("FromUserName") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| protected String fromUserName; | |||
| @XmlElement(name="CreateTime") | |||
| @XStreamAlias("CreateTime") | |||
| protected Long createTime; | |||
| @XmlElement(name="MsgType") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("MsgType") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| protected String msgType; | |||
| public String getToUserName() { | |||
| @@ -65,11 +59,7 @@ public class WxCpXmlOutMessage { | |||
| } | |||
| protected String toXml() { | |||
| try { | |||
| return XmlTransformer.toXml((Class)this.getClass(), this); | |||
| } catch (JAXBException e) { | |||
| throw new RuntimeException(e); | |||
| } | |||
| return XStreamTransformer.toXml((Class)this.getClass(), this); | |||
| } | |||
| /** | |||
| @@ -1,22 +1,20 @@ | |||
| package me.chanjar.weixin.cp.bean; | |||
| import com.thoughtworks.xstream.annotations.XStreamAlias; | |||
| import com.thoughtworks.xstream.annotations.XStreamConverter; | |||
| import me.chanjar.weixin.common.api.WxConsts; | |||
| import me.chanjar.weixin.common.util.xml.AdapterCDATA; | |||
| import me.chanjar.weixin.common.util.xml.XStreamCDataConverter; | |||
| import javax.xml.bind.annotation.*; | |||
| import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| @XmlRootElement(name = "xml") | |||
| @XmlAccessorType(XmlAccessType.FIELD) | |||
| @XStreamAlias("xml") | |||
| public class WxCpXmlOutNewsMessage extends WxCpXmlOutMessage { | |||
| @XmlElement(name = "ArticleCount") | |||
| @XStreamAlias("ArticleCount") | |||
| protected int articleCount; | |||
| @XmlElementWrapper(name="Articles") | |||
| @XmlElement(name = "item") | |||
| @XStreamAlias("Articles") | |||
| protected final List<Item> articles = new ArrayList<Item>(); | |||
| public WxCpXmlOutNewsMessage() { | |||
| @@ -37,24 +35,23 @@ public class WxCpXmlOutNewsMessage extends WxCpXmlOutMessage { | |||
| } | |||
| @XmlRootElement(name = "Item") | |||
| @XmlAccessorType(XmlAccessType.FIELD) | |||
| @XStreamAlias("item") | |||
| public static class Item { | |||
| @XmlElement(name = "Title") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Title") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String Title; | |||
| @XmlElement(name = "Description") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Description") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String Description; | |||
| @XmlElement(name="PicUrl") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("PicUrl") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String PicUrl; | |||
| @XmlElement(name="Url") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Url") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String Url; | |||
| public String getTitle() { | |||
| @@ -1,20 +1,15 @@ | |||
| package me.chanjar.weixin.cp.bean; | |||
| import javax.xml.bind.annotation.XmlAccessType; | |||
| import javax.xml.bind.annotation.XmlAccessorType; | |||
| import javax.xml.bind.annotation.XmlElement; | |||
| import javax.xml.bind.annotation.XmlRootElement; | |||
| import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; | |||
| import com.thoughtworks.xstream.annotations.XStreamAlias; | |||
| import com.thoughtworks.xstream.annotations.XStreamConverter; | |||
| import me.chanjar.weixin.common.api.WxConsts; | |||
| import me.chanjar.weixin.common.util.xml.AdapterCDATA; | |||
| import me.chanjar.weixin.common.util.xml.XStreamCDataConverter; | |||
| @XmlRootElement(name = "xml") | |||
| @XmlAccessorType(XmlAccessType.FIELD) | |||
| @XStreamAlias("xml") | |||
| public class WxCpXmlOutTextMessage extends WxCpXmlOutMessage { | |||
| @XmlElement(name="Content") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Content") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String content; | |||
| public WxCpXmlOutTextMessage() { | |||
| @@ -1,19 +1,14 @@ | |||
| package me.chanjar.weixin.cp.bean; | |||
| import javax.xml.bind.annotation.XmlAccessType; | |||
| import javax.xml.bind.annotation.XmlAccessorType; | |||
| import javax.xml.bind.annotation.XmlElement; | |||
| import javax.xml.bind.annotation.XmlRootElement; | |||
| import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; | |||
| import com.thoughtworks.xstream.annotations.XStreamAlias; | |||
| import com.thoughtworks.xstream.annotations.XStreamConverter; | |||
| import me.chanjar.weixin.common.api.WxConsts; | |||
| import me.chanjar.weixin.common.util.xml.AdapterCDATA; | |||
| import me.chanjar.weixin.common.util.xml.XStreamCDataConverter; | |||
| @XmlRootElement(name = "xml") | |||
| @XmlAccessorType(XmlAccessType.FIELD) | |||
| @XStreamAlias("xml") | |||
| public class WxCpXmlOutVideoMessage extends WxCpXmlOutMessage { | |||
| @XmlElement(name = "Video") | |||
| @XStreamAlias("Video") | |||
| protected final Video video = new Video(); | |||
| public WxCpXmlOutVideoMessage() { | |||
| @@ -45,20 +40,19 @@ public class WxCpXmlOutVideoMessage extends WxCpXmlOutMessage { | |||
| } | |||
| @XmlRootElement(name = "Video") | |||
| @XmlAccessorType(XmlAccessType.FIELD) | |||
| private static class Video { | |||
| @XStreamAlias("Video") | |||
| public static class Video { | |||
| @XmlElement(name = "MediaId") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("MediaId") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String mediaId; | |||
| @XmlElement(name = "Title") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Title") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String title; | |||
| @XmlElement(name = "Description") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Description") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String description; | |||
| public String getMediaId() { | |||
| @@ -1,20 +1,15 @@ | |||
| package me.chanjar.weixin.cp.bean; | |||
| import javax.xml.bind.annotation.XmlAccessType; | |||
| import javax.xml.bind.annotation.XmlAccessorType; | |||
| import javax.xml.bind.annotation.XmlElement; | |||
| import javax.xml.bind.annotation.XmlRootElement; | |||
| import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; | |||
| import com.thoughtworks.xstream.annotations.XStreamAlias; | |||
| import com.thoughtworks.xstream.annotations.XStreamConverter; | |||
| import me.chanjar.weixin.common.api.WxConsts; | |||
| import me.chanjar.weixin.common.util.xml.MediaIdMarshaller; | |||
| import me.chanjar.weixin.common.util.xml.XStreamMediaIdConverter; | |||
| @XmlRootElement(name = "xml") | |||
| @XmlAccessorType(XmlAccessType.FIELD) | |||
| @XStreamAlias("xml") | |||
| public class WxCpXmlOutVoiceMessage extends WxCpXmlOutMessage { | |||
| @XmlElement(name="Voice") | |||
| @XmlJavaTypeAdapter(MediaIdMarshaller.class) | |||
| @XStreamAlias("Voice") | |||
| @XStreamConverter(value=XStreamMediaIdConverter.class) | |||
| private String mediaId; | |||
| public WxCpXmlOutVoiceMessage() { | |||
| @@ -1,11 +1,11 @@ | |||
| package me.chanjar.weixin.cp.bean.outxmlbuilder; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| import me.chanjar.weixin.cp.bean.WxCpXmlOutNewsMessage; | |||
| import me.chanjar.weixin.cp.bean.WxCpXmlOutNewsMessage.Item; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| /** | |||
| * 图文消息builder | |||
| * @author Daniel Qian | |||
| @@ -8,18 +8,11 @@ | |||
| */ | |||
| package me.chanjar.weixin.cp.util.json; | |||
| import java.lang.reflect.Type; | |||
| import com.google.gson.*; | |||
| import me.chanjar.weixin.common.util.json.GsonHelper; | |||
| import me.chanjar.weixin.cp.bean.WxCpDepart; | |||
| import com.google.gson.JsonDeserializationContext; | |||
| import com.google.gson.JsonDeserializer; | |||
| import com.google.gson.JsonElement; | |||
| import com.google.gson.JsonObject; | |||
| import com.google.gson.JsonParseException; | |||
| import com.google.gson.JsonSerializationContext; | |||
| import com.google.gson.JsonSerializer; | |||
| import java.lang.reflect.Type; | |||
| /** | |||
| * @author Daniel Qian | |||
| @@ -2,11 +2,12 @@ package me.chanjar.weixin.cp.util.json; | |||
| import com.google.gson.Gson; | |||
| import com.google.gson.GsonBuilder; | |||
| import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | |||
| import me.chanjar.weixin.common.bean.result.WxError; | |||
| import me.chanjar.weixin.common.util.json.WxMediaUploadResultAdapter; | |||
| import me.chanjar.weixin.common.util.json.WxErrorAdapter; | |||
| import me.chanjar.weixin.cp.bean.*; | |||
| import me.chanjar.weixin.cp.bean.WxCpDepart; | |||
| import me.chanjar.weixin.cp.bean.WxCpMessage; | |||
| import me.chanjar.weixin.cp.bean.WxCpTag; | |||
| import me.chanjar.weixin.cp.bean.WxCpUser; | |||
| public class WxCpGsonBuilder { | |||
| @@ -8,12 +8,12 @@ | |||
| */ | |||
| package me.chanjar.weixin.cp.util.json; | |||
| import java.lang.reflect.Type; | |||
| import com.google.gson.*; | |||
| import me.chanjar.weixin.common.util.json.GsonHelper; | |||
| import me.chanjar.weixin.cp.bean.WxCpUser; | |||
| import java.lang.reflect.Type; | |||
| /** | |||
| * @author Daniel Qian | |||
| */ | |||
| @@ -0,0 +1,106 @@ | |||
| package me.chanjar.weixin.cp.util.xml; | |||
| import com.thoughtworks.xstream.XStream; | |||
| import me.chanjar.weixin.common.util.xml.XStreamInitializer; | |||
| import me.chanjar.weixin.cp.bean.*; | |||
| import java.io.InputStream; | |||
| import java.util.HashMap; | |||
| import java.util.Map; | |||
| /** | |||
| * Created by qianjia on 15/1/19. | |||
| */ | |||
| public class XStreamTransformer { | |||
| protected static final Map<Class, XStream> CLASS_2_XSTREAM_INSTANCE = configXStreamInstance(); | |||
| /** | |||
| * xml -> pojo | |||
| * | |||
| * @param clazz | |||
| * @param xml | |||
| * @return | |||
| */ | |||
| @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 | |||
| * | |||
| * @param clazz | |||
| * @param object | |||
| * @return | |||
| */ | |||
| public static <T> String toXml(Class<T> clazz, T object) { | |||
| return CLASS_2_XSTREAM_INSTANCE.get(clazz).toXML(object); | |||
| } | |||
| private static Map<Class, XStream> configXStreamInstance() { | |||
| Map<Class, XStream> map = new HashMap<Class, XStream>(); | |||
| map.put(WxCpXmlMessage.class, config_WxCpXmlMessage()); | |||
| map.put(WxCpXmlOutNewsMessage.class, config_WxCpXmlOutNewsMessage()); | |||
| map.put(WxCpXmlOutTextMessage.class, config_WxCpXmlOutTextMessage()); | |||
| map.put(WxCpXmlOutImageMessage.class, config_WxCpXmlOutImageMessage()); | |||
| map.put(WxCpXmlOutVideoMessage.class, config_WxCpXmlOutVideoMessage()); | |||
| map.put(WxCpXmlOutVoiceMessage.class, config_WxCpXmlOutVoiceMessage()); | |||
| return map; | |||
| } | |||
| private static XStream config_WxCpXmlMessage() { | |||
| XStream xstream = XStreamInitializer.getInstance(); | |||
| xstream.processAnnotations(WxCpXmlMessage.class); | |||
| xstream.processAnnotations(WxCpXmlMessage.ScanCodeInfo.class); | |||
| xstream.processAnnotations(WxCpXmlMessage.SendPicsInfo.class); | |||
| xstream.processAnnotations(WxCpXmlMessage.SendPicsInfo.Item.class); | |||
| xstream.processAnnotations(WxCpXmlMessage.SendLocationInfo.class); | |||
| return xstream; | |||
| } | |||
| private static XStream config_WxCpXmlOutImageMessage() { | |||
| XStream xstream = XStreamInitializer.getInstance(); | |||
| xstream.processAnnotations(WxCpXmlOutMessage.class); | |||
| xstream.processAnnotations(WxCpXmlOutImageMessage.class); | |||
| return xstream; | |||
| } | |||
| private static XStream config_WxCpXmlOutNewsMessage() { | |||
| XStream xstream = XStreamInitializer.getInstance(); | |||
| xstream.processAnnotations(WxCpXmlOutMessage.class); | |||
| xstream.processAnnotations(WxCpXmlOutNewsMessage.class); | |||
| xstream.processAnnotations(WxCpXmlOutNewsMessage.Item.class); | |||
| return xstream; | |||
| } | |||
| private static XStream config_WxCpXmlOutTextMessage() { | |||
| XStream xstream = XStreamInitializer.getInstance(); | |||
| xstream.processAnnotations(WxCpXmlOutMessage.class); | |||
| xstream.processAnnotations(WxCpXmlOutTextMessage.class); | |||
| return xstream; | |||
| } | |||
| private static XStream config_WxCpXmlOutVideoMessage() { | |||
| XStream xstream = XStreamInitializer.getInstance(); | |||
| xstream.processAnnotations(WxCpXmlOutMessage.class); | |||
| xstream.processAnnotations(WxCpXmlOutVideoMessage.class); | |||
| xstream.processAnnotations(WxCpXmlOutVideoMessage.Video.class); | |||
| return xstream; | |||
| } | |||
| private static XStream config_WxCpXmlOutVoiceMessage() { | |||
| XStream xstream = XStreamInitializer.getInstance(); | |||
| xstream.processAnnotations(WxCpXmlOutMessage.class); | |||
| xstream.processAnnotations(WxCpXmlOutVoiceMessage.class); | |||
| return xstream; | |||
| } | |||
| } | |||
| @@ -1,93 +0,0 @@ | |||
| package me.chanjar.weixin.cp.util.xml; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.io.StringReader; | |||
| import java.io.StringWriter; | |||
| import java.io.Writer; | |||
| import javax.xml.bind.*; | |||
| import me.chanjar.weixin.cp.bean.*; | |||
| import org.xml.sax.InputSource; | |||
| import com.sun.xml.bind.marshaller.CharacterEscapeHandler; | |||
| public class XmlTransformer { | |||
| protected static final JAXBContext JAXB_CONTEXT = initJAXBContext(); | |||
| /** | |||
| * xml -> pojo | |||
| * | |||
| * @param clazz | |||
| * @param xml | |||
| * @return | |||
| * @throws JAXBException | |||
| */ | |||
| @SuppressWarnings("unchecked") | |||
| public static <T> T fromXml(Class<T> clazz, String xml) throws JAXBException { | |||
| Unmarshaller um = JAXB_CONTEXT.createUnmarshaller(); | |||
| T object = (T) um.unmarshal(new StringReader(xml)); | |||
| return object; | |||
| } | |||
| @SuppressWarnings("unchecked") | |||
| public static <T> T fromXml(Class<T> clazz, InputStream is) throws JAXBException { | |||
| Unmarshaller um = JAXB_CONTEXT.createUnmarshaller(); | |||
| InputSource inputSource = new InputSource(is); | |||
| inputSource.setEncoding("utf-8"); | |||
| T object = (T) um.unmarshal(inputSource); | |||
| return object; | |||
| } | |||
| /** | |||
| * pojo -> xml | |||
| * | |||
| * @param clazz | |||
| * @param object | |||
| * @return | |||
| * @throws JAXBException | |||
| */ | |||
| public static <T> String toXml(Class<T> clazz, T object) throws JAXBException { | |||
| StringWriter stringWriter = new StringWriter(); | |||
| toXml(clazz, object, stringWriter); | |||
| return stringWriter.getBuffer().toString(); | |||
| } | |||
| public static <T> void toXml(Class<T> clazz, T object, Writer writer) throws JAXBException { | |||
| Marshaller m = JAXB_CONTEXT.createMarshaller(); | |||
| m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); | |||
| m.setProperty(CharacterEscapeHandler.class.getName(), CHAR_ESCAPE_HANDLER); | |||
| m.setProperty(Marshaller.JAXB_FRAGMENT, true); | |||
| m.marshal(object, writer); | |||
| } | |||
| protected static final CharacterEscapeHandler CHAR_ESCAPE_HANDLER = new CharacterUnescapeHandler(); | |||
| protected static class CharacterUnescapeHandler implements CharacterEscapeHandler { | |||
| public void escape(char[] ac, int i, int j, boolean flag, Writer writer) throws IOException { | |||
| writer.write(ac, i, j); | |||
| } | |||
| } | |||
| private static JAXBContext initJAXBContext() { | |||
| /* | |||
| * JAXBContext对象是线程安全的,根据官方文档的建议将对象作为全局实例 | |||
| * https://jaxb.java.net/guide/Performance_and_thread_safety.html | |||
| */ | |||
| try { | |||
| return JAXBContext.newInstance( | |||
| WxCpXmlOutMessage.class, | |||
| WxCpXmlOutImageMessage.class, | |||
| WxCpXmlOutNewsMessage.class, | |||
| WxCpXmlOutTextMessage.class, | |||
| WxCpXmlOutVideoMessage.class, | |||
| WxCpXmlOutVoiceMessage.class, | |||
| WxCpXmlMessage.class); | |||
| } catch (JAXBException e) { | |||
| throw new RuntimeException(e); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,23 +1,17 @@ | |||
| package me.chanjar.weixin.cp.api; | |||
| import java.io.InputStream; | |||
| import javax.xml.bind.JAXBContext; | |||
| import javax.xml.bind.JAXBException; | |||
| import javax.xml.bind.Unmarshaller; | |||
| import javax.xml.bind.annotation.XmlAccessType; | |||
| import javax.xml.bind.annotation.XmlAccessorType; | |||
| import javax.xml.bind.annotation.XmlRootElement; | |||
| import com.google.inject.Binder; | |||
| import com.google.inject.Module; | |||
| import org.xml.sax.InputSource; | |||
| import com.thoughtworks.xstream.XStream; | |||
| import com.thoughtworks.xstream.annotations.XStreamAlias; | |||
| import me.chanjar.weixin.common.util.xml.XStreamInitializer; | |||
| import java.io.InputStream; | |||
| public class ApiTestModule implements Module { | |||
| @Override | |||
| public void configure(Binder binder) { | |||
| try { | |||
| InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml"); | |||
| WxXmlCpInMemoryConfigStorage config = fromXml(WxXmlCpInMemoryConfigStorage.class, is1); | |||
| WxCpServiceImpl wxService = new WxCpServiceImpl(); | |||
| @@ -25,21 +19,16 @@ public class ApiTestModule implements Module { | |||
| binder.bind(WxCpServiceImpl.class).toInstance(wxService); | |||
| binder.bind(WxCpConfigStorage.class).toInstance(config); | |||
| } catch (JAXBException e) { | |||
| throw new RuntimeException(e); | |||
| } | |||
| } | |||
| public static <T> T fromXml(Class<T> clazz, InputStream is) throws JAXBException { | |||
| Unmarshaller um = JAXBContext.newInstance(clazz).createUnmarshaller(); | |||
| InputSource inputSource = new InputSource(is); | |||
| inputSource.setEncoding("utf-8"); | |||
| T object = (T) um.unmarshal(inputSource); | |||
| return object; | |||
| public static <T> T fromXml(Class<T> clazz, InputStream is) { | |||
| XStream xstream = XStreamInitializer.getInstance(); | |||
| xstream.alias("xml", clazz); | |||
| xstream.processAnnotations(clazz); | |||
| return (T) xstream.fromXML(is); | |||
| } | |||
| @XmlRootElement(name = "xml") | |||
| @XmlAccessorType(XmlAccessType.FIELD) | |||
| @XStreamAlias("xml") | |||
| public static class WxXmlCpInMemoryConfigStorage extends WxCpInMemoryConfigStorage { | |||
| protected String userId; | |||
| @@ -1,14 +1,12 @@ | |||
| package me.chanjar.weixin.cp.api; | |||
| import com.google.inject.Inject; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import me.chanjar.weixin.common.util.StringUtils; | |||
| import org.testng.Assert; | |||
| import org.testng.annotations.Guice; | |||
| import org.testng.annotations.Test; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import com.google.inject.Inject; | |||
| /** | |||
| * 基础API测试 | |||
| * @author Daniel Qian | |||
| @@ -1,15 +1,13 @@ | |||
| package me.chanjar.weixin.cp.api; | |||
| import java.util.List; | |||
| import com.google.inject.Inject; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import me.chanjar.weixin.cp.bean.WxCpDepart; | |||
| import org.testng.Assert; | |||
| import org.testng.annotations.Guice; | |||
| import org.testng.annotations.Test; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import com.google.inject.Inject; | |||
| import java.util.List; | |||
| /** | |||
| * 测试部门接口 | |||
| @@ -1,20 +1,18 @@ | |||
| package me.chanjar.weixin.cp.api; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| import com.google.inject.Inject; | |||
| import me.chanjar.weixin.common.api.WxConsts; | |||
| import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import org.testng.Assert; | |||
| import org.testng.annotations.DataProvider; | |||
| import org.testng.annotations.Guice; | |||
| import org.testng.annotations.Test; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import com.google.inject.Inject; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| /** | |||
| * 测试多媒体文件上传下载 | |||
| @@ -1,14 +1,12 @@ | |||
| package me.chanjar.weixin.cp.api; | |||
| import com.google.inject.Inject; | |||
| import me.chanjar.weixin.common.api.WxConsts; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import me.chanjar.weixin.cp.bean.WxCpMessage; | |||
| import org.testng.annotations.Guice; | |||
| import org.testng.annotations.Test; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import com.google.inject.Inject; | |||
| /*** | |||
| * 测试发送消息 | |||
| * @author Daniel Qian | |||
| @@ -1,7 +1,5 @@ | |||
| package me.chanjar.weixin.cp.api; | |||
| import java.util.Map; | |||
| import me.chanjar.weixin.common.api.WxConsts; | |||
| import me.chanjar.weixin.cp.bean.WxCpXmlMessage; | |||
| import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage; | |||
| @@ -9,6 +7,8 @@ import org.testng.Assert; | |||
| import org.testng.annotations.DataProvider; | |||
| import org.testng.annotations.Test; | |||
| import java.util.Map; | |||
| /** | |||
| * 测试消息路由器 | |||
| * @author Daniel Qian | |||
| @@ -1,9 +1,9 @@ | |||
| package me.chanjar.weixin.cp.api; | |||
| import com.google.inject.Inject; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import me.chanjar.weixin.cp.bean.WxCpDepart; | |||
| import me.chanjar.weixin.cp.bean.WxCpUser; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import org.testng.Assert; | |||
| import org.testng.annotations.Guice; | |||
| import org.testng.annotations.Test; | |||
| @@ -1,19 +1,15 @@ | |||
| package me.chanjar.weixin.cp.api; | |||
| import javax.xml.bind.JAXBException; | |||
| import com.google.inject.Inject; | |||
| import me.chanjar.weixin.common.api.WxConsts; | |||
| import me.chanjar.weixin.common.bean.WxMenu; | |||
| import me.chanjar.weixin.common.bean.WxMenu.WxMenuButton; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import org.testng.Assert; | |||
| import org.testng.annotations.DataProvider; | |||
| import org.testng.annotations.Guice; | |||
| import org.testng.annotations.Test; | |||
| import com.google.inject.Inject; | |||
| import me.chanjar.weixin.common.bean.WxMenu.WxMenuButton; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| /** | |||
| * 测试菜单 | |||
| * @author Daniel Qian | |||
| @@ -42,7 +38,7 @@ public class WxMenuAPITest { | |||
| } | |||
| @DataProvider(name="menu") | |||
| public Object[][] getMenu() throws JAXBException { | |||
| public Object[][] getMenu() { | |||
| WxMenu menu = new WxMenu(); | |||
| WxMenuButton button1 = new WxMenuButton(); | |||
| button1.setType(WxConsts.BUTTON_CLICK); | |||
| @@ -1,11 +1,10 @@ | |||
| package me.chanjar.weixin.cp.bean; | |||
| import me.chanjar.weixin.common.api.WxConsts; | |||
| import me.chanjar.weixin.cp.bean.WxCpMessage.WxArticle; | |||
| import org.testng.Assert; | |||
| import org.testng.annotations.Test; | |||
| import me.chanjar.weixin.cp.bean.WxCpMessage.WxArticle; | |||
| @Test | |||
| public class WxCpMessageTest { | |||
| @@ -1,21 +1,16 @@ | |||
| package me.chanjar.weixin.cp.demo; | |||
| import com.thoughtworks.xstream.XStream; | |||
| import com.thoughtworks.xstream.annotations.XStreamAlias; | |||
| import me.chanjar.weixin.common.util.xml.XStreamInitializer; | |||
| import me.chanjar.weixin.cp.api.WxCpInMemoryConfigStorage; | |||
| import org.xml.sax.InputSource; | |||
| import javax.xml.bind.JAXBContext; | |||
| import javax.xml.bind.JAXBException; | |||
| import javax.xml.bind.Unmarshaller; | |||
| import javax.xml.bind.annotation.XmlAccessType; | |||
| import javax.xml.bind.annotation.XmlAccessorType; | |||
| import javax.xml.bind.annotation.XmlRootElement; | |||
| import java.io.InputStream; | |||
| /** | |||
| * @author Daniel Qian | |||
| */ | |||
| @XmlRootElement(name = "xml") | |||
| @XmlAccessorType(XmlAccessType.FIELD) | |||
| @XStreamAlias("xml") | |||
| class WxCpDemoInMemoryConfigStorage extends WxCpInMemoryConfigStorage { | |||
| @Override | |||
| @@ -25,11 +20,10 @@ class WxCpDemoInMemoryConfigStorage extends WxCpInMemoryConfigStorage { | |||
| } | |||
| public static WxCpDemoInMemoryConfigStorage fromXml(InputStream is) throws JAXBException { | |||
| Unmarshaller um = JAXBContext.newInstance(WxCpDemoInMemoryConfigStorage.class).createUnmarshaller(); | |||
| InputSource inputSource = new InputSource(is); | |||
| inputSource.setEncoding("utf-8"); | |||
| return (WxCpDemoInMemoryConfigStorage) um.unmarshal(inputSource); | |||
| public static WxCpDemoInMemoryConfigStorage fromXml(InputStream is) { | |||
| XStream xstream = XStreamInitializer.getInstance(); | |||
| xstream.processAnnotations(WxCpDemoInMemoryConfigStorage.class); | |||
| return (WxCpDemoInMemoryConfigStorage) xstream.fromXML(is); | |||
| } | |||
| } | |||
| @@ -8,7 +8,6 @@ import org.eclipse.jetty.server.Server; | |||
| import org.eclipse.jetty.servlet.ServletHandler; | |||
| import org.eclipse.jetty.servlet.ServletHolder; | |||
| import javax.xml.bind.JAXBException; | |||
| import java.io.InputStream; | |||
| import java.util.Map; | |||
| @@ -37,7 +36,6 @@ public class WxCpDemoServer { | |||
| } | |||
| private static void initWeixin() { | |||
| try { | |||
| InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml"); | |||
| WxCpDemoInMemoryConfigStorage config = WxCpDemoInMemoryConfigStorage.fromXml(is1); | |||
| @@ -87,8 +85,5 @@ public class WxCpDemoServer { | |||
| .end() | |||
| ; | |||
| } catch (JAXBException e) { | |||
| throw new RuntimeException(e); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,20 +1,18 @@ | |||
| package me.chanjar.weixin.cp.demo; | |||
| import me.chanjar.weixin.common.util.StringUtils; | |||
| import me.chanjar.weixin.cp.api.*; | |||
| import me.chanjar.weixin.cp.api.WxCpConfigStorage; | |||
| import me.chanjar.weixin.cp.api.WxCpMessageRouter; | |||
| import me.chanjar.weixin.cp.api.WxCpService; | |||
| import me.chanjar.weixin.cp.bean.WxCpXmlMessage; | |||
| import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage; | |||
| import me.chanjar.weixin.cp.bean.WxCpXmlOutTextMessage; | |||
| import me.chanjar.weixin.cp.util.crypto.WxCpCryptUtil; | |||
| import javax.servlet.ServletException; | |||
| import javax.servlet.http.HttpServlet; | |||
| import javax.servlet.http.HttpServletRequest; | |||
| import javax.servlet.http.HttpServletResponse; | |||
| import javax.xml.bind.JAXBException; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.util.Map; | |||
| /** | |||
| * @author Daniel Qian | |||
| @@ -1,72 +0,0 @@ | |||
| <?xml version="1.0"?> | |||
| <project | |||
| xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" | |||
| xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> | |||
| <modelVersion>4.0.0</modelVersion> | |||
| <parent> | |||
| <groupId>me.chanjar</groupId> | |||
| <artifactId>weixin-java-parent</artifactId> | |||
| <version>1.0.5-SNAPSHOT</version> | |||
| </parent> | |||
| <artifactId>weixin-java-mp</artifactId> | |||
| <name>WeiXin Java Tools - MP</name> | |||
| <description>微信公众号Java SDK</description> | |||
| <dependencies> | |||
| <dependency> | |||
| <groupId>me.chanjar</groupId> | |||
| <artifactId>weixin-java-common</artifactId> | |||
| <version>${project.version}</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>junit</groupId> | |||
| <artifactId>junit</artifactId> | |||
| <scope>test</scope> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.testng</groupId> | |||
| <artifactId>testng</artifactId> | |||
| <version>6.8.7</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>com.google.inject</groupId> | |||
| <artifactId>guice</artifactId> | |||
| <version>3.0</version> | |||
| <scope>test</scope> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.eclipse.jetty</groupId> | |||
| <artifactId>jetty-server</artifactId> | |||
| <version>9.3.0.M0</version> | |||
| <scope>test</scope> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.eclipse.jetty</groupId> | |||
| <artifactId>jetty-servlet</artifactId> | |||
| <version>9.3.0.M0</version> | |||
| <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> | |||
| @@ -2,10 +2,10 @@ package me.chanjar.weixin.mp.api; | |||
| import me.chanjar.weixin.common.bean.WxMenu; | |||
| import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import me.chanjar.weixin.common.util.http.RequestExecutor; | |||
| import me.chanjar.weixin.mp.bean.*; | |||
| import me.chanjar.weixin.mp.bean.result.*; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import java.io.File; | |||
| import java.io.IOException; | |||
| @@ -1,32 +0,0 @@ | |||
| package me.chanjar.weixin.mp.bean; | |||
| import me.chanjar.weixin.common.api.WxConsts; | |||
| import me.chanjar.weixin.common.util.xml.MediaIdMarshaller; | |||
| import javax.xml.bind.annotation.XmlAccessType; | |||
| import javax.xml.bind.annotation.XmlAccessorType; | |||
| import javax.xml.bind.annotation.XmlElement; | |||
| import javax.xml.bind.annotation.XmlRootElement; | |||
| import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; | |||
| @XmlRootElement(name = "xml") | |||
| @XmlAccessorType(XmlAccessType.FIELD) | |||
| public class WxMpMpXmlOutImageMessage extends WxMpXmlOutMessage { | |||
| @XmlElement(name="Image") | |||
| @XmlJavaTypeAdapter(MediaIdMarshaller.class) | |||
| private String mediaId; | |||
| public WxMpMpXmlOutImageMessage() { | |||
| this.msgType = WxConsts.XML_MSG_IMAGE; | |||
| } | |||
| public String getMediaId() { | |||
| return mediaId; | |||
| } | |||
| public void setMediaId(String mediaId) { | |||
| this.mediaId = mediaId; | |||
| } | |||
| } | |||
| @@ -1,14 +1,13 @@ | |||
| package me.chanjar.weixin.mp.bean; | |||
| import me.chanjar.weixin.common.util.xml.AdapterCDATA; | |||
| import com.thoughtworks.xstream.annotations.XStreamAlias; | |||
| import com.thoughtworks.xstream.annotations.XStreamConverter; | |||
| import me.chanjar.weixin.common.util.xml.XStreamCDataConverter; | |||
| import me.chanjar.weixin.mp.api.WxMpConfigStorage; | |||
| import me.chanjar.weixin.mp.util.crypto.WxMpCryptUtil; | |||
| import me.chanjar.weixin.mp.util.xml.XmlTransformer; | |||
| import me.chanjar.weixin.mp.util.xml.XStreamTransformer; | |||
| import org.apache.commons.io.IOUtils; | |||
| import javax.xml.bind.JAXBException; | |||
| import javax.xml.bind.annotation.*; | |||
| import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.util.ArrayList; | |||
| @@ -25,100 +24,99 @@ import java.util.List; | |||
| * | |||
| * @author chanjarster | |||
| */ | |||
| @XmlRootElement(name = "xml") | |||
| @XmlAccessorType(XmlAccessType.FIELD) | |||
| @XStreamAlias("xml") | |||
| public class WxMpXmlMessage { | |||
| /////////////////////// | |||
| // 以下都是微信推送过来的消息的xml的element所对应的属性 | |||
| /////////////////////// | |||
| @XmlElement(name = "ToUserName") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("ToUserName") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String toUserName; | |||
| @XmlElement(name = "FromUserName") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("FromUserName") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String fromUserName; | |||
| @XmlElement(name = "CreateTime") | |||
| @XStreamAlias("CreateTime") | |||
| private Long createTime; | |||
| @XmlElement(name = "MsgType") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("MsgType") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String msgType; | |||
| @XmlElement(name = "Content") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Content") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String content; | |||
| @XmlElement(name = "MsgId") | |||
| @XStreamAlias("MsgId") | |||
| private Long msgId; | |||
| @XmlElement(name = "PicUrl") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("PicUrl") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String picUrl; | |||
| @XmlElement(name = "MediaId") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("MediaId") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String mediaId; | |||
| @XmlElement(name = "Format") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Format") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String format; | |||
| @XmlElement(name = "ThumbMediaId") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("ThumbMediaId") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String thumbMediaId; | |||
| @XmlElement(name = "Location_X") | |||
| @XStreamAlias("Location_X") | |||
| private Double locationX; | |||
| @XmlElement(name = "Location_Y") | |||
| @XStreamAlias("Location_Y") | |||
| private Double locationY; | |||
| @XmlElement(name = "Scale") | |||
| @XStreamAlias("Scale") | |||
| private Double scale; | |||
| @XmlElement(name = "Label") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Label") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String label; | |||
| @XmlElement(name = "Title") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Title") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String title; | |||
| @XmlElement(name = "Description") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Description") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String description; | |||
| @XmlElement(name = "Url") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Url") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String url; | |||
| @XmlElement(name = "Event") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Event") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String event; | |||
| @XmlElement(name = "EventKey") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("EventKey") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String eventKey; | |||
| @XmlElement(name = "Ticket") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Ticket") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String ticket; | |||
| @XmlElement(name = "Latitude") | |||
| @XStreamAlias("Latitude") | |||
| private Double latitude; | |||
| @XmlElement(name = "Longitude") | |||
| @XStreamAlias("Longitude") | |||
| private Double longitude; | |||
| @XmlElement(name = "Precision") | |||
| @XStreamAlias("Precision") | |||
| private Double precision; | |||
| @XmlElement(name = "Recognition") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Recognition") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String recognition; | |||
| /////////////////////////////////////// | |||
| @@ -127,37 +125,37 @@ public class WxMpXmlMessage { | |||
| /** | |||
| * 群发的结果 | |||
| */ | |||
| @XmlElement(name = "Status") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Status") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String status; | |||
| /** | |||
| * group_id下粉丝数;或者openid_list中的粉丝数 | |||
| */ | |||
| @XmlElement(name = "TotalCount") | |||
| @XStreamAlias("TotalCount") | |||
| private Integer totalCount; | |||
| /** | |||
| * 过滤(过滤是指特定地区、性别的过滤、用户设置拒收的过滤,用户接收已超4条的过滤)后,准备发送的粉丝数,原则上,filterCount = sentCount + errorCount | |||
| */ | |||
| @XmlElement(name = "FilterCount") | |||
| @XStreamAlias("FilterCount") | |||
| private Integer filterCount; | |||
| /** | |||
| * 发送成功的粉丝数 | |||
| */ | |||
| @XmlElement(name = "SentCount") | |||
| @XStreamAlias("SentCount") | |||
| private Integer sentCount; | |||
| /** | |||
| * 发送失败的粉丝数 | |||
| */ | |||
| @XmlElement(name = "ErrorCount") | |||
| @XStreamAlias("ErrorCount") | |||
| private Integer errorCount; | |||
| @XmlElement(name = "ScanCodeInfo") | |||
| @XStreamAlias("ScanCodeInfo") | |||
| private ScanCodeInfo scanCodeInfo = new ScanCodeInfo(); | |||
| @XmlElement(name = "SendPicsInfo") | |||
| @XStreamAlias("SendPicsInfo") | |||
| private SendPicsInfo sendPicsInfo = new SendPicsInfo(); | |||
| @XmlElement(name = "SendLocationInfo") | |||
| @XStreamAlias("SendLocationInfo") | |||
| private SendLocationInfo sendLocationInfo = new SendLocationInfo(); | |||
| public String getToUserName() { | |||
| @@ -380,21 +378,11 @@ public class WxMpXmlMessage { | |||
| } | |||
| public static WxMpXmlMessage fromXml(String xml) { | |||
| try { | |||
| // 操蛋的微信,模板消息推送成功的消息是MsgID,其他消息推送过来是MsgId | |||
| xml = xml.replaceAll("<MsgID>", "<MsgId>").replaceAll("</MsgID>", "</MsgId>"); | |||
| return XmlTransformer.fromXml(WxMpXmlMessage.class, xml); | |||
| } catch (JAXBException e) { | |||
| throw new RuntimeException(e); | |||
| } | |||
| return XStreamTransformer.fromXml(WxMpXmlMessage.class, xml); | |||
| } | |||
| public static WxMpXmlMessage fromXml(InputStream is) { | |||
| try { | |||
| return fromXml(IOUtils.toString(is, "UTF-8")); | |||
| } catch (IOException e) { | |||
| throw new RuntimeException(e); | |||
| } | |||
| return XStreamTransformer.fromXml(WxMpXmlMessage.class, is); | |||
| } | |||
| /** | |||
| @@ -491,16 +479,15 @@ public class WxMpXmlMessage { | |||
| this.sendLocationInfo = sendLocationInfo; | |||
| } | |||
| @XmlRootElement(name = "ScanCodeInfo") | |||
| @XmlAccessorType(XmlAccessType.FIELD) | |||
| @XStreamAlias("ScanCodeInfo") | |||
| public static class ScanCodeInfo { | |||
| @XmlElement(name = "ScanType") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("ScanType") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String scanType; | |||
| @XmlElement(name = "ScanResult") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("ScanResult") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String scanResult; | |||
| /** | |||
| @@ -530,15 +517,13 @@ public class WxMpXmlMessage { | |||
| } | |||
| @XmlRootElement(name = "SendPicsInfo") | |||
| @XmlAccessorType(XmlAccessType.FIELD) | |||
| @XStreamAlias("SendPicsInfo") | |||
| public static class SendPicsInfo { | |||
| @XmlElement(name = "Count") | |||
| @XStreamAlias("Count") | |||
| private Long count; | |||
| @XmlElementWrapper(name="PicList") | |||
| @XmlElement(name = "item") | |||
| @XStreamAlias("PicList") | |||
| protected final List<Item> picList = new ArrayList<Item>(); | |||
| public Long getCount() { | |||
| @@ -553,47 +538,44 @@ public class WxMpXmlMessage { | |||
| return picList; | |||
| } | |||
| @XmlRootElement(name = "item") | |||
| @XmlAccessorType(XmlAccessType.FIELD) | |||
| @XmlType(name = "WxXmlMessage.SendPicsInfo.Item") | |||
| @XStreamAlias("item") | |||
| public static class Item { | |||
| @XmlElement(name = "PicMd5Sum") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| private String PicMd5Sum; | |||
| @XStreamAlias("PicMd5Sum") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String picMd5Sum; | |||
| public String getPicMd5Sum() { | |||
| return PicMd5Sum; | |||
| return picMd5Sum; | |||
| } | |||
| public void setPicMd5Sum(String picMd5Sum) { | |||
| PicMd5Sum = picMd5Sum; | |||
| this.picMd5Sum = picMd5Sum; | |||
| } | |||
| } | |||
| } | |||
| @XmlRootElement(name = "SendLocationInfo") | |||
| @XmlAccessorType(XmlAccessType.FIELD) | |||
| @XStreamAlias("SendLocationInfo") | |||
| public static class SendLocationInfo { | |||
| @XmlElement(name = "Location_X") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Location_X") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String locationX; | |||
| @XmlElement(name = "Location_Y") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Location_Y") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String locationY; | |||
| @XmlElement(name = "Scale") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Scale") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String scale; | |||
| @XmlElement(name = "Label") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Label") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String label; | |||
| @XmlElement(name = "Poiname") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Poiname") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String poiname; | |||
| public String getLocationX() { | |||
| @@ -0,0 +1,27 @@ | |||
| package me.chanjar.weixin.mp.bean; | |||
| import com.thoughtworks.xstream.annotations.XStreamAlias; | |||
| import com.thoughtworks.xstream.annotations.XStreamConverter; | |||
| import me.chanjar.weixin.common.api.WxConsts; | |||
| import me.chanjar.weixin.common.util.xml.XStreamMediaIdConverter; | |||
| @XStreamAlias("xml") | |||
| public class WxMpXmlOutImageMessage extends WxMpXmlOutMessage { | |||
| @XStreamAlias("Image") | |||
| @XStreamConverter(value = XStreamMediaIdConverter.class) | |||
| private String mediaId; | |||
| public String getMediaId() { | |||
| return mediaId; | |||
| } | |||
| public void setMediaId(String mediaId) { | |||
| this.mediaId = mediaId; | |||
| } | |||
| public WxMpXmlOutImageMessage() { | |||
| this.msgType = WxConsts.XML_MSG_IMAGE; | |||
| } | |||
| } | |||
| @@ -1,35 +1,29 @@ | |||
| package me.chanjar.weixin.mp.bean; | |||
| import me.chanjar.weixin.common.util.xml.AdapterCDATA; | |||
| import com.thoughtworks.xstream.annotations.XStreamAlias; | |||
| import com.thoughtworks.xstream.annotations.XStreamConverter; | |||
| import me.chanjar.weixin.common.util.xml.XStreamCDataConverter; | |||
| import me.chanjar.weixin.mp.api.WxMpConfigStorage; | |||
| import me.chanjar.weixin.mp.bean.outxmlbuilder.*; | |||
| import me.chanjar.weixin.mp.util.crypto.WxMpCryptUtil; | |||
| import me.chanjar.weixin.mp.util.xml.XmlTransformer; | |||
| import me.chanjar.weixin.mp.util.xml.XStreamTransformer; | |||
| import javax.xml.bind.JAXBException; | |||
| import javax.xml.bind.annotation.XmlAccessType; | |||
| import javax.xml.bind.annotation.XmlAccessorType; | |||
| import javax.xml.bind.annotation.XmlElement; | |||
| import javax.xml.bind.annotation.XmlRootElement; | |||
| import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; | |||
| @XStreamAlias("xml") | |||
| public abstract class WxMpXmlOutMessage { | |||
| @XmlRootElement(name = "xml") | |||
| @XmlAccessorType(XmlAccessType.FIELD) | |||
| public class WxMpXmlOutMessage { | |||
| @XmlElement(name="ToUserName") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("ToUserName") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| protected String toUserName; | |||
| @XmlElement(name="FromUserName") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("FromUserName") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| protected String fromUserName; | |||
| @XmlElement(name="CreateTime") | |||
| @XStreamAlias("CreateTime") | |||
| protected Long createTime; | |||
| @XmlElement(name="MsgType") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("MsgType") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| protected String msgType; | |||
| public String getToUserName() { | |||
| @@ -65,11 +59,7 @@ public class WxMpXmlOutMessage { | |||
| } | |||
| public String toXml() { | |||
| try { | |||
| return XmlTransformer.toXml((Class)this.getClass(), this); | |||
| } catch (JAXBException e) { | |||
| throw new RuntimeException(e); | |||
| } | |||
| return XStreamTransformer.toXml((Class) this.getClass(), this); | |||
| } | |||
| /** | |||
| @@ -1,19 +1,14 @@ | |||
| package me.chanjar.weixin.mp.bean; | |||
| import com.thoughtworks.xstream.annotations.XStreamAlias; | |||
| import com.thoughtworks.xstream.annotations.XStreamConverter; | |||
| import me.chanjar.weixin.common.api.WxConsts; | |||
| import me.chanjar.weixin.common.util.xml.AdapterCDATA; | |||
| import me.chanjar.weixin.common.util.xml.XStreamCDataConverter; | |||
| import javax.xml.bind.annotation.XmlAccessType; | |||
| import javax.xml.bind.annotation.XmlAccessorType; | |||
| import javax.xml.bind.annotation.XmlElement; | |||
| import javax.xml.bind.annotation.XmlRootElement; | |||
| import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; | |||
| @XmlRootElement(name = "xml") | |||
| @XmlAccessorType(XmlAccessType.FIELD) | |||
| @XStreamAlias("xml") | |||
| public class WxMpXmlOutMusicMessage extends WxMpXmlOutMessage { | |||
| @XmlElement(name = "Music") | |||
| @XStreamAlias("Music") | |||
| protected final Music music = new Music(); | |||
| public WxMpXmlOutMusicMessage() { | |||
| @@ -60,28 +55,27 @@ public class WxMpXmlOutMusicMessage extends WxMpXmlOutMessage { | |||
| music.setHqMusicUrl(hqMusicUrl); | |||
| } | |||
| @XmlRootElement(name = "Music") | |||
| @XmlAccessorType(XmlAccessType.FIELD) | |||
| private static class Music { | |||
| @XStreamAlias("Music") | |||
| public static class Music { | |||
| @XmlElement(name = "Title") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Title") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String title; | |||
| @XmlElement(name = "Description") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Description") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String description; | |||
| @XmlElement(name="ThumbMediaId") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("ThumbMediaId") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String thumbMediaId; | |||
| @XmlElement(name="MusicUrl") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("MusicUrl") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String musicUrl; | |||
| @XmlElement(name="HQMusicUrl") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("HQMusicUrl") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String hqMusicUrl; | |||
| public String getTitle() { | |||
| @@ -1,22 +1,20 @@ | |||
| package me.chanjar.weixin.mp.bean; | |||
| import com.thoughtworks.xstream.annotations.XStreamAlias; | |||
| import com.thoughtworks.xstream.annotations.XStreamConverter; | |||
| import me.chanjar.weixin.common.api.WxConsts; | |||
| import me.chanjar.weixin.common.util.xml.AdapterCDATA; | |||
| import me.chanjar.weixin.common.util.xml.XStreamCDataConverter; | |||
| import javax.xml.bind.annotation.*; | |||
| import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| @XmlRootElement(name = "xml") | |||
| @XmlAccessorType(XmlAccessType.FIELD) | |||
| @XStreamAlias("xml") | |||
| public class WxMpXmlOutNewsMessage extends WxMpXmlOutMessage { | |||
| @XmlElement(name = "ArticleCount") | |||
| @XStreamAlias("ArticleCount") | |||
| protected int articleCount; | |||
| @XmlElementWrapper(name="Articles") | |||
| @XmlElement(name = "item") | |||
| @XStreamAlias("Articles") | |||
| protected final List<Item> articles = new ArrayList<Item>(); | |||
| public WxMpXmlOutNewsMessage() { | |||
| @@ -37,24 +35,23 @@ public class WxMpXmlOutNewsMessage extends WxMpXmlOutMessage { | |||
| } | |||
| @XmlRootElement(name = "Item") | |||
| @XmlAccessorType(XmlAccessType.FIELD) | |||
| @XStreamAlias("item") | |||
| public static class Item { | |||
| @XmlElement(name = "Title") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Title") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String Title; | |||
| @XmlElement(name = "Description") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Description") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String Description; | |||
| @XmlElement(name="PicUrl") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("PicUrl") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String PicUrl; | |||
| @XmlElement(name="Url") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Url") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String Url; | |||
| public String getTitle() { | |||
| @@ -1,20 +1,15 @@ | |||
| package me.chanjar.weixin.mp.bean; | |||
| import com.thoughtworks.xstream.annotations.XStreamAlias; | |||
| import com.thoughtworks.xstream.annotations.XStreamConverter; | |||
| import me.chanjar.weixin.common.api.WxConsts; | |||
| import me.chanjar.weixin.common.util.xml.AdapterCDATA; | |||
| import me.chanjar.weixin.common.util.xml.XStreamCDataConverter; | |||
| import javax.xml.bind.annotation.XmlAccessType; | |||
| import javax.xml.bind.annotation.XmlAccessorType; | |||
| import javax.xml.bind.annotation.XmlElement; | |||
| import javax.xml.bind.annotation.XmlRootElement; | |||
| import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; | |||
| @XmlRootElement(name = "xml") | |||
| @XmlAccessorType(XmlAccessType.FIELD) | |||
| @XStreamAlias("xml") | |||
| public class WxMpXmlOutTextMessage extends WxMpXmlOutMessage { | |||
| @XmlElement(name="Content") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Content") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String content; | |||
| public WxMpXmlOutTextMessage() { | |||
| @@ -1,19 +1,14 @@ | |||
| package me.chanjar.weixin.mp.bean; | |||
| import com.thoughtworks.xstream.annotations.XStreamAlias; | |||
| import com.thoughtworks.xstream.annotations.XStreamConverter; | |||
| import me.chanjar.weixin.common.api.WxConsts; | |||
| import me.chanjar.weixin.common.util.xml.AdapterCDATA; | |||
| import me.chanjar.weixin.common.util.xml.XStreamCDataConverter; | |||
| import javax.xml.bind.annotation.XmlAccessType; | |||
| import javax.xml.bind.annotation.XmlAccessorType; | |||
| import javax.xml.bind.annotation.XmlElement; | |||
| import javax.xml.bind.annotation.XmlRootElement; | |||
| import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; | |||
| @XmlRootElement(name = "xml") | |||
| @XmlAccessorType(XmlAccessType.FIELD) | |||
| @XStreamAlias("xml") | |||
| public class WxMpXmlOutVideoMessage extends WxMpXmlOutMessage { | |||
| @XmlElement(name = "Video") | |||
| @XStreamAlias("Video") | |||
| protected final Video video = new Video(); | |||
| public WxMpXmlOutVideoMessage() { | |||
| @@ -45,20 +40,19 @@ public class WxMpXmlOutVideoMessage extends WxMpXmlOutMessage { | |||
| } | |||
| @XmlRootElement(name = "Video") | |||
| @XmlAccessorType(XmlAccessType.FIELD) | |||
| private static class Video { | |||
| @XStreamAlias("Video") | |||
| public static class Video { | |||
| @XmlElement(name = "MediaId") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("MediaId") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String mediaId; | |||
| @XmlElement(name = "Title") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Title") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String title; | |||
| @XmlElement(name = "Description") | |||
| @XmlJavaTypeAdapter(AdapterCDATA.class) | |||
| @XStreamAlias("Description") | |||
| @XStreamConverter(value=XStreamCDataConverter.class) | |||
| private String description; | |||
| public String getMediaId() { | |||
| @@ -1,26 +1,21 @@ | |||
| package me.chanjar.weixin.mp.bean; | |||
| import com.thoughtworks.xstream.annotations.XStreamAlias; | |||
| import com.thoughtworks.xstream.annotations.XStreamConverter; | |||
| import me.chanjar.weixin.common.api.WxConsts; | |||
| import me.chanjar.weixin.common.util.xml.MediaIdMarshaller; | |||
| import me.chanjar.weixin.common.util.xml.XStreamMediaIdConverter; | |||
| import javax.xml.bind.annotation.XmlAccessType; | |||
| import javax.xml.bind.annotation.XmlAccessorType; | |||
| import javax.xml.bind.annotation.XmlElement; | |||
| import javax.xml.bind.annotation.XmlRootElement; | |||
| import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; | |||
| @XmlRootElement(name = "xml") | |||
| @XmlAccessorType(XmlAccessType.FIELD) | |||
| @XStreamAlias("xml") | |||
| public class WxMpXmlOutVoiceMessage extends WxMpXmlOutMessage { | |||
| @XmlElement(name="Voice") | |||
| @XmlJavaTypeAdapter(MediaIdMarshaller.class) | |||
| @XStreamAlias("Voice") | |||
| @XStreamConverter(value = XStreamMediaIdConverter.class) | |||
| private String mediaId; | |||
| public WxMpXmlOutVoiceMessage() { | |||
| this.msgType = WxConsts.XML_MSG_VOICE; | |||
| } | |||
| public String getMediaId() { | |||
| return mediaId; | |||
| } | |||
| @@ -28,5 +23,5 @@ public class WxMpXmlOutVoiceMessage extends WxMpXmlOutMessage { | |||
| public void setMediaId(String mediaId) { | |||
| this.mediaId = mediaId; | |||
| } | |||
| } | |||
| @@ -1,12 +1,12 @@ | |||
| package me.chanjar.weixin.mp.bean.outxmlbuilder; | |||
| import me.chanjar.weixin.mp.bean.WxMpMpXmlOutImageMessage; | |||
| import me.chanjar.weixin.mp.bean.WxMpXmlOutImageMessage; | |||
| /** | |||
| * 图片消息builder | |||
| * @author chanjarster | |||
| */ | |||
| public final class ImageBuilder extends BaseBuilder<ImageBuilder, WxMpMpXmlOutImageMessage> { | |||
| public final class ImageBuilder extends BaseBuilder<ImageBuilder, WxMpXmlOutImageMessage> { | |||
| private String mediaId; | |||
| @@ -15,8 +15,8 @@ public final class ImageBuilder extends BaseBuilder<ImageBuilder, WxMpMpXmlOutIm | |||
| return this; | |||
| } | |||
| public WxMpMpXmlOutImageMessage build() { | |||
| WxMpMpXmlOutImageMessage m = new WxMpMpXmlOutImageMessage(); | |||
| public WxMpXmlOutImageMessage build() { | |||
| WxMpXmlOutImageMessage m = new WxMpXmlOutImageMessage(); | |||
| setCommon(m); | |||
| m.setMediaId(this.mediaId); | |||
| return m; | |||
| @@ -1,6 +1,5 @@ | |||
| package me.chanjar.weixin.mp.bean.result; | |||
| import me.chanjar.weixin.common.util.json.WxGsonBuilder; | |||
| import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; | |||
| /** | |||
| @@ -1,12 +1,12 @@ | |||
| package me.chanjar.weixin.mp.util.http; | |||
| import me.chanjar.weixin.common.bean.result.WxError; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import me.chanjar.weixin.common.util.fs.FileUtils; | |||
| import me.chanjar.weixin.common.util.http.InputStreamResponseHandler; | |||
| import me.chanjar.weixin.common.util.http.RequestExecutor; | |||
| import me.chanjar.weixin.common.util.http.Utf8ResponseHandler; | |||
| import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import org.apache.http.Header; | |||
| import org.apache.http.HttpHost; | |||
| import org.apache.http.client.ClientProtocolException; | |||
| @@ -4,7 +4,6 @@ import com.google.gson.Gson; | |||
| import com.google.gson.GsonBuilder; | |||
| import me.chanjar.weixin.mp.bean.*; | |||
| import me.chanjar.weixin.mp.bean.result.*; | |||
| import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken; | |||
| public class WxMpGsonBuilder { | |||
| @@ -1,7 +1,6 @@ | |||
| package me.chanjar.weixin.mp.util.json; | |||
| import com.google.gson.*; | |||
| import me.chanjar.weixin.common.bean.WxAccessToken; | |||
| import me.chanjar.weixin.common.util.json.GsonHelper; | |||
| import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken; | |||
| @@ -10,8 +10,6 @@ package me.chanjar.weixin.mp.util.json; | |||
| import com.google.gson.*; | |||
| import me.chanjar.weixin.common.util.json.GsonHelper; | |||
| import me.chanjar.weixin.mp.bean.result.WxMpMassSendResult; | |||
| import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; | |||
| import me.chanjar.weixin.mp.bean.result.WxMpSemanticQueryResult; | |||
| import java.lang.reflect.Type; | |||
| @@ -8,9 +8,10 @@ | |||
| */ | |||
| package me.chanjar.weixin.mp.util.json; | |||
| import com.google.gson.*; | |||
| import me.chanjar.weixin.common.api.WxConsts; | |||
| import me.chanjar.weixin.mp.bean.WxMpCustomMessage; | |||
| import com.google.gson.JsonElement; | |||
| import com.google.gson.JsonObject; | |||
| import com.google.gson.JsonSerializationContext; | |||
| import com.google.gson.JsonSerializer; | |||
| import me.chanjar.weixin.mp.bean.WxMpTemplateData; | |||
| import me.chanjar.weixin.mp.bean.WxMpTemplateMessage; | |||
| @@ -0,0 +1,117 @@ | |||
| package me.chanjar.weixin.mp.util.xml; | |||
| import com.thoughtworks.xstream.XStream; | |||
| import me.chanjar.weixin.common.util.xml.XStreamInitializer; | |||
| import me.chanjar.weixin.mp.bean.*; | |||
| import java.io.InputStream; | |||
| import java.util.HashMap; | |||
| import java.util.Map; | |||
| /** | |||
| * Created by qianjia on 15/1/19. | |||
| */ | |||
| public class XStreamTransformer { | |||
| protected static final Map<Class, XStream> CLASS_2_XSTREAM_INSTANCE = configXStreamInstance(); | |||
| /** | |||
| * xml -> pojo | |||
| * | |||
| * @param clazz | |||
| * @param xml | |||
| * @return | |||
| */ | |||
| @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 | |||
| * | |||
| * @param clazz | |||
| * @param object | |||
| * @return | |||
| */ | |||
| public static <T> String toXml(Class<T> clazz, T object) { | |||
| return CLASS_2_XSTREAM_INSTANCE.get(clazz).toXML(object); | |||
| } | |||
| private static Map<Class, XStream> configXStreamInstance() { | |||
| Map<Class, XStream> map = new HashMap<Class, XStream>(); | |||
| map.put(WxMpXmlMessage.class, config_WxMpXmlMessage()); | |||
| map.put(WxMpXmlOutMusicMessage.class, config_WxMpXmlOutMusicMessage()); | |||
| map.put(WxMpXmlOutNewsMessage.class, config_WxMpXmlOutNewsMessage()); | |||
| map.put(WxMpXmlOutTextMessage.class, config_WxMpXmlOutTextMessage()); | |||
| map.put(WxMpXmlOutImageMessage.class, config_WxMpXmlOutImageMessage()); | |||
| map.put(WxMpXmlOutVideoMessage.class, config_WxMpXmlOutVideoMessage()); | |||
| map.put(WxMpXmlOutVoiceMessage.class, config_WxMpXmlOutVoiceMessage()); | |||
| return map; | |||
| } | |||
| private static XStream config_WxMpXmlMessage() { | |||
| XStream xstream = XStreamInitializer.getInstance(); | |||
| xstream.processAnnotations(WxMpXmlMessage.class); | |||
| xstream.processAnnotations(WxMpXmlMessage.ScanCodeInfo.class); | |||
| xstream.processAnnotations(WxMpXmlMessage.SendPicsInfo.class); | |||
| xstream.processAnnotations(WxMpXmlMessage.SendPicsInfo.Item.class); | |||
| xstream.processAnnotations(WxMpXmlMessage.SendLocationInfo.class); | |||
| xstream.aliasField("MsgID", WxMpXmlMessage.class, "msgId"); | |||
| return xstream; | |||
| } | |||
| private static XStream config_WxMpXmlOutImageMessage() { | |||
| XStream xstream = XStreamInitializer.getInstance(); | |||
| xstream.processAnnotations(WxMpXmlOutMessage.class); | |||
| xstream.processAnnotations(WxMpXmlOutImageMessage.class); | |||
| return xstream; | |||
| } | |||
| private static XStream config_WxMpXmlOutNewsMessage() { | |||
| XStream xstream = XStreamInitializer.getInstance(); | |||
| xstream.processAnnotations(WxMpXmlOutMessage.class); | |||
| xstream.processAnnotations(WxMpXmlOutNewsMessage.class); | |||
| xstream.processAnnotations(WxMpXmlOutNewsMessage.Item.class); | |||
| return xstream; | |||
| } | |||
| private static XStream config_WxMpXmlOutMusicMessage() { | |||
| XStream xstream = XStreamInitializer.getInstance(); | |||
| xstream.processAnnotations(WxMpXmlOutMessage.class); | |||
| xstream.processAnnotations(WxMpXmlOutMusicMessage.class); | |||
| xstream.processAnnotations(WxMpXmlOutMusicMessage.Music.class); | |||
| return xstream; | |||
| } | |||
| private static XStream config_WxMpXmlOutTextMessage() { | |||
| XStream xstream = XStreamInitializer.getInstance(); | |||
| xstream.processAnnotations(WxMpXmlOutMessage.class); | |||
| xstream.processAnnotations(WxMpXmlOutTextMessage.class); | |||
| return xstream; | |||
| } | |||
| private static XStream config_WxMpXmlOutVideoMessage() { | |||
| XStream xstream = XStreamInitializer.getInstance(); | |||
| xstream.processAnnotations(WxMpXmlOutMessage.class); | |||
| xstream.processAnnotations(WxMpXmlOutVideoMessage.class); | |||
| xstream.processAnnotations(WxMpXmlOutVideoMessage.Video.class); | |||
| return xstream; | |||
| } | |||
| private static XStream config_WxMpXmlOutVoiceMessage() { | |||
| XStream xstream = XStreamInitializer.getInstance(); | |||
| xstream.processAnnotations(WxMpXmlOutMessage.class); | |||
| xstream.processAnnotations(WxMpXmlOutVoiceMessage.class); | |||
| return xstream; | |||
| } | |||
| } | |||
| @@ -1,91 +0,0 @@ | |||
| package me.chanjar.weixin.mp.util.xml; | |||
| import com.sun.xml.bind.marshaller.CharacterEscapeHandler; | |||
| import me.chanjar.weixin.mp.bean.*; | |||
| import org.xml.sax.InputSource; | |||
| import javax.xml.bind.JAXBContext; | |||
| import javax.xml.bind.JAXBException; | |||
| import javax.xml.bind.Marshaller; | |||
| import javax.xml.bind.Unmarshaller; | |||
| import java.io.*; | |||
| public class XmlTransformer { | |||
| protected static final JAXBContext JAXB_CONTEXT = initJAXBContext(); | |||
| /** | |||
| * xml -> pojo | |||
| * | |||
| * @param clazz | |||
| * @param xml | |||
| * @return | |||
| * @throws JAXBException | |||
| */ | |||
| @SuppressWarnings("unchecked") | |||
| public static <T> T fromXml(Class<T> clazz, String xml) throws JAXBException { | |||
| Unmarshaller um = JAXB_CONTEXT.createUnmarshaller(); | |||
| T object = (T) um.unmarshal(new StringReader(xml)); | |||
| return object; | |||
| } | |||
| @SuppressWarnings("unchecked") | |||
| public static <T> T fromXml(Class<T> clazz, InputStream is) throws JAXBException { | |||
| Unmarshaller um = JAXB_CONTEXT.createUnmarshaller(); | |||
| InputSource inputSource = new InputSource(is); | |||
| inputSource.setEncoding("utf-8"); | |||
| T object = (T) um.unmarshal(inputSource); | |||
| return object; | |||
| } | |||
| /** | |||
| * pojo -> xml | |||
| * | |||
| * @param clazz | |||
| * @param object | |||
| * @return | |||
| * @throws JAXBException | |||
| */ | |||
| public static <T> String toXml(Class<T> clazz, T object) throws JAXBException { | |||
| StringWriter stringWriter = new StringWriter(); | |||
| toXml(clazz, object, stringWriter); | |||
| return stringWriter.getBuffer().toString(); | |||
| } | |||
| public static <T> void toXml(Class<T> clazz, T object, Writer writer) throws JAXBException { | |||
| Marshaller m = JAXB_CONTEXT.createMarshaller(); | |||
| m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); | |||
| m.setProperty(CharacterEscapeHandler.class.getName(), CHAR_ESCAPE_HANDLER); | |||
| m.setProperty(Marshaller.JAXB_FRAGMENT, true); | |||
| m.marshal(object, writer); | |||
| } | |||
| protected static final CharacterEscapeHandler CHAR_ESCAPE_HANDLER = new CharacterUnescapeHandler(); | |||
| protected static class CharacterUnescapeHandler implements CharacterEscapeHandler { | |||
| public void escape(char[] ac, int i, int j, boolean flag, Writer writer) throws IOException { | |||
| writer.write(ac, i, j); | |||
| } | |||
| } | |||
| private static JAXBContext initJAXBContext() { | |||
| /* | |||
| * JAXBContext对象是线程安全的,根据官方文档的建议将对象作为全局实例 | |||
| * https://jaxb.java.net/guide/Performance_and_thread_safety.html | |||
| */ | |||
| try { | |||
| return JAXBContext.newInstance( | |||
| WxMpXmlOutMessage.class, | |||
| WxMpMpXmlOutImageMessage.class, | |||
| WxMpXmlOutNewsMessage.class, | |||
| WxMpXmlOutMusicMessage.class, | |||
| WxMpXmlOutTextMessage.class, | |||
| WxMpXmlOutVideoMessage.class, | |||
| WxMpXmlOutVoiceMessage.class, | |||
| WxMpXmlMessage.class); | |||
| } catch (JAXBException e) { | |||
| throw new RuntimeException(e); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,46 +1,35 @@ | |||
| package me.chanjar.weixin.mp.api; | |||
| import java.io.InputStream; | |||
| import javax.xml.bind.JAXBContext; | |||
| import javax.xml.bind.JAXBException; | |||
| import javax.xml.bind.Unmarshaller; | |||
| import javax.xml.bind.annotation.XmlAccessType; | |||
| import javax.xml.bind.annotation.XmlAccessorType; | |||
| import javax.xml.bind.annotation.XmlRootElement; | |||
| import com.google.inject.Binder; | |||
| import com.google.inject.Module; | |||
| import org.xml.sax.InputSource; | |||
| import com.thoughtworks.xstream.XStream; | |||
| import com.thoughtworks.xstream.annotations.XStreamAlias; | |||
| import me.chanjar.weixin.common.util.xml.XStreamInitializer; | |||
| import java.io.InputStream; | |||
| public class ApiTestModule implements Module { | |||
| @Override | |||
| public void configure(Binder binder) { | |||
| try { | |||
| InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml"); | |||
| WxXmlMpInMemoryConfigStorage config = fromXml(WxXmlMpInMemoryConfigStorage.class, is1); | |||
| WxMpServiceImpl wxService = new WxMpServiceImpl(); | |||
| wxService.setWxMpConfigStorage(config); | |||
| binder.bind(WxMpServiceImpl.class).toInstance(wxService); | |||
| binder.bind(WxMpConfigStorage.class).toInstance(config); | |||
| } catch (JAXBException e) { | |||
| throw new RuntimeException(e); | |||
| } | |||
| InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml"); | |||
| WxXmlMpInMemoryConfigStorage config = fromXml(WxXmlMpInMemoryConfigStorage.class, is1); | |||
| WxMpServiceImpl wxService = new WxMpServiceImpl(); | |||
| wxService.setWxMpConfigStorage(config); | |||
| binder.bind(WxMpServiceImpl.class).toInstance(wxService); | |||
| binder.bind(WxMpConfigStorage.class).toInstance(config); | |||
| } | |||
| public static <T> T fromXml(Class<T> clazz, InputStream is) throws JAXBException { | |||
| Unmarshaller um = JAXBContext.newInstance(clazz).createUnmarshaller(); | |||
| InputSource inputSource = new InputSource(is); | |||
| inputSource.setEncoding("utf-8"); | |||
| T object = (T) um.unmarshal(inputSource); | |||
| return object; | |||
| public static <T> T fromXml(Class<T> clazz, InputStream is) { | |||
| XStream xstream = XStreamInitializer.getInstance(); | |||
| xstream.alias("xml", clazz); | |||
| xstream.processAnnotations(clazz); | |||
| return (T) xstream.fromXML(is); | |||
| } | |||
| @XmlRootElement(name = "xml") | |||
| @XmlAccessorType(XmlAccessType.FIELD) | |||
| public static class WxXmlMpInMemoryConfigStorage extends WxMpInMemoryConfigStorage { | |||
| @XStreamAlias("xml") | |||
| public static class WxXmlMpInMemoryConfigStorage extends WxMpInMemoryConfigStorage { | |||
| protected String openId; | |||
| @@ -1,14 +1,12 @@ | |||
| package me.chanjar.weixin.mp.api; | |||
| import com.google.inject.Inject; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import me.chanjar.weixin.common.util.StringUtils; | |||
| import org.testng.Assert; | |||
| import org.testng.annotations.Guice; | |||
| import org.testng.annotations.Test; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import com.google.inject.Inject; | |||
| /** | |||
| * 基础API测试 | |||
| * @author chanjarster | |||
| @@ -16,7 +14,7 @@ import com.google.inject.Inject; | |||
| */ | |||
| @Test(groups = "baseAPI") | |||
| @Guice(modules = ApiTestModule.class) | |||
| public class WxBaseAPITest { | |||
| public class WxMpBaseAPITest { | |||
| @Inject | |||
| protected WxMpServiceImpl wxService; | |||
| @@ -1,14 +1,12 @@ | |||
| package me.chanjar.weixin.mp.api; | |||
| import com.google.inject.Inject; | |||
| import me.chanjar.weixin.common.api.WxConsts; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import me.chanjar.weixin.mp.bean.WxMpCustomMessage; | |||
| import org.testng.annotations.Guice; | |||
| import org.testng.annotations.Test; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import com.google.inject.Inject; | |||
| /*** | |||
| * 测试发送客服消息 | |||
| * @author chanjarster | |||
| @@ -1,15 +1,13 @@ | |||
| package me.chanjar.weixin.mp.api; | |||
| import java.util.List; | |||
| import com.google.inject.Inject; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import me.chanjar.weixin.mp.bean.WxMpGroup; | |||
| import org.testng.Assert; | |||
| import org.testng.annotations.Guice; | |||
| import org.testng.annotations.Test; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import com.google.inject.Inject; | |||
| import java.util.List; | |||
| /** | |||
| * 测试分组接口 | |||
| @@ -1,10 +1,9 @@ | |||
| package me.chanjar.weixin.mp.api; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import com.google.inject.Inject; | |||
| import me.chanjar.weixin.common.api.WxConsts; | |||
| import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import me.chanjar.weixin.mp.bean.WxMpMassGroupMessage; | |||
| import me.chanjar.weixin.mp.bean.WxMpMassNews; | |||
| import me.chanjar.weixin.mp.bean.WxMpMassOpenIdsMessage; | |||
| @@ -16,9 +15,8 @@ import org.testng.annotations.DataProvider; | |||
| import org.testng.annotations.Guice; | |||
| import org.testng.annotations.Test; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import com.google.inject.Inject; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| /** | |||
| * 测试群发消息 | |||
| @@ -1,20 +1,18 @@ | |||
| package me.chanjar.weixin.mp.api; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| import com.google.inject.Inject; | |||
| import me.chanjar.weixin.common.api.WxConsts; | |||
| import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import org.testng.Assert; | |||
| import org.testng.annotations.DataProvider; | |||
| import org.testng.annotations.Guice; | |||
| import org.testng.annotations.Test; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import com.google.inject.Inject; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| /** | |||
| * 测试多媒体文件上传下载 | |||
| @@ -1,19 +1,15 @@ | |||
| package me.chanjar.weixin.mp.api; | |||
| import javax.xml.bind.JAXBException; | |||
| import com.google.inject.Inject; | |||
| import me.chanjar.weixin.common.api.WxConsts; | |||
| import me.chanjar.weixin.common.bean.WxMenu; | |||
| import me.chanjar.weixin.common.bean.WxMenu.WxMenuButton; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import org.testng.Assert; | |||
| import org.testng.annotations.DataProvider; | |||
| import org.testng.annotations.Guice; | |||
| import org.testng.annotations.Test; | |||
| import com.google.inject.Inject; | |||
| import me.chanjar.weixin.common.bean.WxMenu; | |||
| import me.chanjar.weixin.common.bean.WxMenu.WxMenuButton; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| /** | |||
| * 测试菜单 | |||
| * @author chanjarster | |||
| @@ -42,7 +38,7 @@ public class WxMpMenuAPITest { | |||
| } | |||
| @DataProvider(name="menu") | |||
| public Object[][] getMenu() throws JAXBException { | |||
| public Object[][] getMenu() { | |||
| WxMenu menu = new WxMenu(); | |||
| WxMenuButton button1 = new WxMenuButton(); | |||
| button1.setType(WxConsts.BUTTON_CLICK); | |||
| @@ -1,7 +1,5 @@ | |||
| package me.chanjar.weixin.mp.api; | |||
| import java.util.Map; | |||
| import me.chanjar.weixin.common.api.WxConsts; | |||
| import me.chanjar.weixin.mp.bean.WxMpXmlMessage; | |||
| import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage; | |||
| @@ -9,6 +7,8 @@ import org.testng.Assert; | |||
| import org.testng.annotations.DataProvider; | |||
| import org.testng.annotations.Test; | |||
| import java.util.Map; | |||
| /** | |||
| * 测试消息路由器 | |||
| * @author chanjarster | |||
| @@ -1,15 +1,13 @@ | |||
| package me.chanjar.weixin.mp.api; | |||
| import java.io.File; | |||
| import com.google.inject.Inject; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; | |||
| import org.testng.Assert; | |||
| import org.testng.annotations.Guice; | |||
| import org.testng.annotations.Test; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import com.google.inject.Inject; | |||
| import java.io.File; | |||
| /** | |||
| * 测试用户相关的接口 | |||
| @@ -1,13 +1,11 @@ | |||
| package me.chanjar.weixin.mp.api; | |||
| import com.google.inject.Inject; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import org.testng.Assert; | |||
| import org.testng.annotations.Guice; | |||
| import org.testng.annotations.Test; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import com.google.inject.Inject; | |||
| /** | |||
| * 测试短连接 | |||
| * | |||
| @@ -1,15 +1,13 @@ | |||
| package me.chanjar.weixin.mp.api; | |||
| import com.google.inject.Inject; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import me.chanjar.weixin.mp.bean.result.WxMpUser; | |||
| import me.chanjar.weixin.mp.bean.result.WxMpUserList; | |||
| import org.testng.Assert; | |||
| import org.testng.annotations.Guice; | |||
| import org.testng.annotations.Test; | |||
| import me.chanjar.weixin.mp.bean.result.WxMpUser; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import com.google.inject.Inject; | |||
| /** | |||
| * 测试用户相关的接口 | |||
| * @author chanjarster | |||
| @@ -1,11 +1,10 @@ | |||
| package me.chanjar.weixin.mp.bean; | |||
| import me.chanjar.weixin.common.api.WxConsts; | |||
| import me.chanjar.weixin.mp.bean.WxMpCustomMessage.WxArticle; | |||
| import org.testng.Assert; | |||
| import org.testng.annotations.Test; | |||
| import me.chanjar.weixin.mp.bean.WxMpCustomMessage.WxArticle; | |||
| @Test | |||
| public class WxMpCustomMessageTest { | |||
| @@ -7,7 +7,7 @@ import org.testng.annotations.Test; | |||
| public class WxMpXmlOutImageMessageTest { | |||
| public void test() { | |||
| WxMpMpXmlOutImageMessage m = new WxMpMpXmlOutImageMessage(); | |||
| WxMpXmlOutImageMessage m = new WxMpXmlOutImageMessage(); | |||
| m.setMediaId("ddfefesfsdfef"); | |||
| m.setCreateTime(1122l); | |||
| m.setFromUserName("from"); | |||
| @@ -25,7 +25,7 @@ public class WxMpXmlOutImageMessageTest { | |||
| } | |||
| public void testBuild() { | |||
| WxMpMpXmlOutImageMessage m = WxMpXmlOutMessage.IMAGE().mediaId("ddfefesfsdfef").fromUser("from").toUser("to").build(); | |||
| WxMpXmlOutImageMessage m = WxMpXmlOutMessage.IMAGE().mediaId("ddfefesfsdfef").fromUser("from").toUser("to").build(); | |||
| String expected = "<xml>" | |||
| + "<ToUserName><![CDATA[to]]></ToUserName>" | |||
| + "<FromUserName><![CDATA[from]]></FromUserName>" | |||
| @@ -1,21 +1,16 @@ | |||
| package me.chanjar.weixin.mp.demo; | |||
| import com.thoughtworks.xstream.XStream; | |||
| import com.thoughtworks.xstream.annotations.XStreamAlias; | |||
| import me.chanjar.weixin.common.util.xml.XStreamInitializer; | |||
| import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage; | |||
| import org.xml.sax.InputSource; | |||
| import javax.xml.bind.JAXBContext; | |||
| import javax.xml.bind.JAXBException; | |||
| import javax.xml.bind.Unmarshaller; | |||
| import javax.xml.bind.annotation.XmlAccessType; | |||
| import javax.xml.bind.annotation.XmlAccessorType; | |||
| import javax.xml.bind.annotation.XmlRootElement; | |||
| import java.io.InputStream; | |||
| /** | |||
| * @author Daniel Qian | |||
| */ | |||
| @XmlRootElement(name = "xml") | |||
| @XmlAccessorType(XmlAccessType.FIELD) | |||
| @XStreamAlias("xml") | |||
| class WxMpDemoInMemoryConfigStorage extends WxMpInMemoryConfigStorage { | |||
| @Override | |||
| @@ -25,11 +20,10 @@ class WxMpDemoInMemoryConfigStorage extends WxMpInMemoryConfigStorage { | |||
| } | |||
| public static WxMpDemoInMemoryConfigStorage fromXml(InputStream is) throws JAXBException { | |||
| Unmarshaller um = JAXBContext.newInstance(WxMpDemoInMemoryConfigStorage.class).createUnmarshaller(); | |||
| InputSource inputSource = new InputSource(is); | |||
| inputSource.setEncoding("utf-8"); | |||
| return (WxMpDemoInMemoryConfigStorage) um.unmarshal(inputSource); | |||
| public static WxMpDemoInMemoryConfigStorage fromXml(InputStream is) { | |||
| XStream xstream = XStreamInitializer.getInstance(); | |||
| xstream.processAnnotations(WxMpDemoInMemoryConfigStorage.class); | |||
| return (WxMpDemoInMemoryConfigStorage) xstream.fromXML(is); | |||
| } | |||
| } | |||
| @@ -4,14 +4,14 @@ import me.chanjar.weixin.common.api.WxConsts; | |||
| import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import me.chanjar.weixin.mp.api.*; | |||
| import me.chanjar.weixin.mp.bean.WxMpMpXmlOutImageMessage; | |||
| import me.chanjar.weixin.mp.bean.WxMpXmlMessage; | |||
| import me.chanjar.weixin.mp.bean.WxMpXmlOutImageMessage; | |||
| import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage; | |||
| import me.chanjar.weixin.mp.bean.WxMpXmlOutTextMessage; | |||
| import org.eclipse.jetty.server.Server; | |||
| import org.eclipse.jetty.servlet.*; | |||
| import org.eclipse.jetty.servlet.ServletHandler; | |||
| import org.eclipse.jetty.servlet.ServletHolder; | |||
| import javax.xml.bind.JAXBException; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.util.Map; | |||
| @@ -41,7 +41,6 @@ public class WxMpDemoServer { | |||
| } | |||
| private static void initWeixin() { | |||
| try { | |||
| InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml"); | |||
| WxMpDemoInMemoryConfigStorage config = WxMpDemoInMemoryConfigStorage.fromXml(is1); | |||
| @@ -67,7 +66,7 @@ public class WxMpDemoServer { | |||
| try { | |||
| WxMediaUploadResult wxMediaUploadResult = wxMpService | |||
| .mediaUpload(WxConsts.MEDIA_IMAGE, WxConsts.FILE_JPG, ClassLoader.getSystemResourceAsStream("mm.jpeg")); | |||
| WxMpMpXmlOutImageMessage m | |||
| WxMpXmlOutImageMessage m | |||
| = WxMpXmlOutMessage | |||
| .IMAGE() | |||
| .mediaId(wxMediaUploadResult.getMediaId()) | |||
| @@ -117,8 +116,5 @@ public class WxMpDemoServer { | |||
| .end() | |||
| ; | |||
| } catch (JAXBException e) { | |||
| throw new RuntimeException(e); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,23 +1,17 @@ | |||
| package me.chanjar.weixin.mp.demo; | |||
| import me.chanjar.weixin.common.api.WxConsts; | |||
| import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import me.chanjar.weixin.common.util.StringUtils; | |||
| import me.chanjar.weixin.mp.api.*; | |||
| import me.chanjar.weixin.mp.bean.WxMpMpXmlOutImageMessage; | |||
| import me.chanjar.weixin.mp.api.WxMpConfigStorage; | |||
| import me.chanjar.weixin.mp.api.WxMpMessageRouter; | |||
| import me.chanjar.weixin.mp.api.WxMpService; | |||
| import me.chanjar.weixin.mp.bean.WxMpXmlMessage; | |||
| import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage; | |||
| import me.chanjar.weixin.mp.bean.WxMpXmlOutTextMessage; | |||
| import javax.servlet.ServletException; | |||
| import javax.servlet.http.HttpServlet; | |||
| import javax.servlet.http.HttpServletRequest; | |||
| import javax.servlet.http.HttpServletResponse; | |||
| import javax.xml.bind.JAXBException; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.util.Map; | |||
| /** | |||
| * @author Daniel Qian | |||
| @@ -1,26 +1,15 @@ | |||
| package me.chanjar.weixin.mp.demo; | |||
| import me.chanjar.weixin.common.api.WxConsts; | |||
| import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | |||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||
| import me.chanjar.weixin.common.util.StringUtils; | |||
| import me.chanjar.weixin.mp.api.*; | |||
| import me.chanjar.weixin.mp.bean.WxMpMpXmlOutImageMessage; | |||
| import me.chanjar.weixin.mp.bean.WxMpXmlMessage; | |||
| import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage; | |||
| import me.chanjar.weixin.mp.bean.WxMpXmlOutTextMessage; | |||
| import me.chanjar.weixin.mp.api.WxMpService; | |||
| import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken; | |||
| import me.chanjar.weixin.mp.bean.result.WxMpUser; | |||
| import javax.servlet.ServletContext; | |||
| import javax.servlet.ServletException; | |||
| import javax.servlet.http.HttpServlet; | |||
| import javax.servlet.http.HttpServletRequest; | |||
| import javax.servlet.http.HttpServletResponse; | |||
| import javax.xml.bind.JAXBException; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.util.Map; | |||
| public class WxMpOAuth2Servlet extends HttpServlet { | |||
| @@ -3,7 +3,7 @@ | |||
| <suite name="Weixin-java-tool-suite" verbose="1"> | |||
| <test name="API_Test"> | |||
| <classes> | |||
| <class name="me.chanjar.weixin.mp.api.WxBaseAPITest" /> | |||
| <class name="me.chanjar.weixin.mp.api.WxMpBaseAPITest" /> | |||
| <class name="me.chanjar.weixin.mp.api.WxMpCustomMessageAPITest" /> | |||
| <class name="me.chanjar.weixin.mp.api.WxMpMenuAPITest" /> | |||
| <class name="me.chanjar.weixin.mp.api.WxMpGroupAPITest" /> | |||