first commit
This commit is contained in:
parent
4bb2115805
commit
6786d7888e
28
.gitignore
vendored
Normal file
28
.gitignore
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
ass
|
||||
|
||||
# Mobile Tools for Java (J2ME)
|
||||
.mtj.tmp/
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
*.ear
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
|
||||
*~
|
||||
|
||||
# eclipse ignore
|
||||
*.settings/*
|
||||
/.project
|
||||
/.classpath
|
||||
/.tomcatplugin
|
||||
|
||||
# maven ignore
|
||||
target/*
|
||||
|
||||
# other ignore
|
||||
*.log
|
||||
*.tmp
|
||||
Thumbs.db
|
||||
189
pom.xml
Normal file
189
pom.xml
Normal file
@ -0,0 +1,189 @@
|
||||
<?xml version="1.0"?>
|
||||
<project
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.foxinmy.weixin</groupId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<artifactId>weixin4j-sdk</artifactId>
|
||||
<name>weixin4j-sdk</name>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.7</source>
|
||||
<target>1.7</target>
|
||||
</configuration>
|
||||
<version>3.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>2.6</version>
|
||||
<configuration>
|
||||
<encoding>${project.build.sourceEncoding}</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.thoughtworks.xstream</groupId>
|
||||
<artifactId>xstream</artifactId>
|
||||
<version>${xstream.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
<version>${commons.codec.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-httpclient</groupId>
|
||||
<artifactId>commons-httpclient</artifactId>
|
||||
<version>${commons.httpclient.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<groupId>commons-logging</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>${fastjson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dom4j</groupId>
|
||||
<artifactId>dom4j</artifactId>
|
||||
<version>${dom4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jaxen</groupId>
|
||||
<artifactId>jaxen</artifactId>
|
||||
<version>${jaxen.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-core</artifactId>
|
||||
<version>${logback.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>${logback.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>logback-core</artifactId>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
<version>${jcl.over.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>log4j-over-slf4j</artifactId>
|
||||
<version>${log4j.over.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jsoup</groupId>
|
||||
<artifactId>jsoup</artifactId>
|
||||
<version>1.7.3</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<id>releases</id>
|
||||
<name>Internal Releases</name>
|
||||
<url>http://42.62.64.62:8081/nexus/content/repositories/releases/
|
||||
</url>
|
||||
</repository>
|
||||
<snapshotRepository>
|
||||
<id>snapshots</id>
|
||||
<name>Internal Snapshots</name>
|
||||
<url>http://42.62.64.62:8081/nexus/content/repositories/snapshots/
|
||||
</url>
|
||||
</snapshotRepository>
|
||||
</distributionManagement>
|
||||
<repositories>
|
||||
<repository>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<id>public</id>
|
||||
<name>Public Repositories</name>
|
||||
<url>http://42.62.64.62:8081/nexus/content/groups/public/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
<id>public</id>
|
||||
<name>Public Repositories</name>
|
||||
<url>http://42.62.64.62:8081/nexus/content/groups/public/</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
<properties>
|
||||
<junit.version>4.8.2</junit.version>
|
||||
<dom4j.version>1.6.1</dom4j.version>
|
||||
<logback.version>1.0.9</logback.version>
|
||||
<jcl.over.version>1.7.6</jcl.over.version>
|
||||
<log4j.over.version>1.7.6</log4j.over.version>
|
||||
<xstream.version>1.4.7</xstream.version>
|
||||
<commons.httpclient.version>3.1</commons.httpclient.version>
|
||||
<commons.codec.version>1.9</commons.codec.version>
|
||||
<fastjson.version>1.1.9</fastjson.version>
|
||||
<jaxen.version>1.1.4</jaxen.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>default</id>
|
||||
<activation>
|
||||
<activeByDefault>true</activeByDefault>
|
||||
</activation>
|
||||
<properties>
|
||||
<maven.test.skip>true</maven.test.skip>
|
||||
</properties>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
912
src/main/java/com/foxinmy/weixin4j/WeixinProxy.java
Normal file
912
src/main/java/com/foxinmy/weixin4j/WeixinProxy.java
Normal file
@ -0,0 +1,912 @@
|
||||
package com.foxinmy.weixin4j;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.apache.commons.httpclient.methods.StringRequestEntity;
|
||||
import org.apache.commons.httpclient.methods.multipart.ByteArrayPartSource;
|
||||
import org.apache.commons.httpclient.methods.multipart.FilePart;
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.DocumentException;
|
||||
import org.dom4j.DocumentHelper;
|
||||
import org.dom4j.io.SAXReader;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.http.HttpRequest;
|
||||
import com.foxinmy.weixin4j.http.Response;
|
||||
import com.foxinmy.weixin4j.model.Button;
|
||||
import com.foxinmy.weixin4j.model.Following;
|
||||
import com.foxinmy.weixin4j.model.Group;
|
||||
import com.foxinmy.weixin4j.model.MpArticle;
|
||||
import com.foxinmy.weixin4j.model.QRParameter;
|
||||
import com.foxinmy.weixin4j.model.Token;
|
||||
import com.foxinmy.weixin4j.model.User;
|
||||
import com.foxinmy.weixin4j.model.UserToken;
|
||||
import com.foxinmy.weixin4j.msg.BaseMessage;
|
||||
import com.foxinmy.weixin4j.msg.notify.BaseNotify;
|
||||
import com.foxinmy.weixin4j.type.EventType;
|
||||
import com.foxinmy.weixin4j.type.MediaType;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
import com.foxinmy.weixin4j.util.WeixinConfig;
|
||||
import com.foxinmy.weixin4j.util.WeixinUtil;
|
||||
import com.foxinmy.weixin4j.xml.XStream;
|
||||
|
||||
/**
|
||||
* 微信服务实现
|
||||
*
|
||||
* @className WeixinServiceImpl
|
||||
* @author jy.hu
|
||||
* @date 2014年3月23日
|
||||
* @since JDK 1.7
|
||||
* @see <a href="http://mp.weixin.qq.com/wiki/index.php">api文档</a>
|
||||
*/
|
||||
public class WeixinProxy {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private HttpRequest request = new HttpRequest();
|
||||
|
||||
/**
|
||||
* 验证微信签名
|
||||
*
|
||||
* @param echostr
|
||||
* 随机字符串
|
||||
* @param timestamp
|
||||
* 时间戳
|
||||
* @param nonce
|
||||
* 随机数
|
||||
* @param signature
|
||||
* 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数
|
||||
* @return
|
||||
* 开发者通过检验signature对请求进行相关校验。若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,则接入生效
|
||||
* ,成为开发者成功,否则接入失败
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E5%85%A5%E6%8C%87%E5%8D%97">接入指南</a>
|
||||
*/
|
||||
public String signature(String echostr, String timestamp, String nonce,
|
||||
String signature) {
|
||||
String app_token = WeixinConfig.getValue("app_token");
|
||||
if (WeixinUtil.isBlank(app_token)) {
|
||||
log.error("signature fail : token is null!");
|
||||
return null;
|
||||
}
|
||||
if (WeixinUtil.isBlank(echostr) || WeixinUtil.isBlank(timestamp)
|
||||
|| WeixinUtil.isBlank(nonce)) {
|
||||
log.error("signature fail : invalid parameter!");
|
||||
return null;
|
||||
}
|
||||
String _signature = null;
|
||||
try {
|
||||
String[] a = { app_token, timestamp, nonce };
|
||||
Arrays.sort(a);
|
||||
StringBuilder sb = new StringBuilder(3);
|
||||
for (String str : a) {
|
||||
sb.append(str);
|
||||
}
|
||||
_signature = DigestUtils.sha1Hex(sb.toString());
|
||||
} catch (Exception e) {
|
||||
log.error("signature error", e);
|
||||
}
|
||||
if (signature.equals(_signature)) {
|
||||
return echostr;
|
||||
} else {
|
||||
log.error("signature fail : invalid signature!");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* xml消息转换为消息对象
|
||||
* <p>
|
||||
* 微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次
|
||||
* </p>
|
||||
*
|
||||
* @param xml
|
||||
* 消息字符串
|
||||
* @return 消息对象
|
||||
* @throws DocumentException
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E9%AA%8C%E8%AF%81%E6%B6%88%E6%81%AF%E7%9C%9F%E5%AE%9E%E6%80%A7">验证消息的合法性</a>
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E6%99%AE%E9%80%9A%E6%B6%88%E6%81%AF">普通消息</a>
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E4%BA%8B%E4%BB%B6%E6%8E%A8%E9%80%81">事件触发</a>
|
||||
* @see com.foxinmy.weixin4j.type.MessageType
|
||||
* @see com.feican.weixin.msg.BaeMessage
|
||||
* @see com.foxinmy.weixin4j.msg.TextMessage
|
||||
* @see com.foxinmy.weixin4j.msg.in.ImageMessage
|
||||
* @see com.foxinmy.weixin4j.msg.in.VoiceMessage
|
||||
* @see com.foxinmy.weixin4j.msg.in.VideoMessage
|
||||
* @see com.foxinmy.weixin4j.msg.in.LocationMessage
|
||||
* @see com.foxinmy.weixin4j.msg.in.LinkMessage
|
||||
* @see com.foxinmy.weixin4j.msg.event.ScribeEventMessage
|
||||
* @see com.foxinmy.weixin4j.msg.event.ScanEventMessage
|
||||
* @see com.foxinmy.weixin4j.msg.event.LocationEventMessage
|
||||
* @see com.foxinmy.weixin4j.msg.event.MenuEventMessage
|
||||
*/
|
||||
public BaseMessage xml2msg(String xmlStr) throws DocumentException {
|
||||
if (WeixinUtil.isBlank(xmlStr))
|
||||
return null;
|
||||
Document doc = DocumentHelper.parseText(xmlStr);
|
||||
String type = doc.selectSingleNode("/xml/MsgType").getStringValue();
|
||||
if (WeixinUtil.isBlank(type)) {
|
||||
return null;
|
||||
}
|
||||
XStream xstream = new XStream();
|
||||
MessageType messageType = MessageType.valueOf(type.toLowerCase());
|
||||
Class<? extends BaseMessage> messageClass = messageType
|
||||
.getMessageClass();
|
||||
if (messageType == MessageType.event) {
|
||||
type = doc.selectSingleNode("/xml/Event").getStringValue();
|
||||
messageClass = EventType.valueOf(type.toLowerCase())
|
||||
.getEventClass();
|
||||
}
|
||||
xstream.alias("xml", messageClass);
|
||||
xstream.ignoreUnknownElements();
|
||||
xstream.autodetectAnnotations(true);
|
||||
xstream.processAnnotations(messageClass);
|
||||
return xstream.fromXML(doc.asXML(), messageClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* xml消息转换为消息对象
|
||||
*
|
||||
* @param inputStream
|
||||
* 带消息字符串的输入流
|
||||
* @return 消息对象
|
||||
* @throws DocumentException
|
||||
* @see {@link com.foxinmy.weixin4j.WeixinProxy#xml2msg(String)}
|
||||
*/
|
||||
public BaseMessage xml2msg(InputStream inputStream)
|
||||
throws DocumentException {
|
||||
SAXReader reader = new SAXReader();
|
||||
Document doc = reader.read(inputStream);
|
||||
return xml2msg(doc.asXML());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取token
|
||||
* <p>
|
||||
* 正常情况下返回{"access_token":"ACCESS_TOKEN","expires_in":7200},否则抛出异常.
|
||||
* </p>
|
||||
*
|
||||
* @return token对象
|
||||
* @throws WeixinException
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96access_token">获取token说明</a>
|
||||
* @see com.foxinmy.weixin4j.model.Token
|
||||
*/
|
||||
public Token getToken() throws WeixinException {
|
||||
XStream xstream = new XStream();
|
||||
xstream.autodetectAnnotations(true);
|
||||
xstream.processAnnotations(Token.class);
|
||||
String appOpenId = WeixinConfig.getValue("app_openId");
|
||||
String token_path = WeixinConfig.getValue("token_path");
|
||||
File token_file = new File(String.format("%s/%s_token.xml", token_path,
|
||||
appOpenId));
|
||||
Token token = null;
|
||||
Calendar ca = Calendar.getInstance();
|
||||
long now_time = ca.getTimeInMillis();
|
||||
try {
|
||||
if (token_file.exists()) {
|
||||
token = (Token) xstream.fromXML(token_file);
|
||||
|
||||
long expise_time = token.getTime()
|
||||
+ (token.getExpires_in() * 1000) - 5;
|
||||
if (expise_time > now_time) {
|
||||
return token;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
token_file.createNewFile();
|
||||
} catch (IOException e) {
|
||||
token_file.getParentFile().mkdirs();
|
||||
}
|
||||
}
|
||||
token_path = WeixinConfig.getValue("api_token_uri");
|
||||
Response response = request.get(token_path);
|
||||
token = response.getAsObject(Token.class);
|
||||
token.setTime(now_time);
|
||||
token.setOpenid(appOpenId);
|
||||
xstream.toXML(token, new FileOutputStream(token_file));
|
||||
} catch (IOException e) {
|
||||
log.error("获取token出错", e);
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取token
|
||||
*
|
||||
* @param code
|
||||
* 用户授权后返回的code
|
||||
* @return token对象
|
||||
* @throws WeixinException
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E7%BD%91%E9%A1%B5%E6%8E%88%E6%9D%83%E8%8E%B7%E5%8F%96%E7%94%A8%E6%88%B7%E5%9F%BA%E6%9C%AC%E4%BF%A1%E6%81%AF#.E7.AC.AC.E4.BA.8C.E6.AD.A5.EF.BC.9A.E9.80.9A.E8.BF.87code.E6.8D.A2.E5.8F.96.E7.BD.91.E9.A1.B5.E6.8E.88.E6.9D.83access_token">获取用户token</a>
|
||||
* @see com.foxinmy.weixin4j.model.UserToken
|
||||
*/
|
||||
public UserToken getAccessToken(String code) throws WeixinException {
|
||||
String user_token_uri = WeixinConfig.getValue("sns_user_token_uri");
|
||||
Response response = request.get(String.format(user_token_uri, code));
|
||||
// 暂时不保存用户token
|
||||
return response.getAsObject(UserToken.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*
|
||||
* @param token
|
||||
* 授权票据
|
||||
* @return 用户对象
|
||||
* @throws WeixinException
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E7%BD%91%E9%A1%B5%E6%8E%88%E6%9D%83%E8%8E%B7%E5%8F%96%E7%94%A8%E6%88%B7%E5%9F%BA%E6%9C%AC%E4%BF%A1%E6%81%AF#.E7.AC.AC.E5.9B.9B.E6.AD.A5.EF.BC.9A.E6.8B.89.E5.8F.96.E7.94.A8.E6.88.B7.E4.BF.A1.E6.81.AF.28.E9.9C.80scope.E4.B8.BA_snsapi_userinfo.29">拉取用户信息</a>
|
||||
* @see com.foxinmy.weixin4j.model.User
|
||||
* @see com.foxinmy.weixin4j.model.UserToken
|
||||
* {@link com.foxinmy.weixin4j.WeixinProxy#getAccessToken(String)}
|
||||
*/
|
||||
public User getUser(UserToken token) throws WeixinException {
|
||||
String user_info_uri = WeixinConfig.getValue("sns_user_info_uri");
|
||||
Response response = request.get(String.format(user_info_uri,
|
||||
token.getAccess_token(), token.getOpenid()));
|
||||
return response.getAsObject(User.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
* <p>
|
||||
* 在关注者与公众号产生消息交互后,公众号可获得关注者的OpenID(加密后的微信号,每个用户对每个公众号的OpenID是唯一的,对于不同公众号,
|
||||
* 同一用户的openid不同),公众号可通过本接口来根据OpenID获取用户基本信息,包括昵称、头像、性别、所在城市、语言和关注时间
|
||||
* </p>
|
||||
*
|
||||
* @param openId
|
||||
* 用户对应的ID
|
||||
* @return 用户对象
|
||||
* @throws WeixinException
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96%E7%94%A8%E6%88%B7%E5%9F%BA%E6%9C%AC%E4%BF%A1%E6%81%AF">获取用户信息</a>
|
||||
* @see com.foxinmy.weixin4j.model.User
|
||||
*/
|
||||
public User getUser(String openId) throws WeixinException {
|
||||
String user_info_uri = WeixinConfig.getValue("api_user_info_uri");
|
||||
Token token = getToken();
|
||||
Response response = request.get(String.format(user_info_uri,
|
||||
token.getAccess_token(), openId));
|
||||
return response.getAsObject(User.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成带参数的二维码
|
||||
*
|
||||
* @param parameter
|
||||
* @return byte数据包
|
||||
* @throws WeixinException
|
||||
* @see {@link com.foxinmy.weixin4j.WeixinProxy#getQR(QRParameter)}
|
||||
*/
|
||||
public byte[] getQRData(QRParameter parameter) throws WeixinException {
|
||||
Token token = getToken();
|
||||
String qr_uri = WeixinConfig.getValue("qr_ticket_uri");
|
||||
Response response = null;
|
||||
try {
|
||||
response = request.post(String.format(qr_uri,
|
||||
token.getAccess_token()),
|
||||
new StringRequestEntity(parameter.toJson(),
|
||||
"application/json", "UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
String ticket = response.getAsJson().getString("ticket");
|
||||
qr_uri = WeixinConfig.getValue("qr_image_uri");
|
||||
response = request.get(String.format(qr_uri, ticket));
|
||||
|
||||
return response.getBody();
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成带参数的二维码
|
||||
* <p>
|
||||
* 二维码分为临时跟永久两种,扫描时触发推送带参数事件
|
||||
* </p>
|
||||
*
|
||||
* @param parameter
|
||||
* 二维码参数
|
||||
* @return 硬盘存储的文件对象
|
||||
* @throws WeixinException
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E7%94%9F%E6%88%90%E5%B8%A6%E5%8F%82%E6%95%B0%E7%9A%84%E4%BA%8C%E7%BB%B4%E7%A0%81">二维码</a>
|
||||
* @see com.foxinmy.weixin4j.model.QRParameter
|
||||
*/
|
||||
public File getQR(QRParameter parameter) throws WeixinException {
|
||||
String qr_path = WeixinConfig.getValue("qr_path");
|
||||
String filename = String
|
||||
.format("%s_%d_%d.jpg", parameter.getQrType().name(),
|
||||
parameter.getScene_id(), parameter.getExpire_seconds());
|
||||
File file = new File(qr_path + File.separator + filename);
|
||||
if (file.exists()) {
|
||||
return file;
|
||||
}
|
||||
FileOutputStream out = null;
|
||||
try {
|
||||
try {
|
||||
file.createNewFile();
|
||||
} catch (IOException e) {
|
||||
file.getParentFile().mkdirs();
|
||||
file.createNewFile();
|
||||
}
|
||||
out = new FileOutputStream(file);
|
||||
byte[] b = getQRData(parameter);
|
||||
out.write(b);
|
||||
} catch (IOException e) {
|
||||
|
||||
} finally {
|
||||
try {
|
||||
if (out != null) {
|
||||
out.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
|
||||
}
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传媒体文件
|
||||
* <p>
|
||||
* 正常情况下返回{"type":"TYPE","media_id":"MEDIA_ID","created_at":123456789},
|
||||
* 否则抛出异常.
|
||||
* </p>
|
||||
*
|
||||
* @param file
|
||||
* 文件对象
|
||||
* @param mediaType
|
||||
* 媒体类型
|
||||
* @return 上传到微信服务器返回的媒体标识
|
||||
* @throws WeixinException
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E4%B8%8A%E4%BC%A0%E4%B8%8B%E8%BD%BD%E5%A4%9A%E5%AA%92%E4%BD%93%E6%96%87%E4%BB%B6">上传下载说明</a>
|
||||
* @see com.foxinmy.weixin4j.type.MediaType
|
||||
*/
|
||||
public String uploadMedia(File file, MediaType mediaType)
|
||||
throws WeixinException {
|
||||
byte[] b = null;
|
||||
ByteArrayOutputStream out = null;
|
||||
FileInputStream in = null;
|
||||
try {
|
||||
b = new byte[4096];
|
||||
out = new ByteArrayOutputStream();
|
||||
in = new FileInputStream(file);
|
||||
int len = -1;
|
||||
while ((len = in.read(b)) != -1) {
|
||||
out.write(b, 0, len);
|
||||
}
|
||||
b = out.toByteArray();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (out != null) {
|
||||
try {
|
||||
out.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
if (in != null) {
|
||||
try {
|
||||
in.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return uploadMedia(file.getName(), b, mediaType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传媒体文件
|
||||
*
|
||||
* @param bytes
|
||||
* 媒体数据包
|
||||
* @param mediaType
|
||||
* 媒体类型
|
||||
* @return 上传到微信服务器返回的媒体标识
|
||||
* @throws WeixinException
|
||||
* @see {@link com.foxinmy.weixin4j.WeixinProxy#uploadMedia(File, MediaType)}
|
||||
*/
|
||||
public String uploadMedia(String fileName, byte[] bytes, MediaType mediaType)
|
||||
throws WeixinException {
|
||||
Token token = getToken();
|
||||
String file_upload_uri = WeixinConfig.getValue("file_upload_uri");
|
||||
Response response = null;
|
||||
|
||||
response = request.post(String.format(file_upload_uri,
|
||||
token.getAccess_token(), mediaType.name()), new FilePart(
|
||||
"media", new ByteArrayPartSource(fileName, bytes), null,
|
||||
"UTF-8"));
|
||||
|
||||
return response.getAsJson().getString("media_id");
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载媒体文件
|
||||
* <p>
|
||||
* 正常情况下返回表头如Content-Type: image/jpeg,否则抛出异常.
|
||||
* </p>
|
||||
*
|
||||
* @param mediaId
|
||||
* 存储在微信服务器上的媒体标识
|
||||
* @param mediaType
|
||||
* 媒体类型
|
||||
* @return 写入硬盘后的文件对象
|
||||
* @throws WeixinException
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E4%B8%8A%E4%BC%A0%E4%B8%8B%E8%BD%BD%E5%A4%9A%E5%AA%92%E4%BD%93%E6%96%87%E4%BB%B6">上传下载说明</a>
|
||||
* @see com.foxinmy.weixin4j.type.MediaType
|
||||
*/
|
||||
public File downloadMedia(String mediaId, MediaType mediaType)
|
||||
throws WeixinException {
|
||||
String media_path = WeixinConfig.getValue("media_path");
|
||||
String filename = mediaId + mediaType.getFormatType();
|
||||
File file = new File(media_path + File.separator + filename);
|
||||
if (file.exists()) {
|
||||
return file;
|
||||
}
|
||||
FileOutputStream out = null;
|
||||
try {
|
||||
try {
|
||||
file.createNewFile();
|
||||
} catch (IOException e) {
|
||||
file.getParentFile().mkdirs();
|
||||
file.createNewFile();
|
||||
}
|
||||
out = new FileOutputStream(file);
|
||||
byte[] b = downloadMediaData(mediaId, mediaType);
|
||||
out.write(b);
|
||||
} catch (IOException e) {
|
||||
|
||||
} finally {
|
||||
try {
|
||||
if (out != null) {
|
||||
out.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
|
||||
}
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载媒体文件
|
||||
*
|
||||
* @param mediaId
|
||||
* @param mediaType
|
||||
* @return 二进制数据包
|
||||
* @throws WeixinException
|
||||
* @see {@link com.foxinmy.weixin4j.WeixinProxy#downloadMedia(String, MediaType)}
|
||||
*/
|
||||
public byte[] downloadMediaData(String mediaId, MediaType mediaType)
|
||||
throws WeixinException {
|
||||
Token token = getToken();
|
||||
String file_download_uri = WeixinConfig.getValue("file_download_uri");
|
||||
Response response = request.get(String.format(file_download_uri,
|
||||
token.getAccess_token(), mediaId));
|
||||
return response.getBody();
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送客服消息(在48小时内不限制发送次数)
|
||||
*
|
||||
* @param notify
|
||||
* 客服消息对象
|
||||
* @throws WeixinException
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E5%AE%A2%E6%9C%8D%E6%B6%88%E6%81%AF">发送客服消息</a>
|
||||
*/
|
||||
public void sendNotify(BaseNotify notify) throws WeixinException {
|
||||
String custom_notify_uri = WeixinConfig.getValue("custom_notify_uri");
|
||||
Token token = getToken();
|
||||
try {
|
||||
request.post(String.format(custom_notify_uri,
|
||||
token.getAccess_token(), notify.getTouser()),
|
||||
new StringRequestEntity(notify.toJson(),
|
||||
"application/json", "UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建分组
|
||||
*
|
||||
* @param name
|
||||
* 组名称
|
||||
* @return group对象
|
||||
* @throws WeixinException
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%88%86%E7%BB%84%E7%AE%A1%E7%90%86%E6%8E%A5%E5%8F%A3#.E5.88.9B.E5.BB.BA.E5.88.86.E7.BB.84">创建分组</a>
|
||||
* @see com.foxinmy.weixin4j.model.Group
|
||||
* @see com.foxinmy.weixin4j.model.Group#toCreateJson()
|
||||
*/
|
||||
public Group createGroup(String name) throws WeixinException {
|
||||
String group_create_uri = WeixinConfig.getValue("group_create_uri");
|
||||
Token token = getToken();
|
||||
Response response = null;
|
||||
Group group = new Group(name);
|
||||
try {
|
||||
response = request.post(String.format(group_create_uri,
|
||||
token.getAccess_token()),
|
||||
new StringRequestEntity(group.toCreateJson(),
|
||||
"application/json", "UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
JSONObject obj = response.getAsJson();
|
||||
return JSON.parseObject(obj.getString("group"), Group.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有分组
|
||||
*
|
||||
* @return 组集合
|
||||
* @throws WeixinException
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%88%86%E7%BB%84%E7%AE%A1%E7%90%86%E6%8E%A5%E5%8F%A3#.E6.9F.A5.E8.AF.A2.E6.89.80.E6.9C.89.E5.88.86.E7.BB.84">查询所有分组</a>
|
||||
* @see com.foxinmy.weixin4j.model.Group
|
||||
*/
|
||||
public List<Group> getGroups() throws WeixinException {
|
||||
String group_get_uri = WeixinConfig.getValue("group_get_uri");
|
||||
Token token = getToken();
|
||||
Response response = request.get(String.format(group_get_uri,
|
||||
token.getAccess_token()));
|
||||
JSONObject obj = response.getAsJson();
|
||||
return JSON.parseArray(obj.getString("groups"), Group.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询用户所在分组
|
||||
*
|
||||
* @param openId
|
||||
* 用户对应的ID
|
||||
* @return 组ID
|
||||
* @throws WeixinException
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%88%86%E7%BB%84%E7%AE%A1%E7%90%86%E6%8E%A5%E5%8F%A3#.E6.9F.A5.E8.AF.A2.E7.94.A8.E6.88.B7.E6.89.80.E5.9C.A8.E5.88.86.E7.BB.84">查询用户所在分组</a>
|
||||
* @see com.foxinmy.weixin4j.model.Group
|
||||
*/
|
||||
public int findGroupByOpenId(String openId) throws WeixinException {
|
||||
String group_getid_uri = WeixinConfig.getValue("group_getid_uri");
|
||||
Token token = getToken();
|
||||
Response response = null;
|
||||
try {
|
||||
response = request.post(
|
||||
String.format(group_getid_uri, token.getAccess_token()),
|
||||
new StringRequestEntity(String.format(
|
||||
"{\"openid\":\"%s\"}", openId), "application/json",
|
||||
"UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return response.getAsJson().getIntValue("groupid");
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改分组名
|
||||
*
|
||||
* @param groupId
|
||||
* 组ID
|
||||
* @param name
|
||||
* 组名称
|
||||
* @throws WeixinException
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%88%86%E7%BB%84%E7%AE%A1%E7%90%86%E6%8E%A5%E5%8F%A3#.E4.BF.AE.E6.94.B9.E5.88.86.E7.BB.84.E5.90.8D">修改分组名</a>
|
||||
* @see com.foxinmy.weixin4j.model.Group
|
||||
* @see com.foxinmy.weixin4j.model.Group#toModifyJson()
|
||||
*/
|
||||
public void modifyGroup(int groupId, String name) throws WeixinException {
|
||||
String group_modify_uri = WeixinConfig.getValue("group_modify_uri");
|
||||
Token token = getToken();
|
||||
Group group = new Group(groupId, name);
|
||||
try {
|
||||
request.post(String.format(group_modify_uri,
|
||||
token.getAccess_token()),
|
||||
new StringRequestEntity(group.toModifyJson(),
|
||||
"application/json", "UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 移动分组
|
||||
*
|
||||
* @param openId
|
||||
* 用户对应的ID
|
||||
* @param groupId
|
||||
* 组ID
|
||||
* @throws WeixinException
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%88%86%E7%BB%84%E7%AE%A1%E7%90%86%E6%8E%A5%E5%8F%A3#.E7.A7.BB.E5.8A.A8.E7.94.A8.E6.88.B7.E5.88.86.E7.BB.84">移动分组</a>
|
||||
* @see com.foxinmy.weixin4j.model.Group
|
||||
*/
|
||||
public void moveGroup(String openId, int groupId) throws WeixinException {
|
||||
String group_move_uri = WeixinConfig.getValue("group_move_uri");
|
||||
Token token = getToken();
|
||||
try {
|
||||
request.post(
|
||||
String.format(group_move_uri, token.getAccess_token()),
|
||||
new StringRequestEntity(String.format(
|
||||
"{\"openid\":\"%s\",\"to_groupid\":%d}", openId,
|
||||
groupId), "application/json", "UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户一定数量(10000)的关注者列表
|
||||
*
|
||||
* @param nextOpenId
|
||||
* 下一次拉取数据的openid
|
||||
* @return 关注信息
|
||||
* @throws WeixinException
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96%E5%85%B3%E6%B3%A8%E8%80%85%E5%88%97%E8%A1%A8">获取关注者列表</a>
|
||||
* @see com.foxinmy.weixin4j.model.Following
|
||||
*/
|
||||
public Following getFollowing(String nextOpenId) throws WeixinException {
|
||||
String fllowing_uri = WeixinConfig.getValue("following_uri");
|
||||
Token token = getToken();
|
||||
Response response = request.get(String.format(fllowing_uri,
|
||||
token.getAccess_token(), nextOpenId == null ? "" : nextOpenId));
|
||||
|
||||
Following following = response.getAsObject(Following.class);
|
||||
|
||||
if (following.getCount() > 0) {
|
||||
List<String> openIds = JSON.parseArray(following.getDataJson()
|
||||
.getString("openid"), String.class);
|
||||
List<User> userList = new ArrayList<User>();
|
||||
for (String openId : openIds) {
|
||||
userList.add(getUser(openId));
|
||||
}
|
||||
following.setUserList(userList);
|
||||
}
|
||||
return following;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户全部的关注者列表
|
||||
* <p>
|
||||
* 当公众号关注者数量超过10000时,可通过填写next_openid的值,从而多次拉取列表的方式来满足需求,
|
||||
* 将上一次调用得到的返回中的next_openid值,作为下一次调用中的next_openid值
|
||||
* </p>
|
||||
*
|
||||
* @return 用户对象集合
|
||||
* @throws WeixinException
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96%E5%85%B3%E6%B3%A8%E8%80%85%E5%88%97%E8%A1%A8">获取关注者列表</a>
|
||||
* @see com.foxinmy.weixin4j.model.Following
|
||||
* @see com.foxinmy.weixin4j.WeixinProxy#getFollowing(String)
|
||||
*/
|
||||
public List<User> getAllFollowing() throws WeixinException {
|
||||
List<User> userList = new ArrayList<User>();
|
||||
String nextOpenId = null;
|
||||
Following f = null;
|
||||
for (;;) {
|
||||
f = getFollowing(nextOpenId);
|
||||
if (f.getCount() == 0) {
|
||||
break;
|
||||
}
|
||||
userList.addAll(f.getUserList());
|
||||
nextOpenId = f.getNextOpenId();
|
||||
}
|
||||
return userList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义菜单
|
||||
*
|
||||
* @param btnList
|
||||
* @throws WeixinException
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E8%87%AA%E5%AE%9A%E4%B9%89%E8%8F%9C%E5%8D%95%E5%88%9B%E5%BB%BA%E6%8E%A5%E5%8F%A3">创建自定义菜单</a>
|
||||
* @see com.foxinmy.weixin4j.model.Button
|
||||
*/
|
||||
public void createMenu(List<Button> btnList) throws WeixinException {
|
||||
String menu_create_uri = WeixinConfig.getValue("menu_create_uri");
|
||||
Token token = getToken();
|
||||
try {
|
||||
JSONObject obj = new JSONObject();
|
||||
obj.put("button", btnList);
|
||||
request.post(
|
||||
String.format(menu_create_uri, token.getAccess_token()),
|
||||
new StringRequestEntity(obj.toJSONString(),
|
||||
"application/json", "UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询菜单
|
||||
*
|
||||
* @return 菜单集合
|
||||
* @throws WeixinException
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E8%87%AA%E5%AE%9A%E4%B9%89%E8%8F%9C%E5%8D%95%E6%9F%A5%E8%AF%A2%E6%8E%A5%E5%8F%A3">查询菜单</a>
|
||||
* @see com.foxinmy.weixin4j.model.Button
|
||||
*/
|
||||
public List<Button> getMenu() throws WeixinException {
|
||||
String menu_get_uri = WeixinConfig.getValue("menu_get_uri");
|
||||
Token token = getToken();
|
||||
Response response = request.get(String.format(menu_get_uri,
|
||||
token.getAccess_token()));
|
||||
String text = response.getAsJson().getJSONObject("menu")
|
||||
.getString("button");
|
||||
return JSON.parseArray(text, Button.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除菜单
|
||||
*
|
||||
* @throws WeixinException
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E8%87%AA%E5%AE%9A%E4%B9%89%E8%8F%9C%E5%8D%95%E5%88%A0%E9%99%A4%E6%8E%A5%E5%8F%A3">删除菜单</a>
|
||||
* @see com.foxinmy.weixin4j.model.Button
|
||||
*/
|
||||
public void deleteMenu() throws WeixinException {
|
||||
String menu_delete_uri = WeixinConfig.getValue("menu_delete_uri");
|
||||
Token token = getToken();
|
||||
request.get(String.format(menu_delete_uri, token.getAccess_token()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传图文消息,一个图文消息支持1到10条图文
|
||||
*
|
||||
* @param articles
|
||||
* 图片消息
|
||||
* @return 媒体ID
|
||||
* @throws WeixinException
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E9%AB%98%E7%BA%A7%E7%BE%A4%E5%8F%91%E6%8E%A5%E5%8F%A3">高级群发</a>
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E9%AB%98%E7%BA%A7%E7%BE%A4%E5%8F%91%E6%8E%A5%E5%8F%A3#.E4.B8.8A.E4.BC.A0.E5.9B.BE.E6.96.87.E6.B6.88.E6.81.AF.E7.B4.A0.E6.9D.90">上传图文消息</a>
|
||||
* @see com.foxinmy.weixin4j.model.MpArticle
|
||||
*/
|
||||
public String uploadNews(List<MpArticle> articles) throws WeixinException {
|
||||
String news_upload_uri = WeixinConfig.getValue("news_upload_uri");
|
||||
Token token = getToken();
|
||||
Response response = null;
|
||||
try {
|
||||
JSONObject obj = new JSONObject();
|
||||
obj.put("articles", articles);
|
||||
response = request.post(String.format(news_upload_uri,
|
||||
token.getAccess_token()),
|
||||
new StringRequestEntity(obj.toJSONString(),
|
||||
"application/json", "UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return response.getAsJson().getString("media_id");
|
||||
}
|
||||
|
||||
/**
|
||||
* 分组群发
|
||||
* <p>
|
||||
* 在返回成功时,意味着群发任务提交成功,并不意味着此时群发已经结束,所以,仍有可能在后续的发送过程中出现异常情况导致用户未收到消息,
|
||||
* 如消息有时会进行审核、服务器不稳定等,此外,群发任务一般需要较长的时间才能全部发送完毕
|
||||
* </p>
|
||||
*
|
||||
* @param articles
|
||||
* 图文消息列表
|
||||
* @param groupId
|
||||
* 分组ID
|
||||
* @return 发送出去的消息ID
|
||||
* @throws WeixinException
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E9%AB%98%E7%BA%A7%E7%BE%A4%E5%8F%91%E6%8E%A5%E5%8F%A3#.E6.A0.B9.E6.8D.AE.E5.88.86.E7.BB.84.E8.BF.9B.E8.A1.8C.E7.BE.A4.E5.8F.91">分组群发</a>
|
||||
* @see com.foxinmy.weixin4j.model.MpArticle
|
||||
* @see com.foxinmy.weixin4j.model.Group
|
||||
* @see {@link com.foxinmy.weixin4j.WeixinProxy#uploadMedia(File, MediaType)}
|
||||
* @see {@link com.foxinmy.weixin4j.WeixinProxy#uploadNews(List)}
|
||||
*/
|
||||
public String massNewsByGroup(List<MpArticle> articles, String groupId)
|
||||
throws WeixinException {
|
||||
String mediaId = uploadNews(articles);
|
||||
JSONObject obj = new JSONObject();
|
||||
obj.put("filter", new JSONObject().put("group_id", groupId));
|
||||
obj.put("mpnews", new JSONObject().put("media_id", mediaId));
|
||||
obj.put("msgtype", "mpnews");
|
||||
String mass_group_uri = WeixinConfig.getValue("mass_group_uri");
|
||||
Token token = getToken();
|
||||
Response response = null;
|
||||
try {
|
||||
response = request.post(String.format(mass_group_uri,
|
||||
token.getAccess_token()),
|
||||
new StringRequestEntity(obj.toJSONString(),
|
||||
"application/json", "UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return response.getAsJson().getString("msg_id");
|
||||
}
|
||||
|
||||
/**
|
||||
* openId群发
|
||||
*
|
||||
* @param articles
|
||||
* 图文消息列表
|
||||
* @param openIds
|
||||
* 目标ID列表
|
||||
* @return 发送出去的消息ID
|
||||
* @throws WeixinException
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E9%AB%98%E7%BA%A7%E7%BE%A4%E5%8F%91%E6%8E%A5%E5%8F%A3#.E6.A0.B9.E6.8D.AEOpenID.E5.88.97.E8.A1.A8.E7.BE.A4.E5.8F.91">openId群发</a>
|
||||
* @see com.foxinmy.weixin4j.model.MpArticle
|
||||
* @see com.foxinmy.weixin4j.model.User
|
||||
* @see {@link com.foxinmy.weixin4j.WeixinProxy#uploadMedia(File, MediaType)}
|
||||
* @see {@link com.foxinmy.weixin4j.WeixinProxy#uploadNews(List)}
|
||||
*/
|
||||
public String massNewsByOpenIds(List<MpArticle> articles, String... openIds)
|
||||
throws WeixinException {
|
||||
String mediaId = uploadNews(articles);
|
||||
JSONObject obj = new JSONObject();
|
||||
obj.put("touser", openIds);
|
||||
obj.put("mpnews", new JSONObject().put("media_id", mediaId));
|
||||
obj.put("msgtype", "mpnews");
|
||||
String mass_openid_uri = WeixinConfig.getValue("mass_openid_uri");
|
||||
Token token = getToken();
|
||||
Response response = null;
|
||||
try {
|
||||
response = request.post(String.format(mass_openid_uri,
|
||||
token.getAccess_token()),
|
||||
new StringRequestEntity(obj.toJSONString(),
|
||||
"application/json", "UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return response.getAsJson().getString("msg_id");
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除群发消息
|
||||
* <p>
|
||||
* 请注意,只有已经发送成功的消息才能删除删除消息只是将消息的图文详情页失效,已经收到的用户,还是能在其本地看到消息卡片
|
||||
* </p>
|
||||
*
|
||||
* @param msgid
|
||||
* 发送出去的消息ID
|
||||
* @throws WeixinException
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E9%AB%98%E7%BA%A7%E7%BE%A4%E5%8F%91%E6%8E%A5%E5%8F%A3#.E5.88.A0.E9.99.A4.E7.BE.A4.E5.8F.91">删除群发</a>
|
||||
* @see {@link com.foxinmy.weixin4j.WeixinProxy#massNewsByGroup(List, String)}
|
||||
* @see {@link com.foxinmy.weixin4j.WeixinProxy#massNewsByOpenIds(List, String...)
|
||||
*/
|
||||
public void deleteMassNews(String msgid) throws WeixinException {
|
||||
JSONObject obj = new JSONObject();
|
||||
obj.put("msgid", msgid);
|
||||
String mass_delete_uri = WeixinConfig.getValue("mass_delete_uri");
|
||||
Token token = getToken();
|
||||
try {
|
||||
request.post(
|
||||
String.format(mass_delete_uri, token.getAccess_token()),
|
||||
new StringRequestEntity(obj.toJSONString(),
|
||||
"application/json", "UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
package com.foxinmy.weixin4j.exception;
|
||||
|
||||
/**
|
||||
* 调用微信接口抛出的异常
|
||||
* @className WeixinException
|
||||
* @author jy.hu
|
||||
* @date 2014年4月10日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class WeixinException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 7148145661883468514L;
|
||||
|
||||
private int errorCode;
|
||||
private String errorMsg;
|
||||
|
||||
public WeixinException(int errorCode) {
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
|
||||
public WeixinException(int errorCode, String errorMsg) {
|
||||
this.errorCode = errorCode;
|
||||
this.errorMsg = errorMsg;
|
||||
}
|
||||
|
||||
public WeixinException(String errorMsg) {
|
||||
this.errorMsg = errorMsg;
|
||||
}
|
||||
|
||||
public int getErrorCode() {
|
||||
return this.errorCode;
|
||||
}
|
||||
|
||||
public String getErrorMsg() {
|
||||
return this.errorMsg;
|
||||
}
|
||||
}
|
||||
133
src/main/java/com/foxinmy/weixin4j/http/HttpRequest.java
Normal file
133
src/main/java/com/foxinmy/weixin4j/http/HttpRequest.java
Normal file
@ -0,0 +1,133 @@
|
||||
package com.foxinmy.weixin4j.http;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
|
||||
import org.apache.commons.httpclient.Header;
|
||||
import org.apache.commons.httpclient.HttpClient;
|
||||
import org.apache.commons.httpclient.HttpMethod;
|
||||
import org.apache.commons.httpclient.HttpStatus;
|
||||
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
|
||||
import org.apache.commons.httpclient.cookie.CookiePolicy;
|
||||
import org.apache.commons.httpclient.methods.GetMethod;
|
||||
import org.apache.commons.httpclient.methods.PostMethod;
|
||||
import org.apache.commons.httpclient.methods.RequestEntity;
|
||||
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
|
||||
import org.apache.commons.httpclient.methods.multipart.Part;
|
||||
import org.apache.commons.httpclient.params.HttpClientParams;
|
||||
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
|
||||
import org.apache.commons.httpclient.params.HttpMethodParams;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
|
||||
public class HttpRequest {
|
||||
private final String CONTENT_CHARSET = "UTF-8";
|
||||
private final String ERROR_CODE_KEY = "errcode";
|
||||
private final String ERROR_MSG_KEY = "errmsg";
|
||||
private HttpClient client;
|
||||
|
||||
public HttpRequest() {
|
||||
this(150, 30000, 30000, 1024 * 1024);
|
||||
}
|
||||
|
||||
public HttpRequest(int maxConPerHost, int conTimeOutMs, int soTimeOutMs, int maxSize) {
|
||||
MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
|
||||
connectionManager = new MultiThreadedHttpConnectionManager();
|
||||
HttpConnectionManagerParams params = connectionManager.getParams();
|
||||
params.setDefaultMaxConnectionsPerHost(maxConPerHost);
|
||||
params.setConnectionTimeout(conTimeOutMs);
|
||||
params.setSoTimeout(soTimeOutMs);
|
||||
|
||||
HttpClientParams clientParams = new HttpClientParams();
|
||||
clientParams.setCookiePolicy(CookiePolicy.IGNORE_COOKIES);
|
||||
client = new HttpClient(clientParams, connectionManager);
|
||||
client.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, CONTENT_CHARSET);
|
||||
}
|
||||
|
||||
public Response get(String url) throws WeixinException {
|
||||
Parameter[] empty = null;
|
||||
return get(url, empty);
|
||||
}
|
||||
|
||||
public Response get(String url, Parameter... parameters) throws WeixinException {
|
||||
StringBuilder sb = new StringBuilder(url);
|
||||
if (parameters != null && parameters.length > 0) {
|
||||
if (url.indexOf("?") < 0) {
|
||||
sb.append(String.format("?%s=%s", parameters[0].getName(), parameters[0].getValue()));
|
||||
}
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
sb.append(parameters[i].toGetPara());
|
||||
}
|
||||
}
|
||||
return doRequest(new GetMethod(sb.toString()));
|
||||
}
|
||||
|
||||
public Response post(String url) throws WeixinException {
|
||||
Parameter[] empty = null;
|
||||
return post(url, empty);
|
||||
}
|
||||
|
||||
public Response post(String url, Parameter... parameters) throws WeixinException {
|
||||
PostMethod method = new PostMethod(url);
|
||||
for (Parameter parameter : parameters) {
|
||||
method.addParameter(parameter.toPostPara());
|
||||
}
|
||||
|
||||
return doRequest(method);
|
||||
}
|
||||
|
||||
public Response post(String url, RequestEntity entity) throws WeixinException {
|
||||
PostMethod method = new PostMethod(url);
|
||||
method.setRequestEntity(entity);
|
||||
return doRequest(method);
|
||||
}
|
||||
|
||||
public Response post(String url, Part... parts) throws WeixinException {
|
||||
PostMethod method = new PostMethod(url);
|
||||
method.getParams().setContentCharset(CONTENT_CHARSET);
|
||||
MultipartRequestEntity entity = new MultipartRequestEntity(parts, method.getParams());
|
||||
method.setRequestEntity(entity);
|
||||
return doRequest(method);
|
||||
}
|
||||
|
||||
protected Response doRequest(HttpMethod method) throws WeixinException {
|
||||
|
||||
try {
|
||||
|
||||
method.getParams().setContentCharset(CONTENT_CHARSET);
|
||||
method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler(3, false));
|
||||
int status = client.executeMethod(method);
|
||||
if (status != HttpStatus.SC_OK) {
|
||||
throw new WeixinException(status, getCause(method.getStatusCode()));
|
||||
}
|
||||
// HttpClient对于要求接受后继服务的请求,象POST和PUT等不能自动处理转发
|
||||
// 301或者302
|
||||
if (status == HttpStatus.SC_MOVED_PERMANENTLY || status == HttpStatus.SC_MOVED_TEMPORARILY) {
|
||||
throw new WeixinException(status, String.format("the page was redirected to %s", method.getResponseHeader("location")));
|
||||
}
|
||||
Response response = new Response(method.getResponseBodyAsString());
|
||||
response.setBody(method.getResponseBody());
|
||||
response.setStatusCode(status);
|
||||
response.setStatusText(method.getStatusText());
|
||||
response.setStream(method.getResponseBodyAsStream());
|
||||
|
||||
Header contentType = method.getResponseHeader("Content-Type");
|
||||
if (contentType.getValue().indexOf("application/json") >= 0 || contentType.getValue().indexOf("text/plain") >= 0) {
|
||||
JSONObject jsonObj = response.getAsJson();
|
||||
if (jsonObj.containsKey(ERROR_CODE_KEY) && jsonObj.getIntValue(ERROR_CODE_KEY) != 0) {
|
||||
throw new WeixinException(jsonObj.getIntValue(ERROR_CODE_KEY), jsonObj.getString(ERROR_MSG_KEY));
|
||||
}
|
||||
}
|
||||
return response;
|
||||
} catch (IOException e) {
|
||||
throw new WeixinException(e.getMessage());
|
||||
} finally {
|
||||
method.releaseConnection();
|
||||
}
|
||||
}
|
||||
|
||||
private String getCause(int statusCode) {
|
||||
return "error---------------" + statusCode;
|
||||
}
|
||||
}
|
||||
58
src/main/java/com/foxinmy/weixin4j/http/Parameter.java
Normal file
58
src/main/java/com/foxinmy/weixin4j/http/Parameter.java
Normal file
@ -0,0 +1,58 @@
|
||||
package com.foxinmy.weixin4j.http;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
|
||||
import org.apache.commons.httpclient.NameValuePair;
|
||||
|
||||
public class Parameter {
|
||||
private String name;
|
||||
private String value;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public Parameter() {
|
||||
|
||||
}
|
||||
|
||||
public Parameter(String name, String value) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String toGetPara() {
|
||||
try {
|
||||
return String.format("&%s=%s", URLEncoder.encode(name, "UTF-8"), URLEncoder.encode(value, "UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
return String.format("&%s=%s", name, value);
|
||||
}
|
||||
}
|
||||
|
||||
public NameValuePair toPostPara() {
|
||||
try {
|
||||
return new NameValuePair(URLEncoder.encode(name, "UTF-8"), URLEncoder.encode(value, "UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
return new NameValuePair(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[Parameter name=%s, value=%s]", name,value);
|
||||
}
|
||||
|
||||
}
|
||||
122
src/main/java/com/foxinmy/weixin4j/http/Response.java
Normal file
122
src/main/java/com/foxinmy/weixin4j/http/Response.java
Normal file
@ -0,0 +1,122 @@
|
||||
package com.foxinmy.weixin4j.http;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.DocumentException;
|
||||
import org.dom4j.Node;
|
||||
import org.dom4j.io.SAXReader;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.foxinmy.weixin4j.msg.ErrorMessage;
|
||||
import com.thoughtworks.xstream.XStream;
|
||||
|
||||
public class Response {
|
||||
|
||||
private final String ERROR_CODE_KEY = "errcode";
|
||||
private final String ERROR_MSG_KEY = "errmsg";
|
||||
|
||||
private String text;
|
||||
private int statusCode;
|
||||
private String statusText;
|
||||
private byte[] body;
|
||||
private InputStream stream;
|
||||
|
||||
public Response(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public String getAsString() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public JSONObject getAsJson() {
|
||||
return JSON.parseObject(text);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getAsObject(Class<? extends Serializable> clazz) {
|
||||
return (T) JSON.parseObject(text, clazz);
|
||||
}
|
||||
|
||||
public Object getAsXml() {
|
||||
XStream xs = new XStream();
|
||||
xs.autodetectAnnotations(true);
|
||||
return xs.fromXML(text);
|
||||
}
|
||||
|
||||
/**
|
||||
* <a href=
|
||||
* "http://mp.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E5%8F%A3%E9%A2%91%E7%8E%87%E9%99%90%E5%88%B6%E8%AF%B4%E6%98%8E"
|
||||
* >全局返回码</a> {"errcode":45009,"errmsg":"api freq out of limit"}
|
||||
*
|
||||
* @return
|
||||
* @throws DocumentException
|
||||
*/
|
||||
public ErrorMessage getErrorMsg() throws DocumentException {
|
||||
JSONObject jsonObj = getAsJson();
|
||||
if (jsonObj.containsKey(ERROR_CODE_KEY)) {
|
||||
SAXReader reader = new SAXReader();
|
||||
Document doc = reader.read(Thread.currentThread().getContextClassLoader().getResourceAsStream("error_code.xml"));
|
||||
Node node = doc.getRootElement().selectSingleNode(String.format("error[@code='%d']", jsonObj.getInteger(ERROR_CODE_KEY)));
|
||||
if (node != null) {
|
||||
return new ErrorMessage(jsonObj.getInteger(ERROR_CODE_KEY), jsonObj.getString(ERROR_MSG_KEY), node.getStringValue());
|
||||
}
|
||||
return new ErrorMessage(jsonObj.getInteger(ERROR_CODE_KEY), "unknown error", "未知错误");
|
||||
}
|
||||
|
||||
return new ErrorMessage(0, "request success", "");
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public int getStatusCode() {
|
||||
return statusCode;
|
||||
}
|
||||
|
||||
public void setStatusCode(int statusCode) {
|
||||
this.statusCode = statusCode;
|
||||
}
|
||||
|
||||
public String getStatusText() {
|
||||
return statusText;
|
||||
}
|
||||
|
||||
public void setStatusText(String statusText) {
|
||||
this.statusText = statusText;
|
||||
}
|
||||
|
||||
public byte[] getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public void setBody(byte[] body) {
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
public InputStream getStream() {
|
||||
return stream;
|
||||
}
|
||||
|
||||
public void setStream(InputStream stream) {
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[Response text=").append(text);
|
||||
sb.append(", statusCode=").append(statusCode);
|
||||
sb.append(", statusText=").append(statusText).append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
89
src/main/java/com/foxinmy/weixin4j/model/AuthResult.java
Normal file
89
src/main/java/com/foxinmy/weixin4j/model/AuthResult.java
Normal file
@ -0,0 +1,89 @@
|
||||
package com.foxinmy.weixin4j.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 网页授权结果
|
||||
* @className AuthResult
|
||||
* @author jy.hu
|
||||
* @date 2014年4月8日
|
||||
* @since JDK 1.7
|
||||
* @see <a href="http://mp.weixin.qq.com/wiki/index.php?title=%E7%BD%91%E9%A1%B5%E6%8E%88%E6%9D%83%E8%8E%B7%E5%8F%96%E7%94%A8%E6%88%B7%E5%9F%BA%E6%9C%AC%E4%BF%A1%E6%81%AF">网页授权获取用户基本资料</a>
|
||||
*/
|
||||
public class AuthResult implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 654855396163854805L;
|
||||
|
||||
/**
|
||||
* 网页授权获取code
|
||||
* @className AuthScope
|
||||
* @author jy.hu
|
||||
* @date 2014年4月8日
|
||||
* @since JDK 1.7
|
||||
* @see <a href="http://mp.weixin.qq.com/wiki/index.php?title=%E7%BD%91%E9%A1%B5%E6%8E%88%E6%9D%83%E8%8E%B7%E5%8F%96%E7%94%A8%E6%88%B7%E5%9F%BA%E6%9C%AC%E4%BF%A1%E6%81%AF#.E7.AC.AC.E4.B8.80.E6.AD.A5.EF.BC.9A.E7.94.A8.E6.88.B7.E5.90.8C.E6.84.8F.E6.8E.88.E6.9D.83.EF.BC.8C.E8.8E.B7.E5.8F.96code">获取code</a>
|
||||
*/
|
||||
public enum AuthScope {
|
||||
BASE("snsapi_base"), USERINFO("snsapi_userinfo");
|
||||
|
||||
private String name;
|
||||
|
||||
AuthScope(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
public enum AuthCode {
|
||||
OK, FAILED, REDIRECT
|
||||
}
|
||||
|
||||
private AuthCode authCode;
|
||||
private String location;
|
||||
private UserToken accessToken;
|
||||
|
||||
public AuthResult(String location) {
|
||||
this.location = location;
|
||||
this.authCode = AuthCode.REDIRECT;
|
||||
}
|
||||
|
||||
public AuthResult(UserToken accessToken) {
|
||||
this.authCode = AuthCode.OK;
|
||||
this.accessToken = accessToken;
|
||||
}
|
||||
|
||||
public AuthCode getAuthCode() {
|
||||
return authCode;
|
||||
}
|
||||
|
||||
public void setAuthCode(AuthCode authCode) {
|
||||
this.authCode = authCode;
|
||||
}
|
||||
|
||||
public String getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public void setLocation(String location) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public UserToken getAccessToken() {
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
public void setAccessToken(UserToken accessToken) {
|
||||
this.accessToken = accessToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[AuthResult authCode=").append(authCode);
|
||||
sb.append(", location=").append(location);
|
||||
sb.append(", accessToken=").append(accessToken).append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
123
src/main/java/com/foxinmy/weixin4j/model/Button.java
Normal file
123
src/main/java/com/foxinmy/weixin4j/model/Button.java
Normal file
@ -0,0 +1,123 @@
|
||||
package com.foxinmy.weixin4j.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
|
||||
/**
|
||||
* 菜单按钮
|
||||
* <p>目前自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单,一级菜单最多4个汉字,二级菜单最多7个汉字,多出来的部分将会以"..."代替
|
||||
* 请注意,创建自定义菜单后,由于微信客户端缓存,需要24小时微信客户端才会展现出来,建议测试时可以尝试取消关注公众账号后再次关注,则可以看到创建后的效果</p>
|
||||
* @className Button
|
||||
* @author jy.hu
|
||||
* @date 2014年4月5日
|
||||
* @since JDK 1.7
|
||||
*/
|
||||
public class Button implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -6422234732203854866L;
|
||||
|
||||
private String name;
|
||||
private BtnType type;
|
||||
private String key;
|
||||
private String url;
|
||||
|
||||
@JSONField(name = "sub_button")
|
||||
private List<Button> subs;
|
||||
|
||||
public Button() {
|
||||
}
|
||||
|
||||
public Button(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Button(String name, String url) {
|
||||
this.name = name;
|
||||
this.url = url;
|
||||
this.type = BtnType.view;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public BtnType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(BtnType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public List<Button> getSubs() {
|
||||
return subs;
|
||||
}
|
||||
|
||||
public void setSubs(List<Button> subs) {
|
||||
this.subs = subs;
|
||||
}
|
||||
|
||||
public void pushSub(Button btn) {
|
||||
if (this.subs == null) {
|
||||
this.subs = new ArrayList<Button>();
|
||||
}
|
||||
this.subs.add(btn);
|
||||
}
|
||||
|
||||
/**
|
||||
* 按钮类型
|
||||
* <p>click:
|
||||
* 用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event 的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互;</p>
|
||||
* <p>view:
|
||||
* 用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的url值(即网页链接),达到打开网页的目的,建议与网页授权获取用户基本信息接口结合,获得用户的登入个人信息</p>
|
||||
* @className BtnType
|
||||
* @author jy.hu
|
||||
* @date 2014年4月8日
|
||||
* @since JDK 1.7
|
||||
*/
|
||||
public enum BtnType {
|
||||
click, view
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[Button name=").append(name);
|
||||
sb.append(" ,type=").append(type);
|
||||
sb.append(" ,key=").append(key);
|
||||
sb.append(" ,url=").append(url);
|
||||
if (subs != null && !subs.isEmpty()) {
|
||||
sb.append("{");
|
||||
for (Button sub : subs) {
|
||||
sb.append(sub.toString());
|
||||
}
|
||||
sb.append("}");
|
||||
}
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
86
src/main/java/com/foxinmy/weixin4j/model/Following.java
Normal file
86
src/main/java/com/foxinmy/weixin4j/model/Following.java
Normal file
@ -0,0 +1,86 @@
|
||||
package com.foxinmy.weixin4j.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
|
||||
/**
|
||||
* 关注信息
|
||||
* @author jy.hu
|
||||
* @date 2014年4月4日
|
||||
* @since JDK 1.7
|
||||
* @see <a href=
|
||||
* "http://mp.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96%E5%85%B3%E6%B3%A8%E8%80%85%E5%88%97%E8%A1%A8"
|
||||
* >关注信息</a>
|
||||
*/
|
||||
public class Following implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1917454368271027134L;
|
||||
|
||||
private int total;
|
||||
private int count;
|
||||
@JSONField(name = "data")
|
||||
private JSONObject dataJson;
|
||||
@JSONField(name = "next_openid")
|
||||
private String nextOpenId;
|
||||
private List<User> userList;
|
||||
|
||||
public int getTotal() {
|
||||
return total;
|
||||
}
|
||||
|
||||
public void setTotal(int total) {
|
||||
this.total = total;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public void setCount(int count) {
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
public List<User> getUserList() {
|
||||
return userList;
|
||||
}
|
||||
|
||||
public void setUserList(List<User> userList) {
|
||||
this.userList = userList;
|
||||
}
|
||||
|
||||
public JSONObject getDataJson() {
|
||||
return dataJson;
|
||||
}
|
||||
|
||||
public void setDataJson(JSONObject dataJson) {
|
||||
this.dataJson = dataJson;
|
||||
}
|
||||
|
||||
public String getNextOpenId() {
|
||||
return nextOpenId;
|
||||
}
|
||||
|
||||
public void setNextOpenId(String nextOpenId) {
|
||||
this.nextOpenId = nextOpenId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[Following total=").append(total);
|
||||
sb.append(", count=").append(count);
|
||||
if (userList != null && !userList.isEmpty()) {
|
||||
sb.append(", users={");
|
||||
for (User u : userList) {
|
||||
sb.append(u.toString());
|
||||
}
|
||||
sb.append("}");
|
||||
}
|
||||
sb.append(", nextOpenId=").append(nextOpenId).append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
96
src/main/java/com/foxinmy/weixin4j/model/Group.java
Normal file
96
src/main/java/com/foxinmy/weixin4j/model/Group.java
Normal file
@ -0,0 +1,96 @@
|
||||
package com.foxinmy.weixin4j.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.foxinmy.weixin4j.xml.XStream;
|
||||
import com.thoughtworks.xstream.io.json.JsonHierarchicalStreamDriver;
|
||||
|
||||
/**
|
||||
* 分组
|
||||
* @author jy.hu
|
||||
* @date 2014年4月4日
|
||||
* @since JDK 1.7
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%88%86%E7%BB%84%E7%AE%A1%E7%90%86%E6%8E%A5%E5%8F%A3">分组</a>
|
||||
*/
|
||||
public class Group implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 6979565973974005954L;
|
||||
|
||||
private int id;
|
||||
private String name;
|
||||
private int count;
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public Group(int id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Group(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Group() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回创建分组所需的json格式字符串
|
||||
* @return {"group": {"id": 107, "name": "test"}}
|
||||
*/
|
||||
public String toCreateJson() {
|
||||
XStream xstream = new XStream(new JsonHierarchicalStreamDriver());
|
||||
xstream.omitField(this.getClass(), "id");
|
||||
xstream.omitField(this.getClass(), "count");
|
||||
xstream.alias("group", this.getClass());
|
||||
xstream.autodetectAnnotations(true);
|
||||
xstream.processAnnotations(this.getClass());
|
||||
return xstream.toXML(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回修改分组所需的json格式字符串
|
||||
* @return
|
||||
*/
|
||||
public String toModifyJson() {
|
||||
XStream xstream = new XStream(new JsonHierarchicalStreamDriver());
|
||||
xstream.omitField(this.getClass(), "count");
|
||||
xstream.alias("group", this.getClass());
|
||||
xstream.autodetectAnnotations(true);
|
||||
xstream.processAnnotations(this.getClass());
|
||||
return xstream.toXML(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof Group) {
|
||||
return id == ((Group) obj).getId();
|
||||
}
|
||||
return super.equals(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[Group id=%d ,name=%s ,count=%d]", id, name, count);
|
||||
}
|
||||
}
|
||||
75
src/main/java/com/foxinmy/weixin4j/model/MpArticle.java
Normal file
75
src/main/java/com/foxinmy/weixin4j/model/MpArticle.java
Normal file
@ -0,0 +1,75 @@
|
||||
package com.foxinmy.weixin4j.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
|
||||
/**
|
||||
* 群发图文消息
|
||||
*
|
||||
* @author jy.hu
|
||||
* @date 2014年4月26日
|
||||
* @since JDK 1.7
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E9%AB%98%E7%BA%A7%E7%BE%A4%E5%8F%91%E6%8E%A5%E5%8F%A3#.E4.B8.8A.E4.BC.A0.E5.9B.BE.E6.96.87.E6.B6.88.E6.81.AF.E7.B4.A0.E6.9D.90">群发消息描述</a>
|
||||
*/
|
||||
public class MpArticle implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 5583479943661639234L;
|
||||
|
||||
@JSONField(name = "thumb_media_id")
|
||||
private String thumbMediaId; // 图文消息缩略图的media_id,可以在基础支持-上传多媒体文件接口中获得 非空
|
||||
private String author;// 图文消息的作者 可为空
|
||||
private String title;// 图文消息的标题 非空
|
||||
@JSONField(name = "content_source_url")
|
||||
private String url;// 在图文消息页面点击“阅读原文”后的页面 可为空
|
||||
private String content;// 图文消息页面的内容,支持HTML标签 非空
|
||||
private String digest;// 图文消息的描述 可为空
|
||||
public String getThumbMediaId() {
|
||||
return thumbMediaId;
|
||||
}
|
||||
public void setThumbMediaId(String thumbMediaId) {
|
||||
this.thumbMediaId = thumbMediaId;
|
||||
}
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
public void setAuthor(String author) {
|
||||
this.author = author;
|
||||
}
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
public String getDigest() {
|
||||
return digest;
|
||||
}
|
||||
public void setDigest(String digest) {
|
||||
this.digest = digest;
|
||||
}
|
||||
|
||||
public MpArticle(String thumbMediaId, String title,String content) {
|
||||
this.thumbMediaId = thumbMediaId;
|
||||
this.title = title;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public MpArticle() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
90
src/main/java/com/foxinmy/weixin4j/model/QRParameter.java
Normal file
90
src/main/java/com/foxinmy/weixin4j/model/QRParameter.java
Normal file
@ -0,0 +1,90 @@
|
||||
package com.foxinmy.weixin4j.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import com.thoughtworks.xstream.annotations.XStreamOmitField;
|
||||
|
||||
/**
|
||||
* 二维码参数对象
|
||||
* <p>目前有2种类型的二维码,分别是临时二维码和永久二维码,前者有过期时间,最大为1800秒,但能够生成较多数量,后者无过期时间,数量较少(目前参数只支持1--100000)</p>
|
||||
* @className QRParameter
|
||||
* @author jy.hu
|
||||
* @date 2014年4月8日
|
||||
* @since JDK 1.7
|
||||
* @see <a href="http://mp.weixin.qq.com/wiki/index.php?title=%E7%94%9F%E6%88%90%E5%B8%A6%E5%8F%82%E6%95%B0%E7%9A%84%E4%BA%8C%E7%BB%B4%E7%A0%81">生成带参数的二维码</a>
|
||||
*/
|
||||
public class QRParameter implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 6611187606558274253L;
|
||||
|
||||
public enum QRType {
|
||||
QR_SCENE, // 临时
|
||||
QR_LIMIT_SCENE; // 永久
|
||||
}
|
||||
|
||||
private int expire_seconds; // 该二维码有效时间,以秒为单位。 最大不超过1800。
|
||||
@XStreamAlias("action_name")
|
||||
private QRType qrType; // 二维码类型,QR_SCENE为临时,QR_LIMIT_SCENE为永久
|
||||
@XStreamOmitField
|
||||
private int scene_id; // 场景值ID,临时二维码时为32位非0整型,永久二维码时最大值为100000(目前参数只支持1--100000)
|
||||
|
||||
public int getExpire_seconds() {
|
||||
return expire_seconds;
|
||||
}
|
||||
|
||||
public void setExpire_seconds(int expire_seconds) {
|
||||
this.expire_seconds = expire_seconds;
|
||||
}
|
||||
|
||||
public QRType getQrType() {
|
||||
return qrType;
|
||||
}
|
||||
|
||||
public void setQrType(QRType qrType) {
|
||||
this.qrType = qrType;
|
||||
}
|
||||
|
||||
public int getScene_id() {
|
||||
return scene_id;
|
||||
}
|
||||
|
||||
public void setScene_id(int scene_id) {
|
||||
this.scene_id = scene_id;
|
||||
}
|
||||
|
||||
public QRParameter(int expire_seconds, QRType qrType, int scene_id) {
|
||||
this.expire_seconds = expire_seconds;
|
||||
this.qrType = qrType;
|
||||
this.scene_id = scene_id;
|
||||
}
|
||||
|
||||
public QRParameter(QRType action_name, int scene_id) {
|
||||
this(0, action_name, scene_id);
|
||||
}
|
||||
|
||||
public String toJson() {
|
||||
/*
|
||||
* XStream xstream = new XStream(new JsonHierarchicalStreamDriver() {
|
||||
* public HierarchicalStreamWriter createWriter(Writer writer) { return
|
||||
* new JsonWriter(writer, JsonWriter.DROP_ROOT_MODE); } });
|
||||
* xstream.setMode(XStream.NO_REFERENCES);
|
||||
* xstream.autodetectAnnotations(true); if (this.qrType ==
|
||||
* QRType.QR_LIMIT_SCENE) { xstream.omitField(QRParameter.class,
|
||||
* "expire_seconds"); } return xstream.toXML(this);
|
||||
*/
|
||||
StringBuilder jsonBuilder = new StringBuilder("{");
|
||||
jsonBuilder.append("\"action_name\":\"").append(qrType.name()).append("\"");
|
||||
if (this.qrType == QRType.QR_SCENE) {
|
||||
jsonBuilder.append(",\"expire_seconds\":").append(expire_seconds);
|
||||
}
|
||||
jsonBuilder.append(",\"action_info\":").append(String.format("{\"scene\": {\"scene_id\": %d}}", scene_id));
|
||||
jsonBuilder.append("}");
|
||||
return jsonBuilder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[QRParameter action_name=%s, expire_seconds=%d, scene_id=%d]", getQrType().name(), getExpire_seconds(), getScene_id());
|
||||
}
|
||||
}
|
||||
75
src/main/java/com/foxinmy/weixin4j/model/Token.java
Normal file
75
src/main/java/com/foxinmy/weixin4j/model/Token.java
Normal file
@ -0,0 +1,75 @@
|
||||
package com.foxinmy.weixin4j.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token,正常情况下access_token有效期为7200秒,重复获取将导致上次获取的access_token失效
|
||||
*
|
||||
* @className Token
|
||||
* @author jy.hu
|
||||
* @date 2014年4月5日
|
||||
* @since JDK 1.7
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96access_token">获取token</a>
|
||||
*/
|
||||
@XStreamAlias("app-token")
|
||||
public class Token implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private String access_token;
|
||||
private int expires_in;
|
||||
private String openid;
|
||||
private long time;
|
||||
|
||||
public String getAccess_token() {
|
||||
return access_token;
|
||||
}
|
||||
|
||||
public void setAccess_token(String access_token) {
|
||||
this.access_token = access_token;
|
||||
}
|
||||
|
||||
public int getExpires_in() {
|
||||
return expires_in;
|
||||
}
|
||||
|
||||
public void setExpires_in(int expires_in) {
|
||||
this.expires_in = expires_in;
|
||||
}
|
||||
|
||||
public String getOpenid() {
|
||||
return openid;
|
||||
}
|
||||
|
||||
public void setOpenid(String openid) {
|
||||
this.openid = openid;
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(long time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof Token) {
|
||||
return access_token.equals(((Token) obj).getAccess_token());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[Token access_token=").append(access_token);
|
||||
sb.append(", expires_in=").append(expires_in);
|
||||
sb.append(", openid=").append(openid);
|
||||
sb.append(", time=").append(time).append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
205
src/main/java/com/foxinmy/weixin4j/model/User.java
Normal file
205
src/main/java/com/foxinmy/weixin4j/model/User.java
Normal file
@ -0,0 +1,205 @@
|
||||
package com.foxinmy.weixin4j.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.foxinmy.weixin4j.util.WeixinUtil;
|
||||
|
||||
/**
|
||||
* 用户对象
|
||||
* <p>当用户与公众号有交互时,可通过openid获取信息</p>
|
||||
* @author jy.hu
|
||||
* @date 2014年4月8日
|
||||
* @since JDK 1.7
|
||||
* @see <a href="http://mp.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96%E7%94%A8%E6%88%B7%E5%9F%BA%E6%9C%AC%E4%BF%A1%E6%81%AF">获取用户基本资料</a>
|
||||
*/
|
||||
public class User implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String openid; // 用户的唯一标识
|
||||
private String nickname; // 用户昵称
|
||||
private int sex; // 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
|
||||
private String province; // 用户个人资料填写的省份
|
||||
private String city; // 普通用户个人资料填写的城市
|
||||
private String country; // 国家,如中国为CN
|
||||
private String headimgurl; // 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空
|
||||
private String privilege; // 用户特权信息,json 数组,如微信沃卡用户为(chinaunicom)
|
||||
private int subscribe; // 是否关注
|
||||
private long subscribe_time; // 关注时间
|
||||
private Lang language; // 使用语言
|
||||
|
||||
// 国家地区语言版本
|
||||
public enum Lang {
|
||||
zh_CN("简体"), zh_TW("繁体"), en("英语");
|
||||
|
||||
private String desc;
|
||||
|
||||
Lang(String desc) {
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
|
||||
// 用户性别 值为1时是男性,值为2时是女性,值为0时是未知
|
||||
public enum Gender {
|
||||
male(1), female(2), unknown(0);
|
||||
|
||||
private int sex;
|
||||
|
||||
Gender(int sex) {
|
||||
this.sex = sex;
|
||||
}
|
||||
|
||||
public int getInt() {
|
||||
return sex;
|
||||
}
|
||||
}
|
||||
|
||||
// (有0、46、64、96、132数值可选,0代表640*640正方形头像)
|
||||
public enum Size {
|
||||
small(46), middle1(64), middle2(96), big(132);
|
||||
private int size;
|
||||
|
||||
Size(int size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public int getInt() {
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
public String getOpenid() {
|
||||
return openid;
|
||||
}
|
||||
|
||||
public void setOpenid(String openid) {
|
||||
this.openid = openid;
|
||||
}
|
||||
|
||||
public String getNickname() {
|
||||
return nickname;
|
||||
}
|
||||
|
||||
public void setNickname(String nickname) {
|
||||
this.nickname = nickname;
|
||||
}
|
||||
|
||||
public int getSex() {
|
||||
return sex;
|
||||
}
|
||||
|
||||
public Gender getGender(){
|
||||
if(sex == 1){
|
||||
return Gender.male;
|
||||
}else if(sex == 2){
|
||||
return Gender.female;
|
||||
}else{
|
||||
return Gender.unknown;
|
||||
}
|
||||
}
|
||||
|
||||
public void setSex(int sex) {
|
||||
this.sex = sex;
|
||||
}
|
||||
|
||||
public String getProvince() {
|
||||
return province;
|
||||
}
|
||||
|
||||
public void setProvince(String province) {
|
||||
this.province = province;
|
||||
}
|
||||
|
||||
public String getCity() {
|
||||
return city;
|
||||
}
|
||||
|
||||
public void setCity(String city) {
|
||||
this.city = city;
|
||||
}
|
||||
|
||||
public String getCountry() {
|
||||
return country;
|
||||
}
|
||||
|
||||
public void setCountry(String country) {
|
||||
this.country = country;
|
||||
}
|
||||
|
||||
public String getHeadimgurl() {
|
||||
return headimgurl;
|
||||
}
|
||||
|
||||
public String getHeadimgurl(Size size) {
|
||||
if (!WeixinUtil.isBlank(headimgurl)) {
|
||||
StringBuilder sb = new StringBuilder(headimgurl);
|
||||
return sb.replace(0, (headimgurl.length() - 1), size.getInt() + "").toString();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public void setHeadimgurl(String headimgurl) {
|
||||
this.headimgurl = headimgurl;
|
||||
}
|
||||
|
||||
public String getPrivilege() {
|
||||
return privilege;
|
||||
}
|
||||
|
||||
public void setPrivilege(String privilege) {
|
||||
this.privilege = privilege;
|
||||
}
|
||||
|
||||
public int getSubscribe() {
|
||||
return subscribe;
|
||||
}
|
||||
|
||||
public void setSubscribe(int subscribe) {
|
||||
this.subscribe = subscribe;
|
||||
}
|
||||
|
||||
public Lang getLanguage() {
|
||||
return language;
|
||||
}
|
||||
|
||||
public void setLanguage(Lang language) {
|
||||
this.language = language;
|
||||
}
|
||||
|
||||
public long getSubscribe_time() {
|
||||
return subscribe_time;
|
||||
}
|
||||
|
||||
public void setSubscribe_time(long subscribe_time) {
|
||||
this.subscribe_time = subscribe_time;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof User) {
|
||||
return openid.equals(((User) obj).getOpenid());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[User openid=").append(openid);
|
||||
sb.append(", nickname=").append(nickname);
|
||||
sb.append(", sex=").append(sex);
|
||||
sb.append(", province=").append(province);
|
||||
sb.append(", city=").append(city);
|
||||
sb.append(", country=").append(country);
|
||||
sb.append(", headimgurl=").append(headimgurl);
|
||||
sb.append(", privilege=").append(privilege);
|
||||
sb.append(", language=").append(language);
|
||||
sb.append(", subscribe_time=").append(subscribe_time);
|
||||
sb.append(", subscribe=").append(subscribe).append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
47
src/main/java/com/foxinmy/weixin4j/model/UserToken.java
Normal file
47
src/main/java/com/foxinmy/weixin4j/model/UserToken.java
Normal file
@ -0,0 +1,47 @@
|
||||
package com.foxinmy.weixin4j.model;
|
||||
|
||||
/**
|
||||
* 用户token 一般通过授权页面获得
|
||||
* @className UserToken
|
||||
* @author jy.hu
|
||||
* @date 2014年4月6日
|
||||
* @since JDK 1.7
|
||||
* @see com.foxinmy.weixin4j.model.AuthResult
|
||||
* @see com.foxinmy.weixin4j.model.AuthResult.AuthScope
|
||||
*/
|
||||
public class UserToken extends Token {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String refresh_token;
|
||||
|
||||
private String scope;
|
||||
|
||||
public String getRefresh_token() {
|
||||
return refresh_token;
|
||||
}
|
||||
|
||||
public void setRefresh_token(String refresh_token) {
|
||||
this.refresh_token = refresh_token;
|
||||
}
|
||||
|
||||
public String getScope() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
public void setScope(String scope) {
|
||||
this.scope = scope;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[UserToken access_token=").append(super.getAccess_token());
|
||||
sb.append(", expires_in=").append(super.getExpires_in());
|
||||
sb.append(", openid=").append(super.getOpenid());
|
||||
sb.append(", refresh_token=").append(refresh_token);
|
||||
sb.append(", scope=").append(scope);
|
||||
sb.append(", time=").append(super.getTime()).append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
126
src/main/java/com/foxinmy/weixin4j/msg/BaseMessage.java
Normal file
126
src/main/java/com/foxinmy/weixin4j/msg/BaseMessage.java
Normal file
@ -0,0 +1,126 @@
|
||||
package com.foxinmy.weixin4j.msg;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.io.Writer;
|
||||
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
import com.foxinmy.weixin4j.util.WeixinConfig;
|
||||
import com.foxinmy.weixin4j.util.WeixinUtil;
|
||||
import com.foxinmy.weixin4j.xml.XStream;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
|
||||
import com.thoughtworks.xstream.io.json.JsonHierarchicalStreamDriver;
|
||||
import com.thoughtworks.xstream.io.json.JsonWriter;
|
||||
|
||||
/**
|
||||
* 普通消息基类
|
||||
* <p><font color="red">回复图片等多媒体消息时需要预先上传多媒体文件到微信服务器,
|
||||
* 假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试</font></p>
|
||||
* @className BaseMessage
|
||||
* @author jy.hu
|
||||
* @date 2014年4月6日
|
||||
* @since JDK 1.7
|
||||
*/
|
||||
public class BaseMessage implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 7761192742840031607L;
|
||||
|
||||
@XStreamAlias("ToUserName")
|
||||
private String toUserName; // 开发者微信号
|
||||
@XStreamAlias("FromUserName")
|
||||
private String fromUserName; // 发送方帐号(一个OpenID)
|
||||
@XStreamAlias("CreateTime")
|
||||
private long createTime = System.currentTimeMillis(); // 消息创建时间 (整型)
|
||||
@XStreamAlias("MsgType")
|
||||
private MessageType msgType; // 消息类型
|
||||
@XStreamAlias("MsgId")
|
||||
private long msgId; // 消息ID
|
||||
|
||||
public BaseMessage(MessageType msgType) {
|
||||
this.msgType = msgType;
|
||||
}
|
||||
|
||||
public String getToUserName() {
|
||||
return toUserName;
|
||||
}
|
||||
|
||||
public void setToUserName(String toUserName) {
|
||||
this.toUserName = toUserName;
|
||||
}
|
||||
|
||||
public String getFromUserName() {
|
||||
return fromUserName;
|
||||
}
|
||||
|
||||
public void setFromUserName(String fromUserName) {
|
||||
this.fromUserName = fromUserName;
|
||||
}
|
||||
|
||||
public long getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
|
||||
public void setCreateTime(long createTime) {
|
||||
this.createTime = createTime;
|
||||
}
|
||||
|
||||
public MessageType getMsgType() {
|
||||
return msgType;
|
||||
}
|
||||
|
||||
public void setMsgType(MessageType msgType) {
|
||||
this.msgType = msgType;
|
||||
}
|
||||
|
||||
public long getMsgId() {
|
||||
return msgId;
|
||||
}
|
||||
|
||||
public void setMsgId(long msgId) {
|
||||
this.msgId = msgId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof BaseMessage) {
|
||||
return ((BaseMessage) obj).getMsgId() == msgId;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 消息对象转换为微信服务器接受的xml格式消息
|
||||
* @return xml字符串
|
||||
*/
|
||||
public String toXml() {
|
||||
XStream xstream = new XStream();
|
||||
xstream.alias("xml", getMsgType().getMessageClass());
|
||||
xstream.autodetectAnnotations(true);
|
||||
xstream.processAnnotations(getMsgType().getMessageClass());
|
||||
xstream.omitField(BaseMessage.class, "msgId");
|
||||
if (WeixinUtil.isBlank(fromUserName)) {
|
||||
setFromUserName(WeixinConfig.getValue("app_openId"));
|
||||
}
|
||||
return xstream.toXML(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 消息对象转换为微信服务器接受的json格式字符串
|
||||
* @return json字符串
|
||||
*/
|
||||
public String toJson() {
|
||||
XStream xstream = new XStream(new JsonHierarchicalStreamDriver() {
|
||||
public HierarchicalStreamWriter createWriter(Writer writer) {
|
||||
return new JsonWriter(writer, JsonWriter.DROP_ROOT_MODE);
|
||||
}
|
||||
});
|
||||
xstream.setMode(XStream.NO_REFERENCES);
|
||||
xstream.autodetectAnnotations(true);
|
||||
xstream.processAnnotations(getMsgType().getMessageClass());
|
||||
xstream.omitField(BaseMessage.class, "msgId");
|
||||
if (WeixinUtil.isBlank(fromUserName)) {
|
||||
setFromUserName(WeixinConfig.getValue("app_openId"));
|
||||
}
|
||||
return xstream.toXML(this);
|
||||
}
|
||||
}
|
||||
54
src/main/java/com/foxinmy/weixin4j/msg/ErrorMessage.java
Normal file
54
src/main/java/com/foxinmy/weixin4j/msg/ErrorMessage.java
Normal file
@ -0,0 +1,54 @@
|
||||
package com.foxinmy.weixin4j.msg;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class ErrorMessage implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 2539772564331987708L;
|
||||
|
||||
private int code;
|
||||
private String msg;
|
||||
private String text;
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(int code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
public void setMsg(String msg) {
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public ErrorMessage(int code, String msg, String text) {
|
||||
this.code = code;
|
||||
this.msg = msg;
|
||||
this.text = text;
|
||||
}
|
||||
public ErrorMessage() {
|
||||
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[ErrorMessage code=").append(code);
|
||||
sb.append(", msg=").append(msg);
|
||||
sb.append(", text=").append(text).append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
53
src/main/java/com/foxinmy/weixin4j/msg/TextMessage.java
Normal file
53
src/main/java/com/foxinmy/weixin4j/msg/TextMessage.java
Normal file
@ -0,0 +1,53 @@
|
||||
package com.foxinmy.weixin4j.msg;
|
||||
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 文本消息(接收|回复)
|
||||
* @className TextMessage
|
||||
* @author jy.hu
|
||||
* @date 2014年4月6日
|
||||
* @since JDK 1.7
|
||||
* @see <a href="http://mp.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E6%99%AE%E9%80%9A%E6%B6%88%E6%81%AF#.E6.96.87.E6.9C.AC.E6.B6.88.E6.81.AF">接收文本消息</a>
|
||||
* @see <a href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E8%A2%AB%E5%8A%A8%E5%93%8D%E5%BA%94%E6%B6%88%E6%81%AF#.E5.9B.9E.E5.A4.8D.E6.96.87.E6.9C.AC.E6.B6.88.E6.81.AF">回复文本消息</a>
|
||||
* @see com.foxinmy.weixin4j.msg.BaseMessage
|
||||
* @see com.foxinmy.weixin4j.msg.BaseMessage#toXml()
|
||||
*/
|
||||
public class TextMessage extends BaseMessage {
|
||||
|
||||
private static final long serialVersionUID = -7018053906644190260L;
|
||||
|
||||
public TextMessage() {
|
||||
super(MessageType.text);
|
||||
}
|
||||
|
||||
public TextMessage(String toUserName, String content) {
|
||||
super(MessageType.text);
|
||||
setToUserName(toUserName);
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
@XStreamAlias("Content")
|
||||
private String content; // 消息内容
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[TextMessage ,toUserName=").append(super.getToUserName());
|
||||
sb.append(" ,fromUserName=").append(super.getFromUserName());
|
||||
sb.append(" ,msgType=").append(super.getMsgType().name());
|
||||
sb.append(" ,content=").append(content);
|
||||
sb.append(" ,createTime=").append(super.getCreateTime());
|
||||
sb.append(" ,msgId=").append(super.getMsgId()).append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
package com.foxinmy.weixin4j.msg.event;
|
||||
|
||||
import com.foxinmy.weixin4j.msg.BaseMessage;
|
||||
import com.foxinmy.weixin4j.type.EventType;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 事件消息基类
|
||||
* @className EventMessage
|
||||
* @author jy.hu
|
||||
* @date 2014年4月6日
|
||||
* @since JDK 1.7
|
||||
* @see <a href="http://mp.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E4%BA%8B%E4%BB%B6%E6%8E%A8%E9%80%81">事件推送</a>
|
||||
*/
|
||||
public class EventMessage extends BaseMessage {
|
||||
|
||||
private static final long serialVersionUID = 7703667223814088865L;
|
||||
|
||||
public EventMessage(EventType eventType) {
|
||||
super(MessageType.event);
|
||||
this.eventType = eventType;
|
||||
}
|
||||
|
||||
@XStreamAlias("Event")
|
||||
private EventType eventType;
|
||||
|
||||
public EventType getEventType() {
|
||||
return eventType;
|
||||
}
|
||||
|
||||
public void setEventType(EventType eventType) {
|
||||
this.eventType = eventType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[EventMessage ,toUserName=").append(super.getToUserName());
|
||||
sb.append(" ,fromUserName=").append(super.getFromUserName());
|
||||
sb.append(" ,msgType=").append(super.getMsgType().name());
|
||||
sb.append(" ,eventType=").append(eventType.name());
|
||||
sb.append(" ,createTime=").append(super.getCreateTime());
|
||||
sb.append(" ,msgId=").append(super.getMsgId()).append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,70 @@
|
||||
package com.foxinmy.weixin4j.msg.event;
|
||||
|
||||
import com.foxinmy.weixin4j.type.EventType;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
|
||||
/**
|
||||
* 上报地理位置事件
|
||||
* @className LocationEventMessage
|
||||
* @author jy.hu
|
||||
* @date 2014年4月6日
|
||||
* @since JDK 1.7
|
||||
* @see <a href="http://mp.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E4%BA%8B%E4%BB%B6%E6%8E%A8%E9%80%81#.E4.B8.8A.E6.8A.A5.E5.9C.B0.E7.90.86.E4.BD.8D.E7.BD.AE.E4.BA.8B.E4.BB.B6">上报地理位置事件</a>
|
||||
* @see com.foxinmy.weixin4j.msg.BaseMessage
|
||||
* @see com.foxinmy.weixin4j.msg.BaseMessage#toXml()
|
||||
*/
|
||||
public class LocationEventMessage extends EventMessage {
|
||||
|
||||
private static final long serialVersionUID = -2030716800669824861L;
|
||||
|
||||
public LocationEventMessage() {
|
||||
super(EventType.location);
|
||||
}
|
||||
|
||||
@XStreamAlias("Latitude")
|
||||
private String latitude;// 地理位置纬度
|
||||
@XStreamAlias("Longitude")
|
||||
private String longitude;// 地理位置经度
|
||||
@XStreamAlias("Precision")
|
||||
private String precision;// 地理位置精度
|
||||
|
||||
public String getLatitude() {
|
||||
return latitude;
|
||||
}
|
||||
|
||||
public void setLatitude(String latitude) {
|
||||
this.latitude = latitude;
|
||||
}
|
||||
|
||||
public String getLongitude() {
|
||||
return longitude;
|
||||
}
|
||||
|
||||
public void setLongitude(String longitude) {
|
||||
this.longitude = longitude;
|
||||
}
|
||||
|
||||
public String getPrecision() {
|
||||
return precision;
|
||||
}
|
||||
|
||||
public void setPrecision(String precision) {
|
||||
this.precision = precision;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[LocationEventMessage ,toUserName=").append(super.getToUserName());
|
||||
sb.append(" ,fromUserName=").append(super.getFromUserName());
|
||||
sb.append(" ,msgType=").append(super.getMsgType().name());
|
||||
sb.append(" ,eventType=").append(super.getEventType().name());
|
||||
sb.append(" ,longitude=").append(longitude);
|
||||
sb.append(" ,latitude=").append(latitude);
|
||||
sb.append(" ,precision=").append(precision);
|
||||
sb.append(" ,createTime=").append(super.getCreateTime());
|
||||
sb.append(" ,msgId=").append(super.getMsgId()).append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,82 @@
|
||||
package com.foxinmy.weixin4j.msg.event;
|
||||
|
||||
import com.foxinmy.weixin4j.type.EventType;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 群发消息事件推送
|
||||
*
|
||||
* @className MassEventMessage
|
||||
* @author jy
|
||||
* @date 2014年4月27日
|
||||
* @since JDK 1.7
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E9%AB%98%E7%BA%A7%E7%BE%A4%E5%8F%91%E6%8E%A5%E5%8F%A3#.E4.BA.8B.E4.BB.B6.E6.8E.A8.E9.80.81.E7.BE.A4.E5.8F.91.E7.BB.93.E6.9E.9C">群发回调</a>
|
||||
*/
|
||||
public class MassEventMessage extends EventMessage {
|
||||
|
||||
private static final long serialVersionUID = -1660543255873723895L;
|
||||
|
||||
public MassEventMessage() {
|
||||
super(EventType.MASSSENDJOBFINISH);
|
||||
}
|
||||
|
||||
@XStreamAlias("Status")
|
||||
private String status;
|
||||
@XStreamAlias("TotalCount")
|
||||
private int totalCount;
|
||||
@XStreamAlias("FilterCount")
|
||||
private int filterCount;
|
||||
@XStreamAlias("SentCount")
|
||||
private int sentCount;
|
||||
@XStreamAlias("ErrorCount")
|
||||
private int errorCount;
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
public int getTotalCount() {
|
||||
return totalCount;
|
||||
}
|
||||
public void setTotalCount(int totalCount) {
|
||||
this.totalCount = totalCount;
|
||||
}
|
||||
public int getFilterCount() {
|
||||
return filterCount;
|
||||
}
|
||||
public void setFilterCount(int filterCount) {
|
||||
this.filterCount = filterCount;
|
||||
}
|
||||
public int getSentCount() {
|
||||
return sentCount;
|
||||
}
|
||||
public void setSentCount(int sentCount) {
|
||||
this.sentCount = sentCount;
|
||||
}
|
||||
public int getErrorCount() {
|
||||
return errorCount;
|
||||
}
|
||||
public void setErrorCount(int errorCount) {
|
||||
this.errorCount = errorCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[MassEventMessage ,toUserName=").append(super.getToUserName());
|
||||
sb.append(" ,fromUserName=").append(super.getFromUserName());
|
||||
sb.append(" ,msgType=").append(super.getMsgType().name());
|
||||
sb.append(" ,eventType=").append(super.getEventType().name());
|
||||
sb.append(" ,status=").append(status);
|
||||
sb.append(" ,totalCount=").append(totalCount);
|
||||
sb.append(" ,filterCount=").append(filterCount);
|
||||
sb.append(" ,sentCount=").append(sentCount);
|
||||
sb.append(" ,errorCount=").append(errorCount);
|
||||
sb.append(" ,createTime=").append(super.getCreateTime());
|
||||
sb.append(" ,msgId=").append(super.getMsgId()).append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
package com.foxinmy.weixin4j.msg.event;
|
||||
|
||||
import com.foxinmy.weixin4j.type.EventType;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 自定义菜单事件
|
||||
* @className MenuEventMessage
|
||||
* @author jy.hu
|
||||
* @date 2014年4月6日
|
||||
* @since JDK 1.7
|
||||
* @see <a href="http://mp.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E4%BA%8B%E4%BB%B6%E6%8E%A8%E9%80%81#.E8.87.AA.E5.AE.9A.E4.B9.89.E8.8F.9C.E5.8D.95.E4.BA.8B.E4.BB.B6">自定义菜单事件</a>
|
||||
* @see com.foxinmy.weixin4j.msg.BaseMessage
|
||||
* @see com.foxinmy.weixin4j.msg.BaseMessage#toXml()
|
||||
*/
|
||||
public class MenuEventMessage extends EventMessage {
|
||||
|
||||
private static final long serialVersionUID = -1049672447995366063L;
|
||||
|
||||
public MenuEventMessage() {
|
||||
super(EventType.click);
|
||||
}
|
||||
|
||||
@XStreamAlias("EventKey")
|
||||
private String eventKey; // 事件KEY值,与自定义菜单接口中KEY值对应
|
||||
|
||||
public String getEventKey() {
|
||||
return eventKey;
|
||||
}
|
||||
|
||||
public void setEventKey(String eventKey) {
|
||||
this.eventKey = eventKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[MenuEventMessage ,toUserName=").append(super.getToUserName());
|
||||
sb.append(" ,fromUserName=").append(super.getFromUserName());
|
||||
sb.append(" ,msgType=").append(super.getMsgType().name());
|
||||
sb.append(" ,eventType=").append(super.getEventType().name());
|
||||
sb.append(" ,eventKey=").append(eventKey);
|
||||
sb.append(" ,createTime=").append(super.getCreateTime());
|
||||
sb.append(" ,msgId=").append(super.getMsgId()).append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
package com.foxinmy.weixin4j.msg.event;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 扫描事件
|
||||
* @className ScanEventMessage
|
||||
* @author jy.hu
|
||||
* @date 2014年4月6日
|
||||
* @since JDK 1.7
|
||||
* @see <a href="http://mp.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E4%BA%8B%E4%BB%B6%E6%8E%A8%E9%80%81#.E6.89.AB.E6.8F.8F.E5.B8.A6.E5.8F.82.E6.95.B0.E4.BA.8C.E7.BB.B4.E7.A0.81.E4.BA.8B.E4.BB.B6">扫描二维码事件</a>
|
||||
* @see com.foxinmy.weixin4j.msg.BaseMessage
|
||||
* @see com.foxinmy.weixin4j.msg.BaseMessage#toXml()
|
||||
*/
|
||||
public class ScanEventMessage extends EventMessage {
|
||||
|
||||
public ScanEventMessage() {
|
||||
super(null);
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 8078674062833071562L;
|
||||
private static final String PARA_PREFIX = "qrscene_";
|
||||
|
||||
@XStreamAlias("EventKey")
|
||||
private String eventKey; // 事件KEY值,是一个32位无符号整数,即创建二维码时的二维码scene_id
|
||||
@XStreamAlias("Ticket")
|
||||
private String ticket; // 二维码的ticket,可用来换取二维码图片
|
||||
|
||||
public String getEventKey() {
|
||||
return eventKey;
|
||||
}
|
||||
|
||||
public void setEventKey(String eventKey) {
|
||||
this.eventKey = eventKey;
|
||||
}
|
||||
|
||||
public String getTicket() {
|
||||
return ticket;
|
||||
}
|
||||
|
||||
public void setTicket(String ticket) {
|
||||
this.ticket = ticket;
|
||||
}
|
||||
|
||||
public String getParameter() {
|
||||
return eventKey.replace(PARA_PREFIX, "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[ScanEventMessage ,toUserName=").append(super.getToUserName());
|
||||
sb.append(" ,fromUserName=").append(super.getFromUserName());
|
||||
sb.append(" ,msgType=").append(super.getMsgType().name());
|
||||
sb.append(" ,eventType=").append(super.getEventType().name());
|
||||
sb.append(" ,eventKey=").append(eventKey);
|
||||
sb.append(" ,ticket=").append(ticket);
|
||||
sb.append(" ,createTime=").append(super.getCreateTime());
|
||||
sb.append(" ,msgId=").append(super.getMsgId()).append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
package com.foxinmy.weixin4j.msg.event;
|
||||
|
||||
|
||||
/**
|
||||
* 关注/取消关注事件
|
||||
* <font color="red">包括直接关注与扫描关注</font>
|
||||
* @className ScribeEventMessage
|
||||
* @author jy.hu
|
||||
* @date 2014年4月6日
|
||||
* @since JDK 1.7
|
||||
* @see <a href="http://mp.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E4%BA%8B%E4%BB%B6%E6%8E%A8%E9%80%81#.E5.85.B3.E6.B3.A8.2F.E5.8F.96.E6.B6.88.E5.85.B3.E6.B3.A8.E4.BA.8B.E4.BB.B6">关注/取消关注事件</a>
|
||||
* @see com.foxinmy.weixin4j.msg.BaseMessage
|
||||
* @see com.foxinmy.weixin4j.msg.BaseMessage#toXml()
|
||||
*/
|
||||
public class ScribeEventMessage extends ScanEventMessage {
|
||||
|
||||
private static final long serialVersionUID = -6846321620262204915L;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[ScribeEventMessage ,toUserName=").append(super.getToUserName());
|
||||
sb.append(" ,fromUserName=").append(super.getFromUserName());
|
||||
sb.append(" ,msgType=").append(super.getMsgType().name());
|
||||
sb.append(" ,eventType=").append(super.getEventType().name());
|
||||
sb.append(" ,eventKey=").append(super.getEventKey());
|
||||
sb.append(" ,ticket=").append(super.getTicket());
|
||||
sb.append(" ,createTime=").append(super.getCreateTime());
|
||||
sb.append(" ,msgId=").append(super.getMsgId()).append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
58
src/main/java/com/foxinmy/weixin4j/msg/in/ImageMessage.java
Normal file
58
src/main/java/com/foxinmy/weixin4j/msg/in/ImageMessage.java
Normal file
@ -0,0 +1,58 @@
|
||||
package com.foxinmy.weixin4j.msg.in;
|
||||
|
||||
import com.foxinmy.weixin4j.msg.BaseMessage;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 图片消息
|
||||
* @className ImageMessage
|
||||
* @author jy.hu
|
||||
* @date 2014年4月6日
|
||||
* @since JDK 1.7
|
||||
* @see <a href="http://mp.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E6%99%AE%E9%80%9A%E6%B6%88%E6%81%AF#.E5.9B.BE.E7.89.87.E6.B6.88.E6.81.AF">图片消息</a>
|
||||
* @see com.foxinmy.weixin4j.msg.BaseMessage
|
||||
* @see com.foxinmy.weixin4j.msg.BaseMessage#toXml()
|
||||
*/
|
||||
public class ImageMessage extends BaseMessage {
|
||||
|
||||
private static final long serialVersionUID = 8430800898756567016L;
|
||||
|
||||
public ImageMessage() {
|
||||
super(MessageType.image);
|
||||
}
|
||||
|
||||
@XStreamAlias("PicUrl")
|
||||
private String picUrl; // 图片链接
|
||||
@XStreamAlias("MediaId")
|
||||
private String mediaId; // 图片消息媒体id,可以调用多媒体文件下载接口拉取数据。
|
||||
|
||||
public String getPicUrl() {
|
||||
return picUrl;
|
||||
}
|
||||
|
||||
public void setPicUrl(String picUrl) {
|
||||
this.picUrl = picUrl;
|
||||
}
|
||||
|
||||
public String getMediaId() {
|
||||
return mediaId;
|
||||
}
|
||||
|
||||
public void setMediaId(String mediaId) {
|
||||
this.mediaId = mediaId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[ImageMessage ,toUserName=").append(super.getToUserName());
|
||||
sb.append(" ,fromUserName=").append(super.getFromUserName());
|
||||
sb.append(" ,msgType=").append(super.getMsgType().name());
|
||||
sb.append(" ,picUrl=").append(picUrl);
|
||||
sb.append(" ,mediaId=").append(mediaId);
|
||||
sb.append(" ,createTime=").append(super.getCreateTime());
|
||||
sb.append(" ,msgId=").append(super.getMsgId()).append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
69
src/main/java/com/foxinmy/weixin4j/msg/in/LinkMessage.java
Normal file
69
src/main/java/com/foxinmy/weixin4j/msg/in/LinkMessage.java
Normal file
@ -0,0 +1,69 @@
|
||||
package com.foxinmy.weixin4j.msg.in;
|
||||
|
||||
import com.foxinmy.weixin4j.msg.BaseMessage;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 链接消息
|
||||
* @className LinkMessage
|
||||
* @author jy.hu
|
||||
* @date 2014年4月6日
|
||||
* @since JDK 1.7
|
||||
* @see <a href="http://mp.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E6%99%AE%E9%80%9A%E6%B6%88%E6%81%AF#.E9.93.BE.E6.8E.A5.E6.B6.88.E6.81.AF">链接消息</a>
|
||||
* @see com.foxinmy.weixin4j.msg.BaseMessage
|
||||
* @see com.foxinmy.weixin4j.msg.BaseMessage#toXml()
|
||||
*/
|
||||
public class LinkMessage extends BaseMessage {
|
||||
|
||||
private static final long serialVersionUID = 754952745115497030L;
|
||||
|
||||
public LinkMessage() {
|
||||
super(MessageType.link);
|
||||
}
|
||||
|
||||
@XStreamAlias("Title")
|
||||
private String title; // 消息标题
|
||||
@XStreamAlias("Description")
|
||||
private String description; // 消息描述
|
||||
@XStreamAlias("url")
|
||||
private String url; // 消息链接
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[LinkMessage ,toUserName=").append(super.getToUserName());
|
||||
sb.append(" ,fromUserName=").append(super.getFromUserName());
|
||||
sb.append(" ,msgType=").append(super.getMsgType().name());
|
||||
sb.append(" ,title=").append(title);
|
||||
sb.append(" ,description=").append(description);
|
||||
sb.append(" ,url=").append(url);
|
||||
sb.append(" ,createTime=").append(super.getCreateTime());
|
||||
sb.append(" ,msgId=").append(super.getMsgId()).append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,80 @@
|
||||
package com.foxinmy.weixin4j.msg.in;
|
||||
|
||||
import com.foxinmy.weixin4j.msg.BaseMessage;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 地理位置消息
|
||||
* @className LocationMessage
|
||||
* @author jy.hu
|
||||
* @date 2014年4月6日
|
||||
* @since JDK 1.7
|
||||
* @see <a href="http://mp.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E6%99%AE%E9%80%9A%E6%B6%88%E6%81%AF#.E5.9C.B0.E7.90.86.E4.BD.8D.E7.BD.AE.E6.B6.88.E6.81.AF">地理位置消息</a>
|
||||
* @see com.foxinmy.weixin4j.msg.BaseMessage
|
||||
* @see com.foxinmy.weixin4j.msg.BaseMessage#toXml()
|
||||
*/
|
||||
public class LocationMessage extends BaseMessage {
|
||||
|
||||
private static final long serialVersionUID = 2866021596599237334L;
|
||||
|
||||
public LocationMessage() {
|
||||
super(MessageType.location);
|
||||
}
|
||||
|
||||
@XStreamAlias("Location_X")
|
||||
private String location_X; // 地理位置维度
|
||||
@XStreamAlias("Location_Y")
|
||||
private String location_Y; // 地理位置经度
|
||||
@XStreamAlias("Scale")
|
||||
private String scale; // 地图缩放大小
|
||||
@XStreamAlias("Label")
|
||||
private String label; // 地理位置信息
|
||||
|
||||
public String getLocation_X() {
|
||||
return location_X;
|
||||
}
|
||||
|
||||
public void setLocation_X(String location_X) {
|
||||
this.location_X = location_X;
|
||||
}
|
||||
|
||||
public String getLocation_Y() {
|
||||
return location_Y;
|
||||
}
|
||||
|
||||
public void setLocation_Y(String location_Y) {
|
||||
this.location_Y = location_Y;
|
||||
}
|
||||
|
||||
public String getScale() {
|
||||
return scale;
|
||||
}
|
||||
|
||||
public void setScale(String scale) {
|
||||
this.scale = scale;
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
public void setLabel(String label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[LocationMessage ,toUserName=").append(super.getToUserName());
|
||||
sb.append(" ,fromUserName=").append(super.getFromUserName());
|
||||
sb.append(" ,msgType=").append(super.getMsgType().name());
|
||||
sb.append(" ,location_X=").append(location_X);
|
||||
sb.append(" ,location_Y=").append(location_Y);
|
||||
sb.append(" ,scale=").append(scale);
|
||||
sb.append(" ,label=").append(label);
|
||||
sb.append(" ,createTime=").append(super.getCreateTime());
|
||||
sb.append(" ,msgId=").append(super.getMsgId()).append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
58
src/main/java/com/foxinmy/weixin4j/msg/in/VideoMessage.java
Normal file
58
src/main/java/com/foxinmy/weixin4j/msg/in/VideoMessage.java
Normal file
@ -0,0 +1,58 @@
|
||||
package com.foxinmy.weixin4j.msg.in;
|
||||
|
||||
import com.foxinmy.weixin4j.msg.BaseMessage;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 视频消息
|
||||
* @className VideoMessage
|
||||
* @author jy.hu
|
||||
* @date 2014年4月6日
|
||||
* @since JDK 1.7
|
||||
* @see <a href="http://mp.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E6%99%AE%E9%80%9A%E6%B6%88%E6%81%AF#.E8.A7.86.E9.A2.91.E6.B6.88.E6.81.AF">视频消息</a>
|
||||
* @see com.foxinmy.weixin4j.msg.BaseMessage
|
||||
* @see com.foxinmy.weixin4j.msg.BaseMessage#toXml()
|
||||
*/
|
||||
public class VideoMessage extends BaseMessage {
|
||||
|
||||
private static final long serialVersionUID = -1013075358679078381L;
|
||||
|
||||
public VideoMessage() {
|
||||
super(MessageType.video);
|
||||
}
|
||||
|
||||
@XStreamAlias("MediaId")
|
||||
private String mediaId; // 视频消息媒体id,可以调用多媒体文件下载接口拉取数据。
|
||||
@XStreamAlias("ThumbMediaId")
|
||||
private String thumbMediaId; // 视频消息缩略图的媒体id,可以调用多媒体文件下载接口拉取数据。
|
||||
|
||||
public String getMediaId() {
|
||||
return mediaId;
|
||||
}
|
||||
|
||||
public void setMediaId(String mediaId) {
|
||||
this.mediaId = mediaId;
|
||||
}
|
||||
|
||||
public String getThumbMediaId() {
|
||||
return thumbMediaId;
|
||||
}
|
||||
|
||||
public void setThumbMediaId(String thumbMediaId) {
|
||||
this.thumbMediaId = thumbMediaId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[VideoMessage ,toUserName=").append(super.getToUserName());
|
||||
sb.append(" ,fromUserName=").append(super.getFromUserName());
|
||||
sb.append(" ,msgType=").append(super.getMsgType().name());
|
||||
sb.append(" ,mediaId=").append(mediaId);
|
||||
sb.append(" ,thumbMediaId=").append(thumbMediaId);
|
||||
sb.append(" ,createTime=").append(super.getCreateTime());
|
||||
sb.append(" ,msgId=").append(super.getMsgId()).append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
71
src/main/java/com/foxinmy/weixin4j/msg/in/VoiceMessage.java
Normal file
71
src/main/java/com/foxinmy/weixin4j/msg/in/VoiceMessage.java
Normal file
@ -0,0 +1,71 @@
|
||||
package com.foxinmy.weixin4j.msg.in;
|
||||
|
||||
import com.foxinmy.weixin4j.msg.BaseMessage;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 语音消息
|
||||
* <p>开通语音识别功能,用户每次发送语音给公众号时,微信会在推送的语音消息XML数据包中,赋值到Recongnition字段.</p>
|
||||
* @className VoiceMessage
|
||||
* @author jy.hu
|
||||
* @date 2014年4月6日
|
||||
* @since JDK 1.7
|
||||
* @see <a href="http://mp.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E6%99%AE%E9%80%9A%E6%B6%88%E6%81%AF#.E8.AF.AD.E9.9F.B3.E6.B6.88.E6.81.AF">语音消息</a>
|
||||
* @see com.foxinmy.weixin4j.msg.BaseMessage
|
||||
* @see com.foxinmy.weixin4j.msg.BaseMessage#toXml()
|
||||
*/
|
||||
public class VoiceMessage extends BaseMessage {
|
||||
|
||||
private static final long serialVersionUID = -7988380977182214003L;
|
||||
|
||||
public VoiceMessage() {
|
||||
super(MessageType.voice);
|
||||
}
|
||||
|
||||
@XStreamAlias("MediaId")
|
||||
private String mediaId; // 语音消息媒体id,可以调用多媒体文件下载接口拉取数据。
|
||||
@XStreamAlias("Format")
|
||||
private String format; // 语音格式,如amr,speex等
|
||||
|
||||
@XStreamAlias("Recognition")
|
||||
private String recognition; // 语音识别结果,UTF8编码
|
||||
|
||||
public String getRecognition() {
|
||||
return recognition;
|
||||
}
|
||||
|
||||
public void setRecognition(String recognition) {
|
||||
this.recognition = recognition;
|
||||
}
|
||||
|
||||
public String getMediaId() {
|
||||
return mediaId;
|
||||
}
|
||||
|
||||
public void setMediaId(String mediaId) {
|
||||
this.mediaId = mediaId;
|
||||
}
|
||||
|
||||
public String getFormat() {
|
||||
return format;
|
||||
}
|
||||
|
||||
public void setFormat(String format) {
|
||||
this.format = format;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[VoiceMessage ,toUserName=").append(super.getToUserName());
|
||||
sb.append(" ,fromUserName=").append(super.getFromUserName());
|
||||
sb.append(" ,msgType=").append(super.getMsgType().name());
|
||||
sb.append(" ,mediaId=").append(mediaId);
|
||||
sb.append(" ,format=").append(format);
|
||||
sb.append(" ,recognition=").append(recognition);
|
||||
sb.append(" ,createTime=").append(super.getCreateTime());
|
||||
sb.append(" ,msgId=").append(super.getMsgId()).append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
105
src/main/java/com/foxinmy/weixin4j/msg/notify/ArticleNotify.java
Normal file
105
src/main/java/com/foxinmy/weixin4j/msg/notify/ArticleNotify.java
Normal file
@ -0,0 +1,105 @@
|
||||
package com.foxinmy.weixin4j.msg.notify;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import com.thoughtworks.xstream.annotations.XStreamOmitField;
|
||||
|
||||
/**
|
||||
* 客服图文消息
|
||||
* @className ArticleNotify
|
||||
* @author jy.hu
|
||||
* @date 2014年4月6日
|
||||
* @since JDK 1.7
|
||||
* @see <a href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E5%AE%A2%E6%9C%8D%E6%B6%88%E6%81%AF#.E5.8F.91.E9.80.81.E5.9B.BE.E6.96.87.E6.B6.88.E6.81.AF">客服图文消息</a>
|
||||
* @see com.foxinmy.weixin4j.msg.notify.BaseNotify
|
||||
* @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson()
|
||||
*/
|
||||
public class ArticleNotify extends BaseNotify {
|
||||
private static final int MAX_ARTICLE_COUNT = 10;
|
||||
private static final long serialVersionUID = 1740696901128709998L;
|
||||
|
||||
public ArticleNotify() {
|
||||
super(MessageType.news);
|
||||
}
|
||||
|
||||
public ArticleNotify(String touser) {
|
||||
super(touser, MessageType.news);
|
||||
}
|
||||
|
||||
@XStreamAlias("news")
|
||||
private News news;
|
||||
|
||||
@XStreamOmitField
|
||||
private int count; // 图文消息个数,限制为10条以内
|
||||
|
||||
public void pushArticle(String title, String desc, String picUrl, String url) {
|
||||
if ((count + 1) > MAX_ARTICLE_COUNT) {
|
||||
return;
|
||||
}
|
||||
if (this.news == null) {
|
||||
this.news = new News();
|
||||
}
|
||||
this.news.pushArticle(title, desc, picUrl, url);
|
||||
count++;
|
||||
}
|
||||
|
||||
private static class News {
|
||||
@XStreamAlias("articles")
|
||||
private List<$> articles;
|
||||
|
||||
public News() {
|
||||
this.articles = new LinkedList<$>();
|
||||
}
|
||||
|
||||
public void pushArticle(String title, String desc, String picUrl, String url) {
|
||||
this.articles.add(new $(title, desc, picUrl, url));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for ($ item : articles) {
|
||||
sb.append("{title=").append(item.title);
|
||||
sb.append(" ,description=").append(item.desc);
|
||||
sb.append(" ,picUrl=").append(item.picUrl);
|
||||
sb.append(" ,url=").append(item.url).append("}");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private static class $ {
|
||||
private String title; // 图文消息标题
|
||||
@XStreamAlias("description")
|
||||
private String desc; // 图文消息描述
|
||||
@XStreamAlias("picurl")
|
||||
private String picUrl; // 图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200
|
||||
@XStreamAlias("url")
|
||||
private String url; // 点击图文消息跳转链接
|
||||
|
||||
public $(String title, String desc, String picUrl, String url) {
|
||||
this.title = title;
|
||||
this.desc = desc;
|
||||
this.picUrl = picUrl;
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("(article ,title=").append(title);
|
||||
sb.append(" ,description=").append(desc);
|
||||
sb.append(" ,picUrl=").append(picUrl);
|
||||
sb.append(" ,url=").append(url).append(")");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[ArticleNotify touser=%s ,msgtype=%s ,articles=%s]", super.getTouser(), super.getMsgtype().name(), this.news.toString());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,71 @@
|
||||
package com.foxinmy.weixin4j.msg.notify;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.io.Writer;
|
||||
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
import com.foxinmy.weixin4j.xml.XStream;
|
||||
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
|
||||
import com.thoughtworks.xstream.io.json.JsonHierarchicalStreamDriver;
|
||||
import com.thoughtworks.xstream.io.json.JsonWriter;
|
||||
|
||||
/**
|
||||
* 客服消息基类(48小时内不限制发送次数)
|
||||
* @author jy.hu
|
||||
* @date 2014年4月4日
|
||||
* @since JDK 1.7
|
||||
* @see <a href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E5%AE%A2%E6%9C%8D%E6%B6%88%E6%81%AF">发送客服消息</a>
|
||||
*/
|
||||
public class BaseNotify implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 7190233634431087729L;
|
||||
|
||||
private String touser;
|
||||
private MessageType msgtype;
|
||||
|
||||
public BaseNotify(MessageType msgtype) {
|
||||
this.msgtype = msgtype;
|
||||
}
|
||||
|
||||
public BaseNotify(String touser, MessageType msgtype) {
|
||||
this.touser = touser;
|
||||
this.msgtype = msgtype;
|
||||
}
|
||||
|
||||
public String getTouser() {
|
||||
return touser;
|
||||
}
|
||||
|
||||
public void setTouser(String touser) {
|
||||
this.touser = touser;
|
||||
}
|
||||
|
||||
public MessageType getMsgtype() {
|
||||
return msgtype;
|
||||
}
|
||||
|
||||
public void setMsgtype(MessageType msgtype) {
|
||||
this.msgtype = msgtype;
|
||||
}
|
||||
|
||||
/**
|
||||
* 客服消息json化
|
||||
* @return {"touser": "to","msgtype": "text","text": {"content": "123"}}
|
||||
*/
|
||||
public String toJson() {
|
||||
XStream xstream = new XStream(new JsonHierarchicalStreamDriver() {
|
||||
public HierarchicalStreamWriter createWriter(Writer writer) {
|
||||
return new JsonWriter(writer, JsonWriter.DROP_ROOT_MODE);
|
||||
}
|
||||
});
|
||||
xstream.setMode(XStream.NO_REFERENCES);
|
||||
xstream.autodetectAnnotations(true);
|
||||
xstream.processAnnotations(this.getClass());
|
||||
return xstream.toXML(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[BaseNotify touser=%s ,msgtype=%s]", touser, msgtype.name());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
package com.foxinmy.weixin4j.msg.notify;
|
||||
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 客服图片消息
|
||||
* @author jy.hu
|
||||
* @date 2014年4月4日
|
||||
* @since JDK 1.7
|
||||
* @see <a href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E5%AE%A2%E6%9C%8D%E6%B6%88%E6%81%AF#.E5.8F.91.E9.80.81.E5.9B.BE.E7.89.87.E6.B6.88.E6.81.AF">客服图片消息</a>
|
||||
* @see com.foxinmy.weixin4j.msg.notify.BaseNotify
|
||||
* @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson()
|
||||
*/
|
||||
public class ImageNotify extends BaseNotify {
|
||||
|
||||
private static final long serialVersionUID = -7698823863398518425L;
|
||||
|
||||
public ImageNotify() {
|
||||
super(MessageType.image);
|
||||
}
|
||||
|
||||
public ImageNotify(String mediaId) {
|
||||
super(MessageType.image);
|
||||
this.image = new $(mediaId);
|
||||
}
|
||||
|
||||
public ImageNotify(String mediaId, String touser) {
|
||||
super(touser, MessageType.image);
|
||||
this.image = new $(mediaId);
|
||||
}
|
||||
|
||||
@XStreamAlias("image")
|
||||
private $ image;
|
||||
|
||||
private static class $ {
|
||||
@XStreamAlias("media_id")
|
||||
private String mediaId;
|
||||
|
||||
public $(String mediaId) {
|
||||
this.mediaId = mediaId;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[ImageNotify touser=%s ,msgtype=%s ,mediaId=%s]", super.getTouser(), super.getMsgtype().name(), this.image.mediaId);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,67 @@
|
||||
package com.foxinmy.weixin4j.msg.notify;
|
||||
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 客服音乐消息
|
||||
* @author jy.hu
|
||||
* @date 2014年4月4日
|
||||
* @since JDK 1.7
|
||||
* @see <a href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E5%AE%A2%E6%9C%8D%E6%B6%88%E6%81%AF#.E5.8F.91.E9.80.81.E9.9F.B3.E4.B9.90.E6.B6.88.E6.81.AF">客服音乐消息</a>
|
||||
* @see com.foxinmy.weixin4j.msg.notify.BaseNotify
|
||||
* @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson()
|
||||
*/
|
||||
public class MusicNotify extends BaseNotify {
|
||||
|
||||
private static final long serialVersionUID = -7698823863398518425L;
|
||||
|
||||
public MusicNotify() {
|
||||
super(MessageType.music);
|
||||
}
|
||||
|
||||
public MusicNotify(String touser) {
|
||||
super(touser, MessageType.music);
|
||||
}
|
||||
|
||||
public void pushMusic(String title, String desc, String url, String hqUrl, String mediaId) {
|
||||
this.music = new $();
|
||||
this.music.thumbMediaId = mediaId;
|
||||
this.music.desc = desc;
|
||||
this.music.hqMusicUrl = hqUrl;
|
||||
this.music.musicUrl = url;
|
||||
this.music.title = title;
|
||||
}
|
||||
|
||||
@XStreamAlias("music")
|
||||
private $ music;
|
||||
|
||||
private static class $ {
|
||||
private String title;
|
||||
@XStreamAlias("description")
|
||||
private String desc;
|
||||
@XStreamAlias("musicurl")
|
||||
private String musicUrl;
|
||||
@XStreamAlias("hqmusicurl")
|
||||
private String hqMusicUrl;
|
||||
@XStreamAlias("thumb_media_id")
|
||||
private String thumbMediaId;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("(music ,title=").append(title);
|
||||
sb.append(" ,description=").append(desc);
|
||||
sb.append(" ,musicURL=").append(musicUrl);
|
||||
sb.append(" ,hqMusicUrl=").append(hqMusicUrl);
|
||||
sb.append(" ,thumbMediaId=").append(thumbMediaId).append(")");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[VideoNotify touser=%s ,msgtype=%s ,music=%s]", super.getTouser(), super.getMsgtype().name(), this.music.toString());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
package com.foxinmy.weixin4j.msg.notify;
|
||||
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 客服文本消息
|
||||
* @author jy.hu
|
||||
* @date 2014年4月4日
|
||||
* @since JDK 1.7
|
||||
* @see <a href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E5%AE%A2%E6%9C%8D%E6%B6%88%E6%81%AF#.E5.8F.91.E9.80.81.E6.96.87.E6.9C.AC.E6.B6.88.E6.81.AF">客服文本消息</a>
|
||||
* @see com.foxinmy.weixin4j.msg.notify.BaseNotify
|
||||
* @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson()
|
||||
*/
|
||||
public class TextNotify extends BaseNotify {
|
||||
|
||||
private static final long serialVersionUID = -7698823863398518425L;
|
||||
|
||||
public TextNotify() {
|
||||
super(MessageType.text);
|
||||
}
|
||||
|
||||
public TextNotify(String content) {
|
||||
super(MessageType.text);
|
||||
this.text = new $(content);
|
||||
}
|
||||
|
||||
public TextNotify(String content, String touser) {
|
||||
super(touser, MessageType.text);
|
||||
this.text = new $(content);
|
||||
}
|
||||
|
||||
@XStreamAlias("text")
|
||||
private $ text;
|
||||
|
||||
private static class $ {
|
||||
@XStreamAlias("content")
|
||||
private String content;
|
||||
|
||||
public $(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[TextNotify touser=%s ,msgtype=%s ,content=%s]", super.getTouser(), super.getMsgtype().name(), this.text.content);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
package com.foxinmy.weixin4j.msg.notify;
|
||||
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 客服视频消息
|
||||
* @author jy.hu
|
||||
* @date 2014年4月4日
|
||||
* @since JDK 1.7
|
||||
* @see <a href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E5%AE%A2%E6%9C%8D%E6%B6%88%E6%81%AF#.E5.8F.91.E9.80.81.E8.A7.86.E9.A2.91.E6.B6.88.E6.81.AF">客服视频消息</a>
|
||||
* @see com.foxinmy.weixin4j.msg.notify.BaseNotify
|
||||
* @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson()
|
||||
*/
|
||||
public class VideoNotify extends BaseNotify {
|
||||
|
||||
private static final long serialVersionUID = -7698823863398518425L;
|
||||
|
||||
public VideoNotify() {
|
||||
super(MessageType.video);
|
||||
}
|
||||
|
||||
public VideoNotify(String touser) {
|
||||
super(touser, MessageType.video);
|
||||
}
|
||||
|
||||
public void pushVideo(String mediaId, String title, String desc) {
|
||||
this.video = new $(mediaId, title, desc);
|
||||
}
|
||||
|
||||
@XStreamAlias("video")
|
||||
private $ video;
|
||||
|
||||
private static class $ {
|
||||
@XStreamAlias("media_id")
|
||||
private String mediaId;
|
||||
private String title;
|
||||
@XStreamAlias("description")
|
||||
private String desc;
|
||||
|
||||
public $(String mediaId, String title, String desc) {
|
||||
this.mediaId = mediaId;
|
||||
this.title = title;
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("(video mediaId=%s ,title=%s ,description=%s)", mediaId, title, desc);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[VideoNotify touser=%s ,msgtype=%s ,video=%s]", super.getTouser(), super.getMsgtype().name(), this.video.toString());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
package com.foxinmy.weixin4j.msg.notify;
|
||||
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 客服语音消息
|
||||
* @author jy.hu
|
||||
* @date 2014年4月4日
|
||||
* @since JDK 1.7
|
||||
* @see <a href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E5%AE%A2%E6%9C%8D%E6%B6%88%E6%81%AF#.E5.8F.91.E9.80.81.E8.AF.AD.E9.9F.B3.E6.B6.88.E6.81.AF">客服语音消息</a>
|
||||
* @see com.foxinmy.weixin4j.msg.notify.BaseNotify
|
||||
* @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson()
|
||||
*/
|
||||
public class VoiceNotify extends BaseNotify {
|
||||
|
||||
private static final long serialVersionUID = -7698823863398518425L;
|
||||
|
||||
public VoiceNotify() {
|
||||
super(MessageType.voice);
|
||||
}
|
||||
|
||||
public VoiceNotify(String mediaId) {
|
||||
super(MessageType.voice);
|
||||
this.voice = new $(mediaId);
|
||||
}
|
||||
|
||||
public VoiceNotify(String mediaId, String touser) {
|
||||
super(touser, MessageType.voice);
|
||||
this.voice = new $(mediaId);
|
||||
}
|
||||
|
||||
@XStreamAlias("voice")
|
||||
private $ voice;
|
||||
|
||||
private static class $ {
|
||||
@XStreamAlias("media_id")
|
||||
private String mediaId;
|
||||
|
||||
public $(String mediaId) {
|
||||
this.mediaId = mediaId;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[VoiceNotify touser=%s ,msgtype=%s ,mediaId=%s]", super.getTouser(), super.getMsgtype().name(), this.voice.mediaId);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,93 @@
|
||||
package com.foxinmy.weixin4j.msg.out;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import com.foxinmy.weixin4j.msg.BaseMessage;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 回复图文消息
|
||||
* @className ArticleMessage
|
||||
* @author jy.hu
|
||||
* @date 2014年3月23日
|
||||
* @since JDK 1.7
|
||||
* @see <a href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E8%A2%AB%E5%8A%A8%E5%93%8D%E5%BA%94%E6%B6%88%E6%81%AF#.E5.9B.9E.E5.A4.8D.E5.9B.BE.E6.96.87.E6.B6.88.E6.81.AF">回复图文消息</a>
|
||||
* @see com.foxinmy.weixin4j.msg.BaseMessage
|
||||
* @see com.foxinmy.weixin4j.msg.BaseMessage#toXml()
|
||||
*/
|
||||
public class ArticleMessage extends BaseMessage {
|
||||
private static final int MAX_ARTICLE_COUNT = 10;
|
||||
private static final long serialVersionUID = -7331603018352309317L;
|
||||
|
||||
public ArticleMessage() {
|
||||
super(MessageType.news);
|
||||
}
|
||||
|
||||
public ArticleMessage(String toUserName) {
|
||||
super(MessageType.news);
|
||||
super.setToUserName(toUserName);
|
||||
}
|
||||
|
||||
@XStreamAlias("ArticleCount")
|
||||
private int count; // 图文消息个数,限制为10条以内
|
||||
@XStreamAlias("Articles")
|
||||
private List<Article> articles;
|
||||
|
||||
public List<Article> getArticles() {
|
||||
return this.articles;
|
||||
}
|
||||
|
||||
public void pushArticle(String title, String desc, String picUrl, String url) {
|
||||
if ((count + 1) > MAX_ARTICLE_COUNT) {
|
||||
return;
|
||||
}
|
||||
if (this.articles == null) {
|
||||
this.articles = new LinkedList<ArticleMessage.Article>();
|
||||
}
|
||||
this.articles.add(new Article(title, desc, picUrl, url));
|
||||
count ++;
|
||||
}
|
||||
|
||||
@XStreamAlias("item")
|
||||
private static class Article {
|
||||
@XStreamAlias("Title")
|
||||
private String title; // 图文消息标题
|
||||
@XStreamAlias("Description")
|
||||
private String desc; // 图文消息描述
|
||||
@XStreamAlias("PicUrl")
|
||||
private String picUrl; // 图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200
|
||||
@XStreamAlias("Url")
|
||||
private String url; // 点击图文消息跳转链接
|
||||
|
||||
public Article(String title, String desc, String picUrl, String url) {
|
||||
this.title = title;
|
||||
this.desc = desc;
|
||||
this.picUrl = picUrl;
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("(Article ,title=").append(title);
|
||||
sb.append(" ,description=").append(desc);
|
||||
sb.append(" ,picUrl=").append(picUrl);
|
||||
sb.append(" ,url=").append(url).append(")");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[ArticleMessage ,toUserName=").append(super.getToUserName());
|
||||
sb.append(" ,fromUserName=").append(super.getFromUserName());
|
||||
sb.append(" ,msgType=").append(super.getMsgType().name());
|
||||
sb.append(" ,articles=").append(getArticles().toString());
|
||||
sb.append(" ,createTime=").append(super.getCreateTime());
|
||||
sb.append(" ,msgId=").append(super.getMsgId()).append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
49
src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java
Normal file
49
src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java
Normal file
@ -0,0 +1,49 @@
|
||||
package com.foxinmy.weixin4j.msg.out;
|
||||
|
||||
import com.foxinmy.weixin4j.msg.BaseMessage;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 回复图片消息
|
||||
* @className ImageMessage
|
||||
* @author jy.hu
|
||||
* @date 2014年3月23日
|
||||
* @since JDK 1.7
|
||||
* @see <a href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E8%A2%AB%E5%8A%A8%E5%93%8D%E5%BA%94%E6%B6%88%E6%81%AF#.E5.9B.9E.E5.A4.8D.E5.9B.BE.E7.89.87.E6.B6.88.E6.81.AF">回复图片消息</a>
|
||||
* @see com.foxinmy.weixin4j.msg.BaseMessage
|
||||
* @see com.foxinmy.weixin4j.msg.BaseMessage#toXml()
|
||||
*/
|
||||
public class ImageMessage extends BaseMessage {
|
||||
private static final long serialVersionUID = 6998255203997554731L;
|
||||
|
||||
public ImageMessage() {
|
||||
super(MessageType.image);
|
||||
super.getMsgType().setMessageClass(ImageMessage.class);
|
||||
}
|
||||
|
||||
@XStreamAlias("Image")
|
||||
private Image image;
|
||||
|
||||
public void pushMediaId(String mediaId) {
|
||||
this.image = new Image();
|
||||
this.image.mediaId = mediaId;
|
||||
}
|
||||
|
||||
private static class Image {
|
||||
@XStreamAlias("MediaId")
|
||||
private String mediaId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[ImageMessage ,toUserName=").append(super.getToUserName());
|
||||
sb.append(" ,fromUserName=").append(super.getFromUserName());
|
||||
sb.append(" ,msgType=").append(super.getMsgType().name());
|
||||
sb.append(" ,mediaId=").append(this.image.mediaId);
|
||||
sb.append(" ,createTime=").append(super.getCreateTime());
|
||||
sb.append(" ,msgId=").append(super.getMsgId()).append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
76
src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java
Normal file
76
src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java
Normal file
@ -0,0 +1,76 @@
|
||||
package com.foxinmy.weixin4j.msg.out;
|
||||
|
||||
import com.foxinmy.weixin4j.msg.BaseMessage;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 回复音乐消息
|
||||
* @className MusicMessage
|
||||
* @author jy.hu
|
||||
* @date 2014年3月23日
|
||||
* @since JDK 1.7
|
||||
* @see <a href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E8%A2%AB%E5%8A%A8%E5%93%8D%E5%BA%94%E6%B6%88%E6%81%AF#.E5.9B.9E.E5.A4.8D.E9.9F.B3.E4.B9.90.E6.B6.88.E6.81.AF">回复音乐消息</a>
|
||||
* @see com.foxinmy.weixin4j.msg.BaseMessage
|
||||
* @see com.foxinmy.weixin4j.msg.BaseMessage#toXml()
|
||||
*/
|
||||
public class MusicMessage extends BaseMessage {
|
||||
|
||||
private static final long serialVersionUID = 4384403772658796395L;
|
||||
|
||||
public MusicMessage() {
|
||||
super(MessageType.music);
|
||||
}
|
||||
|
||||
@XStreamAlias("Music")
|
||||
private Music music;
|
||||
|
||||
public Music getMusic() {
|
||||
return this.music;
|
||||
}
|
||||
|
||||
public void pushMusic(String title, String desc, String url, String hqUrl, String mediaId) {
|
||||
this.music = new Music();
|
||||
this.music.thumbMediaId = mediaId;
|
||||
this.music.desc = desc;
|
||||
this.music.hqMusicUrl = hqUrl;
|
||||
this.music.MusicURL = url;
|
||||
this.music.title = title;
|
||||
}
|
||||
|
||||
private static class Music {
|
||||
@XStreamAlias("Title")
|
||||
private String title; // 音乐标题
|
||||
@XStreamAlias("Description")
|
||||
private String desc; // 音乐描述
|
||||
@XStreamAlias("MusicURL")
|
||||
private String MusicURL; // 音乐链接
|
||||
@XStreamAlias("HQMusicUrl")
|
||||
private String hqMusicUrl; // 高质量音乐链接,WIFI环境优先使用该链接播放音乐
|
||||
@XStreamAlias("ThumbMediaId")
|
||||
private String thumbMediaId; // 缩略图的媒体id,通过上传多媒体文件,得到的id
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("(Music ,title=").append(title);
|
||||
sb.append(" ,description=").append(desc);
|
||||
sb.append(" ,musicURL=").append(MusicURL);
|
||||
sb.append(" ,hqMusicUrl=").append(hqMusicUrl);
|
||||
sb.append(" ,thumbMediaId=").append(thumbMediaId).append(")");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[MusicMessage ,toUserName=").append(super.getToUserName());
|
||||
sb.append(" ,fromUserName=").append(super.getFromUserName());
|
||||
sb.append(" ,msgType=").append(super.getMsgType().name());
|
||||
sb.append(" ,music=").append(getMusic().toString());
|
||||
sb.append(" ,createTime=").append(super.getCreateTime());
|
||||
sb.append(" ,msgId=").append(super.getMsgId()).append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
69
src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java
Normal file
69
src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java
Normal file
@ -0,0 +1,69 @@
|
||||
package com.foxinmy.weixin4j.msg.out;
|
||||
|
||||
import com.foxinmy.weixin4j.msg.BaseMessage;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 回复视频消息
|
||||
* @className VideoMessage
|
||||
* @author jy.hu
|
||||
* @date 2014年4月6日
|
||||
* @since JDK 1.7
|
||||
* @see <a href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E8%A2%AB%E5%8A%A8%E5%93%8D%E5%BA%94%E6%B6%88%E6%81%AF#.E5.9B.9E.E5.A4.8D.E8.A7.86.E9.A2.91.E6.B6.88.E6.81.AF">回复视频消息</a>
|
||||
* @see com.foxinmy.weixin4j.msg.BaseMessage
|
||||
* @see com.foxinmy.weixin4j.msg.BaseMessage#toXml()
|
||||
*/
|
||||
public class VideoMessage extends BaseMessage {
|
||||
|
||||
private static final long serialVersionUID = -1013075358679078381L;
|
||||
|
||||
public VideoMessage() {
|
||||
super(MessageType.video);
|
||||
super.getMsgType().setMessageClass(VideoMessage.class);
|
||||
}
|
||||
|
||||
@XStreamAlias("Video")
|
||||
private Video video;
|
||||
|
||||
public Video getVideo() {
|
||||
return this.video;
|
||||
}
|
||||
|
||||
public void pushVideo(String mediaId, String title, String desc) {
|
||||
this.video = new Video();
|
||||
this.video.desc = desc;
|
||||
this.video.mediaId = mediaId;
|
||||
this.video.title = title;
|
||||
}
|
||||
|
||||
private static class Video {
|
||||
@XStreamAlias("MediaId")
|
||||
private String mediaId;
|
||||
@XStreamAlias("Title")
|
||||
private String title;
|
||||
@XStreamAlias("Description")
|
||||
private String desc;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("(Video mediaId=").append(mediaId);
|
||||
sb.append(" ,title=").append(title);
|
||||
sb.append(" ,desc=").append(desc).append(")");
|
||||
return super.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[VideoMessage ,toUserName=").append(super.getToUserName());
|
||||
sb.append(" ,fromUserName=").append(super.getFromUserName());
|
||||
sb.append(" ,msgType=").append(super.getMsgType().name());
|
||||
sb.append(" ,video=").append(getVideo().toString());
|
||||
sb.append(" ,createTime=").append(super.getCreateTime());
|
||||
sb.append(" ,msgId=").append(super.getMsgId()).append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
55
src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java
Normal file
55
src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java
Normal file
@ -0,0 +1,55 @@
|
||||
package com.foxinmy.weixin4j.msg.out;
|
||||
|
||||
import com.foxinmy.weixin4j.msg.BaseMessage;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 语音消息
|
||||
* @className VoiceMessage
|
||||
* @author jy.hu
|
||||
* @date 2014年3月23日
|
||||
* @since JDK 1.7
|
||||
* @see <a href="http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E8%A2%AB%E5%8A%A8%E5%93%8D%E5%BA%94%E6%B6%88%E6%81%AF#.E5.9B.9E.E5.A4.8D.E8.AF.AD.E9.9F.B3.E6.B6.88.E6.81.AF">回复语音消息</a>
|
||||
* @see com.foxinmy.weixin4j.msg.BaseMessage
|
||||
* @see com.foxinmy.weixin4j.msg.BaseMessage#toXml()
|
||||
*/
|
||||
public class VoiceMessage extends BaseMessage {
|
||||
|
||||
private static final long serialVersionUID = -7944926238652243793L;
|
||||
|
||||
public VoiceMessage() {
|
||||
super(MessageType.voice);
|
||||
super.getMsgType().setMessageClass(VoiceMessage.class);
|
||||
}
|
||||
@XStreamAlias("Voice")
|
||||
private Voice voice;
|
||||
|
||||
public Voice getVocie() {
|
||||
return voice;
|
||||
}
|
||||
public void pushMediaId(String mediaId){
|
||||
this.voice = new Voice();
|
||||
this.voice.setMediaId(mediaId);
|
||||
}
|
||||
|
||||
private static class Voice {
|
||||
@XStreamAlias("MediaId")
|
||||
private String mediaId;
|
||||
|
||||
private void setMediaId(String mediaId) {
|
||||
this.mediaId = mediaId;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[VoiceMessage ,toUserName=").append(super.getToUserName());
|
||||
sb.append(" ,fromUserName=").append(super.getFromUserName());
|
||||
sb.append(" ,msgType=").append(super.getMsgType().name());
|
||||
sb.append(" ,mediaId=").append(getVocie().mediaId);
|
||||
sb.append(" ,createTime=").append(super.getCreateTime());
|
||||
sb.append(" ,msgId=").append(super.getMsgId()).append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
30
src/main/java/com/foxinmy/weixin4j/type/EventType.java
Normal file
30
src/main/java/com/foxinmy/weixin4j/type/EventType.java
Normal file
@ -0,0 +1,30 @@
|
||||
package com.foxinmy.weixin4j.type;
|
||||
|
||||
import com.foxinmy.weixin4j.msg.event.EventMessage;
|
||||
import com.foxinmy.weixin4j.msg.event.LocationEventMessage;
|
||||
import com.foxinmy.weixin4j.msg.event.MassEventMessage;
|
||||
import com.foxinmy.weixin4j.msg.event.MenuEventMessage;
|
||||
import com.foxinmy.weixin4j.msg.event.ScanEventMessage;
|
||||
import com.foxinmy.weixin4j.msg.event.ScribeEventMessage;
|
||||
|
||||
/**
|
||||
*
|
||||
* 事件类型
|
||||
* @author jy.hu
|
||||
*
|
||||
*/
|
||||
public enum EventType {
|
||||
subscribe(ScribeEventMessage.class), unsubscribe(ScribeEventMessage.class),
|
||||
scan(ScanEventMessage.class),click(MenuEventMessage.class),view(MenuEventMessage.class),
|
||||
location(LocationEventMessage.class),MASSSENDJOBFINISH(MassEventMessage.class);
|
||||
|
||||
private Class<? extends EventMessage> eventClass;
|
||||
|
||||
EventType(Class<? extends EventMessage> eventClass) {
|
||||
this.eventClass = eventClass;
|
||||
}
|
||||
|
||||
public Class<? extends EventMessage> getEventClass() {
|
||||
return eventClass;
|
||||
}
|
||||
}
|
||||
32
src/main/java/com/foxinmy/weixin4j/type/MediaType.java
Normal file
32
src/main/java/com/foxinmy/weixin4j/type/MediaType.java
Normal file
@ -0,0 +1,32 @@
|
||||
package com.foxinmy.weixin4j.type;
|
||||
|
||||
/**
|
||||
* 上传的媒体类型<br/>
|
||||
* 图片(image): 128K,支持JPG格式<br/>
|
||||
* 语音(voice):256K,播放长度不超过60s,支持AMR\MP3格式<br/>
|
||||
* 视频(video):1MB,支持MP4格式<br/>
|
||||
* 缩略图(thumb):64KB,支持JPG格式<br/>
|
||||
* <p><font color='red'>媒体文件在后台保存时间为3天,即3天后media_id失效</font><p/>
|
||||
* @author jy.hu
|
||||
* @date 2014年4月2日
|
||||
* @since JDK 1.7
|
||||
*/
|
||||
public enum MediaType {
|
||||
image("image/jpeg",".jpg"), voice("binary/octet-stream","amr"), vedio("binary/octet-stream","mp4"), thumb("image/jpeg","jpg");
|
||||
|
||||
MediaType(String contentType, String formatType) {
|
||||
this.contentType = contentType;
|
||||
this.formatType = formatType;
|
||||
}
|
||||
|
||||
private String contentType;
|
||||
|
||||
public String getContentType() {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
private String formatType;
|
||||
public String getFormatType() {
|
||||
return formatType;
|
||||
}
|
||||
}
|
||||
39
src/main/java/com/foxinmy/weixin4j/type/MessageType.java
Normal file
39
src/main/java/com/foxinmy/weixin4j/type/MessageType.java
Normal file
@ -0,0 +1,39 @@
|
||||
package com.foxinmy.weixin4j.type;
|
||||
|
||||
import com.foxinmy.weixin4j.msg.BaseMessage;
|
||||
import com.foxinmy.weixin4j.msg.TextMessage;
|
||||
import com.foxinmy.weixin4j.msg.event.EventMessage;
|
||||
import com.foxinmy.weixin4j.msg.in.ImageMessage;
|
||||
import com.foxinmy.weixin4j.msg.in.LinkMessage;
|
||||
import com.foxinmy.weixin4j.msg.in.LocationMessage;
|
||||
import com.foxinmy.weixin4j.msg.in.VideoMessage;
|
||||
import com.foxinmy.weixin4j.msg.in.VoiceMessage;
|
||||
import com.foxinmy.weixin4j.msg.out.ArticleMessage;
|
||||
import com.foxinmy.weixin4j.msg.out.MusicMessage;
|
||||
|
||||
/**
|
||||
*
|
||||
* 消息类型
|
||||
*
|
||||
* @author jy.hu
|
||||
*
|
||||
*/
|
||||
public enum MessageType {
|
||||
// 接收到的消息类型
|
||||
text(TextMessage.class), image(ImageMessage.class), voice(VoiceMessage.class), video(VideoMessage.class), location(LocationMessage.class), link(LinkMessage.class), event(EventMessage.class),
|
||||
// 发送的消息类型
|
||||
music(MusicMessage.class), news(ArticleMessage.class);
|
||||
private Class<? extends BaseMessage> messageClass;
|
||||
|
||||
MessageType(Class<? extends BaseMessage> messageClass) {
|
||||
this.messageClass = messageClass;
|
||||
}
|
||||
|
||||
public void setMessageClass(Class<? extends BaseMessage> messageClass) {
|
||||
this.messageClass = messageClass;
|
||||
}
|
||||
|
||||
public Class<? extends BaseMessage> getMessageClass() {
|
||||
return messageClass;
|
||||
}
|
||||
}
|
||||
41
src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java
Normal file
41
src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java
Normal file
@ -0,0 +1,41 @@
|
||||
package com.foxinmy.weixin4j.util;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class WeixinConfig {
|
||||
public WeixinConfig() {
|
||||
}
|
||||
|
||||
private static Properties props = new Properties();
|
||||
static {
|
||||
try {
|
||||
props.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("config.properties"));
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static String getValue(String key) {
|
||||
String url = props.getProperty(key);
|
||||
Pattern p = Pattern.compile("(\\{[^\\}]*\\})");
|
||||
Matcher m = p.matcher(url);
|
||||
StringBuffer sb = new StringBuffer();
|
||||
String sub = null;
|
||||
while (m.find()) {
|
||||
sub = m.group();
|
||||
m.appendReplacement(sb, getValue(sub.substring(1, sub.length() - 1)));
|
||||
}
|
||||
m.appendTail(sb);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(getValue("api_token_uri"));
|
||||
}
|
||||
}
|
||||
8
src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java
Normal file
8
src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java
Normal file
@ -0,0 +1,8 @@
|
||||
package com.foxinmy.weixin4j.util;
|
||||
|
||||
public class WeixinUtil {
|
||||
|
||||
public static boolean isBlank(String str) {
|
||||
return str == null || str.isEmpty();
|
||||
}
|
||||
}
|
||||
44
src/main/java/com/foxinmy/weixin4j/xml/XStream.java
Normal file
44
src/main/java/com/foxinmy/weixin4j/xml/XStream.java
Normal file
@ -0,0 +1,44 @@
|
||||
package com.foxinmy.weixin4j.xml;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.Writer;
|
||||
|
||||
import com.thoughtworks.xstream.core.util.QuickWriter;
|
||||
import com.thoughtworks.xstream.io.HierarchicalStreamDriver;
|
||||
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
|
||||
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
|
||||
import com.thoughtworks.xstream.io.xml.Xpp3Driver;
|
||||
|
||||
public class XStream extends com.thoughtworks.xstream.XStream {
|
||||
|
||||
public XStream() {
|
||||
|
||||
super(new Xpp3Driver() {
|
||||
|
||||
@Override
|
||||
public HierarchicalStreamWriter createWriter(Writer out) {
|
||||
return new PrettyPrintWriter(out) {
|
||||
|
||||
@Override
|
||||
protected void writeText(QuickWriter writer, String text) {
|
||||
writer.write("<![CDATA[");
|
||||
writer.write(text);
|
||||
writer.write("]]>");
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
public XStream(HierarchicalStreamDriver hierarchicalStreamDriver) {
|
||||
super(hierarchicalStreamDriver);
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T fromXML(String xml, Class<T> t) {
|
||||
return (T) super.fromXML(xml);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T fromXML(InputStream inputStream, Class<T> t) {
|
||||
return (T) super.fromXML(inputStream);
|
||||
}
|
||||
}
|
||||
70
src/main/resource/config.properties
Normal file
70
src/main/resource/config.properties
Normal file
@ -0,0 +1,70 @@
|
||||
# app\u4fe1\u606f
|
||||
app_id=wx4ab8f8de58159a57
|
||||
app_secret=1d4eb0f4bf556aaed539f30ed05ca795
|
||||
app_openId=gh_22b350df957b
|
||||
app_token=carsonliu13450438112
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# api\u9996\u9875
|
||||
# http://mp.weixin.qq.com/wiki/index.php
|
||||
# \u63a5\u53e3\u8c03\u7528\u8bf4\u660e
|
||||
# http://mp.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E5%8F%A3%E9%A2%91%E7%8E%87%E9%99%90%E5%88%B6%E8%AF%B4%E6%98%8E
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
api_base_url=https://api.weixin.qq.com/cgi-bin
|
||||
mp_base_url=https://mp.weixin.qq.com/cgi-bin
|
||||
file_base_url=http://file.api.weixin.qq.com/cgi-bin
|
||||
|
||||
# \u7f51\u9875\u6388\u6743\u83b7\u53d6\u7528\u6237\u4fe1\u606f
|
||||
user_auth_uri=https://open.weixin.qq.com/connect/oauth2/authorize?appid={app_id}&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect
|
||||
sns_user_token_uri=https://api.weixin.qq.com/sns/oauth2/access_token?appid={app_id}&secret={app_secret}&code=%s&grant_type=authorization_code
|
||||
sns_user_info_uri=https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN
|
||||
|
||||
# \u76f4\u63a5\u83b7\u53d6\u7528\u6237\u4fe1\u606f
|
||||
api_user_info_uri={api_base_url}/user/info?access_token=%s&openid=%s&lang=zh_CN
|
||||
# \u83b7\u53d6\u6211\u7684token
|
||||
api_token_uri={api_base_url}/token?grant_type=client_credential&appid={app_id}&secret={app_secret}
|
||||
|
||||
# \u83b7\u53d6\u4e8c\u7ef4\u7801
|
||||
qr_ticket_uri={api_base_url}/qrcode/create?access_token=%s
|
||||
qr_image_uri={mp_base_url}/showqrcode?ticket=%s
|
||||
|
||||
# \u4e0a\u4f20\u5a92\u4f53\u6587\u4ef6
|
||||
file_upload_uri={file_base_url}/media/upload?access_token=%s&type=%s
|
||||
file_download_uri={file_base_url}/media/get?access_token=%s&media_id=%s
|
||||
|
||||
# \u53d1\u9001\u5ba2\u670d\u6d88\u606f
|
||||
custom_notify_uri={api_base_url}/message/custom/send?access_token=%s
|
||||
# \u521b\u5efa\u5206\u7ec4
|
||||
group_create_uri={api_base_url}/groups/create?access_token=%s
|
||||
# \u67e5\u8be2\u5206\u7ec4
|
||||
group_get_uri={api_base_url}/groups/get?access_token=%s
|
||||
# \u67e5\u8be2\u7528\u6237\u6240\u5728\u5206\u7ec4
|
||||
group_getid_uri={api_base_url}/groups/getid?access_token=%s
|
||||
# \u4fee\u6539\u5206\u7ec4\u540d
|
||||
group_modify_uri={api_base_url}/groups/update?access_token=%s
|
||||
# \u79fb\u52a8\u7528\u6237\u5206\u7ec4
|
||||
group_move_uri={api_base_url}/groups/members/update?access_token=%s
|
||||
# \u83b7\u53d6\u5173\u6ce8\u7740
|
||||
following_uri={api_base_url}/user/get?access_token=%s&next_openid=%s
|
||||
# \u81ea\u5b9a\u4e49\u83dc\u5355
|
||||
menu_create_uri={api_base_url}/menu/create?access_token=%s
|
||||
# \u67e5\u8be2\u83dc\u5355
|
||||
menu_get_uri={api_base_url}/menu/get?access_token=%s
|
||||
# \u5220\u9664\u83dc\u5355
|
||||
menu_delete_uri={api_base_url}/menu/delete?access_token=%s
|
||||
# \u4e0a\u4f20\u6d88\u606f
|
||||
news_upload_uri={api_base_url}/media/uploadnews?access_token=%s
|
||||
# \u5206\u7ec4\u7fa4\u53d1
|
||||
mass_group_uri={api_base_url}/message/mass/sendall?access_token=%s
|
||||
# openId\u7fa4\u53d1
|
||||
mass_openid_uri={api_base_url}/message/mass/send?access_token=%s
|
||||
# \u5220\u9664\u7fa4\u53d1
|
||||
mass_delete_uri={api_base_url}/message/mass/delete?access_token=%s
|
||||
|
||||
# token\u5b58\u653e\u8def\u5f84
|
||||
token_path=/tmp/weixin/token
|
||||
# \u4e8c\u7ef4\u7801\u4fdd\u5b58\u8def\u5f84
|
||||
qr_path=/tmp/weixin/qr
|
||||
# \u5a92\u4f53\u6587\u4ef6\u4fdd\u5b58\u8def\u5f84
|
||||
media_path=/tmp/weixin/media
|
||||
85
src/main/resource/error_code.xml
Normal file
85
src/main/resource/error_code.xml
Normal file
@ -0,0 +1,85 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- http://mp.weixin.qq.com/wiki/index.php?title=%E5%85%A8%E5%B1%80%E8%BF%94%E5%9B%9E%E7%A0%81%E8%AF%B4%E6%98%8E -->
|
||||
<errors>
|
||||
<error code="-1">系统繁忙</error>
|
||||
<error code="40001">获取access_token时AppSecret错误,或者access_token无效</error>
|
||||
<error code="40002">不合法的凭证类型</error>
|
||||
<error code="40003">不合法的OpenID</error>
|
||||
<error code="40004">不合法的媒体文件类型</error>
|
||||
<error code="40005">不合法的文件类型</error>
|
||||
<error code="40006">不合法的文件大小</error>
|
||||
<error code="40007">不合法的媒体文件id</error>
|
||||
<error code="40008">不合法的消息类型</error>
|
||||
<error code="40009">不合法的图片文件大小</error>
|
||||
<error code="40010">不合法的语音文件大小</error>
|
||||
<error code="40011">不合法的视频文件大小</error>
|
||||
<error code="40012">不合法的缩略图文件大小</error>
|
||||
<error code="40013">不合法的APPID</error>
|
||||
<error code="40014">不合法的access_token</error>
|
||||
<error code="40015">不合法的菜单类型</error>
|
||||
<error code="40016">不合法的按钮个数</error>
|
||||
<error code="40017">不合法的按钮个数</error>
|
||||
<error code="40018">不合法的按钮名字长度</error>
|
||||
<error code="40019">不合法的按钮KEY长度</error>
|
||||
<error code="40020">不合法的按钮URL长度</error>
|
||||
<error code="40021">不合法的菜单版本号</error>
|
||||
<error code="40022">不合法的子菜单级数</error>
|
||||
<error code="40023">不合法的子菜单按钮个数</error>
|
||||
<error code="40024">不合法的子菜单按钮类型</error>
|
||||
<error code="40025">不合法的子菜单按钮名字长度</error>
|
||||
<error code="40026">不合法的子菜单按钮KEY长度</error>
|
||||
<error code="40027">不合法的子菜单按钮URL长度</error>
|
||||
<error code="40028">不合法的自定义菜单使用用户</error>
|
||||
<error code="40029">不合法的oauth_code</error>
|
||||
<error code="40030">不合法的refresh_token</error>
|
||||
<error code="40031">不合法的openid列表</error>
|
||||
<error code="40032">不合法的openid列表长度</error>
|
||||
<error code="40033">不合法的请求字符,不能包含\uxxxx格式的字符</error>
|
||||
<error code="40035">不合法的参数</error>
|
||||
<error code="40038">不合法的请求格式</error>
|
||||
<error code="40039">不合法的URL长度</error>
|
||||
<error code="40050">不合法的分组id</error>
|
||||
<error code="40051">分组名字不合法</error>
|
||||
<error code="41001">缺少access_token参数</error>
|
||||
<error code="41002">缺少appid参数</error>
|
||||
<error code="41003">缺少refresh_token参数</error>
|
||||
<error code="41004">缺少secret参数</error>
|
||||
<error code="41005">缺少多媒体文件数据</error>
|
||||
<error code="41006">缺少media_id参数</error>
|
||||
<error code="41007">缺少子菜单数据</error>
|
||||
<error code="41008">缺少oauth code</error>
|
||||
<error code="41009">缺少openid</error>
|
||||
<error code="42001">access_token超时</error>
|
||||
<error code="42002">refresh_token超时</error>
|
||||
<error code="42003">oauth_code超时</error>
|
||||
<error code="43001">需要GET请求</error>
|
||||
<error code="43002">需要POST请求</error>
|
||||
<error code="43003">需要HTTPS请求</error>
|
||||
<error code="43004">需要接收者关注</error>
|
||||
<error code="43005">需要好友关系</error>
|
||||
<error code="44001">多媒体文件为空</error>
|
||||
<error code="44002">POST的数据包为空</error>
|
||||
<error code="44003">图文消息内容为空</error>
|
||||
<error code="44004">文本消息内容为空</error>
|
||||
<error code="45001">多媒体文件大小超过限制</error>
|
||||
<error code="45002">消息内容超过限制</error>
|
||||
<error code="45003">标题字段超过限制</error>
|
||||
<error code="45004">描述字段超过限制</error>
|
||||
<error code="45005">链接字段超过限制</error>
|
||||
<error code="45006">图片链接字段超过限制</error>
|
||||
<error code="45007">语音播放时间超过限制</error>
|
||||
<error code="45008">图文消息超过限制</error>
|
||||
<error code="45009">接口调用超过限制</error>
|
||||
<error code="45010">创建菜单个数超过限制</error>
|
||||
<error code="45015">回复时间超过限制</error>
|
||||
<error code="45016">系统分组,不允许修改</error>
|
||||
<error code="45017">分组名字过长</error>
|
||||
<error code="45018">分组数量超过上限</error>
|
||||
<error code="46001">不存在媒体数据</error>
|
||||
<error code="46002">不存在的菜单版本</error>
|
||||
<error code="46003">不存在的菜单数据</error>
|
||||
<error code="46004">不存在的用户</error>
|
||||
<error code="47001">解析JSON/XML内容错误</error>
|
||||
<error code="48001">api功能未授权</error>
|
||||
<error code="50001">用户未授权该api</error>
|
||||
</errors>
|
||||
62
src/main/resource/logback.xml
Normal file
62
src/main/resource/logback.xml
Normal file
@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!-- For assistance related to logback-translator or configuration -->
|
||||
<!-- files in general, please contact the logback user mailing list -->
|
||||
<!-- at http://www.qos.ch/mailman/listinfo/logback-user -->
|
||||
<!-- -->
|
||||
<!-- For professional support please see -->
|
||||
<!-- http://www.qos.ch/shop/products/professionalSupport -->
|
||||
<!-- -->
|
||||
<configuration>
|
||||
|
||||
<!-- 控制台输出日志 -->
|
||||
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 文件输出指定项目日志 -->
|
||||
<appender name="file"
|
||||
class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<!--See http://logback.qos.ch/manual/appenders.html#RollingFileAppender -->
|
||||
<!--and http://logback.qos.ch/manual/appenders.html#TimeBasedRollingPolicy -->
|
||||
<!--for further documentation -->
|
||||
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<fileNamePattern>/tmp/weixin/log/%d{yyyy-MM-dd}.log
|
||||
</fileNamePattern>
|
||||
<maxHistory>30</maxHistory>
|
||||
</rollingPolicy>
|
||||
|
||||
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 异步输出指定项目日志 -->
|
||||
<appender name="async" class="ch.qos.logback.classic.AsyncAppender">
|
||||
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
|
||||
<discardingThreshold>0</discardingThreshold>
|
||||
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
|
||||
<queueSize>512</queueSize>
|
||||
<!-- 添加附加的appender,最多只能添加一个 -->
|
||||
<appender-ref ref="file" />
|
||||
</appender>
|
||||
|
||||
<logger name="org.apache" level="INFO">
|
||||
<appender-ref ref="stdout" />
|
||||
</logger>
|
||||
|
||||
<logger name="org.springframework" level="INFO">
|
||||
<appender-ref ref="stdout" />
|
||||
</logger>
|
||||
|
||||
<logger name="com.foxinmy.weixin" level="INFO">
|
||||
<appender-ref ref="async" />
|
||||
</logger>
|
||||
|
||||
</configuration>
|
||||
71
src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java
Normal file
71
src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java
Normal file
@ -0,0 +1,71 @@
|
||||
package com.foxinmy.weixin4j.test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.foxinmy.weixin4j.WeixinProxy;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.model.Button;
|
||||
import com.foxinmy.weixin4j.model.Button.BtnType;
|
||||
|
||||
/**
|
||||
* 自定义菜单测试
|
||||
* @className ButtonTest
|
||||
* @author jy.hu
|
||||
* @date 2014年4月10日
|
||||
* @since JDK 1.7
|
||||
*/
|
||||
public class ButtonTest {
|
||||
private WeixinProxy weixinProxy;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
weixinProxy = new WeixinProxy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void create() {
|
||||
List<Button> btnList = new ArrayList<Button>();
|
||||
|
||||
Button b = new Button("test");
|
||||
b.setType(BtnType.click);
|
||||
b.setKey("123");
|
||||
btnList.add(b);
|
||||
|
||||
b = new Button("news","http://xxx");
|
||||
btnList.add(b);
|
||||
|
||||
try {
|
||||
weixinProxy.createMenu(btnList);
|
||||
} catch (WeixinException e) {
|
||||
System.out.println(e.getErrorCode());
|
||||
System.out.println(e.getErrorMsg());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void get() {
|
||||
try {
|
||||
List<Button> btnList = weixinProxy.getMenu();
|
||||
for (Button btn : btnList) {
|
||||
System.out.println(btn.toString());
|
||||
}
|
||||
} catch (WeixinException e) {
|
||||
System.out.println(e.getErrorCode());
|
||||
System.out.println(e.getErrorMsg());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void delete() {
|
||||
try {
|
||||
weixinProxy.deleteMenu();
|
||||
} catch (WeixinException e) {
|
||||
System.out.println(e.getErrorCode());
|
||||
System.out.println(e.getErrorMsg());
|
||||
}
|
||||
}
|
||||
}
|
||||
78
src/test/java/com/foxinmy/weixin4j/test/GroupTest.java
Normal file
78
src/test/java/com/foxinmy/weixin4j/test/GroupTest.java
Normal file
@ -0,0 +1,78 @@
|
||||
package com.foxinmy.weixin4j.test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.foxinmy.weixin4j.WeixinProxy;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.model.Group;
|
||||
|
||||
/**
|
||||
* 用户分组测试
|
||||
* @className GroupTest
|
||||
* @author jy.hu
|
||||
* @date 2014年4月10日
|
||||
* @since JDK 1.7
|
||||
*/
|
||||
public class GroupTest {
|
||||
private WeixinProxy weixinProxy;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
weixinProxy = new WeixinProxy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void create() {
|
||||
try {
|
||||
System.out.println(weixinProxy.createGroup("test"));
|
||||
} catch (WeixinException e) {
|
||||
System.out.println(e.getErrorCode());
|
||||
System.out.println(e.getErrorMsg());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void get() {
|
||||
try {
|
||||
List<Group> groups = weixinProxy.getGroups();
|
||||
for (Group group : groups) {
|
||||
System.out.println(group);
|
||||
}
|
||||
} catch (WeixinException e) {
|
||||
System.out.println(e.getErrorCode());
|
||||
System.out.println(e.getErrorMsg());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getid() {
|
||||
try {
|
||||
System.out.println(weixinProxy.findGroupByOpenId("owGBft_vbBbOaQOmpEUE4xDLeRSU"));
|
||||
} catch (WeixinException e) {
|
||||
System.out.println(e.getErrorCode());
|
||||
System.out.println(e.getErrorMsg());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void modify() {
|
||||
try {
|
||||
weixinProxy.modifyGroup(100, "test1");
|
||||
} catch (WeixinException e) {
|
||||
System.out.println(e.getErrorCode());
|
||||
System.out.println(e.getErrorMsg());
|
||||
}
|
||||
}
|
||||
@Test
|
||||
public void move() {
|
||||
try {
|
||||
weixinProxy.moveGroup("owGBft_vbBbOaQOmpEUE4xDLeRSU",100);
|
||||
} catch (WeixinException e) {
|
||||
System.out.println(e.getErrorCode());
|
||||
System.out.println(e.getErrorMsg());
|
||||
}
|
||||
}
|
||||
}
|
||||
48
src/test/java/com/foxinmy/weixin4j/test/MediaTest.java
Normal file
48
src/test/java/com/foxinmy/weixin4j/test/MediaTest.java
Normal file
@ -0,0 +1,48 @@
|
||||
package com.foxinmy.weixin4j.test;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.foxinmy.weixin4j.WeixinProxy;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.type.MediaType;
|
||||
|
||||
/**
|
||||
* 媒体上传下载测试
|
||||
* @className MediaTest
|
||||
* @author jy.hu
|
||||
* @date 2014年4月10日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class MediaTest {
|
||||
|
||||
private WeixinProxy weixinProxy;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
weixinProxy = new WeixinProxy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void upload() {
|
||||
File file = new File("D:\\test.jpg");
|
||||
try {
|
||||
System.out.println(weixinProxy.uploadMedia(file, MediaType.image));
|
||||
//usAxLEJxFXAjXVlLu_BSw0GvS2YEEoGeelRBybNZBGvMsdxiIcD1F9yBWYd9jVZx
|
||||
} catch (WeixinException e) {
|
||||
System.out.println(e.getErrorMsg());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void download() {
|
||||
try {
|
||||
System.out.println(weixinProxy.downloadMedia("usAxLEJxFXAjXVlLu_BSw0GvS2YEEoGeelRBybNZBGvMsdxiIcD1F9yBWYd9jVZx", MediaType.image));
|
||||
} catch (WeixinException e) {
|
||||
System.out.println(e.getErrorMsg());
|
||||
}
|
||||
}
|
||||
}
|
||||
270
src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java
Normal file
270
src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java
Normal file
@ -0,0 +1,270 @@
|
||||
package com.foxinmy.weixin4j.test;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.foxinmy.weixin4j.WeixinProxy;
|
||||
|
||||
/**
|
||||
* 接收消息格式测试
|
||||
* @author jy.hu
|
||||
* @date 2014年3月24日
|
||||
* @since JDK 1.7
|
||||
*/
|
||||
public class MessageInTest {
|
||||
private StringBuilder xmlSb = new StringBuilder();
|
||||
private WeixinProxy weixinProxy;
|
||||
|
||||
@Before
|
||||
public void init(){
|
||||
weixinProxy = new WeixinProxy();
|
||||
}
|
||||
|
||||
/***************** event message *********************/
|
||||
@Test
|
||||
public void scribe() {
|
||||
try {
|
||||
xmlSb.delete(0, xmlSb.length());
|
||||
xmlSb.append("<xml>");
|
||||
xmlSb.append("<ToUserName><![CDATA[toUser]]></ToUserName>");
|
||||
xmlSb.append("<FromUserName><![CDATA[FromUser]]></FromUserName>");
|
||||
xmlSb.append("<CreateTime>123456789</CreateTime>");
|
||||
xmlSb.append("<MsgType><![CDATA[event]]></MsgType>");
|
||||
xmlSb.append("<Event><![CDATA[subscribe]]></Event>");
|
||||
xmlSb.append("</xml>");
|
||||
System.out.println(weixinProxy.xml2msg(xmlSb.toString()));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void scan() {
|
||||
try {
|
||||
xmlSb.delete(0, xmlSb.length());
|
||||
xmlSb.append("<xml>");
|
||||
xmlSb.append("<ToUserName><![CDATA[toUser]]></ToUserName>");
|
||||
xmlSb.append("<FromUserName><![CDATA[FromUser]]></FromUserName>");
|
||||
xmlSb.append("<CreateTime>123456789</CreateTime>");
|
||||
xmlSb.append("<MsgType><![CDATA[event]]></MsgType>");
|
||||
xmlSb.append("<Event><![CDATA[SCAN]]></Event>");
|
||||
xmlSb.append("<EventKey><![CDATA[SCENE_VALUE]]></EventKey>");
|
||||
xmlSb.append("<Ticket><![CDATA[TICKET]]></Ticket>");
|
||||
xmlSb.append("</xml>");
|
||||
System.out.println(weixinProxy.xml2msg(xmlSb.toString()));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
@Test
|
||||
public void scan_scribe() {
|
||||
try {
|
||||
xmlSb.delete(0, xmlSb.length());
|
||||
xmlSb.append("<xml><ToUserName><![CDATA[toUser]]></ToUserName>");
|
||||
xmlSb.append("<FromUserName><![CDATA[FromUser]]></FromUserName>");
|
||||
xmlSb.append("<CreateTime>123456789</CreateTime>");
|
||||
xmlSb.append("<MsgType><![CDATA[event]]></MsgType>");
|
||||
xmlSb.append("<Event><![CDATA[subscribe]]></Event>");
|
||||
xmlSb.append("<EventKey><![CDATA[qrscene_123123]]></EventKey>");
|
||||
xmlSb.append("<Ticket><![CDATA[TICKET]]></Ticket>");
|
||||
xmlSb.append("</xml>");
|
||||
System.out.println(weixinProxy.xml2msg(xmlSb.toString()));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void location1() {
|
||||
try {
|
||||
xmlSb.delete(0, xmlSb.length());
|
||||
xmlSb.append("<xml>");
|
||||
xmlSb.append("<ToUserName><![CDATA[toUser]]></ToUserName>");
|
||||
xmlSb.append("<FromUserName><![CDATA[fromUser]]></FromUserName>");
|
||||
xmlSb.append("<CreateTime>123456789</CreateTime>");
|
||||
xmlSb.append("<MsgType><![CDATA[event]]></MsgType>");
|
||||
xmlSb.append("<Event><![CDATA[LOCATION]]></Event>");
|
||||
xmlSb.append("<Latitude>23.137466</Latitude>");
|
||||
xmlSb.append("<Longitude>113.352425</Longitude>");
|
||||
xmlSb.append("<Precision>119.385040</Precision>");
|
||||
xmlSb.append("</xml>");
|
||||
System.out.println(weixinProxy.xml2msg(xmlSb.toString()));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void menu_click() {
|
||||
try {
|
||||
xmlSb.delete(0, xmlSb.length());
|
||||
xmlSb.append("<xml>");
|
||||
xmlSb.append("<ToUserName><![CDATA[toUser]]></ToUserName>");
|
||||
xmlSb.append("<FromUserName><![CDATA[FromUser]]></FromUserName>");
|
||||
xmlSb.append("<CreateTime>123456789</CreateTime>");
|
||||
xmlSb.append("<MsgType><![CDATA[event]]></MsgType>");
|
||||
xmlSb.append("<Event><![CDATA[CLICK]]></Event>");
|
||||
xmlSb.append("<EventKey><![CDATA[EVENTKEY]]></EventKey>");
|
||||
xmlSb.append("</xml>");
|
||||
System.out.println(weixinProxy.xml2msg(xmlSb.toString()));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void menu_link() {
|
||||
try {
|
||||
xmlSb.delete(0, xmlSb.length());
|
||||
xmlSb.append("<xml>");
|
||||
xmlSb.append("<ToUserName><![CDATA[toUser]]></ToUserName>");
|
||||
xmlSb.append("<FromUserName><![CDATA[FromUser]]></FromUserName>");
|
||||
xmlSb.append("<CreateTime>123456789</CreateTime>");
|
||||
xmlSb.append("<MsgType><![CDATA[event]]></MsgType>");
|
||||
xmlSb.append("<Event><![CDATA[VIEW]]></Event>");
|
||||
xmlSb.append("<EventKey><![CDATA[www.qq.com]]></EventKey>");
|
||||
xmlSb.append("</xml>");
|
||||
System.out.println(weixinProxy.xml2msg(xmlSb.toString()));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/***************** common message *********************/
|
||||
|
||||
@Test
|
||||
public void text() {
|
||||
try {
|
||||
xmlSb.delete(0, xmlSb.length());
|
||||
xmlSb.append("<xml>");
|
||||
xmlSb.append("<ToUserName><![CDATA[toUser]]></ToUserName>");
|
||||
xmlSb.append("<FromUserName><![CDATA[fromUser]]></FromUserName>");
|
||||
xmlSb.append("<CreateTime>1348831860</CreateTime>");
|
||||
xmlSb.append("<MsgType><![CDATA[text]]></MsgType>");
|
||||
xmlSb.append("<Content><![CDATA[this is a test]]></Content>");
|
||||
xmlSb.append("<MsgId>1234567890123456</MsgId>");
|
||||
xmlSb.append("</xml>");
|
||||
System.out.println(weixinProxy.xml2msg(xmlSb.toString()));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void image() {
|
||||
try {
|
||||
xmlSb.delete(0, xmlSb.length());
|
||||
xmlSb.append("<xml>");
|
||||
xmlSb.append("<ToUserName><![CDATA[toUser]]></ToUserName>");
|
||||
xmlSb.append("<FromUserName><![CDATA[FromUser]]></FromUserName>");
|
||||
xmlSb.append("<CreateTime>123456789</CreateTime>");
|
||||
xmlSb.append("<MsgType><![CDATA[image]]></MsgType>");
|
||||
xmlSb.append("<PicUrl><![CDATA[this is a url]]></PicUrl>");
|
||||
xmlSb.append("<MediaId><![CDATA[media_id]]></MediaId>");
|
||||
xmlSb.append("<MsgId>1234567890123456</MsgId>");
|
||||
xmlSb.append("</xml>");
|
||||
System.out.println(weixinProxy.xml2msg(xmlSb.toString()));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void voice() {
|
||||
try {
|
||||
xmlSb.delete(0, xmlSb.length());
|
||||
xmlSb.append("<xml>");
|
||||
xmlSb.append("<ToUserName><![CDATA[toUser]]></ToUserName>");
|
||||
xmlSb.append("<FromUserName><![CDATA[FromUser]]></FromUserName>");
|
||||
xmlSb.append("<CreateTime>123456789</CreateTime>");
|
||||
xmlSb.append("<MsgType><![CDATA[voice]]></MsgType>");
|
||||
xmlSb.append("<MediaId><![CDATA[media_id]]></MediaId>");
|
||||
xmlSb.append("<Format><![CDATA[Format]]></Format>");
|
||||
xmlSb.append("<MsgId>1234567890123456</MsgId>");
|
||||
xmlSb.append("</xml>");
|
||||
System.out.println(weixinProxy.xml2msg(xmlSb.toString()));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void re_voice() {
|
||||
try {
|
||||
xmlSb.delete(0, xmlSb.length());
|
||||
xmlSb.append("<xml>");
|
||||
xmlSb.append("<ToUserName><![CDATA[toUser]]></ToUserName>");
|
||||
xmlSb.append("<FromUserName><![CDATA[FromUser]]></FromUserName>");
|
||||
xmlSb.append("<CreateTime>123456789</CreateTime>");
|
||||
xmlSb.append("<MsgType><![CDATA[voice]]></MsgType>");
|
||||
xmlSb.append("<MediaId><![CDATA[media_id]]></MediaId>");
|
||||
xmlSb.append("<Format><![CDATA[Format]]></Format>");
|
||||
xmlSb.append("<Recognition><![CDATA[腾讯微信团队]]></Recognition>");
|
||||
xmlSb.append("<MsgId>1234567890123456</MsgId>");
|
||||
xmlSb.append("</xml>");
|
||||
System.out.println(weixinProxy.xml2msg(xmlSb.toString()));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void video() {
|
||||
try {
|
||||
xmlSb.delete(0, xmlSb.length());
|
||||
xmlSb.append("<xml>");
|
||||
xmlSb.append("<ToUserName><![CDATA[toUser]]></ToUserName>");
|
||||
xmlSb.append("<FromUserName><![CDATA[FromUser]]></FromUserName>");
|
||||
xmlSb.append("<CreateTime>123456789</CreateTime>");
|
||||
xmlSb.append("<MsgType><![CDATA[video]]></MsgType>");
|
||||
xmlSb.append("<MediaId><![CDATA[media_id]]></MediaId>");
|
||||
xmlSb.append("<ThumbMediaId><![CDATA[thumb_media_id]]></ThumbMediaId>");
|
||||
xmlSb.append("<MsgId>1234567890123456</MsgId>");
|
||||
xmlSb.append("</xml>");
|
||||
System.out.println(weixinProxy.xml2msg(xmlSb.toString()));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void location2() {
|
||||
try {
|
||||
xmlSb.delete(0, xmlSb.length());
|
||||
xmlSb.append("<xml>");
|
||||
xmlSb.append("<ToUserName><![CDATA[toUser]]></ToUserName>");
|
||||
xmlSb.append("<FromUserName><![CDATA[FromUser]]></FromUserName>");
|
||||
xmlSb.append("<CreateTime>123456789</CreateTime>");
|
||||
xmlSb.append("<MsgType><![CDATA[location]]></MsgType>");
|
||||
xmlSb.append("<Location_X>23.134521</Location_X>");
|
||||
xmlSb.append("<Location_Y>113.358803</Location_Y>");
|
||||
xmlSb.append("<Scale>20</Scale>");
|
||||
xmlSb.append("<Label><![CDATA[位置信息]]></Label>");
|
||||
xmlSb.append("<MsgId>1234567890123456</MsgId>");
|
||||
xmlSb.append("</xml>");
|
||||
System.out.println(weixinProxy.xml2msg(xmlSb.toString()));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void link() {
|
||||
try {
|
||||
xmlSb.delete(0, xmlSb.length());
|
||||
xmlSb.append("<xml>");
|
||||
xmlSb.append("<ToUserName><![CDATA[toUser]]></ToUserName>");
|
||||
xmlSb.append("<FromUserName><![CDATA[FromUser]]></FromUserName>");
|
||||
xmlSb.append("<CreateTime>123456789</CreateTime>");
|
||||
xmlSb.append("<MsgType><![CDATA[link]]></MsgType>");
|
||||
xmlSb.append("<Title><![CDATA[公众平台官网链接]]></Title>");
|
||||
xmlSb.append("<Description><![CDATA[公众平台官网链接]]></Description>");
|
||||
xmlSb.append("<Url><![CDATA[url]]></Url>");
|
||||
xmlSb.append("<MsgId>1234567890123456</MsgId>");
|
||||
xmlSb.append("</xml>");
|
||||
System.out.println(weixinProxy.xml2msg(xmlSb.toString()));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,89 @@
|
||||
package com.foxinmy.weixin4j.test;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.foxinmy.weixin4j.WeixinProxy;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.msg.notify.ArticleNotify;
|
||||
import com.foxinmy.weixin4j.msg.notify.BaseNotify;
|
||||
import com.foxinmy.weixin4j.msg.notify.ImageNotify;
|
||||
import com.foxinmy.weixin4j.msg.notify.MusicNotify;
|
||||
import com.foxinmy.weixin4j.msg.notify.TextNotify;
|
||||
import com.foxinmy.weixin4j.msg.notify.VideoNotify;
|
||||
import com.foxinmy.weixin4j.msg.notify.VoiceNotify;
|
||||
import com.foxinmy.weixin4j.type.MediaType;
|
||||
|
||||
/**
|
||||
* 客服消息测试
|
||||
* @className MessageNotifyTest
|
||||
* @author jy.hu
|
||||
* @date 2014年4月10日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class MessageNotifyTest {
|
||||
|
||||
private WeixinProxy weixinProxy;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
weixinProxy = new WeixinProxy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void text() {
|
||||
TextNotify notify = new TextNotify("123", "to");
|
||||
System.out.println(notify.toJson());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void image() {
|
||||
ImageNotify notify = new ImageNotify("123", "to");
|
||||
System.out.println(notify.toJson());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void voice() {
|
||||
VoiceNotify notify = new VoiceNotify("123", "to");
|
||||
System.out.println(notify.toJson());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void video() {
|
||||
VideoNotify notify = new VideoNotify("to");
|
||||
notify.pushVideo("123", "title", "desc");
|
||||
System.out.println(notify.toJson());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void music() {
|
||||
MusicNotify notify = new MusicNotify("to");
|
||||
notify.pushMusic("title", "desc", "url", "hqUrl", "mediaId");
|
||||
System.out.println(notify.toJson());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void article() {
|
||||
ArticleNotify notify = new ArticleNotify("to");
|
||||
notify.pushArticle("title1", "desc1", "picUrl1", "url1");
|
||||
notify.pushArticle("title2", "desc2", "picUrl2", "url2");
|
||||
System.out.println(notify.toJson());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void send() {
|
||||
BaseNotify t = new TextNotify("哈哈哈哈", "owGBft_vbBbOaQOmpEUE4xDLeRSU");
|
||||
try {
|
||||
weixinProxy.sendNotify(t);
|
||||
String mediaId = weixinProxy.uploadMedia(new File("D:\\test.jpg"), MediaType.image);
|
||||
t = new ImageNotify(mediaId, "owGBft_vbBbOaQOmpEUE4xDLeRSU");
|
||||
weixinProxy.sendNotify(t);
|
||||
} catch (WeixinException e) {
|
||||
System.out.println(e.getErrorCode());
|
||||
System.out.println(e.getErrorMsg());
|
||||
}
|
||||
}
|
||||
}
|
||||
74
src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java
Normal file
74
src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java
Normal file
@ -0,0 +1,74 @@
|
||||
package com.foxinmy.weixin4j.test;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.foxinmy.weixin4j.msg.TextMessage;
|
||||
import com.foxinmy.weixin4j.msg.out.ArticleMessage;
|
||||
import com.foxinmy.weixin4j.msg.out.ImageMessage;
|
||||
import com.foxinmy.weixin4j.msg.out.MusicMessage;
|
||||
import com.foxinmy.weixin4j.msg.out.VideoMessage;
|
||||
import com.foxinmy.weixin4j.msg.out.VoiceMessage;
|
||||
|
||||
/**
|
||||
* 发送消息格式测试
|
||||
*
|
||||
* @author jy.hu
|
||||
* @date 2014年3月24日
|
||||
* @since JDK 1.7
|
||||
*/
|
||||
public class MessageOutTest {
|
||||
@Test
|
||||
public void text() {
|
||||
TextMessage message = new TextMessage();
|
||||
message.setFromUserName("fromUser");
|
||||
message.setToUserName("toUser");
|
||||
message.setContent("text message");
|
||||
System.out.println(message.toXml());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void image() {
|
||||
ImageMessage message = new ImageMessage();
|
||||
message.setFromUserName("fromUser");
|
||||
message.setToUserName("toUser");
|
||||
message.pushMediaId("mediaId");
|
||||
System.out.println(message.toXml());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void voice() {
|
||||
VoiceMessage message = new VoiceMessage();
|
||||
message.setFromUserName("fromUser");
|
||||
message.setToUserName("toUser");
|
||||
message.pushMediaId("mediaId");
|
||||
System.out.println(message.toXml());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void video() {
|
||||
VideoMessage message = new VideoMessage();
|
||||
message.setFromUserName("fromUser");
|
||||
message.setToUserName("toUser");
|
||||
message.pushVideo("mediaId", "title", "title");
|
||||
System.out.println(message.toXml());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void music() {
|
||||
MusicMessage message = new MusicMessage();
|
||||
message.setFromUserName("fromUser");
|
||||
message.setToUserName("toUser");
|
||||
message.pushMusic("title", "desc", "url", "hqurl", "mediaId");
|
||||
System.out.println(message.toXml());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void article() {
|
||||
ArticleMessage message = new ArticleMessage();
|
||||
message.setFromUserName("fromUser");
|
||||
message.setToUserName("toUser");
|
||||
message.pushArticle("title1", "desc1", "picUrl1", "url1");
|
||||
message.pushArticle("title2", "desc2", "picUrl2", "url2");
|
||||
System.out.println(message.toXml());
|
||||
}
|
||||
}
|
||||
67
src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java
Normal file
67
src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java
Normal file
@ -0,0 +1,67 @@
|
||||
package com.foxinmy.weixin4j.test;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.foxinmy.weixin4j.WeixinProxy;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.model.MpArticle;
|
||||
import com.foxinmy.weixin4j.type.MediaType;
|
||||
|
||||
/**
|
||||
* 群发消息
|
||||
*
|
||||
* @className MpNewsTest
|
||||
* @author jy
|
||||
* @date 2014年4月27日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class MpNewsTest {
|
||||
private WeixinProxy weixinProxy;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
this.weixinProxy = new WeixinProxy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void massByGroup(){
|
||||
List<MpArticle> articles = new ArrayList<MpArticle>();
|
||||
try {
|
||||
String thumbMediaId = weixinProxy.uploadMedia(new File("/tmp/test.jpg"), MediaType.image);
|
||||
articles.add(new MpArticle(thumbMediaId, "title", "content"));
|
||||
weixinProxy.massNewsByGroup(articles, "0");
|
||||
} catch (WeixinException e) {
|
||||
System.out.println(e.getErrorCode());
|
||||
System.out.println(e.getErrorMsg());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void massByOpenIds(){
|
||||
List<MpArticle> articles = new ArrayList<MpArticle>();
|
||||
try {
|
||||
String thumbMediaId = weixinProxy.uploadMedia(new File("/tmp/test.jpg"), MediaType.image);
|
||||
articles.add(new MpArticle(thumbMediaId, "title", "content"));
|
||||
weixinProxy.massNewsByOpenIds(articles, "owGBft_vbBbOaQOmpEUE4xDLeRSU");
|
||||
} catch (WeixinException e) {
|
||||
System.out.println(e.getErrorCode());
|
||||
System.out.println(e.getErrorMsg());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteMass(){
|
||||
try {
|
||||
weixinProxy.deleteMassNews("34182");
|
||||
} catch (WeixinException e) {
|
||||
System.out.println(e.getErrorCode());
|
||||
System.out.println(e.getErrorMsg());
|
||||
}
|
||||
}
|
||||
}
|
||||
48
src/test/java/com/foxinmy/weixin4j/test/QRTest.java
Normal file
48
src/test/java/com/foxinmy/weixin4j/test/QRTest.java
Normal file
@ -0,0 +1,48 @@
|
||||
package com.foxinmy.weixin4j.test;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.foxinmy.weixin4j.WeixinProxy;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.model.QRParameter;
|
||||
import com.foxinmy.weixin4j.model.QRParameter.QRType;
|
||||
|
||||
/**
|
||||
* 二维码相关测试
|
||||
* @className QRTest
|
||||
* @author jy.hu
|
||||
* @date 2014年4月10日
|
||||
* @since JDK 1.7
|
||||
*/
|
||||
public class QRTest {
|
||||
private WeixinProxy weixinProxy;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
weixinProxy = new WeixinProxy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void temp_qr() {
|
||||
QRParameter qr = new QRParameter(1200, QRType.QR_SCENE, 1);
|
||||
try {
|
||||
System.out.println(qr.toJson());
|
||||
weixinProxy.getQR(qr);
|
||||
} catch (WeixinException e) {
|
||||
System.out.println(e.getErrorCode());
|
||||
System.out.println(e.getErrorMsg());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void forever_qr() {
|
||||
QRParameter qr = new QRParameter(QRType.QR_LIMIT_SCENE, 1);
|
||||
try {
|
||||
System.out.println(qr.toJson());
|
||||
weixinProxy.getQR(qr);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
32
src/test/java/com/foxinmy/weixin4j/test/TokenTest.java
Normal file
32
src/test/java/com/foxinmy/weixin4j/test/TokenTest.java
Normal file
@ -0,0 +1,32 @@
|
||||
package com.foxinmy.weixin4j.test;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.foxinmy.weixin4j.WeixinProxy;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
|
||||
/**
|
||||
* token相关测试
|
||||
* @className TokenTest
|
||||
* @author jy.hu
|
||||
* @date 2014年4月10日
|
||||
* @since JDK 1.7
|
||||
*/
|
||||
public class TokenTest {
|
||||
private WeixinProxy weixinProxy;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
weixinProxy = new WeixinProxy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getToken() {
|
||||
try {
|
||||
System.out.println(weixinProxy.getToken());
|
||||
} catch (WeixinException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
50
src/test/java/com/foxinmy/weixin4j/test/UserTest.java
Normal file
50
src/test/java/com/foxinmy/weixin4j/test/UserTest.java
Normal file
@ -0,0 +1,50 @@
|
||||
package com.foxinmy.weixin4j.test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.foxinmy.weixin4j.WeixinProxy;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.model.User;
|
||||
|
||||
/**
|
||||
* 用户相关测试
|
||||
* @className UserTest
|
||||
* @author jy.hu
|
||||
* @date 2014年4月10日
|
||||
* @since JDK 1.7
|
||||
*/
|
||||
public class UserTest {
|
||||
private WeixinProxy weixinProxy;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
weixinProxy = new WeixinProxy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getUser() {
|
||||
try {
|
||||
System.out.println(weixinProxy.getUser("owGBft_vbBbOaQOmpEUE4xDLeRSU"));
|
||||
} catch (WeixinException e) {
|
||||
System.out.println(e.getErrorCode());
|
||||
System.out.println(e.getErrorMsg());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void following() {
|
||||
try {
|
||||
System.out.println(weixinProxy.getFollowing(null));
|
||||
List<User> userList = weixinProxy.getAllFollowing();
|
||||
for (User user : userList) {
|
||||
System.out.println(user);
|
||||
}
|
||||
} catch (WeixinException e) {
|
||||
System.out.println(e.getErrorCode());
|
||||
System.out.println(e.getErrorMsg());
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user