@@ -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,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,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,46 @@ | |||
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 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.setMode(XStream.NO_REFERENCES); | |||
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,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 | |||
@@ -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 | |||
@@ -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 { | |||