maven多模块分离

This commit is contained in:
jy.hu
2014-10-27 21:10:38 +08:00
parent 4cee4678af
commit cde0f75069
169 changed files with 1308 additions and 798 deletions
-30
View File
@@ -1,30 +0,0 @@
<assembly>
<id>bin</id>
<formats>
<format>zip</format>
</formats>
<dependencySets>
<dependencySet>
<useProjectArtifact>true</useProjectArtifact>
<outputDirectory>lib</outputDirectory>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<directory>src/main</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>*.sh</include>
<include>*.bat</include>
</includes>
</fileSet>
<fileSet>
<directory>target/classes</directory>
<outputDirectory>/conf</outputDirectory>
<includes>
<include>*.properties</include>
<include>*.xml</include>
</includes>
</fileSet>
</fileSets>
</assembly>
@@ -1 +0,0 @@
所有的API调用入口类
@@ -1,707 +0,0 @@
package com.foxinmy.weixin4j;
import java.io.File;
import java.io.IOException;
import java.util.List;
import com.alibaba.fastjson.JSONObject;
import com.foxinmy.weixin4j.api.GroupApi;
import com.foxinmy.weixin4j.api.HelperApi;
import com.foxinmy.weixin4j.api.MassApi;
import com.foxinmy.weixin4j.api.MediaApi;
import com.foxinmy.weixin4j.api.MenuApi;
import com.foxinmy.weixin4j.api.NotifyApi;
import com.foxinmy.weixin4j.api.QrApi;
import com.foxinmy.weixin4j.api.TmplApi;
import com.foxinmy.weixin4j.api.UserApi;
import com.foxinmy.weixin4j.api.token.FileTokenApi;
import com.foxinmy.weixin4j.api.token.TokenApi;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.BaseResult;
import com.foxinmy.weixin4j.model.Button;
import com.foxinmy.weixin4j.model.CustomRecord;
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.User;
import com.foxinmy.weixin4j.model.UserToken;
import com.foxinmy.weixin4j.msg.model.Article;
import com.foxinmy.weixin4j.msg.model.BaseMsg;
import com.foxinmy.weixin4j.msg.notify.BaseNotify;
import com.foxinmy.weixin4j.msg.out.TemplateMessage;
import com.foxinmy.weixin4j.type.MediaType;
/**
* 微信服务实现
*
* @className WeixinProxy
* @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 MediaApi mediaApi;
private final NotifyApi notifyApi;
private final MassApi massApi;
private final UserApi userApi;
private final GroupApi groupApi;
private final MenuApi menuApi;
private final QrApi qrApi;
private final TmplApi tmplApi;
private final HelperApi helperApi;
/**
* 默认采用文件存放Token跟配置文件中的appi信息
*/
public WeixinProxy() {
this(new FileTokenApi());
}
/**
* 也可接受传递过来的appid跟appsecret
*
* @param appid
* @param appsecret
*/
public WeixinProxy(String appid, String appsecret) {
this(new FileTokenApi(appid, appsecret));
}
public WeixinProxy(TokenApi tokenApi) {
this.mediaApi = new MediaApi(tokenApi);
this.notifyApi = new NotifyApi(tokenApi);
this.massApi = new MassApi(tokenApi);
this.userApi = new UserApi(tokenApi);
this.groupApi = new GroupApi(tokenApi);
this.menuApi = new MenuApi(tokenApi);
this.qrApi = new QrApi(tokenApi);
this.tmplApi = new TmplApi(tokenApi);
this.helperApi = new HelperApi(tokenApi);
}
/**
* 上传媒体文件
* <p>
* 正常情况下返回{"type":"TYPE","media_id":"MEDIA_ID","created_at":123456789},
* 否则抛出异常.
* </p>
*
* @param file
* 文件对象
* @param mediaType
* 媒体类型
* @return 上传到微信服务器返回的媒体标识
* @throws WeixinException
* @throws IOException
* @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
* @see com.foxinmy.weixin4j.api.MediaApi
*/
public String uploadMedia(File file, MediaType mediaType)
throws WeixinException, IOException {
return mediaApi.uploadMedia(file, mediaType);
}
/**
* 上传媒体文件
*
* @param bytes
* 媒体数据包
* @param mediaType
* 媒体类型
* @return 上传到微信服务器返回的媒体标识
* @throws WeixinException
* @see com.foxinmy.weixin4j.api.MediaApi
* @see {@link com.foxinmy.weixin4j.WeixinProxy#uploadMedia(File, MediaType)}
*/
public String uploadMedia(String fileName, byte[] data, MediaType mediaType)
throws WeixinException {
return mediaApi.uploadMedia(fileName, data, mediaType);
}
/**
* 下载媒体文件
* <p>
* 正常情况下返回表头如Content-Type: image/jpeg,否则抛出异常.
* </p>
*
* @param mediaId
* 存储在微信服务器上的媒体标识
* @param mediaType
* 媒体类型
* @return 写入硬盘后的文件对象
* @throws WeixinException
* @throws IOException
* @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
* @see com.foxinmy.weixin4j.api.MediaApi
*/
public File downloadMedia(String mediaId, MediaType mediaType)
throws WeixinException, IOException {
return mediaApi.downloadMedia(mediaId, mediaType);
}
/**
* 下载媒体文件
*
* @param mediaId
* @param mediaType
* @return 二进制数据包
* @throws WeixinException
* @see com.foxinmy.weixin4j.api.MediaApi
* @see {@link com.foxinmy.weixin4j.WeixinProxy#downloadMedia(String, MediaType)}
*/
public byte[] downloadMediaData(String mediaId, MediaType mediaType)
throws WeixinException {
return mediaApi.downloadMediaData(mediaId, mediaType);
}
/**
* 发送客服消息(在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>
* @see com.foxinmy.weixin4j.msg.notify.TextNotify
* @see com.foxinmy.weixin4j.msg.notify.ImageNotify
* @see com.foxinmy.weixin4j.msg.notify.MusicNotify
* @see com.foxinmy.weixin4j.msg.notify.VideoNotify
* @see com.foxinmy.weixin4j.msg.notify.VoiceNotify
* @see com.foxinmy.weixin4j.msg.notify.ArticleNotify
* @see com.foxinmy.weixin4j.api.NotifyApi
*/
public BaseResult sendNotify(BaseNotify notify) throws WeixinException {
return notifyApi.sendNotify(notify);
}
/**
* 发送图文消息
*
* @param touser
* 目标ID
* @param articles
* 图文列表
* @return 发送结果
* @throws WeixinException
* @see com.foxinmy.weixin4j.msg.model.Article
* @see com.foxinmy.weixin4j.msg.notify.ArticleNotify
* @see com.foxinmy.weixin4j.api.NotifyApi
*/
public BaseResult sendNotify(String touser, List<Article> articles)
throws WeixinException {
return notifyApi.sendNotify(touser, articles);
}
/**
* 发送客服消息(不包含图文消息)
*
* @param touser
* 目标用户
* @param baseMsg
* 消息类型
* @return 发送结果
* @throws WeixinException
* @see com.foxinmy.weixin4j.msg.model.Text
* @see com.foxinmy.weixin4j.msg.model.Image
* @see com.foxinmy.weixin4j.msg.model.Music
* @see com.foxinmy.weixin4j.msg.model.Video
* @see com.foxinmy.weixin4j.msg.model.Voice
* @see com.foxinmy.weixin4j.api.NotifyApi
*/
public BaseResult sendNotify(String touser, BaseMsg baseMsg)
throws WeixinException {
return notifyApi.sendNotify(touser, baseMsg);
}
/**
* 客服聊天记录
*
* @param openId
* 用户标识 可为空
* @param starttime
* 查询开始时间
* @param endtime
* 查询结束时间 每次查询不能跨日查询
* @param pagesize
* 每页大小 每页最多拉取1000条
* @param pageindex
* 查询第几页 从1开始
* @throws WeixinException
* @see com.foxinmy.weixin4j.model.CustomRecord
* @see com.foxinmy.weixin4j.api.NotifyApi
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96%E5%AE%A2%E6%9C%8D%E8%81%8A%E5%A4%A9%E8%AE%B0%E5%BD%95">查询客服聊天记录</a>
*/
public List<CustomRecord> getCustomRecord(String openId, long starttime,
long endtime, int pagesize, int pageindex) throws WeixinException {
return notifyApi.getCustomRecord(openId, starttime, endtime, pagesize,
pageindex);
}
/**
* 上传图文消息,一个图文消息支持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
* @see com.foxinmy.weixin4j.api.MassApi
*/
public String uploadArticle(List<MpArticle> articles)
throws WeixinException {
return massApi.uploadArticle(articles);
}
/**
* 上传分组群发的视频素材
*
* @param mediaId
* 媒体文件中上传得到的Id
* @param title
* 标题 可为空
* @param desc
* 描述 可为空
* @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 com.foxinmy.weixin4j.api.MassApi
* @see {@link com.foxinmy.weixin4j.api.MediaApi#uploadMedia(File, MediaType)}
*/
public String uploadVideo(String mediaId, String title, String desc)
throws WeixinException {
return massApi.uploadVideo(mediaId, title, desc);
}
/**
* 分组群发
*
* @param mediaId
* 媒体ID 如果为text 则表示content
* @param mediaType
* 媒体类型
* @param groupId
* 分组ID
* @return
* @throws WeixinException
* @see com.foxinmy.weixin4j.model.Group
* @see com.foxinmy.weixin4j.type.MediaType
* @see com.foxinmy.weixin4j.api.MassApi
* @see {@link com.foxinmy.weixin4j.api.MediaApi#uploadMedia(File, MediaType)}
* @see {@link com.foxinmy.weixin4j.api.GroupApi#getGroupByOpenId(String)}
* @see {@link com.foxinmy.weixin4j.api.GroupApi#getGroups()}
*/
public String massByGroup(String mediaId, MediaType mediaType,
String groupId) throws WeixinException {
return massApi.massByGroup(mediaId, mediaType, groupId);
}
/**
* 分组群发图文消息
*
* @param articles
* 图文消息列表
* @param groupId
* 分组ID
* @return 发送出去的消息ID
* @throws WeixinException
* @see com.foxinmy.weixin4j.model.MpArticle
* @see com.foxinmy.weixin4j.model.Group
* @see com.foxinmy.weixin4j.api.MassApi
* @see {@link com.foxinmy.weixin4j.api.MediaApi#uploadMedia(File, MediaType)}
* @see {@link com.foxinmy.weixin4j.api.MassApi#uploadNews(List)}
* @see {@link com.foxinmy.weixin4j.WeixinProxy#massByGroup(String,MediaType,String)}
*/
public String massArticleByGroup(List<MpArticle> articles, String groupId)
throws WeixinException {
return massApi.massArticleByGroup(articles, groupId);
}
/**
* openId群发
*
* @param mediaId
* 媒体ID 如果为text 则表示content
* @param mediaType
* 媒体类型
* @param openIds
* openId列表
* @return
* @throws WeixinException
* @see com.foxinmy.weixin4j.model.User
* @see com.foxinmy.weixin4j.type.MediaType
* @see com.foxinmy.weixin4j.api.MassApi
* @see {@link com.foxinmy.weixin4j.api.MediaApi#uploadMedia(File, MediaType)}
* @see {@link com.foxinmy.weixin4j.WeixinProxy#massByOpenIds(JSONObject,String...)}
*/
public String massByOpenIds(String mediaId, MediaType mediaType,
String... openIds) throws WeixinException {
return massApi.massByOpenIds(mediaId, mediaType, openIds);
}
/**
* openId图文群发
*
* @param articles
* 图文消息列表
* @param openIds
* 目标ID列表
* @return 发送出去的消息ID
* @throws WeixinException
* @see com.foxinmy.weixin4j.model.MpArticle
* @see com.foxinmy.weixin4j.model.User
* @see com.foxinmy.weixin4j.api.MassApi
* @see {@link com.foxinmy.weixin4j.api.MediaApi#uploadMedia(File, MediaType)}
* @see {@link com.foxinmy.weixin4j.api.MediaApi#uploadNews(List)}
* @see {@link com.foxinmy.weixin4j.WeixinProxy#massByOpenIds(String,MediaType,String...)}
*/
public String massArticleByOpenIds(List<MpArticle> articles,
String... openIds) throws WeixinException {
return massApi.massArticleByOpenIds(articles, openIds);
}
/**
* 删除群发消息
* <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 com.foxinmy.weixin4j.api.MassApi
* @see {@link com.foxinmy.weixin4j.WeixinProxy#massByGroup(JSONObject, String)}
* @see {@link com.foxinmy.weixin4j.WeixinProxy#massByOpenIds(JSONObject, String...)
*/
public BaseResult deleteMassNews(String msgid) throws WeixinException {
return massApi.deleteMassNews(msgid);
}
/**
* 获取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
* @see com.foxinmy.weixin4j.api.UserApi
*/
public UserToken getAccessToken(String code) throws WeixinException {
return userApi.getAccessToken(code);
}
/**
* 获取用户信息
*
* @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
* @see com.foxinmy.weixin4j.api.UserApi
* @see {@link com.foxinmy.weixin4j.WeixinProxy#getAccessToken(String)}
*/
public User getUser(UserToken token) throws WeixinException {
return userApi.getUser(token);
}
/**
* 获取用户信息
* <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
* @see com.foxinmy.weixin4j.api.UserApi
*/
public User getUser(String openId) throws WeixinException {
return userApi.getUser(openId);
}
/**
* 获取用户一定数量(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
* @see com.foxinmy.weixin4j.api.UserApi
*/
public Following getFollowing(String nextOpenId) throws WeixinException {
return userApi.getFollowing(nextOpenId);
}
/**
* 获取用户全部的关注者列表
* <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.api.UserApi
* @see {@link com.foxinmy.weixin4j.WeixinProxy#getFollowing(String)}
*/
public List<User> getAllFollowing() throws WeixinException {
return userApi.getAllFollowing();
}
/**
* 设置用户备注名
*
* @param openId
* 用户ID
* @param remark
* 备注名
* @throws WeixinException
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E8%AE%BE%E7%BD%AE%E7%94%A8%E6%88%B7%E5%A4%87%E6%B3%A8%E5%90%8D%E6%8E%A5%E5%8F%A3">设置用户备注名</a>
* @see com.foxinmy.weixin4j.api.UserApi
*/
public BaseResult remarkUserName(String openId, String remark)
throws WeixinException {
return userApi.remarkUserName(openId, remark);
}
/**
* 创建分组
*
* @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()
* @see com.foxinmy.weixin4j.api.GroupApi
*/
public Group createGroup(String name) throws WeixinException {
return groupApi.createGroup(name);
}
/**
* 查询所有分组
*
* @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
* @see com.foxinmy.weixin4j.api.GroupApi
*/
public List<Group> getGroups() throws WeixinException {
return groupApi.getGroups();
}
/**
* 查询用户所在分组
*
* @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
* @see com.foxinmy.weixin4j.api.GroupApi
*/
public int getGroupByOpenId(String openId) throws WeixinException {
return groupApi.getGroupByOpenId(openId);
}
/**
* 修改分组名
*
* @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()
* @see com.foxinmy.weixin4j.api.GroupApi
*/
public BaseResult modifyGroup(int groupId, String name)
throws WeixinException {
return groupApi.modifyGroup(groupId, name);
}
/**
* 移动分组
*
* @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
* @see com.foxinmy.weixin4j.api.GroupApi
*/
public BaseResult moveGroup(String openId, int groupId)
throws WeixinException {
return groupApi.moveGroup(openId, groupId);
}
/**
* 自定义菜单
*
* @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
* @see com.foxinmy.weixin4j.type.ButtonType
* @see com.foxinmy.weixin4j.api.MenuApi
*/
public BaseResult createMenu(List<Button> btnList) throws WeixinException {
return menuApi.createMenu(btnList);
}
/**
* 查询菜单
*
* @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
* @see com.foxinmy.weixin4j.api.MenuApi
*/
public List<Button> getMenu() throws WeixinException {
return menuApi.getMenu();
}
/**
* 删除菜单
*
* @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
* @see com.foxinmy.weixin4j.api.MenuApi
*/
public BaseResult deleteMenu() throws WeixinException {
return menuApi.deleteMenu();
}
/**
* 生成带参数的二维码
*
* @param parameter
* @return byte数据包
* @throws WeixinException
* @see com.foxinmy.weixin4j.api.QrApi
* @see {@link com.foxinmy.weixin4j.WeixinProxy.QrApi#getQR(QRParameter)}
*/
public byte[] getQRData(QRParameter parameter) throws WeixinException {
return qrApi.getQRData(parameter);
}
/**
* 生成带参数的二维码
*
* @param sceneId
* 场景值
* @param expireSeconds
* 过期秒数 如果小于等于0则 视为永久二维码
* @return byte数据包
* @throws WeixinException
* @see com.foxinmy.weixin4j.api.QrApi
* @see {@link com.foxinmy.weixin4j.WeixinProxy.QrApi#getQR(QRParameter)}
*/
public byte[] getQRData(int sceneId, int expireSeconds)
throws WeixinException {
return qrApi.getQRData(sceneId, expireSeconds);
}
/**
* 生成带参数的二维码
* <p>
* 二维码分为临时跟永久两种,扫描时触发推送带参数事件
* </p>
*
* @param parameter
* 二维码参数
* @return 硬盘存储的文件对象
* @throws WeixinException
* @throws IOException
* @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
* @see com.foxinmy.weixin4j.api.QrApi
*/
public File getQR(QRParameter parameter) throws WeixinException,
IOException {
return qrApi.getQR(parameter);
}
/**
* 发送模板消息
*
* @param message
* @return 发送结果
* @throws WeixinException
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E6%A8%A1%E6%9D%BF%E6%B6%88%E6%81%AF%E6%8E%A5%E5%8F%A3">模板消息</a>
* @see com.foxinmy.weixin4j.msg.out.TemplateMessage
* @seee com.foxinmy.weixin4j.msg.event.TemplatesendjobfinishMessage
* @see com.foxinmy.weixin4j.api.TmplApi
*/
public BaseResult sendTmplMessage(TemplateMessage tplMessage)
throws WeixinException {
return tmplApi.sendTmplMessage(tplMessage);
}
/**
* 长链接转短链接
*
* @param url
* @return 短链接
* @throws WeixinException
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E9%95%BF%E9%93%BE%E6%8E%A5%E8%BD%AC%E7%9F%AD%E9%93%BE%E6%8E%A5%E6%8E%A5%E5%8F%A3">长链接转短链接</a>
* @see com.foxinmy.weixin4j.api.HelperApi
*/
public String getShorturl(String url) throws WeixinException {
return helperApi.getShorturl(url);
}
@@ -1,53 +0,0 @@
package com.foxinmy.weixin4j.action;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import org.dom4j.DocumentException;
import com.foxinmy.weixin4j.msg.BaseMessage;
import com.foxinmy.weixin4j.util.MessageUtil;
import com.foxinmy.weixin4j.xml.XStream;
/**
* 继承的类需实现execute(M inMessage)
*
* @className AbstractAction
* @author jy
* @date 2014年10月12日
* @since JDK 1.7
* @see
*/
public abstract class AbstractAction<M extends BaseMessage> implements
WeixinAction {
public abstract String execute(M inMessage);
@SuppressWarnings("unchecked")
@Override
public String execute(String msg) throws DocumentException {
BaseMessage message = MessageUtil.xml2msg(msg);
if (message == null) {
Class<M> messageClass = getGenericType();
XStream xstream = new XStream();
xstream.ignoreUnknownElements();
xstream.autodetectAnnotations(true);
xstream.processAnnotations(messageClass);
xstream.alias("xml", messageClass);
return execute(xstream.fromXML(msg, messageClass));
}
return execute((M) message);
}
@SuppressWarnings("unchecked")
private Class<M> getGenericType() {
Class<M> clazz = null;
Type type = getClass().getGenericSuperclass();
if (type instanceof ParameterizedType) {
ParameterizedType ptype = ((ParameterizedType) type);
Type[] args = ptype.getActualTypeArguments();
clazz = (Class<M>) args[0];
}
return clazz;
}
}
@@ -1,26 +0,0 @@
package com.foxinmy.weixin4j.action;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.foxinmy.weixin4j.type.EventType;
import com.foxinmy.weixin4j.type.MessageType;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
/**
* 标注
* @className Action
* @author jy
* @date 2014年10月12日
* @since JDK 1.7
* @see
*/
public @interface Action {
MessageType msgType();
EventType[] eventType() default {};
}
@@ -1,23 +0,0 @@
package com.foxinmy.weixin4j.action;
import com.foxinmy.weixin4j.msg.BaseMessage;
/**
* 返回空白消息
*
* @className BlankAction
* @author jy.hu
* @date 2014年10月2日
* @since JDK 1.7
* @see
*/
public abstract class BlankAction<M extends BaseMessage> extends
AbstractAction<M> {
private final String BLANK = "";
@Override
public String execute(M message) {
return BLANK;
}
}
@@ -1,23 +0,0 @@
package com.foxinmy.weixin4j.action;
import com.foxinmy.weixin4j.msg.BaseMessage;
import com.foxinmy.weixin4j.msg.TextMessage;
/**
* 显示调试信息
*
* @className DebugAction
* @author jy
* @date 2014年10月8日
* @since JDK 1.7
* @see
*/
public abstract class DebugAction<M extends BaseMessage> extends
AbstractAction<M> {
@Override
public String execute(M message) {
BaseMessage response = new TextMessage(message.toString(), message);
return response.toXml();
}
}
@@ -1,18 +0,0 @@
package com.foxinmy.weixin4j.action;
import com.foxinmy.weixin4j.msg.in.ImageMessage;
import com.foxinmy.weixin4j.type.MessageType;
/**
* 图片消息响应
*
* @className ImageAction
* @author jy
* @date 2014年10月9日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.msg.in.ImageMessage
*/
@Action(msgType = MessageType.image)
public class ImageAction extends DebugAction<ImageMessage> {
}
@@ -1,18 +0,0 @@
package com.foxinmy.weixin4j.action;
import com.foxinmy.weixin4j.msg.in.LinkMessage;
import com.foxinmy.weixin4j.type.MessageType;
/**
* 链接消息响应
*
* @className LinkAction
* @author jy
* @date 2014年10月9日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.msg.in.LinkMessage
*/
@Action(msgType = MessageType.link)
public class LinkAction extends DebugAction<LinkMessage> {
}
@@ -1,18 +0,0 @@
package com.foxinmy.weixin4j.action;
import com.foxinmy.weixin4j.msg.in.LocationMessage;
import com.foxinmy.weixin4j.type.MessageType;
/**
* 地理位置响应
*
* @className LocationAction
* @author jy
* @date 2014年10月9日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.msg.in.LocationMessage
*/
@Action(msgType = MessageType.location)
public class LocationAction extends DebugAction<LocationMessage> {
}
@@ -1 +0,0 @@
普通消息对应的Action
@@ -1,47 +0,0 @@
package com.foxinmy.weixin4j.action;
import io.netty.handler.codec.http.QueryStringDecoder;
import java.util.List;
import java.util.Map;
import org.dom4j.DocumentException;
import com.foxinmy.weixin4j.type.MessageType;
import com.foxinmy.weixin4j.util.ConfigUtil;
import com.foxinmy.weixin4j.util.MessageUtil;
/**
* 用于校验消息安全性
*
* @className SignatureAction
* @author jy
* @date 2014年10月24日
* @since JDK 1.7
* @see
*/
@Action(msgType = MessageType.signature)
public class SignatureAction implements WeixinAction {
@Override
public String execute(String uri) throws DocumentException {
String[] paths = uri.split("\\?");
if (paths == null || paths.length < 2) {
return "";
}
QueryStringDecoder queryDecoder = new QueryStringDecoder(paths[1],
false);
Map<String, List<String>> parameters = queryDecoder.parameters();
String echostr = parameters.containsKey("echostr") ? parameters.get(
"echostr").get(0) : null;
String timestamp = parameters.containsKey("timestamp") ? parameters
.get("timestamp").get(0) : null;
String nonce = parameters.containsKey("nonce") ? parameters
.get("nonce").get(0) : null;
String signature = parameters.containsKey("signature") ? parameters
.get("signature").get(0) : null;
String token = ConfigUtil.getValue("app_token");
return MessageUtil.signature(token, echostr, timestamp, nonce,
signature);
}
}
@@ -1,22 +0,0 @@
package com.foxinmy.weixin4j.action;
import com.foxinmy.weixin4j.msg.TextMessage;
import com.foxinmy.weixin4j.type.MessageType;
/**
* 文字消息响应
*
* @className TextAction
* @author jy
* @date 2014年10月9日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.msg.TextMessage
*/
@Action(msgType = MessageType.text)
public class TextAction extends AbstractAction<TextMessage> {
@Override
public String execute(TextMessage inMessage) {
return new TextMessage("Hello World!", inMessage).toXml();
}
}
@@ -1,18 +0,0 @@
package com.foxinmy.weixin4j.action;
import com.foxinmy.weixin4j.msg.in.VideoMessage;
import com.foxinmy.weixin4j.type.MessageType;
/**
* 视频消息响应
*
* @className VideoAction
* @author jy
* @date 2014年10月9日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.msg.in.VideoMessage
*/
@Action(msgType = MessageType.video)
public class VideoAction extends DebugAction<VideoMessage> {
}
@@ -1,18 +0,0 @@
package com.foxinmy.weixin4j.action;
import com.foxinmy.weixin4j.msg.in.VoiceMessage;
import com.foxinmy.weixin4j.type.MessageType;
/**
* 语音消息响应
*
* @className VoiceAction
* @author jy
* @date 2014年10月9日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.msg.in.VoiceMessage
*/
@Action(msgType = MessageType.voice)
public class VoiceAction extends DebugAction<VoiceMessage> {
}
@@ -1,18 +0,0 @@
package com.foxinmy.weixin4j.action;
import org.dom4j.DocumentException;
/**
* 消息处理接口
*
* @className Action
* @author jy.hu
* @date 2014年10月2日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.action.AbstractAction
* @see com.foxinmy.weixin4j.action.BlankAction
* @see com.foxinmy.weixin4j.action.DebugAction
*/
public interface WeixinAction {
public String execute(String msg) throws DocumentException;
}
@@ -1,21 +0,0 @@
package com.foxinmy.weixin4j.action.event;
import com.foxinmy.weixin4j.action.Action;
import com.foxinmy.weixin4j.action.DebugAction;
import com.foxinmy.weixin4j.msg.event.LocationEventMessage;
import com.foxinmy.weixin4j.type.EventType;
import com.foxinmy.weixin4j.type.MessageType;
/**
* 上报地理位置后触发
*
* @className LocationAction
* @author jy
* @date 2014年10月9日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.msg.event.LocationEventMessage
*/
@Action(msgType = MessageType.event, eventType = { EventType.location })
public class LocationAction extends DebugAction<LocationEventMessage> {
}
@@ -1,21 +0,0 @@
package com.foxinmy.weixin4j.action.event;
import com.foxinmy.weixin4j.action.Action;
import com.foxinmy.weixin4j.action.DebugAction;
import com.foxinmy.weixin4j.msg.event.MassEventMessage;
import com.foxinmy.weixin4j.type.EventType;
import com.foxinmy.weixin4j.type.MessageType;
/**
* 群发消息发送动作完成后触发
*
* @className MassSendAction
* @author jy
* @date 2014年10月9日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.msg.event.MassEventMessage
*/
@Action(msgType = MessageType.event, eventType = { EventType.massendjobfinish })
public class MassSendAction extends DebugAction<MassEventMessage> {
}
@@ -1,21 +0,0 @@
package com.foxinmy.weixin4j.action.event;
import com.foxinmy.weixin4j.action.Action;
import com.foxinmy.weixin4j.action.DebugAction;
import com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage;
import com.foxinmy.weixin4j.type.EventType;
import com.foxinmy.weixin4j.type.MessageType;
/**
* 菜单点击click事件时触发
*
* @className MenuClickAction
* @author jy
* @date 2014年10月9日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage
*/
@Action(msgType = MessageType.event, eventType = { EventType.click })
public class MenuClickAction extends DebugAction<MenuEventMessage> {
}
@@ -1,21 +0,0 @@
package com.foxinmy.weixin4j.action.event;
import com.foxinmy.weixin4j.action.Action;
import com.foxinmy.weixin4j.action.DebugAction;
import com.foxinmy.weixin4j.msg.event.menu.MenuLocationEventMessage;
import com.foxinmy.weixin4j.type.EventType;
import com.foxinmy.weixin4j.type.MessageType;
/**
* 菜单发送地理位置时触发
*
* @className MenuLocationAction
* @author jy
* @date 2014年10月9日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.msg.event.menu.MenuLocationEventMessage
*/
@Action(msgType = MessageType.event, eventType = { EventType.location_select })
public class MenuLocationAction extends DebugAction<MenuLocationEventMessage> {
}
@@ -1,23 +0,0 @@
package com.foxinmy.weixin4j.action.event;
import com.foxinmy.weixin4j.action.Action;
import com.foxinmy.weixin4j.action.DebugAction;
import com.foxinmy.weixin4j.msg.event.menu.MenuPhotoEventMessage;
import com.foxinmy.weixin4j.type.EventType;
import com.foxinmy.weixin4j.type.MessageType;
/**
* 菜单发送图片时触发
*
* @className MenuPhotoAction
* @author jy
* @date 2014年10月9日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.msg.event.menu.MenuPhotoEventMessage
*/
@Action(msgType = MessageType.event, eventType = {
EventType.pic_photo_or_album, EventType.pic_sysphoto,
EventType.pic_weixin })
public class MenuPhotoAction extends DebugAction<MenuPhotoEventMessage> {
}
@@ -1,22 +0,0 @@
package com.foxinmy.weixin4j.action.event;
import com.foxinmy.weixin4j.action.Action;
import com.foxinmy.weixin4j.action.DebugAction;
import com.foxinmy.weixin4j.msg.event.menu.MenuScanEventMessage;
import com.foxinmy.weixin4j.type.EventType;
import com.foxinmy.weixin4j.type.MessageType;
/**
* 菜单扫描时触发
*
* @className MenuScanAction
* @author jy
* @date 2014年10月9日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.msg.event.menu.MenuScanEventMessage
*/
@Action(msgType = MessageType.event, eventType = { EventType.scancode_push,
EventType.scancode_waitmsg })
public class MenuScanAction extends DebugAction<MenuScanEventMessage> {
}
@@ -1,21 +0,0 @@
package com.foxinmy.weixin4j.action.event;
import com.foxinmy.weixin4j.action.Action;
import com.foxinmy.weixin4j.action.DebugAction;
import com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage;
import com.foxinmy.weixin4j.type.EventType;
import com.foxinmy.weixin4j.type.MessageType;
/**
* 菜单点击view事件时触发
*
* @className MenuViewAction
* @author jy
* @date 2014年10月9日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage
*/
@Action(msgType = MessageType.event, eventType = { EventType.view })
public class MenuViewAction extends DebugAction<MenuEventMessage> {
}
@@ -1 +0,0 @@
事件消息对应的Action
@@ -1,21 +0,0 @@
package com.foxinmy.weixin4j.action.event;
import com.foxinmy.weixin4j.action.Action;
import com.foxinmy.weixin4j.action.DebugAction;
import com.foxinmy.weixin4j.msg.event.ScanEventMessage;
import com.foxinmy.weixin4j.type.EventType;
import com.foxinmy.weixin4j.type.MessageType;
/**
* 扫描事件时触发
*
* @className ScanAction
* @author jy
* @date 2014年10月9日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.msg.event.ScanEventMessage
*/
@Action(msgType = MessageType.event, eventType = { EventType.scan })
public class ScanAction extends DebugAction<ScanEventMessage> {
}
@@ -1,21 +0,0 @@
package com.foxinmy.weixin4j.action.event;
import com.foxinmy.weixin4j.action.Action;
import com.foxinmy.weixin4j.action.DebugAction;
import com.foxinmy.weixin4j.msg.event.ScribeEventMessage;
import com.foxinmy.weixin4j.type.EventType;
import com.foxinmy.weixin4j.type.MessageType;
/**
* 关注时触发
*
* @className SubscribeAction
* @author jy
* @date 2014年10月9日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.msg.event.ScanEventMessage
*/
@Action(msgType = MessageType.event, eventType = { EventType.subscribe })
public class SubscribeAction extends DebugAction<ScribeEventMessage> {
}
@@ -1,22 +0,0 @@
package com.foxinmy.weixin4j.action.event;
import com.foxinmy.weixin4j.action.Action;
import com.foxinmy.weixin4j.action.DebugAction;
import com.foxinmy.weixin4j.msg.event.TemplatesendjobfinishMessage;
import com.foxinmy.weixin4j.type.EventType;
import com.foxinmy.weixin4j.type.MessageType;
/**
* 模板消息发送动作完成时触发
*
* @className TemplateSendAction
* @author jy
* @date 2014年10月10日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.msg.event.TemplatesendjobfinishMessage
*/
@Action(msgType = MessageType.event, eventType = { EventType.templatesendjobfinish })
public class TemplateSendAction extends
DebugAction<TemplatesendjobfinishMessage> {
}
@@ -1,21 +0,0 @@
package com.foxinmy.weixin4j.action.event;
import com.foxinmy.weixin4j.action.Action;
import com.foxinmy.weixin4j.action.DebugAction;
import com.foxinmy.weixin4j.msg.event.ScribeEventMessage;
import com.foxinmy.weixin4j.type.EventType;
import com.foxinmy.weixin4j.type.MessageType;
/**
* 取消关注时触发
*
* @className UnsubscribeAction
* @author jy
* @date 2014年10月10日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.msg.event.ScanEventMessage
*/
@Action(msgType = MessageType.event, eventType = { EventType.unsubscribe })
public class UnsubscribeAction extends DebugAction<ScribeEventMessage> {
}
@@ -1,15 +0,0 @@
package com.foxinmy.weixin4j.api;
import com.foxinmy.weixin4j.http.HttpRequest;
/**
*
* @className BaseApi
* @author jy.hu
* @date 2014年9月26日
* @since JDK 1.7
* @see <a href="http://mp.weixin.qq.com/wiki/index.php">api文档</a>
*/
public class BaseApi {
protected final HttpRequest request = new HttpRequest();
}
@@ -1,142 +0,0 @@
package com.foxinmy.weixin4j.api;
import java.util.List;
import com.alibaba.fastjson.JSON;
import com.foxinmy.weixin4j.api.token.TokenApi;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.BaseResult;
import com.foxinmy.weixin4j.http.Response;
import com.foxinmy.weixin4j.model.Group;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.util.ConfigUtil;
/**
* 分组相关API
*
* @className GroupApi
* @author jy.hu
* @date 2014年9月25日
* @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>
* @see com.foxinmy.weixin4j.model.Group
*/
public class GroupApi extends BaseApi {
private final TokenApi tokenApi;
public GroupApi(TokenApi tokenApi) {
this.tokenApi = tokenApi;
}
/**
* 创建分组
*
* @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 = ConfigUtil.getValue("group_create_uri");
Token token = tokenApi.getToken();
Group group = new Group(name);
Response response = request.post(
String.format(group_create_uri, token.getAccessToken()),
group.toCreateJson());
return response.getAsJson().getObject("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 = ConfigUtil.getValue("group_get_uri");
Token token = tokenApi.getToken();
Response response = request.get(String.format(group_get_uri,
token.getAccessToken()));
return JSON.parseArray(response.getAsJson().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 getGroupByOpenId(String openId) throws WeixinException {
String group_getid_uri = ConfigUtil.getValue("group_getid_uri");
Token token = tokenApi.getToken();
Response response = request.post(
String.format(group_getid_uri, token.getAccessToken()),
String.format("{\"openid\":\"%s\"}", openId));
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 BaseResult modifyGroup(int groupId, String name)
throws WeixinException {
String group_modify_uri = ConfigUtil.getValue("group_modify_uri");
Token token = tokenApi.getToken();
Group group = new Group(groupId, name);
Response response = request.post(
String.format(group_modify_uri, token.getAccessToken()),
group.toModifyJson());
return response.getAsResult();
}
/**
* 移动分组
*
* @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 BaseResult moveGroup(String openId, int groupId)
throws WeixinException {
String group_move_uri = ConfigUtil.getValue("group_move_uri");
Token token = tokenApi.getToken();
Response response = request.post(String.format(group_move_uri,
token.getAccessToken()), String.format(
"{\"openid\":\"%s\",\"to_groupid\":%d}", openId, groupId));
return response.getAsResult();
}
}
@@ -1,45 +0,0 @@
package com.foxinmy.weixin4j.api;
import com.alibaba.fastjson.JSONObject;
import com.foxinmy.weixin4j.api.token.TokenApi;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.Response;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.util.ConfigUtil;
/**
* 辅助相关API
*
* @className HelperApi
* @author jy.hu
* @date 2014年9月26日
* @since JDK 1.7
* @see
*/
public class HelperApi extends BaseApi {
private final TokenApi tokenApi;
public HelperApi(TokenApi tokenApi){
this.tokenApi = tokenApi;
}
/**
* 长链接转短链接
*
* @param url
* @return 短链接
* @throws WeixinException
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E9%95%BF%E9%93%BE%E6%8E%A5%E8%BD%AC%E7%9F%AD%E9%93%BE%E6%8E%A5%E6%8E%A5%E5%8F%A3">长链接转短链接</a>
*/
public String getShorturl(String url) throws WeixinException {
String shorturl_uri = ConfigUtil.getValue("shorturl_uri");
Token token = tokenApi.getToken();
JSONObject obj = new JSONObject();
obj.put("action", "long2short");
obj.put("long_url", url);
Response response = request.post(String.format(shorturl_uri, token.getAccessToken()), obj.toJSONString());
return response.getAsJson().getString("short_url");
}
}
@@ -1,270 +0,0 @@
package com.foxinmy.weixin4j.api;
import java.io.File;
import java.util.List;
import com.alibaba.fastjson.JSONObject;
import com.foxinmy.weixin4j.api.token.TokenApi;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.BaseResult;
import com.foxinmy.weixin4j.http.Response;
import com.foxinmy.weixin4j.model.MpArticle;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.type.MediaType;
import com.foxinmy.weixin4j.util.ConfigUtil;
/**
* 群发相关API
*
* @className MassApi
* @author jy.hu
* @date 2014年9月25日
* @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">群发接口</a>
* @see com.foxinmy.weixin4j.model.MpArticle
*/
public class MassApi extends BaseApi {
private final TokenApi tokenApi;
public MassApi(TokenApi tokenApi) {
this.tokenApi = tokenApi;
}
/**
* 上传图文消息,一个图文消息支持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 uploadArticle(List<MpArticle> articles)
throws WeixinException {
String article_upload_uri = ConfigUtil.getValue("article_upload_uri");
Token token = tokenApi.getToken();
JSONObject obj = new JSONObject();
obj.put("articles", articles);
Response response = request.post(
String.format(article_upload_uri, token.getAccessToken()),
obj.toJSONString());
return response.getAsJson().getString("media_id");
}
/**
* 上传分组群发的视频素材
*
* @param mediaId
* 媒体文件中上传得到的Id
* @param title
* 标题 可为空
* @param desc
* 描述 可为空
* @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 {@link com.foxinmy.weixin4j.api.MediaApi#uploadMedia(File, MediaType)}
*/
public String uploadVideo(String mediaId, String title, String desc)
throws WeixinException {
String video_upload_uri = ConfigUtil.getValue("video_upload_uri");
Token token = tokenApi.getToken();
JSONObject obj = new JSONObject();
obj.put("media_id", mediaId);
obj.put("title", title);
obj.put("description", desc);
Response response = request.post(
String.format(video_upload_uri, token.getAccessToken()),
obj.toJSONString());
return response.getAsJson().getString("media_id");
}
/**
* 分组群发
* <p>
* 在返回成功时,意味着群发任务提交成功,并不意味着此时群发已经结束,所以,仍有可能在后续的发送过程中出现异常情况导致用户未收到消息,
* 如消息有时会进行审核、服务器不稳定等,此外,群发任务一般需要较长的时间才能全部发送完毕
* </p>
*
* @param jsonPara
* json格式的参数
* @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.Group
* @see {@link com.foxinmy.weixin4j.api.GroupApi#getGroupByOpenId(String)}
* @see {@link com.foxinmy.weixin4j.api.GroupApi#getGroups()}
*/
private String massByGroup(JSONObject jsonPara, String groupId)
throws WeixinException {
String mass_group_uri = ConfigUtil.getValue("mass_group_uri");
Token token = tokenApi.getToken();
Response response = request.post(
String.format(mass_group_uri, token.getAccessToken()),
jsonPara.toJSONString());
return response.getAsJson().getString("msg_id");
}
/**
* openId群发
*
* @param jsonPara
* json格式的参数
* @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.User
*/
private String massByOpenIds(JSONObject jsonPara, String... openIds)
throws WeixinException {
String mass_openid_uri = ConfigUtil.getValue("mass_openid_uri");
Token token = tokenApi.getToken();
Response response = request.post(
String.format(mass_openid_uri, token.getAccessToken()),
jsonPara.toJSONString());
return response.getAsJson().getString("msg_id");
}
/**
* 分组群发
*
* @param mediaId
* 媒体ID 如果为text 则表示content
* @param mediaType
* 媒体类型
* @param groupId
* 分组ID
* @return
* @throws WeixinException
* @see com.foxinmy.weixin4j.model.Group
* @see com.foxinmy.weixin4j.type.MediaType
* @see {@link com.foxinmy.weixin4j.api.MediaApi#uploadMedia(File, MediaType)}
* @see {@link com.foxinmy.weixin4j.api.GroupApi#getGroupByOpenId(String)}
* @see {@link com.foxinmy.weixin4j.api.GroupApi#getGroups()}
* @see {@link com.foxinmy.weixin4j.api.MassApi#massByGroup(JSONObject,String)}
*/
public String massByGroup(String mediaId, MediaType mediaType,
String groupId) throws WeixinException {
JSONObject jsonPara = new JSONObject();
jsonPara.put("filter", new JSONObject().put("group_id", groupId));
jsonPara.put(mediaType.name(), new JSONObject().put(
mediaType == MediaType.text ? "content" : "media_id", mediaId));
jsonPara.put("msgtype", mediaType.name());
return massByGroup(jsonPara, groupId);
}
/**
* 分组群发图文消息
*
* @param articles
* 图文消息列表
* @param groupId
* 分组ID
* @return 发送出去的消息ID
* @throws WeixinException
* @see com.foxinmy.weixin4j.model.MpArticle
* @see com.foxinmy.weixin4j.model.Group
* @see {@link com.foxinmy.weixin4j.api.MediaApi#uploadMedia(File, MediaType)}
* @see {@link com.foxinmy.weixin4j.api.MassApi#uploadNews(List)}
* @see {@link com.foxinmy.weixin4j.api.MassApi#massByGroup(String,MediaType,String)}
*/
public String massArticleByGroup(List<MpArticle> articles, String groupId)
throws WeixinException {
String mediaId = uploadArticle(articles);
return massByGroup(mediaId, MediaType.mpnews, groupId);
}
/**
* openId群发
*
* @param mediaId
* 媒体ID 如果为text 则表示content
* @param mediaType
* 媒体类型
* @param openIds
* openId列表
* @return
* @throws WeixinException
* @see com.foxinmy.weixin4j.model.User
* @see com.foxinmy.weixin4j.type.MediaType
* @see {@link com.foxinmy.weixin4j.api.MediaApi#uploadMedia(File, MediaType)}
* @see {@link com.foxinmy.weixin4j.api.MassApi#massByOpenIds(JSONObject,String...)}
*/
public String massByOpenIds(String mediaId, MediaType mediaType,
String... openIds) throws WeixinException {
JSONObject jsonPara = new JSONObject();
jsonPara.put("touser", openIds);
jsonPara.put(mediaType.name(), new JSONObject().put(
mediaType == MediaType.text ? "content" : "media_id", mediaId));
jsonPara.put("msgtype", mediaType.name());
return massByOpenIds(jsonPara, openIds);
}
/**
* openId图文群发
*
* @param articles
* 图文消息列表
* @param openIds
* 目标ID列表
* @return 发送出去的消息ID
* @throws WeixinException
* @see com.foxinmy.weixin4j.model.MpArticle
* @see com.foxinmy.weixin4j.model.User
* @see {@link com.foxinmy.weixin4j.api.MediaApi#uploadMedia(File, MediaType)}
* @see {@link com.foxinmy.weixin4j.api.MediaApi#uploadNews(List)}
* @see {@link com.foxinmy.weixin4j.api.MassApi#massByOpenIds(String,MediaType,String...)}
*/
public String massArticleByOpenIds(List<MpArticle> articles,
String... openIds) throws WeixinException {
String mediaId = uploadArticle(articles);
return massByOpenIds(mediaId, MediaType.mpnews, openIds);
}
/**
* 删除群发消息
* <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.api.MassApi#massByGroup(JSONObject, String)}
* @see {@link com.foxinmy.weixin4j.api.MassApi#massByOpenIds(JSONObject, String...)
*/
public BaseResult deleteMassNews(String msgid) throws WeixinException {
JSONObject obj = new JSONObject();
obj.put("msgid", msgid);
String mass_delete_uri = ConfigUtil.getValue("mass_delete_uri");
Token token = tokenApi.getToken();
Response response = request.post(
String.format(mass_delete_uri, token.getAccessToken()),
obj.toJSONString());
return response.getAsResult();
}
@@ -1,142 +0,0 @@
package com.foxinmy.weixin4j.api;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.http.entity.mime.content.ByteArrayBody;
import com.foxinmy.weixin4j.api.token.TokenApi;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.PartParameter;
import com.foxinmy.weixin4j.http.Response;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.type.MediaType;
import com.foxinmy.weixin4j.util.ConfigUtil;
import com.foxinmy.weixin4j.util.IOUtil;
/**
* 媒体相关API
*
* @className MediaApi
* @author jy.hu
* @date 2014年9月25日
* @since JDK 1.7
* @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 class MediaApi extends BaseApi {
private final TokenApi tokenApi;
public MediaApi(TokenApi tokenApi) {
this.tokenApi = tokenApi;
}
/**
* 上传媒体文件
* <p>
* 正常情况下返回{"type":"TYPE","media_id":"MEDIA_ID","created_at":123456789},
* 否则抛出异常.
* </p>
*
* @param file
* 文件对象
* @param mediaType
* 媒体类型
* @return 上传到微信服务器返回的媒体标识
* @throws WeixinException
* @throws IOException
* @throws
* @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, IOException {
byte[] datas = IOUtil.toByteArray(new FileInputStream(file));
return uploadMedia(file.getName(), datas, mediaType);
}
/**
* 上传媒体文件
*
* @param bytes
* 媒体数据包
* @param mediaType
* 媒体类型
* @return 上传到微信服务器返回的媒体标识
* @throws WeixinException
* @see {@link com.foxinmy.weixin4j.api.MediaApi#uploadMedia(File, MediaType)}
*/
public String uploadMedia(String fileName, byte[] bytes, MediaType mediaType)
throws WeixinException {
Token token = tokenApi.getToken();
String file_upload_uri = ConfigUtil.getValue("file_upload_uri");
Response response = request.post(String.format(file_upload_uri,
token.getAccessToken(), mediaType.name()), new PartParameter(
"media", new ByteArrayBody(bytes, fileName)));
return response.getAsJson().getString("media_id");
}
/**
* 下载媒体文件
* <p>
* 正常情况下返回表头如Content-Type: image/jpeg,否则抛出异常.
* </p>
*
* @param mediaId
* 存储在微信服务器上的媒体标识
* @param mediaType
* 媒体类型
* @return 写入硬盘后的文件对象
* @throws WeixinException
* @throws IOException
* @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, IOException {
String media_path = ConfigUtil.getValue("media_path");
byte[] datas = downloadMediaData(mediaId, mediaType);
String filename = mediaId + "." + mediaType.getFormatType();
File file = new File(media_path + File.separator + filename);
if (file.exists()) {
return file;
}
FileOutputStream out = null;
try {
file.createNewFile();
} catch (IOException e) {
file.getParentFile().mkdirs();
file.createNewFile();
}
out = new FileOutputStream(file);
out.write(datas);
out.close();
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 = tokenApi.getToken();
String file_download_uri = ConfigUtil.getValue("file_download_uri");
Response response = request.get(String.format(file_download_uri,
token.getAccessToken(), mediaId));
return response.getBody();
}
}
@@ -1,89 +0,0 @@
package com.foxinmy.weixin4j.api;
import java.util.List;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.foxinmy.weixin4j.api.token.TokenApi;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.BaseResult;
import com.foxinmy.weixin4j.http.Response;
import com.foxinmy.weixin4j.model.Button;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.util.ConfigUtil;
/**
* 菜单相关API
*
* @className MenuApi
* @author jy.hu
* @date 2014年9月25日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.model.Button
*/
public class MenuApi extends BaseApi {
private final TokenApi tokenApi;
public MenuApi(TokenApi tokenApi) {
this.tokenApi = tokenApi;
}
/**
* 自定义菜单
*
* @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 BaseResult createMenu(List<Button> btnList) throws WeixinException {
String menu_create_uri = ConfigUtil.getValue("menu_create_uri");
Token token = tokenApi.getToken();
JSONObject obj = new JSONObject();
obj.put("button", btnList);
Response response = request.post(
String.format(menu_create_uri, token.getAccessToken()),
obj.toJSONString());
return response.getAsResult();
}
/**
* 查询菜单
*
* @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 = ConfigUtil.getValue("menu_get_uri");
Token token = tokenApi.getToken();
Response response = request.get(String.format(menu_get_uri,
token.getAccessToken()));
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 BaseResult deleteMenu() throws WeixinException {
String menu_delete_uri = ConfigUtil.getValue("menu_delete_uri");
Token token = tokenApi.getToken();
Response response = request.get(String.format(menu_delete_uri,
token.getAccessToken()));
return response.getAsResult();
}
}
@@ -1,166 +0,0 @@
package com.foxinmy.weixin4j.api;
import java.util.List;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.foxinmy.weixin4j.api.token.TokenApi;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.BaseResult;
import com.foxinmy.weixin4j.http.Response;
import com.foxinmy.weixin4j.model.CustomRecord;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.msg.model.Article;
import com.foxinmy.weixin4j.msg.model.BaseMsg;
import com.foxinmy.weixin4j.msg.notify.ArticleNotify;
import com.foxinmy.weixin4j.msg.notify.BaseNotify;
import com.foxinmy.weixin4j.util.ConfigUtil;
/**
* 客服相关API
*
* @className NotifyApi
* @author jy.hu
* @date 2014年9月26日
* @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>
* @see com.foxinmy.weixin4j.msg.notify.TextNotify
* @see com.foxinmy.weixin4j.msg.notify.ImageNotify
* @see com.foxinmy.weixin4j.msg.notify.MusicNotify
* @see com.foxinmy.weixin4j.msg.notify.VideoNotify
* @see com.foxinmy.weixin4j.msg.notify.VoiceNotify
* @see com.foxinmy.weixin4j.msg.notify.ArticleNotify
*/
public class NotifyApi extends BaseApi {
private final TokenApi tokenApi;
public NotifyApi(TokenApi tokenApi) {
this.tokenApi = tokenApi;
}
/**
* 发送客服消息
*
* @param jsonPara
* @return
* @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#.E5.8F.91.E9.80.81.E9.9F.B3.E4.B9.90.E6.B6.88.E6.81.AF">发送客服消息</a>
*/
private BaseResult sendNotify(String jsonPara) throws WeixinException {
String custom_notify_uri = ConfigUtil.getValue("custom_notify_uri");
Token token = tokenApi.getToken();
Response response = request.post(
String.format(custom_notify_uri, token.getAccessToken()),
jsonPara);
return response.getAsResult();
}
/**
* 发送客服消息(在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>
* @see com.foxinmy.weixin4j.msg.notify.TextNotify
* @see com.foxinmy.weixin4j.msg.notify.ImageNotify
* @see com.foxinmy.weixin4j.msg.notify.MusicNotify
* @see com.foxinmy.weixin4j.msg.notify.VideoNotify
* @see com.foxinmy.weixin4j.msg.notify.VoiceNotify
* @see com.foxinmy.weixin4j.msg.notify.ArticleNotify
* @see {@link com.foxinmy.weixin4j.api.NotifyApi#sendNotify(String)}
*/
public BaseResult sendNotify(BaseNotify notify) throws WeixinException {
return sendNotify(notify.toJson());
}
/**
* 发送图文消息
*
* @param touser
* 目标ID
* @param articles
* 图文列表
* @return 发送结果
* @throws WeixinException
* @see com.foxinmy.weixin4j.msg.model.Article
* @see com.foxinmy.weixin4j.msg.notify.ArticleNotify
*/
public BaseResult sendNotify(String touser, List<Article> articles)
throws WeixinException {
ArticleNotify notify = new ArticleNotify(touser);
notify.pushAll(articles);
return sendNotify(notify);
}
/**
* 发送客服消息(不包含图文消息)
*
* @param touser
* 目标用户
* @param baseMsg
* 消息类型
* @return 发送结果
* @throws WeixinException
* @see com.foxinmy.weixin4j.msg.model.Text
* @see com.foxinmy.weixin4j.msg.model.Image
* @see com.foxinmy.weixin4j.msg.model.Music
* @see com.foxinmy.weixin4j.msg.model.Video
* @see com.foxinmy.weixin4j.msg.model.Voice
* @see {@link com.foxinmy.weixin4j.msg.model.BaseMsg#toNotifyJson()}
* @see {@link com.foxinmy.weixin4j.api.NotifyApi#sendNotify(String)}
*/
public BaseResult sendNotify(String touser, BaseMsg baseMsg)
throws WeixinException {
StringBuilder jsonPara = new StringBuilder();
String mediaType = baseMsg.getMediaType().name();
jsonPara.append("{");
jsonPara.append("\"touser\":\"").append(touser).append("\",");
jsonPara.append("\"msgtype\":\"").append(mediaType).append("\",");
jsonPara.append("\"").append(mediaType).append("\":");
jsonPara.append(baseMsg.toNotifyJson()).append("}");
return sendNotify(jsonPara.toString());
}
/**
* 客服聊天记录
*
* @param openId
* 用户标识 可为空
* @param starttime
* 查询开始时间
* @param endtime
* 查询结束时间 每次查询不能跨日查询
* @param pagesize
* 每页大小 每页最多拉取1000条
* @param pageindex
* 查询第几页 从1开始
* @throws WeixinException
* @see com.foxinmy.weixin4j.model.CustomRecord
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96%E5%AE%A2%E6%9C%8D%E8%81%8A%E5%A4%A9%E8%AE%B0%E5%BD%95">查询客服聊天记录</a>
*/
public List<CustomRecord> getCustomRecord(String openId, long starttime,
long endtime, int pagesize, int pageindex) throws WeixinException {
JSONObject obj = new JSONObject();
obj.put("openId", openId == null ? "" : openId);
obj.put("starttime", starttime);
obj.put("endtime", endtime);
obj.put("pagesize", pagesize > 1000 ? 1000 : pagesize);
obj.put("pageindex", pageindex);
String custom_record_uri = ConfigUtil.getValue("custom_record_uri");
Token token = tokenApi.getToken();
Response response = request.post(
String.format(custom_record_uri, token.getAccessToken()),
obj.toJSONString());
String text = response.getAsJson().getString("recordlist");
return JSON.parseArray(text, CustomRecord.class);
}
}
@@ -1,113 +0,0 @@
package com.foxinmy.weixin4j.api;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import com.foxinmy.weixin4j.api.token.TokenApi;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.Response;
import com.foxinmy.weixin4j.model.QRParameter;
import com.foxinmy.weixin4j.model.QRParameter.QRType;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.util.ConfigUtil;
/**
* 二维码相关API
*
* @className QrApi
* @author jy.hu
* @date 2014年9月25日
* @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 QrApi extends BaseApi {
private final TokenApi tokenApi;
public QrApi(TokenApi tokenApi) {
this.tokenApi = tokenApi;
}
/**
* 生成带参数的二维码
*
* @param parameter
* @return byte数据包
* @throws WeixinException
* @see {@link com.foxinmy.weixin4j.api.QrApi#getQR(QRParameter)}
*/
public byte[] getQRData(QRParameter parameter) throws WeixinException {
Token token = tokenApi.getToken();
String qr_uri = ConfigUtil.getValue("qr_ticket_uri");
Response response = request.post(
String.format(qr_uri, token.getAccessToken()),
parameter.toJson());
String ticket = response.getAsJson().getString("ticket");
qr_uri = ConfigUtil.getValue("qr_image_uri");
response = request.get(String.format(qr_uri, ticket));
return response.getBody();
}
/**
* 生成带参数的二维码
*
* @param sceneId
* 场景值
* @param expireSeconds
* 过期秒数 如果小于等于0则 视为永久二维码
* @return byte数据包
* @throws WeixinException
* @see {@link com.foxinmy.weixin4j.api.QrApi#getQR(QRParameter)}
*/
public byte[] getQRData(int sceneId, int expireSeconds)
throws WeixinException {
QRParameter parameter = new QRParameter(sceneId, QRType.TEMPORARY,
expireSeconds);
if (expireSeconds <= 0) {
parameter.setQrType(QRType.PERMANENCE);
}
return getQRData(parameter);
}
/**
* 生成带参数的二维码
* <p>
* 二维码分为临时跟永久两种,扫描时触发推送带参数事件
* </p>
*
* @param parameter
* 二维码参数
* @return 硬盘存储的文件对象
* @throws WeixinException
* @throws FileNotFoundException
* @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,
IOException {
String qr_path = ConfigUtil.getValue("qr_path");
String filename = String.format("%s_%d_%d.jpg", parameter.getQrType()
.name(), parameter.getSceneId(), parameter.getExpireSeconds());
File file = new File(qr_path + File.separator + filename);
if (parameter.getQrType() == QRType.PERMANENCE && file.exists()) {
return file;
}
byte[] datas = getQRData(parameter);
FileOutputStream out = null;
try {
file.createNewFile();
} catch (IOException e) {
file.getParentFile().mkdirs();
file.createNewFile();
}
out = new FileOutputStream(file);
out.write(datas);
out.close();
return file;
}
}
@@ -1 +0,0 @@
API的实现
@@ -1,49 +0,0 @@
package com.foxinmy.weixin4j.api;
import com.foxinmy.weixin4j.api.token.TokenApi;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.BaseResult;
import com.foxinmy.weixin4j.http.Response;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.msg.out.TemplateMessage;
import com.foxinmy.weixin4j.util.ConfigUtil;
/**
* 模板消息相关API
*
* @className TemplApi
* @author jy
* @date 2014年9月30日
* @since JDK 1.7
* @see
*/
public class TmplApi extends BaseApi {
private final TokenApi tokenApi;
public TmplApi(TokenApi tokenApi) {
this.tokenApi = tokenApi;
}
/**
* 发送模板消息
*
* @param message
* @return 发送结果
* @throws WeixinException
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E6%A8%A1%E6%9D%BF%E6%B6%88%E6%81%AF%E6%8E%A5%E5%8F%A3">模板消息</a>
* @see com.foxinmy.weixin4j.msg.out.TemplateMessage
* @seee com.foxinmy.weixin4j.msg.event.TemplatesendjobfinishMessage
*/
public BaseResult sendTmplMessage(TemplateMessage tplMessage)
throws WeixinException {
Token token = tokenApi.getToken();
String template_send_uri = ConfigUtil.getValue("template_send_uri");
Response response = request.post(
String.format(template_send_uri, token.getAccessToken()),
tplMessage.toJson());
return response.getAsResult();
}
}
@@ -1,182 +0,0 @@
package com.foxinmy.weixin4j.api;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.foxinmy.weixin4j.api.token.TokenApi;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.BaseResult;
import com.foxinmy.weixin4j.http.Response;
import com.foxinmy.weixin4j.model.Following;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.model.User;
import com.foxinmy.weixin4j.model.UserToken;
import com.foxinmy.weixin4j.util.ConfigUtil;
/**
* 用户相关API
*
* @className UserApi
* @author jy.hu
* @date 2014年9月25日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.model.User
*/
public class UserApi extends BaseApi {
private final TokenApi tokenApi;
public UserApi(TokenApi tokenApi) {
this.tokenApi = tokenApi;
}
/**
* 获取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 = ConfigUtil.getValue("sns_user_token_uri");
Response response = request.get(String.format(user_token_uri, code));
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.api.UserApi#getAccessToken(String)}
*/
public User getUser(UserToken token) throws WeixinException {
String user_info_uri = ConfigUtil.getValue("sns_user_info_uri");
Response response = request.get(String.format(user_info_uri,
token.getAccessToken(), 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 = ConfigUtil.getValue("api_user_info_uri");
Token token = tokenApi.getToken();
Response response = request.get(String.format(user_info_uri,
token.getAccessToken(), openId));
return response.getAsObject(User.class);
}
/**
* 获取用户一定数量(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 = ConfigUtil.getValue("following_uri");
Token token = tokenApi.getToken();
Response response = request.get(String.format(fllowing_uri,
token.getAccessToken(), 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.api.UserApi#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 openId
* 用户ID
* @param remark
* 备注名
* @throws WeixinException
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E8%AE%BE%E7%BD%AE%E7%94%A8%E6%88%B7%E5%A4%87%E6%B3%A8%E5%90%8D%E6%8E%A5%E5%8F%A3">设置用户备注名</a>
*/
public BaseResult remarkUserName(String openId, String remark)
throws WeixinException {
String updateremark_uri = ConfigUtil.getValue("updateremark_uri");
Token token = tokenApi.getToken();
JSONObject obj = new JSONObject();
obj.put("openid", openId);
obj.put("remark", remark);
Response response = request.post(
String.format(updateremark_uri, token.getAccessToken()),
obj.toJSONString());
return response.getAsResult();
}
}
@@ -1,23 +0,0 @@
package com.foxinmy.weixin4j.api.token;
import com.foxinmy.weixin4j.util.ConfigUtil;
/**
* 获取config.properties中的appid&appsecret信息
*
* @className AbstractTokenApi
* @author jy
* @date 2014年10月6日
* @since JDK 1.7
* @see
*/
public abstract class AbstractTokenApi implements TokenApi {
protected String getAppid() {
return ConfigUtil.getValue("app_id");
}
protected String getAppsecret() {
return ConfigUtil.getValue("app_secret");
}
}
@@ -1,101 +0,0 @@
package com.foxinmy.weixin4j.api.token;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Calendar;
import org.jsoup.helper.StringUtil;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.HttpRequest;
import com.foxinmy.weixin4j.http.Response;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.util.ConfigUtil;
import com.foxinmy.weixin4j.xml.XStream;
/**
* 基于文件保存的Token获取类
*
* @className FileTokenApi
* @author jy.hu
* @date 2014年9月27日
* @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>
* @see com.foxinmy.weixin4j.model.Token
*/
public class FileTokenApi extends AbstractTokenApi {
private final HttpRequest request = new HttpRequest();
private final String appid;
private final String appsecret;
public FileTokenApi() {
this.appid = getAppid();
this.appsecret = getAppsecret();
}
public FileTokenApi(String appid, String appsecret) {
this.appid = appid;
this.appsecret = appsecret;
}
/**
* 获取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
*/
@Override
public Token getToken() throws WeixinException {
if (StringUtil.isBlank(appid) || StringUtil.isBlank(appsecret)) {
throw new IllegalArgumentException(
"appid or appsecret not be null!");
}
XStream xstream = new XStream();
xstream.autodetectAnnotations(true);
xstream.processAnnotations(Token.class);
File token_file = new File(String.format("%s/token_%s.xml",
ConfigUtil.getValue("token_path"), appid));
Token token = null;
Calendar ca = Calendar.getInstance();
long now_time = ca.getTimeInMillis();
try {
String api_token_uri = String.format(
ConfigUtil.getValue("api_token_uri"), appid, appsecret);
Response response = null;
if (token_file.exists()) {
token = (Token) xstream.fromXML(token_file);
long expise_time = token.getTime()
+ (token.getExpiresIn() * 1000) - 3;
if (expise_time > now_time) {
return token;
}
response = request.get(api_token_uri);
} else {
response = request.get(api_token_uri);
try {
token_file.createNewFile();
} catch (IOException e) {
token_file.getParentFile().mkdirs();
}
}
token = response.getAsObject(Token.class);
token.setTime(now_time);
token.setOpenid(appid);
xstream.toXML(token, new FileOutputStream(token_file));
} catch (IOException e) {
;
}
return token;
}
}
@@ -1 +0,0 @@
Token的实现
@@ -1,86 +0,0 @@
package com.foxinmy.weixin4j.api.token;
import org.jsoup.helper.StringUtil;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.HttpRequest;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.util.ConfigUtil;
/**
* 基于redis保存的Token获取类
*
* @className RedisTokenApi
* @author jy.hu
* @date 2014年9月27日
* @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>
* @see com.foxinmy.weixin4j.model.Token
*/
public class RedisTokenApi extends AbstractTokenApi {
private final HttpRequest request = new HttpRequest();
private final String appid;
private final String appsecret;
private JedisPool jedisPool;
public RedisTokenApi() {
this.appid = getAppid();
this.appsecret = getAppsecret();
}
public RedisTokenApi(String appid, String appsecret) {
this(appid, appsecret, "localhost", 6379);
}
public RedisTokenApi(String appid, String appsecret, String host, int port) {
this.appid = appid;
this.appsecret = appsecret;
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(50);
poolConfig.setMaxIdle(5);
poolConfig.setMaxWaitMillis(2000);
poolConfig.setTestOnBorrow(false);
poolConfig.setTestOnReturn(true);
this.jedisPool = new JedisPool(poolConfig, host, port);
}
@Override
public Token getToken() throws WeixinException {
if (StringUtil.isBlank(appid) || StringUtil.isBlank(appsecret)) {
throw new IllegalArgumentException(
"appid or appsecret not be null!");
}
Token token = null;
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
String key = String.format("token:%s", appid);
String accessToken = jedis.get(key);
if (StringUtil.isBlank(accessToken)) {
String api_token_uri = String.format(
ConfigUtil.getValue("api_token_uri"), appid, appsecret);
token = request.get(api_token_uri).getAsObject(Token.class);
jedis.setex(key, token.getExpiresIn() - 3,
token.getAccessToken());
} else {
token = new Token();
token.setAccessToken(accessToken);
token.setExpiresIn(jedis.ttl(key).intValue());
}
token.setTime(System.currentTimeMillis());
token.setOpenid(appid);
} catch (Exception e) {
jedisPool.returnBrokenResource(jedis);
} finally {
jedisPool.returnResource(jedis);
}
return token;
}
}
@@ -1,20 +0,0 @@
package com.foxinmy.weixin4j.api.token;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.model.Token;
/**
* 获取Token接口
*
* @className TokenApi
* @author jy.hu
* @date 2014年9月27日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.model.Token
* @see com.foxinmy.weixin4j.api.token.AbstractTokenApi
* @see com.foxinmy.weixin4j.api.token.FileTokenApi
* @see com.foxinmy.weixin4j.api.token.RedisTokenApi
*/
public interface TokenApi {
public Token getToken() throws WeixinException;
}
@@ -1,44 +0,0 @@
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 errorCode;
}
public String getErrorMsg() {
return errorMsg;
}
@Override
public String getMessage() {
return this.errorCode + "," + this.errorMsg;
}
}
@@ -1,78 +0,0 @@
package com.foxinmy.weixin4j.http;
import java.io.Serializable;
/**
* 调用接口响应值
*
* @className BaseResult
* @author jy.hu
* @date 2014年9月24日
* @since JDK 1.7
* @see <a
* href="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">全局返回码</a>
*/
public class BaseResult implements Serializable {
private static final long serialVersionUID = -6185313616955051150L;
private int errcode;
private String errmsg;
private String msgid;
private String text;
public BaseResult() {
}
public BaseResult(int errcode, String errmsg, String text) {
this.errcode = errcode;
this.errmsg = errmsg;
this.text = text;
}
public BaseResult(int errcode, String errmsg, String msgid, String text) {
this.errcode = errcode;
this.errmsg = errmsg;
this.msgid = msgid;
this.text = text;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public int getErrcode() {
return errcode;
}
public void setErrcode(int errcode) {
this.errcode = errcode;
}
public String getErrmsg() {
return errmsg;
}
public void setErrmsg(String errmsg) {
this.errmsg = errmsg;
}
public String getMsgid() {
return msgid;
}
public void setMsgid(String msgid) {
this.msgid = msgid;
}
@Override
public String toString() {
return "BaseResult [errcode=" + errcode + ", errmsg=" + errmsg
+ ", msgid=" + msgid + ", text=" + text + "]";
}
}
@@ -1,195 +0,0 @@
package com.foxinmy.weixin4j.http;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.codec.binary.StringUtils;
import org.apache.http.Consts;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.StatusLine;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.client.params.CookiePolicy;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.FileEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.impl.client.AbstractHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.PoolingClientConnectionManager;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.util.EntityUtils;
import com.foxinmy.weixin4j.exception.WeixinException;
/**
* 调用微信相关接口的HttpRequest,对于其他请求可能并不试用
*
* @className HttpRequest
* @author jy
* @date 2014年8月21日
* @since JDK 1.7
* @see
*/
public class HttpRequest {
private AbstractHttpClient client;
public HttpRequest() {
this(150, 100, 10000, 10000);
}
public HttpRequest(int maxConPerRoute, int maxTotal, int socketTimeout,
int connectionTimeout) {
PoolingClientConnectionManager connectionManager = new PoolingClientConnectionManager();
// 指定IP并发最大数
connectionManager.setDefaultMaxPerRoute(maxConPerRoute);
// socket最大创建数
connectionManager.setMaxTotal(maxTotal);
client = new DefaultHttpClient(connectionManager);
client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT,
socketTimeout);
client.getParams().setParameter(
CoreConnectionPNames.CONNECTION_TIMEOUT, connectionTimeout);
client.getParams().setBooleanParameter(
CoreConnectionPNames.TCP_NODELAY, false);
client.getParams().setParameter(
CoreConnectionPNames.SOCKET_BUFFER_SIZE, 1024 * 1024);
client.getParams().setParameter(ClientPNames.COOKIE_POLICY,
CookiePolicy.IGNORE_COOKIES);
client.getParams().setParameter(
CoreProtocolPNames.HTTP_CONTENT_CHARSET, Consts.UTF_8);
client.getParams().setParameter(HttpHeaders.CONTENT_ENCODING,
Consts.UTF_8);
client.getParams().setParameter(HttpHeaders.ACCEPT_CHARSET,
Consts.UTF_8);
}
public Response get(String url) throws WeixinException {
return get(url, (Parameter[]) null);
}
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 HttpGet(sb.toString()));
}
public Response post(String url) throws WeixinException {
return post(url, (Parameter[]) null);
}
public Response post(String url, Parameter... parameters)
throws WeixinException {
HttpPost method = new HttpPost(url);
List<NameValuePair> params = new ArrayList<NameValuePair>();
for (Parameter parameter : parameters) {
params.add(parameter.toPostPara());
}
method.setEntity(new UrlEncodedFormEntity(params, Consts.UTF_8));
return doRequest(method);
}
public Response post(String url, String body) throws WeixinException {
HttpPost method = new HttpPost(url);
method.setEntity(new StringEntity(body, ContentType.create(
ContentType.APPLICATION_JSON.getMimeType(), Consts.UTF_8)));
return doRequest(method);
}
public Response post(String url, byte[] bytes) throws WeixinException {
HttpPost method = new HttpPost(url);
method.setEntity(new ByteArrayEntity(bytes, ContentType.create(
ContentType.MULTIPART_FORM_DATA.getMimeType(), Consts.UTF_8)));
return doRequest(method);
}
public Response post(String url, File file) throws WeixinException {
HttpPost method = new HttpPost(url);
method.setEntity(new FileEntity(file, ContentType.create(
ContentType.APPLICATION_OCTET_STREAM.getMimeType(),
Consts.UTF_8)));
return doRequest(method);
}
public Response post(String url, PartParameter... paramters)
throws WeixinException {
HttpPost method = new HttpPost(url);
MultipartEntity entity = new MultipartEntity();
for (PartParameter paramter : paramters) {
entity.addPart(paramter.getName(), paramter.getContentBody());
}
method.setEntity(entity);
return doRequest(method);
}
protected Response doRequest(HttpRequestBase request)
throws WeixinException {
try {
HttpResponse httpResponse = client.execute(request);
StatusLine statusLine = httpResponse.getStatusLine();
HttpEntity httpEntity = httpResponse.getEntity();
int status = statusLine.getStatusCode();
if (status != HttpStatus.SC_OK) {
throw new WeixinException(status, "request fail");
}
// 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",
httpResponse.getFirstHeader("location")));
}
byte[] data = EntityUtils.toByteArray(httpEntity);
Response response = new Response();
response.setBody(data);
response.setStatusCode(status);
response.setStatusText(statusLine.getReasonPhrase());
response.setStream(new ByteArrayInputStream(data));
response.setText(StringUtils.newStringUtf8(data));
Header contentType = httpResponse
.getFirstHeader(HttpHeaders.CONTENT_TYPE);
if (contentType.getValue().contains(
ContentType.APPLICATION_JSON.getMimeType())
|| contentType.getValue().contains(
ContentType.TEXT_PLAIN.getMimeType())) {
BaseResult result = response.getAsResult();
if (result.getErrcode() != 0) {
throw new WeixinException(result.getErrcode(),
result.getErrmsg());
}
}
EntityUtils.consume(httpEntity);
return response;
} catch (IOException e) {
throw new WeixinException(e.getMessage());
} finally {
request.releaseConnection();
}
}
}
@@ -1,63 +0,0 @@
package com.foxinmy.weixin4j.http;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
public class Parameter {
private final static String CHARSET = StandardCharsets.UTF_8.name();
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", name, URLEncoder.encode(value, CHARSET));
} catch (UnsupportedEncodingException e) {
return String.format("&%s=%s", name, value);
}
}
public NameValuePair toPostPara() {
try {
return new BasicNameValuePair(name, URLEncoder.encode(value, CHARSET));
} catch (UnsupportedEncodingException e) {
return new BasicNameValuePair(name, value);
}
}
@Override
public String toString() {
return String.format("[Parameter name=%s, value=%s]", name, value);
}
}
@@ -1,35 +0,0 @@
package com.foxinmy.weixin4j.http;
import org.apache.http.entity.mime.content.ContentBody;
public class PartParameter {
private String name;
private ContentBody contentBody;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ContentBody getContentBody() {
return contentBody;
}
public void setContentBody(ContentBody contentBody) {
this.contentBody = contentBody;
}
public PartParameter(String name, ContentBody contentBody) {
super();
this.name = name;
this.contentBody = contentBody;
}
@Override
public String toString() {
return "PartParameter [name=" + name + ", contentBody=" + contentBody + "]";
}
}
@@ -1 +0,0 @@
基于HttpClient封装的针对微信公众平台API的HttpRequest
@@ -1,124 +0,0 @@
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.thoughtworks.xstream.XStream;
public class Response {
private String text;
private int statusCode;
private String statusText;
private byte[] body;
private InputStream stream;
public Response() {
}
public Response(String text) {
this.text = text;
}
public String getAsString() {
return text;
}
public BaseResult getAsResult() {
return JSON.parseObject(text, BaseResult.class);
}
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 BaseResult getBaseError() throws DocumentException {
BaseResult result = getAsResult();
if (result.getErrcode() != 0) {
SAXReader reader = new SAXReader();
Document doc = reader.read(Thread.currentThread()
.getContextClassLoader().getResourceAsStream("error.xml"));
Node node = doc.getRootElement().selectSingleNode(
String.format("error[@code='%d']", result.getErrcode()));
if (node != null) {
result.setText(node.getStringValue());
}
}
return result;
}
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();
}
}
@@ -1,98 +0,0 @@
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 AuthResult(String location, AuthCode authCode) {
this.location = location;
this.authCode = authCode;
}
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();
}
}
@@ -1,113 +0,0 @@
package com.foxinmy.weixin4j.model;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.type.ButtonType;
/**
* 菜单按钮
* <p>
* 目前自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单,一级菜单最多4个汉字,二级菜单最多7个汉字,多出来的部分将会以"..."代替
* 请注意,创建自定义菜单后,由于微信客户端缓存,需要24小时微信客户端才会展现出来,建议测试时可以尝试取消关注公众账号后再次关注,则可以看到创建后的效果
* </p>
*
* @className Button
* @author jy.hu
* @date 2014年4月5日
* @since JDK 1.7
* @see com.foxinmy.weixin4j.type.ButtonType
*/
public class Button implements Serializable {
private static final long serialVersionUID = -6422234732203854866L;
private String name;
private ButtonType type; // 菜单的响应动作类型
private String key; // click等点击类型必须
private String url; // view类型必须
@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 = ButtonType.view;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ButtonType getType() {
return type;
}
public void setType(ButtonType 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 Button pushSub(Button btn) {
if (this.subs == null) {
this.subs = new ArrayList<Button>();
}
this.subs.add(btn);
return this;
}
@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();
}
}
@@ -1,95 +0,0 @@
package com.foxinmy.weixin4j.model;
import java.io.Serializable;
import java.util.Date;
/**
* 客服聊天记录
*
* @className CustomRecord
* @author jy
* @date 2014年6月28日
* @since JDK 1.7
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96%E5%AE%A2%E6%9C%8D%E8%81%8A%E5%A4%A9%E8%AE%B0%E5%BD%95">客服聊天记录</a>
*/
public class CustomRecord implements Serializable {
private static final long serialVersionUID = -4024147769411601325L;
private String worker;// 客服账号
private String openid;// 用户的标识
private Opercode opercode;// 操作ID(会话状态)
private Date time;// 操作时间
private String text;// 聊天记录
public String getWorker() {
return worker;
}
public void setWorker(String worker) {
this.worker = worker;
}
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public Opercode getOpercode() {
return opercode;
}
public void setOpercode(Opercode opercode) {
this.opercode = opercode;
}
public Date getTime() {
return time;
}
public void setTime(Date time) {
this.time = time;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public enum Opercode {
MISS(1000, "创建未接入会话"), ONLINE(1001, "接入会话"), CALL(1002, "主动发起会话"), CLOSE(
1004, "关闭会话"), RASE(1005, "抢接会话"), RECEIVE1(2001, "公众号收到消息"), SEND(
2002, "客服发送消息"), RECEIVE2(2003, "客服收到消息");
private int code;
private String desc;
Opercode(int code, String desc) {
this.code = code;
this.desc = desc;
}
public int getCode() {
return code;
}
public String getDesc() {
return desc;
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[CustomRecord worker=").append(worker);
sb.append(" ,openid=").append(openid);
sb.append(" ,opercode=").append(opercode);
sb.append(" ,time=").append(time);
sb.append(" ,text=").append(text);
sb.append("]");
return sb.toString();
}
}
@@ -1,86 +0,0 @@
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();
}
}
@@ -1,96 +0,0 @@
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);
}
}
@@ -1,93 +0,0 @@
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;// 图文消息的描述 可为空
@JSONField(name = "show_cover_pic")
private short showCoverPic; // 是否显示封面,1为显示,0为不显示 可为空
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 short getShowCoverPic() {
return showCoverPic;
}
public void setShowCoverPic(short showCoverPic) {
this.showCoverPic = showCoverPic;
}
public MpArticle(String thumbMediaId, String title, String content) {
this.thumbMediaId = thumbMediaId;
this.title = title;
this.content = content;
}
public MpArticle() {
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[MpArticle thumbMediaId=").append(thumbMediaId);
sb.append(", author=").append(author);
sb.append(", title=").append(title);
sb.append(", url=").append(url);
sb.append(", content=").append(content);
sb.append(", digest=").append(digest);
sb.append(", showCoverPic=").append(showCoverPic).append("]");
return sb.toString();
}
}
@@ -1,110 +0,0 @@
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 {
TEMPORARY("QR_SCENE"), // 临时
PERMANENCE("QR_LIMIT_SCENE"); // 永久
private String name;
QRType(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
@XStreamAlias("expire_seconds")
private int expireSeconds; // 该二维码有效时间,以秒为单位。 最大不超过1800。
@XStreamAlias("action_name")
private QRType qrType; // 二维码类型,QR_SCENE为临时,QR_LIMIT_SCENE为永久
@XStreamOmitField
@XStreamAlias("scene_id")
private int sceneId; // 场景值ID,临时二维码时为32位非0整型,永久二维码时最大值为100000(目前参数只支持1--100000
public int getExpireSeconds() {
return expireSeconds;
}
public void setExpireSeconds(int expireSeconds) {
this.expireSeconds = expireSeconds;
}
public QRType getQrType() {
return qrType;
}
public void setQrType(QRType qrType) {
this.qrType = qrType;
}
public int getSceneId() {
return sceneId;
}
public void setSceneId(int sceneId) {
this.sceneId = sceneId;
}
public QRParameter(int expireSeconds, QRType qrType, int sceneId) {
this.expireSeconds = expireSeconds;
this.qrType = qrType;
this.sceneId = sceneId;
}
public QRParameter(QRType qrType, int sceneId) {
this(0, qrType, sceneId);
}
public QRParameter(int sceneId, int expireSeconds) {
this(0, null, sceneId);
}
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.getName()).append("\"");
if (this.qrType == QRType.TEMPORARY) {
jsonBuilder.append(",\"expire_seconds\":").append(expireSeconds);
}
jsonBuilder.append(",\"action_info\":").append(String.format("{\"scene\": {\"scene_id\": %d}}", sceneId));
jsonBuilder.append("}");
return jsonBuilder.toString();
}
@Override
public String toString() {
return "QRParameter [expireSeconds=" + expireSeconds + ", qrType=" + qrType + ", sceneId=" + sceneId + "]";
}
}
@@ -1,74 +0,0 @@
package com.foxinmy.weixin4j.model;
import java.io.Serializable;
import com.alibaba.fastjson.annotation.JSONField;
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;
@JSONField(name = "access_token")
private String accessToken;
@JSONField(name = "expires_in")
private int expiresIn;
private String openid;
private long time;
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public int getExpiresIn() {
return expiresIn;
}
public void setExpiresIn(int expiresIn) {
this.expiresIn = expiresIn;
}
public String 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 accessToken.equals(((Token) obj).getAccessToken());
}
return false;
}
@Override
public String toString() {
return "Token [accessToken=" + accessToken + ", expiresIn=" + expiresIn + ", openid=" + openid + ", time=" + time + "]";
}
}
@@ -1,220 +0,0 @@
package com.foxinmy.weixin4j.model;
import java.io.Serializable;
import org.jsoup.helper.StringUtil;
/**
* 用户对象
* <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; // 使用语言
private String unionid; // 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段
// 国家地区语言版本
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 (!StringUtil.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;
}
public String getUnionid() {
return unionid;
}
public void setUnionid(String unionid) {
this.unionid = unionid;
}
@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(", unionid=").append(unionid);
sb.append(", subscribe=").append(subscribe).append("]");
return sb.toString();
}
}
@@ -1,44 +0,0 @@
package com.foxinmy.weixin4j.model;
import com.alibaba.fastjson.annotation.JSONField;
/**
* 用户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;
@JSONField(name = "refresh_token")
private String refreshToken;
private String scope;
public String getRefreshToken() {
return refreshToken;
}
public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
@Override
public String toString() {
return "UserToken [refreshToken=" + refreshToken + ", scope=" + scope + ", getAccessToken()=" + getAccessToken() + ", getExpiresIn()=" + getExpiresIn() + ", getOpenid()=" + getOpenid() + ", getTime()=" + getTime() + "]";
}
}
@@ -1,150 +0,0 @@
package com.foxinmy.weixin4j.msg;
import java.io.Serializable;
import java.io.Writer;
import com.foxinmy.weixin4j.type.MessageType;
import com.foxinmy.weixin4j.util.ClassUtil;
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;
private final static XStream xmlStream = new XStream();
private final static XStream jsonStream = new XStream(
new JsonHierarchicalStreamDriver() {
public HierarchicalStreamWriter createWriter(Writer writer) {
return new JsonWriter(writer, JsonWriter.DROP_ROOT_MODE);
}
});
@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
static {
Class<?>[] classes = ClassUtil.getClasses(
TextMessage.class.getPackage()).toArray(new Class[0]);
xmlStream.ignoreUnknownElements();
xmlStream.autodetectAnnotations(true);
xmlStream.processAnnotations(classes);
xmlStream.omitField(BaseMessage.class, "msgId");
jsonStream.setMode(XStream.NO_REFERENCES);
jsonStream.autodetectAnnotations(true);
jsonStream.processAnnotations(classes);
jsonStream.omitField(BaseMessage.class, "msgId");
}
public BaseMessage(MessageType msgType) {
this.msgType = msgType;
}
public BaseMessage(MessageType msgType, BaseMessage inMessage) {
this(msgType, inMessage.getFromUserName(), inMessage.getToUserName());
}
public BaseMessage(MessageType msgType, String toUserName,
String fromUserName) {
this.msgType = msgType;
this.toUserName = toUserName;
this.fromUserName = fromUserName;
}
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;
}
protected XStream getXStream() {
Class<? extends BaseMessage> targetClass = getMsgType()
.getMessageClass();
xmlStream.alias("xml", targetClass);
return xmlStream;
}
/**
* 消息对象转换为微信服务器接受的xml格式消息
*
* @return xml字符串
*/
public String toXml() {
return getXStream().toXML(this);
}
/**
* 消息对象转换为微信服务器接受的json格式字符串
*
* @return json字符串
*/
public String toJson() {
return jsonStream.toXML(this);
}
}
@@ -1,55 +0,0 @@
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 content, BaseMessage inMessage) {
super(MessageType.text, inMessage);
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();
}
}
@@ -1,47 +0,0 @@
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();
}
}
@@ -1,58 +0,0 @@
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>
*/
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 String getLongitude() {
return longitude;
}
public String getPrecision() {
return 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();
}
}
@@ -1,72 +0,0 @@
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.massendjobfinish);
}
@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 int getTotalCount() {
return totalCount;
}
public int getFilterCount() {
return filterCount;
}
public int getSentCount() {
return sentCount;
}
public int getErrorCount() {
return 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();
}
}
@@ -1 +0,0 @@
事件消息
@@ -1,55 +0,0 @@
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>
*/
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 String getTicket() {
return 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();
}
}
@@ -1,30 +0,0 @@
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>
*/
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();
}
}
@@ -1,35 +0,0 @@
package com.foxinmy.weixin4j.msg.event;
import com.foxinmy.weixin4j.type.EventType;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* 模板消息事件推送
*
* @className TemplatesendjobfinishMessage
* @author jy
* @date 2014年9月19日
* @since JDK 1.7
* @see <a
* href="http://mp.weixin.qq.com/wiki/index.php?title=%E6%A8%A1%E6%9D%BF%E6%B6%88%E6%81%AF%E6%8E%A5%E5%8F%A3">模板消息事件推送</a>
*/
public class TemplatesendjobfinishMessage extends EventMessage {
private static final long serialVersionUID = -2903359365988594012L;
public TemplatesendjobfinishMessage() {
super(EventType.templatesendjobfinish);
}
@XStreamAlias("Status")
private String status; // 推送状态
public String getStatus() {
return status;
}
@Override
public String toString() {
return "TemplatesendjobfinishMessage [status=" + status + "]";
}
}
@@ -1,45 +0,0 @@
package com.foxinmy.weixin4j.msg.event.menu;
import com.foxinmy.weixin4j.msg.event.EventMessage;
import com.foxinmy.weixin4j.type.EventType;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* 自定义菜单事件(view|click)
*
* @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=%E8%87%AA%E5%AE%9A%E4%B9%89%E8%8F%9C%E5%8D%95%E4%BA%8B%E4%BB%B6%E6%8E%A8%E9%80%81#.E7.82.B9.E5.87.BB.E8.8F.9C.E5.8D.95.E6.8B.89.E5.8F.96.E6.B6.88.E6.81.AF.E6.97.B6.E7.9A.84.E4.BA.8B.E4.BB.B6.E6.8E.A8.E9.80.81">菜单事件</a>
*/
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;
}
@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();
}
}
@@ -1,74 +0,0 @@
package com.foxinmy.weixin4j.msg.event.menu;
import com.foxinmy.weixin4j.type.EventType;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* 弹出地理位置选择器的事件推送
*
* @className MenuLocationEventMessage
* @author jy
* @date 2014年9月30日
* @since JDK 1.7
* @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%E4%BA%8B%E4%BB%B6%E6%8E%A8%E9%80%81#location_select.EF.BC.9A.E5.BC.B9.E5.87.BA.E5.9C.B0.E7.90.86.E4.BD.8D.E7.BD.AE.E9.80.89.E6.8B.A9.E5.99.A8.E7.9A.84.E4.BA.8B.E4.BB.B6.E6.8E.A8.E9.80.81">弹出地理位置选择事件推送</a>
*/
public class MenuLocationEventMessage extends MenuEventMessage {
private static final long serialVersionUID = 145223888272819563L;
public MenuLocationEventMessage() {
super.setEventType(EventType.location_select);
}
@XStreamAlias("SendLocationInfo")
private LocationInfo locationInfo;
public LocationInfo getLocationInfo() {
return locationInfo;
}
public static class LocationInfo {
@XStreamAlias("Location_X")
private double x; // 地理位置维度
@XStreamAlias("Location_Y")
private double y; // 地理位置经度
@XStreamAlias("Scale")
private double scale; // 地图缩放大小
@XStreamAlias("Label")
private String label; // 地理位置信息
@XStreamAlias("Poiname")
private String poiname;
public double getX() {
return x;
}
public double getY() {
return y;
}
public double getScale() {
return scale;
}
public String getLabel() {
return label;
}
public String getPoiname() {
return poiname;
}
@Override
public String toString() {
return "LocationInfo [x=" + x + ", y=" + y + ", scale=" + scale
+ ", label=" + label + ", poiname=" + poiname + "]";
}
}
@Override
public String toString() {
return "MenuLocationEventMessage [locationInfo=" + locationInfo + "]";
}
}
@@ -1,63 +0,0 @@
package com.foxinmy.weixin4j.msg.event.menu;
import java.util.List;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* 弹出拍照或者相册发图的事件推送(pic_sysphoto|pic_photo_or_album|pic_weixin)
*
* @className MenuPhotoEventMessage
* @author jy
* @date 2014年9月30日
* @since JDK 1.7
* @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%E4%BA%8B%E4%BB%B6%E6%8E%A8%E9%80%81#pic_sysphoto.EF.BC.9A.E5.BC.B9.E5.87.BA.E7.B3.BB.E7.BB.9F.E6.8B.8D.E7.85.A7.E5.8F.91.E5.9B.BE.E7.9A.84.E4.BA.8B.E4.BB.B6.E6.8E.A8.E9.80.81">弹出系统拍照发图的事件推送</a>
*/
public class MenuPhotoEventMessage extends MenuEventMessage {
private static final long serialVersionUID = 3142350663022709730L;
@XStreamAlias("SendPicsInfo")
private PictureInfo pictureInfo;
public PictureInfo getPictureInfo() {
return pictureInfo;
}
public static class PictureInfo {
@XStreamAlias("Count")
private int count;
@XStreamAlias("PicList")
private List<PictureItem> items;
public int getCount() {
return count;
}
public List<PictureItem> getItems() {
return items;
}
@Override
public String toString() {
return "PictureInfo [count=" + count + ", items=" + items + "]";
}
}
@XStreamAlias("item")
public static class PictureItem {
@XStreamAlias("PicMd5Sum")
private String md5;
@Override
public String toString() {
return "PictureItem [md5=" + md5 + "]";
}
}
@Override
public String toString() {
return "MenuPhotoEventMessage [pictureInfo=" + pictureInfo + "]";
}
}
@@ -1,51 +0,0 @@
package com.foxinmy.weixin4j.msg.event.menu;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* 扫码推事件(scancode_push|scancode_waitmsg)
*
* @className MenuScanPushEventMessage
* @author jy
* @date 2014年9月30日
* @since JDK 1.7
* @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%E4%BA%8B%E4%BB%B6%E6%8E%A8%E9%80%81#scancode_push.EF.BC.9A.E6.89.AB.E7.A0.81.E6.8E.A8.E4.BA.8B.E4.BB.B6.E7.9A.84.E4.BA.8B.E4.BB.B6.E6.8E.A8.E9.80.81">扫码推事件的事件推送</a>
*/
public class MenuScanEventMessage extends MenuEventMessage {
private static final long serialVersionUID = 3142350663022709730L;
@XStreamAlias("ScanCodeInfo")
private ScanInfo scanInfo;
public ScanInfo getScanInfo() {
return scanInfo;
}
public static class ScanInfo {
@XStreamAlias("ScanType")
private String type;
@XStreamAlias("ScanResult")
private String result;
public String getType() {
return type;
}
public String getResult() {
return result;
}
@Override
public String toString() {
return "ScanInfo [type=" + type + ", result=" + result + "]";
}
}
@Override
public String toString() {
return "MenuScanPushEventMessage [scanInfo=" + scanInfo + "]";
}
}
@@ -1 +0,0 @@
底部菜单消息
@@ -1,50 +0,0 @@
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>
*/
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 String getMediaId() {
return 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();
}
}
@@ -1,57 +0,0 @@
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>
*/
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 String getDescription() {
return description;
}
public String getUrl() {
return 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();
}
}
@@ -1,69 +0,0 @@
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>
*/
public class LocationMessage extends BaseMessage {
private static final long serialVersionUID = 2866021596599237334L;
public LocationMessage() {
super(MessageType.location);
}
@XStreamAlias("Location_X")
private double x; // 地理位置维度
@XStreamAlias("Location_Y")
private double y; // 地理位置经度
@XStreamAlias("Scale")
private double scale; // 地图缩放大小
@XStreamAlias("Label")
private String label; // 地理位置信息
public double getX() {
return x;
}
public double getY() {
return y;
}
public double getScale() {
return 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(x);
sb.append(" ,location_Y=").append(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();
}
}
@@ -1 +0,0 @@
普通消息
@@ -1,50 +0,0 @@
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>
*/
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 String getThumbMediaId() {
return 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();
}
}
@@ -1,61 +0,0 @@
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>
*/
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; // 语音格式,如amrspeex等
@XStreamAlias("Recognition")
private String recognition; // 语音识别结果,UTF8编码
public String getRecognition() {
return recognition;
}
public String getMediaId() {
return mediaId;
}
public String getFormat() {
return 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();
}
}
@@ -1,75 +0,0 @@
package com.foxinmy.weixin4j.msg.model;
import com.foxinmy.weixin4j.type.MediaType;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* 图文对象
*
* @className Article
* @author jy
* @date 2014年9月29日
* @since JDK 1.7
* @see
*/
public class Article extends BaseMsg {
private static final long serialVersionUID = 1L;
private String title; // 图文消息标题
@XStreamAlias("description")
private String desc; // 图文消息描述
@XStreamAlias("picurl")
private String picUrl; // 图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200
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;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getPicUrl() {
return picUrl;
}
public void setPicUrl(String picUrl) {
this.picUrl = picUrl;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
@Override
public String toString() {
return "Article [title=" + title + ", desc=" + desc + ", picUrl="
+ picUrl + ", url=" + url + "]";
}
@Override
public MediaType getMediaType() {
return MediaType.mpnews;
}
}
@@ -1,39 +0,0 @@
package com.foxinmy.weixin4j.msg.model;
import java.io.Serializable;
import java.io.Writer;
import com.foxinmy.weixin4j.msg.notify.BaseNotify;
import com.foxinmy.weixin4j.type.MediaType;
import com.foxinmy.weixin4j.util.ClassUtil;
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;
public abstract class BaseMsg implements Serializable {
private static final long serialVersionUID = 1L;
private final static XStream xstream = new XStream(
new JsonHierarchicalStreamDriver() {
public HierarchicalStreamWriter createWriter(Writer writer) {
return new JsonWriter(writer, JsonWriter.DROP_ROOT_MODE);
}
});
static {
xstream.setMode(XStream.NO_REFERENCES);
xstream.autodetectAnnotations(true);
xstream.processAnnotations(ClassUtil.getClasses(
BaseNotify.class.getPackage()).toArray(new Class[0]));
}
public abstract MediaType getMediaType();
/**
* 客服消息json化,适用于客服消息接口
*
* @return {"touser": "to","msgtype": "text","text": {"content": "123"}}
*/
public String toNotifyJson() {
return xstream.toXML(this);
}
}
@@ -1,38 +0,0 @@
package com.foxinmy.weixin4j.msg.model;
import com.foxinmy.weixin4j.type.MediaType;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* 图片对象
*
* @className Image
* @author jy
* @date 2014年9月29日
* @since JDK 1.7
* @see
*/
public class Image extends BaseMsg {
private static final long serialVersionUID = 1L;
@XStreamAlias("media_id")
private String mediaId;
public Image(String mediaId) {
this.mediaId = mediaId;
}
public String getMediaId() {
return mediaId;
}
public void setMediaId(String mediaId) {
this.mediaId = mediaId;
}
@Override
public MediaType getMediaType() {
return MediaType.image;
}
}
@@ -1,93 +0,0 @@
package com.foxinmy.weixin4j.msg.model;
import com.foxinmy.weixin4j.type.MediaType;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* 音乐对象
*
* @className Music
* @author jy
* @date 2014年9月29日
* @since JDK 1.7
* @see
*/
public class Music extends BaseMsg {
private static final long serialVersionUID = 1L;
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;
public Music(String thumbMediaId) {
this(null, null, null, null, thumbMediaId);
}
public Music(String title, String desc, String musicUrl, String hqMusicUrl,
String thumbMediaId) {
this.title = title;
this.desc = desc;
this.musicUrl = musicUrl;
this.hqMusicUrl = hqMusicUrl;
this.thumbMediaId = thumbMediaId;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getMusicUrl() {
return musicUrl;
}
public void setMusicUrl(String musicUrl) {
this.musicUrl = musicUrl;
}
public String getHqMusicUrl() {
return hqMusicUrl;
}
public void setHqMusicUrl(String hqMusicUrl) {
this.hqMusicUrl = hqMusicUrl;
}
public String getThumbMediaId() {
return thumbMediaId;
}
public void setThumbMediaId(String thumbMediaId) {
this.thumbMediaId = thumbMediaId;
}
@Override
public String toString() {
return "Music [title=" + title + ", desc=" + desc + ", musicUrl="
+ musicUrl + ", hqMusicUrl=" + hqMusicUrl + ", thumbMediaId="
+ thumbMediaId + "]";
}
@Override
public MediaType getMediaType() {
return MediaType.music;
}
}
@@ -1 +0,0 @@
不同的消息类型中的模型
@@ -1,40 +0,0 @@
package com.foxinmy.weixin4j.msg.model;
import com.foxinmy.weixin4j.type.MediaType;
/**
* 文本对象
* @className Text
* @author jy
* @date 2014年9月29日
* @since JDK 1.7
* @see
*/
public class Text extends BaseMsg {
private static final long serialVersionUID = 1L;
private String content;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Text(String content) {
this.content = content;
}
@Override
public String toString() {
return "Text [content=" + content + "]";
}
@Override
public MediaType getMediaType() {
return MediaType.text;
}
}
@@ -1,88 +0,0 @@
package com.foxinmy.weixin4j.msg.model;
import com.foxinmy.weixin4j.type.MediaType;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* 视频对象
*
* @className Video
* @author jy
* @date 2014年9月29日
* @since JDK 1.7
* @see
*/
public class Video extends BaseMsg {
private static final long serialVersionUID = 1L;
@XStreamAlias("media_id")
private String mediaId;
@XStreamAlias("thumb_media_id")
private String thumbMediaId;
private String title;
@XStreamAlias("description")
private String desc;
public Video(String mediaId) {
this(mediaId, null, null, null);
}
public Video(String mediaId, String thumbMediaId) {
this(mediaId, thumbMediaId, null, null);
}
public Video(String mediaId, String title, String desc) {
this(mediaId, null, title, desc);
}
public Video(String mediaId, String thumbMediaId, String title, String desc) {
this.mediaId = mediaId;
this.thumbMediaId = thumbMediaId;
this.title = title;
this.desc = desc;
}
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;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
@Override
public String toString() {
return "Video [mediaId=" + mediaId + ", thumbMediaId=" + thumbMediaId
+ ", title=" + title + ", desc=" + desc + "]";
}
@Override
public MediaType getMediaType() {
return MediaType.vedio;
}
}
@@ -1,38 +0,0 @@
package com.foxinmy.weixin4j.msg.model;
import com.foxinmy.weixin4j.type.MediaType;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* 语音对象
*
* @className Image
* @author jy
* @date 2014年9月29日
* @since JDK 1.7
* @see
*/
public class Voice extends BaseMsg {
private static final long serialVersionUID = 1L;
@XStreamAlias("media_id")
private String mediaId;
public Voice(String mediaId) {
this.mediaId = mediaId;
}
public String getMediaId() {
return mediaId;
}
public void setMediaId(String mediaId) {
this.mediaId = mediaId;
}
@Override
public MediaType getMediaType() {
return MediaType.voice;
}
}
@@ -1,102 +0,0 @@
package com.foxinmy.weixin4j.msg.notify;
import java.util.LinkedList;
import java.util.List;
import com.foxinmy.weixin4j.msg.model.Article;
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.weixin.msg.model.Article
* @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++;
}
public void pushAll(List<Article> articles) {
count = articles.size();
if (articles.size() > MAX_ARTICLE_COUNT) {
count = MAX_ARTICLE_COUNT;
articles = articles.subList(0, count);
}
if (this.news == null) {
this.news = new News();
}
this.news.setArticles(articles);
}
private static class News {
@XStreamAlias("articles")
private List<Article> articles;
public News() {
this.articles = new LinkedList<Article>();
}
public void pushArticle(String title, String desc, String picUrl,
String url) {
this.articles.add(new Article(title, desc, picUrl, url));
}
public void setArticles(List<Article> articles) {
this.articles = articles;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
for (Article article : articles) {
sb.append("{title=").append(article.getTitle());
sb.append(" ,description=").append(article.getDesc());
sb.append(" ,picUrl=").append(article.getPicUrl());
sb.append(" ,url=").append(article.getUrl()).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());
}
}
@@ -1,71 +0,0 @@
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());
}
}
@@ -1,47 +0,0 @@
package com.foxinmy.weixin4j.msg.notify;
import com.foxinmy.weixin4j.msg.model.Image;
import com.foxinmy.weixin4j.type.MessageType;
/**
* 客服图片消息
*
* @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.model.Image
* @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 touser) {
super(touser, MessageType.image);
}
public ImageNotify(String mediaId, String touser) {
super(touser, MessageType.image);
this.pushMediaId(mediaId);
}
public void pushMediaId(String mediaId) {
this.image = new Image(mediaId);
}
private Image image;
@Override
public String toString() {
return String.format("[ImageNotify touser=%s ,msgtype=%s ,mediaId=%s]",
super.getTouser(), super.getMsgtype().name(),
this.image.getMediaId());
}
}
@@ -1,46 +0,0 @@
package com.foxinmy.weixin4j.msg.notify;
import com.foxinmy.weixin4j.msg.model.Music;
import com.foxinmy.weixin4j.type.MessageType;
/**
* 客服音乐消息
*
* @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.model.Music
* @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 musicurl, String hqUrl, String mediaId) {
this.music = new Music(null, null, musicurl, hqUrl, mediaId);
}
private Music music;
public void setMusic(Music music) {
this.music = music;
}
@Override
public String toString() {
return String.format("[MusicNotify touser=%s ,msgtype=%s ,music=%s]",
super.getTouser(), super.getMsgtype().name(),
this.music.toString());
}
}
@@ -1 +0,0 @@
客服消息
@@ -1,48 +0,0 @@
package com.foxinmy.weixin4j.msg.notify;
import com.foxinmy.weixin4j.msg.model.Text;
import com.foxinmy.weixin4j.type.MessageType;
/**
* 客服文本消息
*
* @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.weixin.msg.model.Text
* @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 Text(content);
}
public TextNotify(String content, String touser) {
super(touser, MessageType.text);
this.text = new Text(content);
}
public void setContent(String content) {
this.text = new Text(content);
}
private Text text;
@Override
public String toString() {
return String.format("[TextNotify touser=%s ,msgtype=%s ,content=%s]",
super.getTouser(), super.getMsgtype().name(),
this.text.getContent());
}
}
@@ -1,46 +0,0 @@
package com.foxinmy.weixin4j.msg.notify;
import com.foxinmy.weixin4j.msg.model.Video;
import com.foxinmy.weixin4j.type.MessageType;
/**
* 客服视频消息
*
* @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.model.Video
* @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 thumbMediaId) {
this.video = new Video(mediaId, thumbMediaId);
}
private Video video;
public void setVideo(Video video) {
this.video = video;
}
@Override
public String toString() {
return String.format("[VideoNotify touser=%s ,msgtype=%s ,video=%s]",
super.getTouser(), super.getMsgtype().name(),
this.video.toString());
}
}
@@ -1,47 +0,0 @@
package com.foxinmy.weixin4j.msg.notify;
import com.foxinmy.weixin4j.msg.model.Voice;
import com.foxinmy.weixin4j.type.MessageType;
/**
* 客服语音消息
*
* @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.model.Voice
* @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 touser) {
super(touser, MessageType.voice);
}
public VoiceNotify(String mediaId, String touser) {
super(touser, MessageType.voice);
this.pushMediaId(mediaId);
}
public void pushMediaId(String mediaId) {
this.voice = new Voice(mediaId);
}
private Voice voice;
@Override
public String toString() {
return String.format("[VoiceNotify touser=%s ,msgtype=%s ,mediaId=%s]",
super.getTouser(), super.getMsgtype().name(),
this.voice.getMediaId());
}
}
@@ -1,105 +0,0 @@
package com.foxinmy.weixin4j.msg.out;
import java.util.LinkedList;
import com.foxinmy.weixin4j.msg.BaseMessage;
import com.foxinmy.weixin4j.msg.model.Article;
import com.foxinmy.weixin4j.type.MessageType;
import com.foxinmy.weixin4j.xml.XStream;
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.weixin.msg.model.Article
* @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(BaseMessage inMessage) {
super(MessageType.news, inMessage);
}
@XStreamAlias("ArticleCount")
private int count; // 图文消息个数,限制为10条以内
@XStreamAlias("Articles")
private LinkedList<Article> articles;
public void pushArticle(String title, String desc, String picUrl, String url) {
if (this.articles == null) {
this.articles = new LinkedList<Article>();
}
if ((articles.size() + 1) > MAX_ARTICLE_COUNT) {
return;
}
this.articles.add(new Article(title, desc, picUrl, url));
}
public void pushFirstArticle(String title, String desc, String picUrl,
String url) {
if (this.articles == null) {
this.articles = new LinkedList<Article>();
}
this.articles.addFirst(new Article(title, desc, picUrl, url));
}
public void pushLastArticle(String title, String desc, String picUrl,
String url) {
if (this.articles == null) {
this.articles = new LinkedList<Article>();
}
this.articles.addLast(new Article(title, desc, picUrl, url));
}
public Article removeLastArticle() {
Article article = null;
if (this.articles != null) {
article = this.articles.removeLast();
}
return article;
}
public Article removeFirstArticle() {
if (this.articles != null) {
return this.articles.removeFirst();
}
return null;
}
public boolean isMaxCount() {
return this.articles.size() == MAX_ARTICLE_COUNT;
}
@Override
public String toXml() {
this.count = articles.size();
XStream xstream = getXStream();
xstream.alias("item", Article.class);
xstream.aliasField("Title", Article.class, "title");
xstream.aliasField("Description", Article.class, "desc");
xstream.aliasField("PicUrl", Article.class, "picUrl");
xstream.aliasField("Url", Article.class, "url");
return xstream.toXML(this);
}
@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(this.articles.toString());
sb.append(" ,createTime=").append(super.getCreateTime());
sb.append(" ,msgId=").append(super.getMsgId()).append("]");
return sb.toString();
}
}
@@ -1,60 +0,0 @@
package com.foxinmy.weixin4j.msg.out;
import com.foxinmy.weixin4j.msg.BaseMessage;
import com.foxinmy.weixin4j.msg.model.Image;
import com.foxinmy.weixin4j.type.MessageType;
import com.foxinmy.weixin4j.xml.XStream;
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.model.Image
* @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(BaseMessage inMessage) {
this(null, inMessage);
}
public ImageMessage(String mediaId, BaseMessage inMessage) {
super(MessageType.image, inMessage);
super.getMsgType().setMessageClass(ImageMessage.class);
this.pushMediaId(mediaId);
}
@XStreamAlias("Image")
private Image image;
public void pushMediaId(String mediaId) {
this.image = new Image(mediaId);
}
@Override
public String toXml() {
XStream xstream = getXStream();
xstream.aliasField("MediaId", Image.class, "mediaId");
return xstream.toXML(this);
}
@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.getMediaId());
sb.append(" ,createTime=").append(super.getCreateTime());
sb.append(" ,msgId=").append(super.getMsgId()).append("]");
return sb.toString();
}
}
@@ -1,63 +0,0 @@
package com.foxinmy.weixin4j.msg.out;
import com.foxinmy.weixin4j.msg.BaseMessage;
import com.foxinmy.weixin4j.msg.model.Music;
import com.foxinmy.weixin4j.type.MessageType;
import com.foxinmy.weixin4j.xml.XStream;
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.model.Music
* @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(BaseMessage inMessage) {
super(MessageType.music, inMessage);
}
@XStreamAlias("Music")
private Music music;
public void pushMusic(String mediaId) {
this.music = new Music(mediaId);
}
public void setMusic(Music music) {
this.music = music;
}
@Override
public String toXml() {
XStream xstream = getXStream();
xstream.aliasField("MediaId", Music.class, "musicUrl");
xstream.aliasField("Title", Music.class, "title");
xstream.aliasField("Description", Music.class, "desc");
xstream.aliasField("HQMusicUrl", Music.class, "hqMusicUrl");
xstream.aliasField("ThumbMediaId", Music.class, "thumbMediaId");
return xstream.toXML(this);
}
@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(music.toString());
sb.append(" ,createTime=").append(super.getCreateTime());
sb.append(" ,msgId=").append(super.getMsgId()).append("]");
return sb.toString();
}
}

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