articles) throws WeixinException { - String mediaId = uploadNews(articles); - JSONObject obj = new JSONObject(); - obj.put("filter", new JSONObject().put("group_id", groupId)); - obj.put("mpnews", new JSONObject().put("media_id", mediaId)); - obj.put("msgtype", "mpnews"); - String mass_group_uri = WeixinConfig.getValue("mass_group_uri"); - Token token = getToken(); - Response response = null; - try { - response = request.post(String.format(mass_group_uri, - token.getAccess_token()), - new StringRequestEntity(obj.toJSONString(), - "application/json", "UTF-8")); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } - return response.getAsJson().getString("msg_id"); + return notifyApi.sendNotify(touser, articles); } /** - * openId群发 + * 发送客服消息(不包含图文消息) * - * @param articles - * 图文消息列表 - * @param openIds - * 目标ID列表 - * @return 发送出去的消息ID + * @param touser + * 目标用户 + * @param baseMsg + * 消息类型 + * @return 发送结果 * @throws WeixinException - * @see openId群发 - * @see com.foxinmy.weixin4j.model.MpArticle - * @see com.foxinmy.weixin4j.model.User - * @see {@link com.foxinmy.weixin4j.WeixinProxy#uploadMedia(File, MediaType)} - * @see {@link com.foxinmy.weixin4j.WeixinProxy#uploadNews(List)} + * @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 */ - public String massNewsByOpenIds(List articles, String... openIds) + public BaseResult sendNotify(String touser, BaseMsg baseMsg) throws WeixinException { - String mediaId = uploadNews(articles); - JSONObject obj = new JSONObject(); - obj.put("touser", openIds); - obj.put("mpnews", new JSONObject().put("media_id", mediaId)); - obj.put("msgtype", "mpnews"); - String mass_openid_uri = WeixinConfig.getValue("mass_openid_uri"); - Token token = getToken(); - Response response = null; - try { - response = request.post(String.format(mass_openid_uri, - token.getAccess_token()), - new StringRequestEntity(obj.toJSONString(), - "application/json", "UTF-8")); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } - return response.getAsJson().getString("msg_id"); - } - - /** - * 删除群发消息 - * - * 请注意,只有已经发送成功的消息才能删除删除消息只是将消息的图文详情页失效,已经收到的用户,还是能在其本地看到消息卡片 - * - * - * @param msgid - * 发送出去的消息ID - * @throws WeixinException - * @see 删除群发 - * @see {@link com.foxinmy.weixin4j.WeixinProxy#massNewsByGroup(List, String)} - * @see {@link com.foxinmy.weixin4j.WeixinProxy#massNewsByOpenIds(List, String...) - */ - public void deleteMassNews(String msgid) throws WeixinException { - JSONObject obj = new JSONObject(); - obj.put("msgid", msgid); - String mass_delete_uri = WeixinConfig.getValue("mass_delete_uri"); - Token token = getToken(); - try { - request.post( - String.format(mass_delete_uri, token.getAccess_token()), - new StringRequestEntity(obj.toJSONString(), - "application/json", "UTF-8")); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } + return notifyApi.sendNotify(touser, baseMsg); } /** @@ -932,25 +226,426 @@ public class WeixinProxy { */ public List 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 = WeixinConfig.getValue("custom_record_uri"); - Token token = getToken(); - Response response = null; - try { - response = request.post(String.format(custom_record_uri, - token.getAccess_token()), - new StringRequestEntity(obj.toJSONString(), - "application/json", "UTF-8")); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } + return notifyApi.getCustomRecord(openId, starttime, endtime, pagesize, + pageindex); + } - String text = response.getAsJson().getString("recordlist"); - return JSON.parseArray(text, CustomRecord.class); + /** + * 上传图文消息,一个图文消息支持1到10条图文 + * + * @param articles + * 图片消息 + * @return 媒体ID + * @throws WeixinException + * @see 高级群发 + * @see 上传图文消息 + * @see com.foxinmy.weixin4j.model.MpArticle + */ + public String uploadArticle(List articles) + throws WeixinException { + return massApi.uploadArticle(articles); + } + + /** + * 上传分组群发的视频素材 + * + * @param mediaId + * 媒体文件中上传得到的Id + * @param title + * 标题 可为空 + * @param desc + * 描述 可为空 + * @return 上传后的ID + * @throws WeixinException + * @see 高级群发 + * @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 {@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 {@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 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 {@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 {@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 articles, + String... openIds) throws WeixinException { + return massApi.massArticleByOpenIds(articles, openIds); + } + + /** + * 删除群发消息 + * + * 请注意,只有已经发送成功的消息才能删除删除消息只是将消息的图文详情页失效,已经收到的用户,还是能在其本地看到消息卡片 + * + * + * @param msgid + * 发送出去的消息ID + * @throws WeixinException + * @see 删除群发 + * @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 获取用户token + * @see com.foxinmy.weixin4j.model.UserToken + */ + public UserToken getAccessToken(String code) throws WeixinException { + return userApi.getAccessToken(code); + } + + /** + * 获取用户信息 + * + * @param token + * 授权票据 + * @return 用户对象 + * @throws WeixinException + * @see 拉取用户信息 + * @see com.foxinmy.weixin4j.model.User + * @see com.foxinmy.weixin4j.model.UserToken + * {@link com.foxinmy.weixin4j.WeixinProxy#getAccessToken(String)} + */ + public User getUser(UserToken token) throws WeixinException { + return userApi.getUser(token); + } + + /** + * 获取用户信息 + * + * 在关注者与公众号产生消息交互后,公众号可获得关注者的OpenID(加密后的微信号,每个用户对每个公众号的OpenID是唯一的,对于不同公众号, + * 同一用户的openid不同),公众号可通过本接口来根据OpenID获取用户基本信息,包括昵称、头像、性别、所在城市、语言和关注时间 + * + * + * @param openId + * 用户对应的ID + * @return 用户对象 + * @throws WeixinException + * @see 获取用户信息 + * @see com.foxinmy.weixin4j.model.User + */ + public User getUser(String openId) throws WeixinException { + return userApi.getUser(openId); + } + + /** + * 获取用户一定数量(10000)的关注者列表 + * + * @param nextOpenId + * 下一次拉取数据的openid + * @return 关注信息 + * @throws WeixinException + * @see 获取关注者列表 + * @see com.foxinmy.weixin4j.model.Following + */ + public Following getFollowing(String nextOpenId) throws WeixinException { + return userApi.getFollowing(nextOpenId); + } + + /** + * 获取用户全部的关注者列表 + * + * 当公众号关注者数量超过10000时,可通过填写next_openid的值,从而多次拉取列表的方式来满足需求, + * 将上一次调用得到的返回中的next_openid值,作为下一次调用中的next_openid值 + * + * + * @return 用户对象集合 + * @throws WeixinException + * @see 获取关注者列表 + * @see com.foxinmy.weixin4j.model.Following + * @see com.foxinmy.weixin4j.WeixinProxy#getFollowing(String) + */ + public List getAllFollowing() throws WeixinException { + return userApi.getAllFollowing(); + } + + /** + * 设置用户备注名 + * + * @param openId + * 用户ID + * @param remark + * 备注名 + * @throws WeixinException + * @see 设置用户备注名 + */ + public BaseResult updateUserRemark(String openId, String remark) + throws WeixinException { + return userApi.updateUserRemark(openId, remark); + } + + /** + * 创建分组 + * + * @param name + * 组名称 + * @return group对象 + * @throws WeixinException + * @see 创建分组 + * @see com.foxinmy.weixin4j.model.Group + * @see com.foxinmy.weixin4j.model.Group#toCreateJson() + */ + public Group createGroup(String name) throws WeixinException { + return groupApi.createGroup(name); + } + + /** + * 查询所有分组 + * + * @return 组集合 + * @throws WeixinException + * @see 查询所有分组 + * @see com.foxinmy.weixin4j.model.Group + */ + public List getGroups() throws WeixinException { + return groupApi.getGroups(); + } + + /** + * 查询用户所在分组 + * + * @param openId + * 用户对应的ID + * @return 组ID + * @throws WeixinException + * @see 查询用户所在分组 + * @see com.foxinmy.weixin4j.model.Group + */ + public int getGroupByOpenId(String openId) throws WeixinException { + return groupApi.getGroupByOpenId(openId); + } + + /** + * 修改分组名 + * + * @param groupId + * 组ID + * @param name + * 组名称 + * @throws WeixinException + * @see 修改分组名 + * @see com.foxinmy.weixin4j.model.Group + * @see com.foxinmy.weixin4j.model.Group#toModifyJson() + */ + public BaseResult modifyGroup(int groupId, String name) + throws WeixinException { + return groupApi.modifyGroup(groupId, name); + } + + /** + * 移动分组 + * + * @param openId + * 用户对应的ID + * @param groupId + * 组ID + * @throws WeixinException + * @see 移动分组 + * @see com.foxinmy.weixin4j.model.Group + */ + public BaseResult moveGroup(String openId, int groupId) + throws WeixinException { + return groupApi.moveGroup(openId, groupId); + } + + /** + * 自定义菜单 + * + * @param btnList + * @throws WeixinException + * @see 创建自定义菜单 + * @see com.foxinmy.weixin4j.model.Button + * @see com.foxinmy.weixin4j.type.ButtonType + */ + public BaseResult createMenu(List btnList) throws WeixinException { + return menuApi.createMenu(btnList); + } + + /** + * 查询菜单 + * + * @return 菜单集合 + * @throws WeixinException + * @see 查询菜单 + * @see com.foxinmy.weixin4j.model.Button + */ + public List getMenu() throws WeixinException { + return menuApi.getMenu(); + } + + /** + * 删除菜单 + * + * @throws WeixinException + * @see 删除菜单 + * @see com.foxinmy.weixin4j.model.Button + */ + public BaseResult deleteMenu() throws WeixinException { + return menuApi.deleteMenu(); + } + + /** + * 生成带参数的二维码 + * + * @param parameter + * @return byte数据包 + * @throws WeixinException + * @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 {@link com.foxinmy.weixin4j.WeixinProxy.QrApi#getQR(QRParameter)} + */ + public byte[] getQRData(int sceneId, int expireSeconds) + throws WeixinException { + return qrApi.getQRData(sceneId, expireSeconds); + } + + /** + * 生成带参数的二维码 + * + * 二维码分为临时跟永久两种,扫描时触发推送带参数事件 + * + * + * @param parameter + * 二维码参数 + * @return 硬盘存储的文件对象 + * @throws WeixinException + * @see 二维码 + * @see com.foxinmy.weixin4j.model.QRParameter + */ + public File getQR(QRParameter parameter) throws WeixinException { + return qrApi.getQR(parameter); + } + + /** + * 发送模板消息 + * + * @param message + * @return 发送结果 + * @throws WeixinException + * @see 模板消息 + * @see com.foxinmy.weixin4j.msg.out.TemplateMessage + * @seee com.foxinmy.weixin4j.msg.event.TemplatesendjobfinishMessage + */ + public BaseResult sendTplMessage(TemplateMessage tplMessage) + throws WeixinException { + return templApi.sendTplMessage(tplMessage); } } diff --git a/src/main/java/com/foxinmy/weixin4j/api/BaseApi.java b/src/main/java/com/foxinmy/weixin4j/api/BaseApi.java new file mode 100644 index 00000000..1b407b4b --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/api/BaseApi.java @@ -0,0 +1,15 @@ +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 api文档 + */ +public class BaseApi { + protected final HttpRequest request = new HttpRequest(); +} diff --git a/src/main/java/com/foxinmy/weixin4j/api/GroupApi.java b/src/main/java/com/foxinmy/weixin4j/api/GroupApi.java new file mode 100644 index 00000000..ed024bbd --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/api/GroupApi.java @@ -0,0 +1,142 @@ +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.Response; +import com.foxinmy.weixin4j.model.Group; +import com.foxinmy.weixin4j.model.Token; +import com.foxinmy.weixin4j.msg.BaseResult; +import com.foxinmy.weixin4j.util.ConfigUtil; + +/** + * 分组相关API + * + * @className GroupApi + * @author jy.hu + * @date 2014年9月25日 + * @since JDK 1.7 + * @see 分组接口 + * @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 创建分组 + * @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 查询所有分组 + * @see com.foxinmy.weixin4j.model.Group + */ + public List 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 查询用户所在分组 + * @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 修改分组名 + * @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 移动分组 + * @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(); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/api/HelperApi.java b/src/main/java/com/foxinmy/weixin4j/api/HelperApi.java new file mode 100644 index 00000000..7ff44e6a --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/api/HelperApi.java @@ -0,0 +1,45 @@ +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 长链接转短链接 + */ + 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"); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/api/MassApi.java b/src/main/java/com/foxinmy/weixin4j/api/MassApi.java new file mode 100644 index 00000000..be0c994d --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/api/MassApi.java @@ -0,0 +1,270 @@ +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.Response; +import com.foxinmy.weixin4j.model.MpArticle; +import com.foxinmy.weixin4j.model.Token; +import com.foxinmy.weixin4j.msg.BaseResult; +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 群发接口 + * @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 高级群发 + * @see 上传图文消息 + * @see com.foxinmy.weixin4j.model.MpArticle + */ + public String uploadArticle(List 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 高级群发 + * @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"); + } + + /** + * 分组群发 + * + * 在返回成功时,意味着群发任务提交成功,并不意味着此时群发已经结束,所以,仍有可能在后续的发送过程中出现异常情况导致用户未收到消息, + * 如消息有时会进行审核、服务器不稳定等,此外,群发任务一般需要较长的时间才能全部发送完毕 + * + * + * @param jsonPara + * json格式的参数 + * @param groupId + * 分组ID + * @return 发送出去的消息ID + * @throws WeixinException + * @see 分组群发 + * @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 openId群发 + * @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 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 articles, + String... openIds) throws WeixinException { + String mediaId = uploadArticle(articles); + + return massByOpenIds(mediaId, MediaType.mpnews, openIds); + } + + /** + * 删除群发消息 + * + * 请注意,只有已经发送成功的消息才能删除删除消息只是将消息的图文详情页失效,已经收到的用户,还是能在其本地看到消息卡片 + * + * + * @param msgid + * 发送出去的消息ID + * @throws WeixinException + * @see 删除群发 + * @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(); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/api/MediaApi.java b/src/main/java/com/foxinmy/weixin4j/api/MediaApi.java new file mode 100644 index 00000000..21e4fb4b --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/api/MediaApi.java @@ -0,0 +1,174 @@ +package com.foxinmy.weixin4j.api; + +import java.io.ByteArrayOutputStream; +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 上传多媒体文件 + * @see com.foxinmy.weixin4j.type.MediaType + */ +public class MediaApi extends BaseApi { + + private final TokenApi tokenApi; + + public MediaApi(TokenApi tokenApi) { + this.tokenApi = tokenApi; + } + + /** + * 上传媒体文件 + * + * 正常情况下返回{"type":"TYPE","media_id":"MEDIA_ID","created_at":123456789}, + * 否则抛出异常. + * + * + * @param file + * 文件对象 + * @param mediaType + * 媒体类型 + * @return 上传到微信服务器返回的媒体标识 + * @throws WeixinException + * @see 上传下载说明 + * @see com.foxinmy.weixin4j.type.MediaType + */ + public String uploadMedia(File file, MediaType mediaType) + throws WeixinException { + byte[] b = null; + ByteArrayOutputStream out = null; + FileInputStream in = null; + try { + in = new FileInputStream(file); + b = IOUtil.toByteArray(in); + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (out != null) { + try { + out.close(); + } catch (IOException e) { + ; + } + } + if (in != null) { + try { + in.close(); + } catch (IOException e) { + ; + } + } + } + return uploadMedia(file.getName(), b, mediaType); + } + + /** + * 上传媒体文件 + * + * @param bytes + * 媒体数据包 + * @param mediaType + * 媒体类型 + * @return 上传到微信服务器返回的媒体标识 + * @throws WeixinException + * @see {@link com.foxinmy.weixin4j.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"); + } + + /** + * 下载媒体文件 + * + * 正常情况下返回表头如Content-Type: image/jpeg,否则抛出异常. + * + * + * @param mediaId + * 存储在微信服务器上的媒体标识 + * @param mediaType + * 媒体类型 + * @return 写入硬盘后的文件对象 + * @throws WeixinException + * @see 上传下载说明 + * @see com.foxinmy.weixin4j.type.MediaType + */ + public File downloadMedia(String mediaId, MediaType mediaType) + throws WeixinException { + String media_path = ConfigUtil.getValue("media_path"); + String filename = mediaId + mediaType.getFormatType(); + File file = new File(media_path + File.separator + filename); + if (file.exists()) { + return file; + } + FileOutputStream out = null; + try { + try { + file.createNewFile(); + } catch (IOException e) { + file.getParentFile().mkdirs(); + file.createNewFile(); + } + out = new FileOutputStream(file); + byte[] b = downloadMediaData(mediaId, mediaType); + out.write(b); + } catch (IOException e) { + + } finally { + try { + if (out != null) { + out.close(); + } + } catch (IOException e) { + + } + } + return file; + } + + /** + * 下载媒体文件 + * + * @param mediaId + * @param mediaType + * @return 二进制数据包 + * @throws WeixinException + * @see {@link com.foxinmy.weixin4j.WeixinProxy#downloadMedia(String, MediaType)} + */ + public byte[] downloadMediaData(String mediaId, MediaType mediaType) + throws WeixinException { + Token token = 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(); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/api/MenuApi.java b/src/main/java/com/foxinmy/weixin4j/api/MenuApi.java new file mode 100644 index 00000000..7e063a04 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/api/MenuApi.java @@ -0,0 +1,89 @@ +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.Response; +import com.foxinmy.weixin4j.model.Button; +import com.foxinmy.weixin4j.model.Token; +import com.foxinmy.weixin4j.msg.BaseResult; +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 创建自定义菜单 + * @see com.foxinmy.weixin4j.model.Button + */ + public BaseResult createMenu(List 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 查询菜单 + * @see com.foxinmy.weixin4j.model.Button + */ + public List 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 删除菜单 + * @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(); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/api/NotifyApi.java b/src/main/java/com/foxinmy/weixin4j/api/NotifyApi.java new file mode 100644 index 00000000..1ca09cc7 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/api/NotifyApi.java @@ -0,0 +1,166 @@ +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.Response; +import com.foxinmy.weixin4j.model.CustomRecord; +import com.foxinmy.weixin4j.model.Token; +import com.foxinmy.weixin4j.msg.BaseResult; +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 客服消息 + * @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 发送客服消息 + */ + 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 发送客服消息 + * @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 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 查询客服聊天记录 + */ + public List 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); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/api/QrApi.java b/src/main/java/com/foxinmy/weixin4j/api/QrApi.java new file mode 100644 index 00000000..d006b3dc --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/api/QrApi.java @@ -0,0 +1,115 @@ +package com.foxinmy.weixin4j.api; + +import java.io.File; +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 二维码支持 + */ +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); + } + + /** + * 生成带参数的二维码 + * + * 二维码分为临时跟永久两种,扫描时触发推送带参数事件 + * + * + * @param parameter + * 二维码参数 + * @return 硬盘存储的文件对象 + * @throws WeixinException + * @see 二维码 + * @see com.foxinmy.weixin4j.model.QRParameter + */ + public File getQR(QRParameter parameter) throws WeixinException { + 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; + } + FileOutputStream out = null; + try { + try { + file.createNewFile(); + } catch (IOException e) { + file.getParentFile().mkdirs(); + file.createNewFile(); + } + out = new FileOutputStream(file); + byte[] b = getQRData(parameter); + out.write(b); + } catch (IOException e) { + ; + } finally { + try { + if (out != null) { + out.close(); + } + } catch (IOException e) { + ; + } + } + return file; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/api/TemplApi.java b/src/main/java/com/foxinmy/weixin4j/api/TemplApi.java new file mode 100644 index 00000000..4cb4e922 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/api/TemplApi.java @@ -0,0 +1,49 @@ +package com.foxinmy.weixin4j.api; + +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.msg.BaseResult; +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 TemplApi extends BaseApi { + + private final TokenApi tokenApi; + + public TemplApi(TokenApi tokenApi) { + this.tokenApi = tokenApi; + } + + /** + * 发送模板消息 + * + * @param message + * @return 发送结果 + * @throws WeixinException + * @see 模板消息 + * @see com.foxinmy.weixin4j.msg.out.TemplateMessage + * @seee com.foxinmy.weixin4j.msg.event.TemplatesendjobfinishMessage + */ + public BaseResult sendTplMessage(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(); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/api/UserApi.java b/src/main/java/com/foxinmy/weixin4j/api/UserApi.java new file mode 100644 index 00000000..8ce55535 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/api/UserApi.java @@ -0,0 +1,182 @@ +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.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.msg.BaseResult; +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 获取用户token + * @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 拉取用户信息 + * @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); + } + + /** + * 获取用户信息 + * + * 在关注者与公众号产生消息交互后,公众号可获得关注者的OpenID(加密后的微信号,每个用户对每个公众号的OpenID是唯一的,对于不同公众号, + * 同一用户的openid不同),公众号可通过本接口来根据OpenID获取用户基本信息,包括昵称、头像、性别、所在城市、语言和关注时间 + * + * + * @param openId + * 用户对应的ID + * @return 用户对象 + * @throws WeixinException + * @see 获取用户信息 + * @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 获取关注者列表 + * @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 openIds = JSON.parseArray(following.getDataJson() + .getString("openid"), String.class); + List userList = new ArrayList(); + for (String openId : openIds) { + userList.add(getUser(openId)); + } + following.setUserList(userList); + } + return following; + } + + /** + * 获取用户全部的关注者列表 + * + * 当公众号关注者数量超过10000时,可通过填写next_openid的值,从而多次拉取列表的方式来满足需求, + * 将上一次调用得到的返回中的next_openid值,作为下一次调用中的next_openid值 + * + * + * @return 用户对象集合 + * @throws WeixinException + * @see 获取关注者列表 + * @see com.foxinmy.weixin4j.model.Following + * @see com.foxinmy.weixin4j.api.UserApi#getFollowing(String) + */ + public List getAllFollowing() throws WeixinException { + List userList = new ArrayList(); + 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 设置用户备注名 + */ + public BaseResult updateUserRemark(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(); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/api/token/FileTokenApi.java b/src/main/java/com/foxinmy/weixin4j/api/token/FileTokenApi.java new file mode 100644 index 00000000..ac8a5a1e --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/api/token/FileTokenApi.java @@ -0,0 +1,95 @@ +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 获取token说明 + * @see com.foxinmy.weixin4j.model.Token + */ +public class FileTokenApi implements TokenApi { + + private final HttpRequest request = new HttpRequest(); + + private final String appid; + private final String appsecret; + public FileTokenApi() { + this(ConfigUtil.getValue("app_id"), ConfigUtil.getValue("app_secret")); + } + + public FileTokenApi(String appid, String appsecret) { + this.appid = appid; + this.appsecret = appsecret; + } + + /** + * 获取token + * + * 正常情况下返回{"access_token":"ACCESS_TOKEN","expires_in":7200},否则抛出异常. + * + * + * @return token对象 + * @throws WeixinException + * @see 获取token说明 + * @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; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/api/token/RedisTokenApi.java b/src/main/java/com/foxinmy/weixin4j/api/token/RedisTokenApi.java new file mode 100644 index 00000000..dfc0079d --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/api/token/RedisTokenApi.java @@ -0,0 +1,82 @@ +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 获取token说明 + * @see com.foxinmy.weixin4j.model.Token + */ +public class RedisTokenApi implements TokenApi { + + private final HttpRequest request = new HttpRequest(); + + private final String appid; + private final String appsecret; + private JedisPool jedisPool; + + public RedisTokenApi() { + this(ConfigUtil.getValue("app_id"), ConfigUtil.getValue("app_secret")); + } + + 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; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/api/token/TokenApi.java b/src/main/java/com/foxinmy/weixin4j/api/token/TokenApi.java new file mode 100644 index 00000000..c2c3c351 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/api/token/TokenApi.java @@ -0,0 +1,19 @@ +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.FileTokenApi + * @see com.foxinmy.weixin4j.api.token.RedisTokenApi + */ +public interface TokenApi { + public Token getToken() throws WeixinException; +} diff --git a/src/main/java/com/foxinmy/weixin4j/config.properties b/src/main/java/com/foxinmy/weixin4j/config.properties index 938b23e5..f0f037a2 100644 --- a/src/main/java/com/foxinmy/weixin4j/config.properties +++ b/src/main/java/com/foxinmy/weixin4j/config.properties @@ -15,6 +15,7 @@ api_base_url=https://api.weixin.qq.com/cgi-bin mp_base_url=https://mp.weixin.qq.com/cgi-bin file_base_url=http://file.api.weixin.qq.com/cgi-bin + # \u7f51\u9875\u6388\u6743\u83b7\u53d6\u7528\u6237\u4fe1\u606f user_auth_uri=https://open.weixin.qq.com/connect/oauth2/authorize?appid={app_id}&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect sns_user_token_uri=https://api.weixin.qq.com/sns/oauth2/access_token?appid={app_id}&secret={app_secret}&code=%s&grant_type=authorization_code @@ -23,7 +24,7 @@ sns_user_info_uri=https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid= # \u76f4\u63a5\u83b7\u53d6\u7528\u6237\u4fe1\u606f api_user_info_uri={api_base_url}/user/info?access_token=%s&openid=%s&lang=zh_CN # \u83b7\u53d6\u6211\u7684token -api_token_uri={api_base_url}/token?grant_type=client_credential&appid={app_id}&secret={app_secret} +api_token_uri={api_base_url}/token?grant_type=client_credential&appid=%s&secret=%s # \u83b7\u53d6\u4e8c\u7ef4\u7801 qr_ticket_uri={api_base_url}/qrcode/create?access_token=%s @@ -53,14 +54,25 @@ menu_create_uri={api_base_url}/menu/create?access_token=%s menu_get_uri={api_base_url}/menu/get?access_token=%s # \u5220\u9664\u83dc\u5355 menu_delete_uri={api_base_url}/menu/delete?access_token=%s -# \u4e0a\u4f20\u6d88\u606f -news_upload_uri={api_base_url}/media/uploadnews?access_token=%s +# \u4e0a\u4f20\u56fe\u6587 +article_upload_uri={api_base_url}/media/uploadnews?access_token=%s +# \u4e0a\u4f20\u89c6\u9891 +video_upload_uri={file_base_url}/media/uploadvideo?access_token=%s # \u5206\u7ec4\u7fa4\u53d1 mass_group_uri={api_base_url}/message/mass/sendall?access_token=%s # openId\u7fa4\u53d1 mass_openid_uri={api_base_url}/message/mass/send?access_token=%s # \u5220\u9664\u7fa4\u53d1 mass_delete_uri={api_base_url}/message/mass/delete?access_token=%s +# \u5ba2\u670d\u804a\u5929\u8bb0\u5f55 +custom_record_uri={api_base_url}/customservice/getrecord?access_token=%s +# \u957f\u94fe\u63a5\u8f6c\u77ed\u94fe\u63a5 +shorturl_uri={api_base_url}/shorturl?access_token=%s +# \u8bbe\u7f6e\u5907\u6ce8\u540d +updateremark_uri={api_base_url}/user/info/updateremark?access_token=%s +# \u6a21\u677f\u6d88\u606f +template_send_uri={api_base_url}/message/template/send?access_token=%s + # token\u5b58\u653e\u8def\u5f84 token_path=/tmp/weixin/token diff --git a/src/main/java/com/foxinmy/weixin4j/http/HttpRequest.java b/src/main/java/com/foxinmy/weixin4j/http/HttpRequest.java index 4559afd1..9ecee3e8 100644 --- a/src/main/java/com/foxinmy/weixin4j/http/HttpRequest.java +++ b/src/main/java/com/foxinmy/weixin4j/http/HttpRequest.java @@ -1,53 +1,76 @@ package com.foxinmy.weixin4j.http; -import java.io.IOException; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.util.ArrayList; +import java.util.List; -import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler; -import org.apache.commons.httpclient.Header; -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.HttpStatus; -import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; -import org.apache.commons.httpclient.cookie.CookiePolicy; -import org.apache.commons.httpclient.methods.GetMethod; -import org.apache.commons.httpclient.methods.PostMethod; -import org.apache.commons.httpclient.methods.RequestEntity; -import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity; -import org.apache.commons.httpclient.methods.multipart.Part; -import org.apache.commons.httpclient.params.HttpClientParams; -import org.apache.commons.httpclient.params.HttpConnectionManagerParams; -import org.apache.commons.httpclient.params.HttpMethodParams; +import 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.alibaba.fastjson.JSONObject; import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.msg.BaseResult; +/** + * 调用微信相关接口的HttpRequest,对于其他请求可能并不试用 + * + * @className HttpRequest + * @author jy + * @date 2014年8月21日 + * @since JDK 1.7 + * @see + */ public class HttpRequest { - private final String CONTENT_CHARSET = "UTF-8"; - private final String ERROR_CODE_KEY = "errcode"; - private final String ERROR_MSG_KEY = "errmsg"; - private HttpClient client; + private AbstractHttpClient client; public HttpRequest() { - this(150, 30000, 30000, 1024 * 1024); + this(150, 100, 10000, 10000); } - public HttpRequest(int maxConPerHost, int conTimeOutMs, int soTimeOutMs, int maxSize) { - MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager(); - connectionManager = new MultiThreadedHttpConnectionManager(); - HttpConnectionManagerParams params = connectionManager.getParams(); - params.setDefaultMaxConnectionsPerHost(maxConPerHost); - params.setConnectionTimeout(conTimeOutMs); - params.setSoTimeout(soTimeOutMs); + public HttpRequest(int maxConPerRoute, int maxTotal, int socketTimeout, int connectionTimeout) { + PoolingClientConnectionManager connectionManager = new PoolingClientConnectionManager(); + // 指定IP并发最大数 + connectionManager.setDefaultMaxPerRoute(maxConPerRoute); + // socket最大创建数 + connectionManager.setMaxTotal(maxTotal); - HttpClientParams clientParams = new HttpClientParams(); - clientParams.setCookiePolicy(CookiePolicy.IGNORE_COOKIES); - client = new HttpClient(clientParams, connectionManager); - client.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, CONTENT_CHARSET); + 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 { - Parameter[] empty = null; - return get(url, empty); + return get(url, (Parameter[]) null); } public Response get(String url, Parameter... parameters) throws WeixinException { @@ -60,70 +83,87 @@ public class HttpRequest { sb.append(parameters[i].toGetPara()); } } - return doRequest(new GetMethod(sb.toString())); + return doRequest(new HttpGet(sb.toString())); } public Response post(String url) throws WeixinException { - Parameter[] empty = null; - return post(url, empty); + return post(url, (Parameter[]) null); } public Response post(String url, Parameter... parameters) throws WeixinException { - PostMethod method = new PostMethod(url); + HttpPost method = new HttpPost(url); + List params = new ArrayList(); for (Parameter parameter : parameters) { - method.addParameter(parameter.toPostPara()); + 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); } - public Response post(String url, RequestEntity entity) throws WeixinException { - PostMethod method = new PostMethod(url); - method.setRequestEntity(entity); - return doRequest(method); - } - - public Response post(String url, Part... parts) throws WeixinException { - PostMethod method = new PostMethod(url); - method.getParams().setContentCharset(CONTENT_CHARSET); - MultipartRequestEntity entity = new MultipartRequestEntity(parts, method.getParams()); - method.setRequestEntity(entity); - return doRequest(method); - } - - protected Response doRequest(HttpMethod method) throws WeixinException { - + protected Response doRequest(HttpRequestBase request) throws WeixinException { try { + HttpResponse httpResponse = client.execute(request); + StatusLine statusLine = httpResponse.getStatusLine(); + HttpEntity httpEntity = httpResponse.getEntity(); - method.getParams().setContentCharset(CONTENT_CHARSET); - method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler(3, false)); - int status = client.executeMethod(method); + int status = statusLine.getStatusCode(); if (status != HttpStatus.SC_OK) { throw new WeixinException(status, "request fail"); } - // HttpClient对于要求接受后继服务的请求,象POST和PUT等不能自动处理转发 // 301或者302 if (status == HttpStatus.SC_MOVED_PERMANENTLY || status == HttpStatus.SC_MOVED_TEMPORARILY) { - throw new WeixinException(status, String.format("the page was redirected to %s", method.getResponseHeader("location"))); + throw new WeixinException(status, String.format("the page was redirected to %s", httpResponse.getFirstHeader("location"))); } - Response response = new Response(method.getResponseBodyAsString()); - response.setBody(method.getResponseBody()); + byte[] data = EntityUtils.toByteArray(httpEntity); + Response response = new Response(); + response.setBody(data); response.setStatusCode(status); - response.setStatusText(method.getStatusText()); - response.setStream(method.getResponseBodyAsStream()); + response.setStatusText(statusLine.getReasonPhrase()); + response.setStream(new ByteArrayInputStream(data)); + response.setText(StringUtils.newStringUtf8(data)); - Header contentType = method.getResponseHeader("Content-Type"); - if (contentType.getValue().indexOf("application/json") >= 0 || contentType.getValue().indexOf("text/plain") >= 0) { - JSONObject jsonObj = response.getAsJson(); - if (jsonObj.containsKey(ERROR_CODE_KEY) && jsonObj.getIntValue(ERROR_CODE_KEY) != 0) { - throw new WeixinException(jsonObj.getIntValue(ERROR_CODE_KEY), jsonObj.getString(ERROR_MSG_KEY)); + Header contentType = httpResponse.getFirstHeader(HttpHeaders.CONTENT_TYPE); + if (contentType.getValue().contains(ContentType.APPLICATION_JSON.getMimeType())) { + BaseResult result = response.getAsResult(); + if (result.getErrcode() != 0) { + throw new WeixinException(result.getErrcode(), result.getErrmsg()); } } + EntityUtils.consume(httpEntity); return response; - } catch (IOException e) { + } catch (Exception e) { throw new WeixinException(e.getMessage()); } finally { - method.releaseConnection(); + request.releaseConnection(); } } } diff --git a/src/main/java/com/foxinmy/weixin4j/http/Parameter.java b/src/main/java/com/foxinmy/weixin4j/http/Parameter.java index cacfcd28..ecf69374 100644 --- a/src/main/java/com/foxinmy/weixin4j/http/Parameter.java +++ b/src/main/java/com/foxinmy/weixin4j/http/Parameter.java @@ -2,10 +2,15 @@ package com.foxinmy.weixin4j.http; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; -import org.apache.commons.httpclient.NameValuePair; +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; @@ -36,7 +41,7 @@ public class Parameter { public String toGetPara() { try { - return String.format("&%s=%s", URLEncoder.encode(name, "UTF-8"), URLEncoder.encode(value, "UTF-8")); + return String.format("&%s=%s", name, URLEncoder.encode(value, CHARSET)); } catch (UnsupportedEncodingException e) { return String.format("&%s=%s", name, value); } @@ -44,15 +49,15 @@ public class Parameter { public NameValuePair toPostPara() { try { - return new NameValuePair(URLEncoder.encode(name, "UTF-8"), URLEncoder.encode(value, "UTF-8")); + return new BasicNameValuePair(name, URLEncoder.encode(value, CHARSET)); } catch (UnsupportedEncodingException e) { - return new NameValuePair(name, value); + return new BasicNameValuePair(name, value); } } @Override public String toString() { - return String.format("[Parameter name=%s, value=%s]", name,value); + return String.format("[Parameter name=%s, value=%s]", name, value); } - + } diff --git a/src/main/java/com/foxinmy/weixin4j/http/PartParameter.java b/src/main/java/com/foxinmy/weixin4j/http/PartParameter.java new file mode 100644 index 00000000..c522a8dd --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/http/PartParameter.java @@ -0,0 +1,35 @@ +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 + "]"; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/http/Response.java b/src/main/java/com/foxinmy/weixin4j/http/Response.java index caeec808..b1b2e274 100644 --- a/src/main/java/com/foxinmy/weixin4j/http/Response.java +++ b/src/main/java/com/foxinmy/weixin4j/http/Response.java @@ -11,20 +11,20 @@ import org.dom4j.io.SAXReader; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.foxinmy.weixin4j.WeixinProxy; -import com.foxinmy.weixin4j.msg.ErrorMessage; +import com.foxinmy.weixin4j.msg.BaseResult; import com.thoughtworks.xstream.XStream; public class Response { - private final String ERROR_CODE_KEY = "errcode"; - private final String ERROR_MSG_KEY = "errmsg"; - private String text; private int statusCode; private String statusText; private byte[] body; private InputStream stream; + public Response() { + } + public Response(String text) { this.text = text; } @@ -33,6 +33,10 @@ public class Response { return text; } + public BaseResult getAsResult() { + return JSON.parseObject(text, BaseResult.class); + } + public JSONObject getAsJson() { return JSON.parseObject(text); } @@ -56,24 +60,17 @@ public class Response { * @return * @throws DocumentException */ - public ErrorMessage getErrorMsg() throws DocumentException { - JSONObject jsonObj = getAsJson(); - if (jsonObj.containsKey(ERROR_CODE_KEY)) { + public BaseResult getBaseError() throws DocumentException { + BaseResult result = getAsResult(); + if (result.getErrcode() != 0) { SAXReader reader = new SAXReader(); - Document doc = reader.read(WeixinProxy.class - .getResourceAsStream("error.xml")); - Node node = doc.getRootElement().selectSingleNode( - String.format("error[@code='%d']", - jsonObj.getInteger(ERROR_CODE_KEY))); + Document doc = reader.read(WeixinProxy.class.getResourceAsStream("error.xml")); + Node node = doc.getRootElement().selectSingleNode(String.format("error[@code='%d']", result.getErrcode())); if (node != null) { - return new ErrorMessage(jsonObj.getInteger(ERROR_CODE_KEY), - jsonObj.getString(ERROR_MSG_KEY), node.getStringValue()); + result.setText(node.getStringValue()); } - return new ErrorMessage(jsonObj.getInteger(ERROR_CODE_KEY), - "unknown error", "未知错误"); } - - return new ErrorMessage(0, "request success", ""); + return result; } public String getText() { @@ -124,5 +121,4 @@ public class Response { sb.append(", statusText=").append(statusText).append("]"); return sb.toString(); } - } diff --git a/src/main/java/com/foxinmy/weixin4j/model/AuthResult.java b/src/main/java/com/foxinmy/weixin4j/model/AuthResult.java index 03fec1cb..799534ee 100644 --- a/src/main/java/com/foxinmy/weixin4j/model/AuthResult.java +++ b/src/main/java/com/foxinmy/weixin4j/model/AuthResult.java @@ -4,11 +4,13 @@ import java.io.Serializable; /** * 网页授权结果 + * * @className AuthResult * @author jy.hu * @date 2014年4月8日 * @since JDK 1.7 - * @see 网页授权获取用户基本资料 + * @see 网页授权获取用户基本资料 */ public class AuthResult implements Serializable { @@ -16,11 +18,13 @@ public class AuthResult implements Serializable { /** * 网页授权获取code + * * @className AuthScope * @author jy.hu * @date 2014年4月8日 * @since JDK 1.7 - * @see 获取code + * @see 获取code */ public enum AuthScope { BASE("snsapi_base"), USERINFO("snsapi_userinfo"); @@ -54,6 +58,11 @@ public class AuthResult implements Serializable { this.accessToken = accessToken; } + public AuthResult(String location, AuthCode authCode) { + this.location = location; + this.authCode = authCode; + } + public AuthCode getAuthCode() { return authCode; } diff --git a/src/main/java/com/foxinmy/weixin4j/model/Button.java b/src/main/java/com/foxinmy/weixin4j/model/Button.java index 2c678d76..8c3d89cd 100644 --- a/src/main/java/com/foxinmy/weixin4j/model/Button.java +++ b/src/main/java/com/foxinmy/weixin4j/model/Button.java @@ -5,24 +5,29 @@ import java.util.ArrayList; import java.util.List; import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.type.ButtonType; /** * 菜单按钮 - * 目前自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单,一级菜单最多4个汉字,二级菜单最多7个汉字,多出来的部分将会以"..."代替 - * 请注意,创建自定义菜单后,由于微信客户端缓存,需要24小时微信客户端才会展现出来,建议测试时可以尝试取消关注公众账号后再次关注,则可以看到创建后的效果 + * + * 目前自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单,一级菜单最多4个汉字,二级菜单最多7个汉字,多出来的部分将会以"..."代替 + * 请注意,创建自定义菜单后,由于微信客户端缓存,需要24小时微信客户端才会展现出来,建议测试时可以尝试取消关注公众账号后再次关注,则可以看到创建后的效果 + * + * * @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 BtnType type; - private String key; - private String url; + private ButtonType type; // 菜单的响应动作类型 + private String key; // click等点击类型必须 + private String url; // view类型必须 @JSONField(name = "sub_button") private List subs; @@ -37,7 +42,7 @@ public class Button implements Serializable { public Button(String name, String url) { this.name = name; this.url = url; - this.type = BtnType.view; + this.type = ButtonType.view; } public String getName() { @@ -48,11 +53,11 @@ public class Button implements Serializable { this.name = name; } - public BtnType getType() { + public ButtonType getType() { return type; } - public void setType(BtnType type) { + public void setType(ButtonType type) { this.type = type; } @@ -80,26 +85,12 @@ public class Button implements Serializable { this.subs = subs; } - public void pushSub(Button btn) { + public Button pushSub(Button btn) { if (this.subs == null) { this.subs = new ArrayList(); } this.subs.add(btn); - } - - /** - * 按钮类型 - * click: - * 用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event 的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互; - * view: - * 用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的url值(即网页链接),达到打开网页的目的,建议与网页授权获取用户基本信息接口结合,获得用户的登入个人信息 - * @className BtnType - * @author jy.hu - * @date 2014年4月8日 - * @since JDK 1.7 - */ - public enum BtnType { - click, view + return this; } @Override @@ -119,5 +110,4 @@ public class Button implements Serializable { sb.append("]"); return sb.toString(); } - } diff --git a/src/main/java/com/foxinmy/weixin4j/model/CustomRecord.java b/src/main/java/com/foxinmy/weixin4j/model/CustomRecord.java index ddd7da86..f54e2870 100644 --- a/src/main/java/com/foxinmy/weixin4j/model/CustomRecord.java +++ b/src/main/java/com/foxinmy/weixin4j/model/CustomRecord.java @@ -72,7 +72,6 @@ public class CustomRecord implements Serializable { this.code = code; this.desc = desc; } - public int getCode() { return code; } diff --git a/src/main/java/com/foxinmy/weixin4j/model/MpArticle.java b/src/main/java/com/foxinmy/weixin4j/model/MpArticle.java index 99b6c1eb..2a1d4d64 100644 --- a/src/main/java/com/foxinmy/weixin4j/model/MpArticle.java +++ b/src/main/java/com/foxinmy/weixin4j/model/MpArticle.java @@ -25,6 +25,8 @@ public class MpArticle implements Serializable { 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; } @@ -61,15 +63,31 @@ public class MpArticle implements Serializable { public void setDigest(String digest) { this.digest = digest; } - - public MpArticle(String thumbMediaId, String title,String content) { + 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(); } - } diff --git a/src/main/java/com/foxinmy/weixin4j/model/QRParameter.java b/src/main/java/com/foxinmy/weixin4j/model/QRParameter.java index fe076cfe..32bdafb3 100644 --- a/src/main/java/com/foxinmy/weixin4j/model/QRParameter.java +++ b/src/main/java/com/foxinmy/weixin4j/model/QRParameter.java @@ -7,34 +7,50 @@ import com.thoughtworks.xstream.annotations.XStreamOmitField; /** * 二维码参数对象 - * 目前有2种类型的二维码,分别是临时二维码和永久二维码,前者有过期时间,最大为1800秒,但能够生成较多数量,后者无过期时间,数量较少(目前参数只支持1--100000) + * + * 目前有2种类型的二维码,分别是临时二维码和永久二维码,前者有过期时间,最大为1800秒,但能够生成较多数量,后者无过期时间,数量较少(目前参数只支持1-- + * 100000) + * + * * @className QRParameter * @author jy.hu * @date 2014年4月8日 * @since JDK 1.7 - * @see 生成带参数的二维码 + * @see 生成带参数的二维码 */ public class QRParameter implements Serializable { private static final long serialVersionUID = 6611187606558274253L; public enum QRType { - QR_SCENE, // 临时 - QR_LIMIT_SCENE; // 永久 + TEMPORARY("QR_SCENE"), // 临时 + PERMANENCE("QR_LIMIT_SCENE"); // 永久 + private String name; + + QRType(String name) { + this.name = name; + } + + public String getName() { + return name; + } } - private int expire_seconds; // 该二维码有效时间,以秒为单位。 最大不超过1800。 + @XStreamAlias("expire_seconds") + private int expireSeconds; // 该二维码有效时间,以秒为单位。 最大不超过1800。 @XStreamAlias("action_name") private QRType qrType; // 二维码类型,QR_SCENE为临时,QR_LIMIT_SCENE为永久 @XStreamOmitField - private int scene_id; // 场景值ID,临时二维码时为32位非0整型,永久二维码时最大值为100000(目前参数只支持1--100000) + @XStreamAlias("scene_id") + private int sceneId; // 场景值ID,临时二维码时为32位非0整型,永久二维码时最大值为100000(目前参数只支持1--100000) - public int getExpire_seconds() { - return expire_seconds; + public int getExpireSeconds() { + return expireSeconds; } - public void setExpire_seconds(int expire_seconds) { - this.expire_seconds = expire_seconds; + public void setExpireSeconds(int expireSeconds) { + this.expireSeconds = expireSeconds; } public QRType getQrType() { @@ -45,22 +61,26 @@ public class QRParameter implements Serializable { this.qrType = qrType; } - public int getScene_id() { - return scene_id; + public int getSceneId() { + return sceneId; } - public void setScene_id(int scene_id) { - this.scene_id = scene_id; + public void setSceneId(int sceneId) { + this.sceneId = sceneId; } - public QRParameter(int expire_seconds, QRType qrType, int scene_id) { - this.expire_seconds = expire_seconds; + public QRParameter(int expireSeconds, QRType qrType, int sceneId) { + this.expireSeconds = expireSeconds; this.qrType = qrType; - this.scene_id = scene_id; + this.sceneId = sceneId; } - public QRParameter(QRType action_name, int scene_id) { - this(0, action_name, scene_id); + public QRParameter(QRType qrType, int sceneId) { + this(0, qrType, sceneId); + } + + public QRParameter(int sceneId, int expireSeconds) { + this(0, null, sceneId); } public String toJson() { @@ -74,17 +94,17 @@ public class QRParameter implements Serializable { * "expire_seconds"); } return xstream.toXML(this); */ StringBuilder jsonBuilder = new StringBuilder("{"); - jsonBuilder.append("\"action_name\":\"").append(qrType.name()).append("\""); - if (this.qrType == QRType.QR_SCENE) { - jsonBuilder.append(",\"expire_seconds\":").append(expire_seconds); + jsonBuilder.append("\"action_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}}", scene_id)); + jsonBuilder.append(",\"action_info\":").append(String.format("{\"scene\": {\"scene_id\": %d}}", sceneId)); jsonBuilder.append("}"); return jsonBuilder.toString(); } @Override public String toString() { - return String.format("[QRParameter action_name=%s, expire_seconds=%d, scene_id=%d]", getQrType().name(), getExpire_seconds(), getScene_id()); + return "QRParameter [expireSeconds=" + expireSeconds + ", qrType=" + qrType + ", sceneId=" + sceneId + "]"; } } diff --git a/src/main/java/com/foxinmy/weixin4j/model/Token.java b/src/main/java/com/foxinmy/weixin4j/model/Token.java index 0f9a29fa..abaa2e09 100644 --- a/src/main/java/com/foxinmy/weixin4j/model/Token.java +++ b/src/main/java/com/foxinmy/weixin4j/model/Token.java @@ -2,10 +2,12 @@ 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失效 + * access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token,正常情况下access_token有效期为7200秒, + * 重复获取将导致上次获取的access_token失效 * * @className Token * @author jy.hu @@ -18,25 +20,27 @@ import com.thoughtworks.xstream.annotations.XStreamAlias; public class Token implements Serializable { private static final long serialVersionUID = 1L; - private String access_token; - private int expires_in; + @JSONField(name = "access_token") + private String accessToken; + @JSONField(name = "expires_in") + private int expiresIn; private String openid; private long time; - public String getAccess_token() { - return access_token; + public String getAccessToken() { + return accessToken; } - public void setAccess_token(String access_token) { - this.access_token = access_token; + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; } - public int getExpires_in() { - return expires_in; + public int getExpiresIn() { + return expiresIn; } - public void setExpires_in(int expires_in) { - this.expires_in = expires_in; + public void setExpiresIn(int expiresIn) { + this.expiresIn = expiresIn; } public String getOpenid() { @@ -58,18 +62,13 @@ public class Token implements Serializable { @Override public boolean equals(Object obj) { if (obj instanceof Token) { - return access_token.equals(((Token) obj).getAccess_token()); + return accessToken.equals(((Token) obj).getAccessToken()); } return false; } @Override public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("[Token access_token=").append(access_token); - sb.append(", expires_in=").append(expires_in); - sb.append(", openid=").append(openid); - sb.append(", time=").append(time).append("]"); - return sb.toString(); + return "Token [accessToken=" + accessToken + ", expiresIn=" + expiresIn + ", openid=" + openid + ", time=" + time + "]"; } } diff --git a/src/main/java/com/foxinmy/weixin4j/model/User.java b/src/main/java/com/foxinmy/weixin4j/model/User.java index df89a4dc..9db48888 100644 --- a/src/main/java/com/foxinmy/weixin4j/model/User.java +++ b/src/main/java/com/foxinmy/weixin4j/model/User.java @@ -2,15 +2,19 @@ package com.foxinmy.weixin4j.model; import java.io.Serializable; -import com.foxinmy.weixin4j.util.WeixinUtil; +import org.jsoup.helper.StringUtil; /** * 用户对象 - * 当用户与公众号有交互时,可通过openid获取信息 + * + * 当用户与公众号有交互时,可通过openid获取信息 + * + * * @author jy.hu * @date 2014年4月8日 * @since JDK 1.7 - * @see 获取用户基本资料 + * @see 获取用户基本资料 */ public class User implements Serializable { @@ -27,6 +31,7 @@ public class User implements Serializable { private int subscribe; // 是否关注 private long subscribe_time; // 关注时间 private Lang language; // 使用语言 + private String unionid; // 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段 // 国家地区语言版本 public enum Lang { @@ -92,14 +97,14 @@ public class User implements Serializable { return sex; } - public Gender getGender(){ - if(sex == 1){ + public Gender getGender() { + if (sex == 1) { return Gender.male; - }else if(sex == 2){ + } else if (sex == 2) { return Gender.female; - }else{ + } else { return Gender.unknown; - } + } } public void setSex(int sex) { @@ -135,9 +140,10 @@ public class User implements Serializable { } public String getHeadimgurl(Size size) { - if (!WeixinUtil.isBlank(headimgurl)) { + if (!StringUtil.isBlank(headimgurl)) { StringBuilder sb = new StringBuilder(headimgurl); - return sb.replace(0, (headimgurl.length() - 1), size.getInt() + "").toString(); + return sb.replace(0, (headimgurl.length() - 1), size.getInt() + "") + .toString(); } return ""; } @@ -178,6 +184,14 @@ public class User implements Serializable { 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) { @@ -199,6 +213,7 @@ public class User implements Serializable { 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(); } diff --git a/src/main/java/com/foxinmy/weixin4j/model/UserToken.java b/src/main/java/com/foxinmy/weixin4j/model/UserToken.java index aea3eace..08827e17 100644 --- a/src/main/java/com/foxinmy/weixin4j/model/UserToken.java +++ b/src/main/java/com/foxinmy/weixin4j/model/UserToken.java @@ -1,7 +1,10 @@ package com.foxinmy.weixin4j.model; +import com.alibaba.fastjson.annotation.JSONField; + /** * 用户token 一般通过授权页面获得 + * * @className UserToken * @author jy.hu * @date 2014年4月6日 @@ -13,16 +16,17 @@ public class UserToken extends Token { private static final long serialVersionUID = 1L; - private String refresh_token; + @JSONField(name = "refresh_token") + private String refreshToken; private String scope; - public String getRefresh_token() { - return refresh_token; + public String getRefreshToken() { + return refreshToken; } - public void setRefresh_token(String refresh_token) { - this.refresh_token = refresh_token; + public void setRefreshToken(String refreshToken) { + this.refreshToken = refreshToken; } public String getScope() { @@ -35,13 +39,6 @@ public class UserToken extends Token { @Override public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("[UserToken access_token=").append(super.getAccess_token()); - sb.append(", expires_in=").append(super.getExpires_in()); - sb.append(", openid=").append(super.getOpenid()); - sb.append(", refresh_token=").append(refresh_token); - sb.append(", scope=").append(scope); - sb.append(", time=").append(super.getTime()).append("]"); - return sb.toString(); + return "UserToken [refreshToken=" + refreshToken + ", scope=" + scope + ", getAccessToken()=" + getAccessToken() + ", getExpiresIn()=" + getExpiresIn() + ", getOpenid()=" + getOpenid() + ", getTime()=" + getTime() + "]"; } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/BaseMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/BaseMessage.java index 4f03502b..dbfe975a 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/BaseMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/BaseMessage.java @@ -4,8 +4,6 @@ import java.io.Serializable; import java.io.Writer; import com.foxinmy.weixin4j.type.MessageType; -import com.foxinmy.weixin4j.util.WeixinConfig; -import com.foxinmy.weixin4j.util.WeixinUtil; import com.foxinmy.weixin4j.xml.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; @@ -14,8 +12,11 @@ import com.thoughtworks.xstream.io.json.JsonWriter; /** * 普通消息基类 - * 回复图片等多媒体消息时需要预先上传多媒体文件到微信服务器, - * 假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试 + * + * 回复图片等多媒体消息时需要预先上传多媒体文件到微信服务器, + * 假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试 + * + * * @className BaseMessage * @author jy.hu * @date 2014年4月6日 @@ -24,7 +25,8 @@ import com.thoughtworks.xstream.io.json.JsonWriter; public class BaseMessage implements Serializable { private static final long serialVersionUID = 7761192742840031607L; - + private static XStream xstream; + @XStreamAlias("ToUserName") private String toUserName; // 开发者微信号 @XStreamAlias("FromUserName") @@ -36,10 +38,25 @@ public class BaseMessage implements Serializable { @XStreamAlias("MsgId") private long msgId; // 消息ID + static{ + xstream = new XStream(); + } + 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; } @@ -87,25 +104,35 @@ public class BaseMessage implements Serializable { } return false; } - + + protected XStream getXStream() { + Class extends BaseMessage> targetClass = getMsgType() + .getMessageClass(); + xstream.alias("xml", targetClass); + xstream.autodetectAnnotations(true); + xstream.processAnnotations(targetClass); + xstream.omitField(BaseMessage.class, "msgId"); + return xstream; + } + /** * 消息对象转换为微信服务器接受的xml格式消息 + * * @return xml字符串 */ public String toXml() { - XStream xstream = new XStream(); - xstream.alias("xml", getMsgType().getMessageClass()); + Class extends BaseMessage> targetClass = getMsgType() + .getMessageClass(); + xstream.alias("xml", targetClass); xstream.autodetectAnnotations(true); - xstream.processAnnotations(getMsgType().getMessageClass()); + xstream.processAnnotations(targetClass); xstream.omitField(BaseMessage.class, "msgId"); - if (WeixinUtil.isBlank(fromUserName)) { - setFromUserName(WeixinConfig.getValue("app_openId")); - } return xstream.toXML(this); } /** * 消息对象转换为微信服务器接受的json格式字符串 + * * @return json字符串 */ public String toJson() { @@ -118,9 +145,6 @@ public class BaseMessage implements Serializable { xstream.autodetectAnnotations(true); xstream.processAnnotations(getMsgType().getMessageClass()); xstream.omitField(BaseMessage.class, "msgId"); - if (WeixinUtil.isBlank(fromUserName)) { - setFromUserName(WeixinConfig.getValue("app_openId")); - } return xstream.toXML(this); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/BaseResult.java b/src/main/java/com/foxinmy/weixin4j/msg/BaseResult.java new file mode 100644 index 00000000..0e46f846 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/BaseResult.java @@ -0,0 +1,78 @@ +package com.foxinmy.weixin4j.msg; + +import java.io.Serializable; + +/** + * 调用接口响应值 + * + * @className BaseResult + * @author jy.hu + * @date 2014年9月24日 + * @since JDK 1.7 + * @see 全局返回码 + */ +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 + "]"; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/ErrorMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/ErrorMessage.java deleted file mode 100644 index bb2ac329..00000000 --- a/src/main/java/com/foxinmy/weixin4j/msg/ErrorMessage.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.foxinmy.weixin4j.msg; - -import java.io.Serializable; - -public class ErrorMessage implements Serializable { - - private static final long serialVersionUID = 2539772564331987708L; - - private int code; - private String msg; - private String text; - - public int getCode() { - return code; - } - - public void setCode(int code) { - this.code = code; - } - - public String getMsg() { - return msg; - } - - public void setMsg(String msg) { - this.msg = msg; - } - - public String getText() { - return text; - } - - public void setText(String text) { - this.text = text; - } - - public ErrorMessage(int code, String msg, String text) { - this.code = code; - this.msg = msg; - this.text = text; - } - public ErrorMessage() { - - } - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("[ErrorMessage code=").append(code); - sb.append(", msg=").append(msg); - sb.append(", text=").append(text).append("]"); - return sb.toString(); - } - -} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/TextMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/TextMessage.java index ad167215..43fdcc94 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/TextMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/TextMessage.java @@ -5,12 +5,15 @@ import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 文本消息(接收|回复) + * * @className TextMessage * @author jy.hu * @date 2014年4月6日 * @since JDK 1.7 - * @see 接收文本消息 - * @see 回复文本消息 + * @see 接收文本消息 + * @see 回复文本消息 * @see com.foxinmy.weixin4j.msg.BaseMessage * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ @@ -22,9 +25,8 @@ public class TextMessage extends BaseMessage { super(MessageType.text); } - public TextMessage(String toUserName, String content) { - super(MessageType.text); - setToUserName(toUserName); + public TextMessage(String content, BaseMessage inMessage) { + super(MessageType.text, inMessage); this.content = content; } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/event/LocationEventMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/event/LocationEventMessage.java index ff1091ed..2e7c155c 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/event/LocationEventMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/event/LocationEventMessage.java @@ -3,16 +3,15 @@ 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 上报地理位置事件 - * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see 上报地理位置事件 */ public class LocationEventMessage extends EventMessage { @@ -21,7 +20,7 @@ public class LocationEventMessage extends EventMessage { public LocationEventMessage() { super(EventType.location); } - + @XStreamAlias("Latitude") private String latitude;// 地理位置纬度 @XStreamAlias("Longitude") @@ -33,30 +32,19 @@ public class LocationEventMessage extends EventMessage { return latitude; } - public void setLatitude(String latitude) { - this.latitude = latitude; - } - public String getLongitude() { return longitude; } - public void setLongitude(String longitude) { - this.longitude = longitude; - } - public String getPrecision() { return precision; } - public void setPrecision(String precision) { - this.precision = precision; - } - @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("[LocationEventMessage ,toUserName=").append(super.getToUserName()); + sb.append("[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()); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/event/MassEventMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/event/MassEventMessage.java index 346e7172..c59d187c 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/event/MassEventMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/event/MassEventMessage.java @@ -18,7 +18,7 @@ public class MassEventMessage extends EventMessage { private static final long serialVersionUID = -1660543255873723895L; public MassEventMessage() { - super(EventType.MASSSENDJOBFINISH); + super(EventType.massendjobfinish); } @XStreamAlias("Status") @@ -35,38 +35,28 @@ public class MassEventMessage extends EventMessage { public String getStatus() { return status; } - public void setStatus(String status) { - this.status = status; - } + public int getTotalCount() { return totalCount; } - public void setTotalCount(int totalCount) { - this.totalCount = totalCount; - } + public int getFilterCount() { return filterCount; } - public void setFilterCount(int filterCount) { - this.filterCount = filterCount; - } + public int getSentCount() { return sentCount; } - public void setSentCount(int sentCount) { - this.sentCount = sentCount; - } + public int getErrorCount() { return errorCount; } - public void setErrorCount(int errorCount) { - this.errorCount = errorCount; - } - + @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("[MassEventMessage ,toUserName=").append(super.getToUserName()); + sb.append("[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()); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/event/ScanEventMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/event/ScanEventMessage.java index 9e621530..ccf2a6b8 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/event/ScanEventMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/event/ScanEventMessage.java @@ -3,14 +3,14 @@ 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 扫描二维码事件 - * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see 扫描二维码事件 */ public class ScanEventMessage extends EventMessage { @@ -20,7 +20,7 @@ public class ScanEventMessage extends EventMessage { private static final long serialVersionUID = 8078674062833071562L; private static final String PARA_PREFIX = "qrscene_"; - + @XStreamAlias("EventKey") private String eventKey; // 事件KEY值,是一个32位无符号整数,即创建二维码时的二维码scene_id @XStreamAlias("Ticket") @@ -30,18 +30,10 @@ public class ScanEventMessage extends EventMessage { return eventKey; } - public void setEventKey(String eventKey) { - this.eventKey = eventKey; - } - public String getTicket() { return ticket; } - public void setTicket(String ticket) { - this.ticket = ticket; - } - public String getParameter() { return eventKey.replace(PARA_PREFIX, ""); } @@ -49,7 +41,8 @@ public class ScanEventMessage extends EventMessage { @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("[ScanEventMessage ,toUserName=").append(super.getToUserName()); + 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()); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/event/ScribeEventMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/event/ScribeEventMessage.java index 21053b24..645ab6b6 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/event/ScribeEventMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/event/ScribeEventMessage.java @@ -9,8 +9,6 @@ package com.foxinmy.weixin4j.msg.event; * @date 2014年4月6日 * @since JDK 1.7 * @see 关注/取消关注事件 - * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class ScribeEventMessage extends ScanEventMessage { diff --git a/src/main/java/com/foxinmy/weixin4j/msg/event/TemplatesendjobfinishMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/event/TemplatesendjobfinishMessage.java new file mode 100644 index 00000000..45a9f023 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/event/TemplatesendjobfinishMessage.java @@ -0,0 +1,35 @@ +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 模板消息事件推送 + */ +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 + "]"; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/event/MenuEventMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/event/menu/MenuEventMessage.java similarity index 64% rename from src/main/java/com/foxinmy/weixin4j/msg/event/MenuEventMessage.java rename to src/main/java/com/foxinmy/weixin4j/msg/event/menu/MenuEventMessage.java index f4d3c752..01b3f5d0 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/event/MenuEventMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/event/menu/MenuEventMessage.java @@ -1,17 +1,18 @@ -package com.foxinmy.weixin4j.msg.event; +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 自定义菜单事件 - * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see 菜单事件 */ public class MenuEventMessage extends EventMessage { @@ -28,14 +29,11 @@ public class MenuEventMessage extends EventMessage { return eventKey; } - public void setEventKey(String eventKey) { - this.eventKey = eventKey; - } - @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("[MenuEventMessage ,toUserName=").append(super.getToUserName()); + sb.append("[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()); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/event/menu/MenuLocationEventMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/event/menu/MenuLocationEventMessage.java new file mode 100644 index 00000000..4811681f --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/event/menu/MenuLocationEventMessage.java @@ -0,0 +1,74 @@ +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 弹出地理位置选择事件推送 + */ +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 + "]"; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/event/menu/MenuPhotoEventMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/event/menu/MenuPhotoEventMessage.java new file mode 100644 index 00000000..674303f3 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/event/menu/MenuPhotoEventMessage.java @@ -0,0 +1,63 @@ +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 弹出系统拍照发图的事件推送 + */ +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 items; + + public int getCount() { + return count; + } + + public List 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 + "]"; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/event/menu/MenuScanEventMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/event/menu/MenuScanEventMessage.java new file mode 100644 index 00000000..cc6e4a1e --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/event/menu/MenuScanEventMessage.java @@ -0,0 +1,51 @@ +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 扫码推事件的事件推送 + */ +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 + "]"; + } + +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/in/ImageMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/in/ImageMessage.java index d749b26c..37b5e9c7 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/in/ImageMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/in/ImageMessage.java @@ -6,13 +6,13 @@ import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 图片消息 + * * @className ImageMessage * @author jy.hu * @date 2014年4月6日 * @since JDK 1.7 - * @see 图片消息 - * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see 图片消息 */ public class ImageMessage extends BaseMessage { @@ -21,7 +21,7 @@ public class ImageMessage extends BaseMessage { public ImageMessage() { super(MessageType.image); } - + @XStreamAlias("PicUrl") private String picUrl; // 图片链接 @XStreamAlias("MediaId") @@ -31,18 +31,10 @@ public class ImageMessage extends BaseMessage { return picUrl; } - public void setPicUrl(String picUrl) { - this.picUrl = picUrl; - } - public String getMediaId() { return mediaId; } - public void setMediaId(String mediaId) { - this.mediaId = mediaId; - } - @Override public String toString() { StringBuilder sb = new StringBuilder(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/in/LinkMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/in/LinkMessage.java index 5defa28e..7faca8d8 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/in/LinkMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/in/LinkMessage.java @@ -6,13 +6,13 @@ import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 链接消息 + * * @className LinkMessage * @author jy.hu * @date 2014年4月6日 * @since JDK 1.7 - * @see 链接消息 - * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see 链接消息 */ public class LinkMessage extends BaseMessage { @@ -21,7 +21,7 @@ public class LinkMessage extends BaseMessage { public LinkMessage() { super(MessageType.link); } - + @XStreamAlias("Title") private String title; // 消息标题 @XStreamAlias("Description") @@ -33,26 +33,14 @@ public class LinkMessage extends BaseMessage { return title; } - public void setTitle(String title) { - this.title = title; - } - public String getDescription() { return description; } - public void setDescription(String description) { - this.description = description; - } - public String getUrl() { return url; } - public void setUrl(String url) { - this.url = url; - } - @Override public String toString() { StringBuilder sb = new StringBuilder(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/in/LocationMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/in/LocationMessage.java index 4a883208..70b19da2 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/in/LocationMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/in/LocationMessage.java @@ -6,13 +6,13 @@ import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 地理位置消息 + * * @className LocationMessage * @author jy.hu * @date 2014年4月6日 * @since JDK 1.7 - * @see 地理位置消息 - * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see 地理位置消息 */ public class LocationMessage extends BaseMessage { @@ -23,38 +23,26 @@ public class LocationMessage extends BaseMessage { } @XStreamAlias("Location_X") - private String location_X; // 地理位置维度 + private double x; // 地理位置维度 @XStreamAlias("Location_Y") - private String location_Y; // 地理位置经度 + private double y; // 地理位置经度 @XStreamAlias("Scale") - private String scale; // 地图缩放大小 + private double scale; // 地图缩放大小 @XStreamAlias("Label") private String label; // 地理位置信息 - public String getLocation_X() { - return location_X; + public double getX() { + return x; } - public void setLocation_X(String location_X) { - this.location_X = location_X; + public double getY() { + return y; } - public String getLocation_Y() { - return location_Y; - } - - public void setLocation_Y(String location_Y) { - this.location_Y = location_Y; - } - - public String getScale() { + public double getScale() { return scale; } - public void setScale(String scale) { - this.scale = scale; - } - public String getLabel() { return label; } @@ -66,11 +54,12 @@ public class LocationMessage extends BaseMessage { @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("[LocationMessage ,toUserName=").append(super.getToUserName()); + sb.append("[LocationMessage ,toUserName=") + .append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,location_X=").append(location_X); - sb.append(" ,location_Y=").append(location_Y); + sb.append(" ,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()); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/in/VideoMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/in/VideoMessage.java index ce240885..053c1974 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/in/VideoMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/in/VideoMessage.java @@ -6,13 +6,13 @@ import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 视频消息 + * * @className VideoMessage * @author jy.hu * @date 2014年4月6日 * @since JDK 1.7 - * @see 视频消息 - * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see 视频消息 */ public class VideoMessage extends BaseMessage { @@ -31,18 +31,10 @@ public class VideoMessage extends BaseMessage { return mediaId; } - public void setMediaId(String mediaId) { - this.mediaId = mediaId; - } - public String getThumbMediaId() { return thumbMediaId; } - public void setThumbMediaId(String thumbMediaId) { - this.thumbMediaId = thumbMediaId; - } - @Override public String toString() { StringBuilder sb = new StringBuilder(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/in/VoiceMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/in/VoiceMessage.java index af168e77..57fde9ec 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/in/VoiceMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/in/VoiceMessage.java @@ -6,14 +6,16 @@ import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 语音消息 - * 开通语音识别功能,用户每次发送语音给公众号时,微信会在推送的语音消息XML数据包中,赋值到Recongnition字段. + * + * 开通语音识别功能,用户每次发送语音给公众号时,微信会在推送的语音消息XML数据包中,赋值到Recongnition字段. + * + * * @className VoiceMessage * @author jy.hu * @date 2014年4月6日 * @since JDK 1.7 - * @see 语音消息 - * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see 语音消息 */ public class VoiceMessage extends BaseMessage { @@ -27,7 +29,7 @@ public class VoiceMessage extends BaseMessage { private String mediaId; // 语音消息媒体id,可以调用多媒体文件下载接口拉取数据。 @XStreamAlias("Format") private String format; // 语音格式,如amr,speex等 - + @XStreamAlias("Recognition") private String recognition; // 语音识别结果,UTF8编码 @@ -35,26 +37,14 @@ public class VoiceMessage extends BaseMessage { return recognition; } - public void setRecognition(String recognition) { - this.recognition = recognition; - } - public String getMediaId() { return mediaId; } - public void setMediaId(String mediaId) { - this.mediaId = mediaId; - } - public String getFormat() { return format; } - public void setFormat(String format) { - this.format = format; - } - @Override public String toString() { StringBuilder sb = new StringBuilder(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/model/Article.java b/src/main/java/com/foxinmy/weixin4j/msg/model/Article.java new file mode 100644 index 00000000..28f4c861 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/model/Article.java @@ -0,0 +1,75 @@ +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; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/model/BaseMsg.java b/src/main/java/com/foxinmy/weixin4j/msg/model/BaseMsg.java new file mode 100644 index 00000000..61b5648c --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/model/BaseMsg.java @@ -0,0 +1,33 @@ +package com.foxinmy.weixin4j.msg.model; + +import java.io.Serializable; +import java.io.Writer; + +import com.foxinmy.weixin4j.type.MediaType; +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; + + public abstract MediaType getMediaType(); + + /** + * 客服消息json化,适用于客服消息接口 + * + * @return {"touser": "to","msgtype": "text","text": {"content": "123"}} + */ + public String toNotifyJson() { + 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); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/model/Image.java b/src/main/java/com/foxinmy/weixin4j/msg/model/Image.java new file mode 100644 index 00000000..00197ff5 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/model/Image.java @@ -0,0 +1,38 @@ +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; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/model/Music.java b/src/main/java/com/foxinmy/weixin4j/msg/model/Music.java new file mode 100644 index 00000000..7754c1ed --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/model/Music.java @@ -0,0 +1,93 @@ +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; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/model/Text.java b/src/main/java/com/foxinmy/weixin4j/msg/model/Text.java new file mode 100644 index 00000000..8375e59e --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/model/Text.java @@ -0,0 +1,40 @@ +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; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/model/Video.java b/src/main/java/com/foxinmy/weixin4j/msg/model/Video.java new file mode 100644 index 00000000..3795b714 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/model/Video.java @@ -0,0 +1,88 @@ +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; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/model/Voice.java b/src/main/java/com/foxinmy/weixin4j/msg/model/Voice.java new file mode 100644 index 00000000..c99201a2 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/model/Voice.java @@ -0,0 +1,38 @@ +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; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/notify/ArticleNotify.java b/src/main/java/com/foxinmy/weixin4j/msg/notify/ArticleNotify.java index abb74af7..4fb91621 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/notify/ArticleNotify.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/notify/ArticleNotify.java @@ -3,17 +3,21 @@ 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 客服图文消息 + * @see 客服图文消息 + * @see com.foxinmy.weixin.msg.model.Article * @see com.foxinmy.weixin4j.msg.notify.BaseNotify * @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson() */ @@ -46,60 +50,53 @@ public class ArticleNotify extends BaseNotify { count++; } - private static class News { - @XStreamAlias("articles") - private List<$> articles; - - public News() { - this.articles = new LinkedList<$>(); + public void pushAll(List articles) { + count = articles.size(); + if (articles.size() > MAX_ARTICLE_COUNT) { + count = MAX_ARTICLE_COUNT; + articles = articles.subList(0, count); } - - public void pushArticle(String title, String desc, String picUrl, String url) { - this.articles.add(new $(title, desc, picUrl, url)); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - for ($ item : articles) { - sb.append("{title=").append(item.title); - sb.append(" ,description=").append(item.desc); - sb.append(" ,picUrl=").append(item.picUrl); - sb.append(" ,url=").append(item.url).append("}"); - } - return sb.toString(); + if (this.news == null) { + this.news = new News(); } + this.news.setArticles(articles); } - private static class $ { - private String title; // 图文消息标题 - @XStreamAlias("description") - private String desc; // 图文消息描述 - @XStreamAlias("picurl") - private String picUrl; // 图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200 - @XStreamAlias("url") - private String url; // 点击图文消息跳转链接 + private static class News { + @XStreamAlias("articles") + private List articles; - public $(String title, String desc, String picUrl, String url) { - this.title = title; - this.desc = desc; - this.picUrl = picUrl; - this.url = url; + public News() { + this.articles = new LinkedList(); + } + + public void pushArticle(String title, String desc, String picUrl, + String url) { + this.articles.add(new Article(title, desc, picUrl, url)); + } + + public void setArticles(List articles) { + this.articles = articles; } @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("(article ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,picUrl=").append(picUrl); - sb.append(" ,url=").append(url).append(")"); + 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()); + return String.format( + "[ArticleNotify touser=%s ,msgtype=%s ,articles=%s]", + super.getTouser(), super.getMsgtype().name(), + this.news.toString()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/notify/ImageNotify.java b/src/main/java/com/foxinmy/weixin4j/msg/notify/ImageNotify.java index f9a52263..d2e47096 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/notify/ImageNotify.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/notify/ImageNotify.java @@ -1,14 +1,17 @@ package com.foxinmy.weixin4j.msg.notify; +import com.foxinmy.weixin4j.msg.model.Image; import com.foxinmy.weixin4j.type.MessageType; -import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 客服图片消息 + * * @author jy.hu * @date 2014年4月4日 * @since JDK 1.7 - * @see 客服图片消息 + * @see 客服图片消息 + * @see com.foxinmy.weixin4j.msg.model.Image * @see com.foxinmy.weixin4j.msg.notify.BaseNotify * @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson() */ @@ -20,30 +23,25 @@ public class ImageNotify extends BaseNotify { super(MessageType.image); } - public ImageNotify(String mediaId) { - super(MessageType.image); - this.image = new $(mediaId); + public ImageNotify(String touser) { + super(touser, MessageType.image); } public ImageNotify(String mediaId, String touser) { super(touser, MessageType.image); - this.image = new $(mediaId); + this.pushMediaId(mediaId); } - @XStreamAlias("image") - private $ image; - - private static class $ { - @XStreamAlias("media_id") - private String mediaId; - - public $(String mediaId) { - this.mediaId = 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.mediaId); + return String.format("[ImageNotify touser=%s ,msgtype=%s ,mediaId=%s]", + super.getTouser(), super.getMsgtype().name(), + this.image.getMediaId()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/notify/MusicNotify.java b/src/main/java/com/foxinmy/weixin4j/msg/notify/MusicNotify.java index 6f3e66fa..1e328677 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/notify/MusicNotify.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/notify/MusicNotify.java @@ -1,14 +1,17 @@ package com.foxinmy.weixin4j.msg.notify; +import com.foxinmy.weixin4j.msg.model.Music; import com.foxinmy.weixin4j.type.MessageType; -import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 客服音乐消息 + * * @author jy.hu * @date 2014年4月4日 * @since JDK 1.7 - * @see 客服音乐消息 + * @see 客服音乐消息 + * @see com.foxinmy.weixin4j.msg.model.Music * @see com.foxinmy.weixin4j.msg.notify.BaseNotify * @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson() */ @@ -24,44 +27,20 @@ public class MusicNotify extends BaseNotify { super(touser, MessageType.music); } - public void pushMusic(String title, String desc, String url, String hqUrl, String mediaId) { - this.music = new $(); - this.music.thumbMediaId = mediaId; - this.music.desc = desc; - this.music.hqMusicUrl = hqUrl; - this.music.musicUrl = url; - this.music.title = title; + public void pushMusic(String musicurl, String hqUrl, String mediaId) { + this.music = new Music(null, null, musicurl, hqUrl, mediaId); } - @XStreamAlias("music") - private $ music; - - private static class $ { - private String title; - @XStreamAlias("description") - private String desc; - @XStreamAlias("musicurl") - private String musicUrl; - @XStreamAlias("hqmusicurl") - private String hqMusicUrl; - @XStreamAlias("thumb_media_id") - private String thumbMediaId; - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(music ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,musicURL=").append(musicUrl); - sb.append(" ,hqMusicUrl=").append(hqMusicUrl); - sb.append(" ,thumbMediaId=").append(thumbMediaId).append(")"); - return sb.toString(); - } + private Music music; + public void setMusic(Music music) { + this.music = music; } @Override public String toString() { - return String.format("[VideoNotify touser=%s ,msgtype=%s ,music=%s]", super.getTouser(), super.getMsgtype().name(), this.music.toString()); + return String.format("[MusicNotify touser=%s ,msgtype=%s ,music=%s]", + super.getTouser(), super.getMsgtype().name(), + this.music.toString()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/notify/TextNotify.java b/src/main/java/com/foxinmy/weixin4j/msg/notify/TextNotify.java index edcf2565..6ec09a3a 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/notify/TextNotify.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/notify/TextNotify.java @@ -1,14 +1,17 @@ package com.foxinmy.weixin4j.msg.notify; +import com.foxinmy.weixin4j.msg.model.Text; import com.foxinmy.weixin4j.type.MessageType; -import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 客服文本消息 + * * @author jy.hu * @date 2014年4月4日 * @since JDK 1.7 - * @see 客服文本消息 + * @see 客服文本消息 + * @see com.foxinmy.weixin.msg.model.Text * @see com.foxinmy.weixin4j.msg.notify.BaseNotify * @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson() */ @@ -22,27 +25,24 @@ public class TextNotify extends BaseNotify { public TextNotify(String content) { super(MessageType.text); - this.text = new $(content); + this.text = new Text(content); } public TextNotify(String content, String touser) { super(touser, MessageType.text); - this.text = new $(content); + this.text = new Text(content); } - @XStreamAlias("text") - private $ text; - - private static class $ { - @XStreamAlias("content") - private String content; - - public $(String content) { - this.content = 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.content); + return String.format("[TextNotify touser=%s ,msgtype=%s ,content=%s]", + super.getTouser(), super.getMsgtype().name(), + this.text.getContent()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/notify/VideoNotify.java b/src/main/java/com/foxinmy/weixin4j/msg/notify/VideoNotify.java index d8865910..8e433c03 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/notify/VideoNotify.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/notify/VideoNotify.java @@ -1,14 +1,17 @@ package com.foxinmy.weixin4j.msg.notify; +import com.foxinmy.weixin4j.msg.model.Video; import com.foxinmy.weixin4j.type.MessageType; -import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 客服视频消息 + * * @author jy.hu * @date 2014年4月4日 * @since JDK 1.7 - * @see 客服视频消息 + * @see 客服视频消息 + * @see com.foxinmy.weixin4j.msg.model.Video * @see com.foxinmy.weixin4j.msg.notify.BaseNotify * @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson() */ @@ -23,36 +26,21 @@ public class VideoNotify extends BaseNotify { public VideoNotify(String touser) { super(touser, MessageType.video); } - - public void pushVideo(String mediaId, String title, String desc) { - this.video = new $(mediaId, title, desc); + + public void pushVideo(String mediaId, String thumbMediaId) { + this.video = new Video(mediaId, thumbMediaId); } - @XStreamAlias("video") - private $ video; - - private static class $ { - @XStreamAlias("media_id") - private String mediaId; - private String title; - @XStreamAlias("description") - private String desc; - - public $(String mediaId, String title, String desc) { - this.mediaId = mediaId; - this.title = title; - this.desc = desc; - } - - @Override - public String toString() { - return String.format("(video mediaId=%s ,title=%s ,description=%s)", mediaId, title, desc); - } + 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()); + return String.format("[VideoNotify touser=%s ,msgtype=%s ,video=%s]", + super.getTouser(), super.getMsgtype().name(), + this.video.toString()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/notify/VoiceNotify.java b/src/main/java/com/foxinmy/weixin4j/msg/notify/VoiceNotify.java index 8e0787b6..4cfb7a7f 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/notify/VoiceNotify.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/notify/VoiceNotify.java @@ -1,14 +1,17 @@ package com.foxinmy.weixin4j.msg.notify; +import com.foxinmy.weixin4j.msg.model.Voice; import com.foxinmy.weixin4j.type.MessageType; -import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 客服语音消息 + * * @author jy.hu * @date 2014年4月4日 * @since JDK 1.7 - * @see 客服语音消息 + * @see 客服语音消息 + * @see com.foxinmy.weixin4j.msg.model.Voice * @see com.foxinmy.weixin4j.msg.notify.BaseNotify * @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson() */ @@ -20,30 +23,25 @@ public class VoiceNotify extends BaseNotify { super(MessageType.voice); } - public VoiceNotify(String mediaId) { - super(MessageType.voice); - this.voice = new $(mediaId); + public VoiceNotify(String touser) { + super(touser, MessageType.voice); } public VoiceNotify(String mediaId, String touser) { super(touser, MessageType.voice); - this.voice = new $(mediaId); + this.pushMediaId(mediaId); } - @XStreamAlias("voice") - private $ voice; - - private static class $ { - @XStreamAlias("media_id") - private String mediaId; - - public $(String mediaId) { - this.mediaId = 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.mediaId); + return String.format("[VoiceNotify touser=%s ,msgtype=%s ,mediaId=%s]", + super.getTouser(), super.getMsgtype().name(), + this.voice.getMediaId()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/ArticleMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/ArticleMessage.java index e892aeaa..9c3737a7 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/ArticleMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/ArticleMessage.java @@ -4,36 +4,36 @@ import java.util.LinkedList; import java.util.List; 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 回复图文消息 + * @see 回复图文消息 + * @see com.foxinmy.weixin.msg.model.Article * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class ArticleMessage extends BaseMessage { private static final int MAX_ARTICLE_COUNT = 10; private static final long serialVersionUID = -7331603018352309317L; - public ArticleMessage() { - super(MessageType.news); - } - - public ArticleMessage(String toUserName) { - super(MessageType.news); - super.setToUserName(toUserName); + public ArticleMessage(BaseMessage inMessage) { + super(MessageType.news, inMessage); } @XStreamAlias("ArticleCount") private int count; // 图文消息个数,限制为10条以内 @XStreamAlias("Articles") - private List articles; + private LinkedList articles; public List getArticles() { return this.articles; @@ -44,39 +44,55 @@ public class ArticleMessage extends BaseMessage { return; } if (this.articles == null) { - this.articles = new LinkedList(); + this.articles = new LinkedList(); } this.articles.add(new Article(title, desc, picUrl, url)); - count ++; + count++; } - @XStreamAlias("item") - private static class Article { - @XStreamAlias("Title") - private String title; // 图文消息标题 - @XStreamAlias("Description") - private String desc; // 图文消息描述 - @XStreamAlias("PicUrl") - private String picUrl; // 图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200 - @XStreamAlias("Url") - private String url; // 点击图文消息跳转链接 - - public Article(String title, String desc, String picUrl, String url) { - this.title = title; - this.desc = desc; - this.picUrl = picUrl; - this.url = url; + public void pushFirstArticle(String title, String desc, String picUrl, + String url) { + if (this.articles == null) { + this.articles = new LinkedList(); } + this.articles.addFirst(new Article(title, desc, picUrl, url)); + } - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Article ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,picUrl=").append(picUrl); - sb.append(" ,url=").append(url).append(")"); - return sb.toString(); + public void pushLastArticle(String title, String desc, String picUrl, + String url) { + if (this.articles == null) { + this.articles = new LinkedList(); } + this.articles.addLast(new Article(title, desc, picUrl, url)); + } + + public Article removeLastArticle() { + if (this.articles != null) { + return this.articles.removeLast(); + } + return null; + } + + 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() { + 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 diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java index 2da50a01..fb58ecb8 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java @@ -1,38 +1,50 @@ 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 回复图片消息 + * @see 回复图片消息 + * @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() { - super(MessageType.image); + public ImageMessage(BaseMessage inMessage) { + super(MessageType.image, inMessage); super.getMsgType().setMessageClass(ImageMessage.class); } + 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(); - this.image.mediaId = mediaId; + this.image = new Image(mediaId); } - private static class Image { - @XStreamAlias("MediaId") - private String mediaId; + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Image.class, "mediaId"); + return xstream.toXML(this); } @Override @@ -41,7 +53,7 @@ public class ImageMessage extends BaseMessage { sb.append("[ImageMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,mediaId=").append(this.image.mediaId); + sb.append(" ,mediaId=").append(this.image.getMediaId()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java index c790b9ac..419f32d6 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java @@ -1,74 +1,61 @@ 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 回复音乐消息 + * @see 回复音乐消息 + * @see com.foxinmy.weixin4j.msg.model.Music * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class MusicMessage extends BaseMessage { private static final long serialVersionUID = 4384403772658796395L; - public MusicMessage() { - super(MessageType.music); + public MusicMessage(BaseMessage inMessage) { + super(MessageType.music, inMessage); } @XStreamAlias("Music") private Music music; - public Music getMusic() { - return this.music; + public void pushMusic(String mediaId) { + this.music = new Music(mediaId); } - public void pushMusic(String title, String desc, String url, String hqUrl, String mediaId) { - this.music = new Music(); - this.music.thumbMediaId = mediaId; - this.music.desc = desc; - this.music.hqMusicUrl = hqUrl; - this.music.MusicURL = url; - this.music.title = title; + public void setMusic(Music music) { + this.music = music; } - private static class Music { - @XStreamAlias("Title") - private String title; // 音乐标题 - @XStreamAlias("Description") - private String desc; // 音乐描述 - @XStreamAlias("MusicURL") - private String MusicURL; // 音乐链接 - @XStreamAlias("HQMusicUrl") - private String hqMusicUrl; // 高质量音乐链接,WIFI环境优先使用该链接播放音乐 - @XStreamAlias("ThumbMediaId") - private String thumbMediaId; // 缩略图的媒体id,通过上传多媒体文件,得到的id - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Music ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,musicURL=").append(MusicURL); - sb.append(" ,hqMusicUrl=").append(hqMusicUrl); - sb.append(" ,thumbMediaId=").append(thumbMediaId).append(")"); - return sb.toString(); - } + @Override + public String 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(getMusic().toString()); + sb.append(" ,music=").append(music.toString()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java new file mode 100644 index 00000000..3721504b --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java @@ -0,0 +1,117 @@ +package com.foxinmy.weixin4j.msg.out; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +import com.alibaba.fastjson.JSON; + +/** + * 模板消息 + * + * @className TemplateMessage + * @author jy + * @date 2014年9月29日 + * @since JDK 1.7 + * @see + */ +public class TemplateMessage implements Serializable { + + private static final long serialVersionUID = 7950608393821661436L; + + private String touser; + private String template_id; + private String url; + private String topcolor = "#FF0000"; + private Map data; + + public void pushData(String key, String value) { + this.data.put(key, new Item(value)); + } + + public TemplateMessage(String touser, String template_id, String url) { + this.touser = touser; + this.template_id = template_id; + this.url = url; + this.data = new HashMap(); + } + + private static class Item implements Serializable { + private static final long serialVersionUID = 1L; + private String value; + private String color; + + public Item(String value) { + this(value, "#173177"); + } + + public Item(String value, String color) { + this.value = value; + this.color = color; + } + + public String getValue() { + return value; + } + + public String getColor() { + return color; + } + + @Override + public String toString() { + return "$ [value=" + getValue() + ", color=" + getColor() + "]"; + } + } + + public String getTouser() { + return touser; + } + + public void setTouser(String touser) { + this.touser = touser; + } + + public String getTemplate_id() { + return template_id; + } + + public void setTemplate_id(String template_id) { + this.template_id = template_id; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getTopcolor() { + return topcolor; + } + + public void setTopcolor(String topcolor) { + this.topcolor = topcolor; + } + + public Map getData() { + return data; + } + + public void setData(Map data) { + this.data = data; + } + + @Override + public String toString() { + return "TemplateMessage [touser=" + touser + ", template_id=" + + template_id + ", url=" + url + ", topcolor=" + topcolor + + ", data=" + data + "]"; + } + + public String toJson() { + return JSON.toJSONString(this); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java new file mode 100644 index 00000000..b89621aa --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java @@ -0,0 +1,25 @@ +package com.foxinmy.weixin4j.msg.out; + +import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.type.MessageType; + +/** + * 转移消息到多客服端消息 + * + * @className TransferMessage + * @author jy.hu + * @date 2014年6月28日 + * @since JDK 1.7 + * @see 多客服转移消息 + * @see com.foxinmy.weixin4j.msg.BaseMessage + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + */ +public class TransferMessage extends BaseMessage { + + private static final long serialVersionUID = -5479496746108594940L; + + public TransferMessage(BaseMessage inMessage) { + super(MessageType.transfer_customer_service,inMessage); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java index d16c5a12..d6cdfc91 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java @@ -1,58 +1,52 @@ package com.foxinmy.weixin4j.msg.out; import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.msg.model.Video; import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 回复视频消息 + * * @className VideoMessage * @author jy.hu * @date 2014年4月6日 * @since JDK 1.7 - * @see 回复视频消息 + * @see 回复视频消息 + * @see com.foxinmy.weixin4j.msg.model.Video * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class VideoMessage extends BaseMessage { private static final long serialVersionUID = -1013075358679078381L; - public VideoMessage() { - super(MessageType.video); + public VideoMessage(BaseMessage inMessage) { + super(MessageType.video, inMessage); super.getMsgType().setMessageClass(VideoMessage.class); } @XStreamAlias("Video") private Video video; - public Video getVideo() { - return this.video; + public void pushVideo(String mediaId) { + this.video = new Video(mediaId); } - public void pushVideo(String mediaId, String title, String desc) { - this.video = new Video(); - this.video.desc = desc; - this.video.mediaId = mediaId; - this.video.title = title; + public void setVideo(Video video) { + this.video = video; } - private static class Video { - @XStreamAlias("MediaId") - private String mediaId; - @XStreamAlias("Title") - private String title; - @XStreamAlias("Description") - private String desc; - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Video mediaId=").append(mediaId); - sb.append(" ,title=").append(title); - sb.append(" ,desc=").append(desc).append(")"); - return super.toString(); - } + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Video.class, "mediaId"); + xstream.aliasField("Title", Video.class, "title"); + xstream.aliasField("Description", Video.class, "desc"); + xstream.omitField(Video.class, "thumbMediaId"); + return xstream.toXML(this); } @Override @@ -61,7 +55,7 @@ public class VideoMessage extends BaseMessage { sb.append("[VideoMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,video=").append(getVideo().toString()); + sb.append(" ,video=").append(video.toString()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java index 93052907..dcac1046 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java @@ -1,53 +1,60 @@ package com.foxinmy.weixin4j.msg.out; import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.msg.model.Voice; import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 语音消息 + * * @className VoiceMessage * @author jy.hu * @date 2014年3月23日 * @since JDK 1.7 - * @see 回复语音消息 + * @see 回复语音消息 + * @see com.foxinmy.weixin4j.msg.model.Voice * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class VoiceMessage extends BaseMessage { private static final long serialVersionUID = -7944926238652243793L; - public VoiceMessage() { - super(MessageType.voice); + public VoiceMessage(BaseMessage inMessage) { + super(MessageType.voice, inMessage); super.getMsgType().setMessageClass(VoiceMessage.class); } + + public VoiceMessage(String mediaId, BaseMessage inMessage) { + super(MessageType.voice, inMessage); + super.getMsgType().setMessageClass(VoiceMessage.class); + this.pushMediaId(mediaId); + } + @XStreamAlias("Voice") private Voice voice; - - public Voice getVocie() { - return voice; + + public void pushMediaId(String mediaId) { + this.voice = new Voice(mediaId); } - public void pushMediaId(String mediaId){ - this.voice = new Voice(); - this.voice.setMediaId(mediaId); - } - - private static class Voice { - @XStreamAlias("MediaId") - private String mediaId; - - private void setMediaId(String mediaId) { - this.mediaId = mediaId; - } + + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Voice.class, "mediaId"); + return xstream.toXML(this); } + @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("[VoiceMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,mediaId=").append(getVocie().mediaId); + sb.append(" ,mediaId=").append(voice.getMediaId()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java b/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java new file mode 100644 index 00000000..cf2ab68e --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java @@ -0,0 +1,55 @@ +package com.foxinmy.weixin4j.type; + +/** + * 自定义菜单类型 + * scancode_push 到 location_selec + * 仅支持微信iPhone5.4.1以上版本,和Android5 .4以上版本的微信用户 旧版本微信用户点击后将没有回应 + * 开发者也不能正常接收到事件推送。 + * + * @className ButtonType + * @author jy + * @date 2014年9月30日 + * @since JDK 1.7 + * @see 按钮类型 + */ +public enum ButtonType { + /** + * 点击推事件 用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event + * 的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互; + */ + click, + /** + * 跳转URL 用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的网页URL,可与网页授权获取用户基本信息接口结合,获得用户基本信息。 + */ + view, + /** + * 扫码推事件 用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后显示扫描结果(如果是URL,将进入URL),且会将扫码的结果传给开发者, + * 开发者可以下发消息。 + */ + scancode_push, + /** + * 扫码推事件且弹出“消息接收中”提示框用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后,将扫码的结果传给开发者,同时收起扫一扫工具, + * 然后弹出“消息接收中”提示框,随后可能会收到开发者下发的消息。 + */ + scancode_waitmsg, + /** + * 弹出系统拍照发图用户点击按钮后,微信客户端将调起系统相机,完成拍照操作后,会将拍摄的相片发送给开发者,并推送事件给开发者,同时收起系统相机, + * 随后可能会收到开发者下发的消息。 + */ + pic_sysphoto, + /** + * 弹出拍照或者相册发图用户点击按钮后,微信客户端将弹出选择器供用户选择“拍照”或者“从手机相册选择”。用户选择后即走其他两种流程。 + */ + pic_photo_or_albu, + /** + * 弹出微信相册发图器用户点击按钮后,微信客户端将调起微信相册,完成选择操作后,将选择的相片发送给开发者的服务器,并推送事件给开发者,同时收起相册, + * 随后可能会收到开发者下发的消息。 + */ + pic_weixin, + /** + * 弹出地理位置选择器用户点击按钮后,微信客户端将调起地理位置选择工具,完成选择操作后,将选择的地理位置发送给开发者的服务器,同时收起位置选择工具, + * 随后可能会收到开发者下发的消息。 + */ + location_select; +} diff --git a/src/main/java/com/foxinmy/weixin4j/type/EventType.java b/src/main/java/com/foxinmy/weixin4j/type/EventType.java index a8e864b8..bc85ce90 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/EventType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/EventType.java @@ -3,21 +3,36 @@ package com.foxinmy.weixin4j.type; import com.foxinmy.weixin4j.msg.event.EventMessage; import com.foxinmy.weixin4j.msg.event.LocationEventMessage; import com.foxinmy.weixin4j.msg.event.MassEventMessage; -import com.foxinmy.weixin4j.msg.event.MenuEventMessage; import com.foxinmy.weixin4j.msg.event.ScanEventMessage; import com.foxinmy.weixin4j.msg.event.ScribeEventMessage; +import com.foxinmy.weixin4j.msg.event.TemplatesendjobfinishMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuLocationEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuPhotoEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuScanEventMessage; /** - * * 事件类型 - * @author jy.hu - * + * + * @className EventType + * @author jy + * @date 2014年9月30日 + * @since JDK 1.7 + * @see */ public enum EventType { - subscribe(ScribeEventMessage.class), unsubscribe(ScribeEventMessage.class), - scan(ScanEventMessage.class),click(MenuEventMessage.class),view(MenuEventMessage.class), - location(LocationEventMessage.class),MASSSENDJOBFINISH(MassEventMessage.class); - + subscribe(ScribeEventMessage.class), unsubscribe(ScribeEventMessage.class), scan( + ScanEventMessage.class), scancode_push(MenuScanEventMessage.class), view( + MenuEventMessage.class), scancode_waitmsg( + MenuScanEventMessage.class), pic_sysphoto( + MenuPhotoEventMessage.class), pic_photo_or_album( + MenuPhotoEventMessage.class), pic_weixin( + MenuPhotoEventMessage.class), location_select( + MenuLocationEventMessage.class), click(MenuEventMessage.class), location( + LocationEventMessage.class), massendjobfinish( + MassEventMessage.class), templatesendjobfinish( + TemplatesendjobfinishMessage.class); + private Class extends EventMessage> eventClass; EventType(Class extends EventMessage> eventClass) { diff --git a/src/main/java/com/foxinmy/weixin4j/type/MediaType.java b/src/main/java/com/foxinmy/weixin4j/type/MediaType.java index 1f567181..322ba3ce 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/MediaType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/MediaType.java @@ -6,13 +6,20 @@ package com.foxinmy.weixin4j.type; * 语音(voice):256K,播放长度不超过60s,支持AMR\MP3格式 * 视频(video):1MB,支持MP4格式 * 缩略图(thumb):64KB,支持JPG格式 - * 媒体文件在后台保存时间为3天,即3天后media_id失效 + * + * 媒体文件在后台保存时间为3天,即3天后media_id失效 + * + * * @author jy.hu * @date 2014年4月2日 * @since JDK 1.7 */ public enum MediaType { - image("image/jpeg",".jpg"), voice("binary/octet-stream","amr"), vedio("binary/octet-stream","mp4"), thumb("image/jpeg","jpg"); + image("image/jpeg", "jpg"), voice("binary/octet-stream", "amr"), vedio( + "binary/octet-stream", "mp4"), thumb("image/jpeg", "jpg"), text( + "application/json", ""), music("binary/octet-stream", "mp3"), news( + "application/json", ""), mpnews("application/json", ""), mpvideo( + "binary/octet-stream", ""); MediaType(String contentType, String formatType) { this.contentType = contentType; @@ -26,6 +33,7 @@ public enum MediaType { } private String formatType; + public String getFormatType() { return formatType; } diff --git a/src/main/java/com/foxinmy/weixin4j/type/MessageType.java b/src/main/java/com/foxinmy/weixin4j/type/MessageType.java index 21a7b6dc..a883d993 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/MessageType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/MessageType.java @@ -10,6 +10,7 @@ import com.foxinmy.weixin4j.msg.in.VideoMessage; import com.foxinmy.weixin4j.msg.in.VoiceMessage; import com.foxinmy.weixin4j.msg.out.ArticleMessage; import com.foxinmy.weixin4j.msg.out.MusicMessage; +import com.foxinmy.weixin4j.msg.out.TransferMessage; /** * @@ -20,9 +21,13 @@ import com.foxinmy.weixin4j.msg.out.MusicMessage; */ public enum MessageType { // 接收到的消息类型 - text(TextMessage.class), image(ImageMessage.class), voice(VoiceMessage.class), video(VideoMessage.class), location(LocationMessage.class), link(LinkMessage.class), event(EventMessage.class), + text(TextMessage.class), image(ImageMessage.class), voice( + VoiceMessage.class), video(VideoMessage.class), location( + LocationMessage.class), link(LinkMessage.class), event( + EventMessage.class), // 发送的消息类型 - music(MusicMessage.class), news(ArticleMessage.class); + music(MusicMessage.class), news(ArticleMessage.class), transfer_customer_service( + TransferMessage.class); private Class extends BaseMessage> messageClass; MessageType(Class extends BaseMessage> messageClass) { diff --git a/src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java b/src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java similarity index 91% rename from src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java rename to src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java index f428c33b..b419bd1c 100644 --- a/src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java +++ b/src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java @@ -8,8 +8,8 @@ import java.util.regex.Pattern; import com.foxinmy.weixin4j.WeixinProxy; -public class WeixinConfig { - public WeixinConfig() { +public class ConfigUtil { + public ConfigUtil() { } private static Properties props = new Properties(); @@ -38,7 +38,6 @@ public class WeixinConfig { m.appendTail(sb); return sb.toString(); } - public static void main(String[] args) { System.out.println(getValue("api_token_uri")); } diff --git a/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java b/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java new file mode 100644 index 00000000..60eae107 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java @@ -0,0 +1,67 @@ +package com.foxinmy.weixin4j.util; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.Writer; +import java.nio.charset.Charset; + +/** + * IOUtil + * + * @className IOUtil + * @author jy.hu + * @date 2014年9月22日 + * @since JDK 1.7 + * @see org.apache.commons.io.IOUtils + */ +public class IOUtil { + + private static final int EOF = -1; + private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; + + public static byte[] toByteArray(Reader input) throws IOException { + return toByteArray(input, Charset.defaultCharset()); + } + + public static byte[] toByteArray(Reader input, Charset encoding) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + copy(input, output, encoding); + return output.toByteArray(); + } + + public static void copy(Reader input, OutputStream output, Charset encoding) throws IOException { + OutputStreamWriter out = new OutputStreamWriter(output, encoding); + copyLarge(input, out, new char[DEFAULT_BUFFER_SIZE]); + out.flush(); + } + + public static byte[] toByteArray(InputStream input) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + copyLarge(input, output, new byte[DEFAULT_BUFFER_SIZE]); + return output.toByteArray(); + } + + private static long copyLarge(InputStream input, OutputStream output, byte[] buffer) throws IOException { + long count = 0; + int n = 0; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } + + private static long copyLarge(Reader input, Writer output, char[] buffer) throws IOException { + long count = 0; + int n = 0; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java b/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java new file mode 100644 index 00000000..82a23ef3 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java @@ -0,0 +1,135 @@ +package com.foxinmy.weixin4j.util; + +import java.io.InputStream; +import java.util.Arrays; + +import org.apache.commons.codec.digest.DigestUtils; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.DocumentHelper; +import org.dom4j.io.SAXReader; +import org.jsoup.helper.StringUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.type.EventType; +import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; + +public class MessageUtil { + + private final static Logger log = LoggerFactory.getLogger(MessageUtil.class); + + /** + * 验证微信签名 + * + * @param echostr + * 随机字符串 + * @param timestamp + * 时间戳 + * @param nonce + * 随机数 + * @param signature + * 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数 + * @return 开发者通过检验signature对请求进行相关校验。若确认此次GET请求来自微信服务器 + * 请原样返回echostr参数内容,则接入生效 成为开发者成功,否则接入失败 + * @see 接入指南 + */ + public static String signature(String echostr, String timestamp, String nonce, String signature) { + String app_token = ConfigUtil.getValue("app_token"); + if (StringUtil.isBlank(app_token)) { + log.error("signature fail : token is null!"); + return null; + } + if (StringUtil.isBlank(echostr) || StringUtil.isBlank(timestamp) || StringUtil.isBlank(nonce)) { + log.error("signature fail : invalid parameter!"); + return null; + } + String _signature = null; + try { + String[] a = { app_token, timestamp, nonce }; + Arrays.sort(a); + StringBuilder sb = new StringBuilder(3); + for (String str : a) { + sb.append(str); + } + _signature = DigestUtils.sha1Hex(sb.toString()); + } catch (Exception e) { + log.error("signature error", e); + } + if (signature.equals(_signature)) { + return echostr; + } else { + log.error("signature fail : invalid signature!"); + return null; + } + } + + /** + * xml消息转换为消息对象 + * + * 微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次 + * + * + * @param xml + * 消息字符串 + * @return 消息对象 + * @throws DocumentException + * @see 验证消息的合法性 + * @see 普通消息 + * @see 事件触发 + * @see com.foxinmy.weixin4j.type.MessageType + * @see com.feican.weixin.msg.BaeMessage + * @see com.foxinmy.weixin4j.msg.TextMessage + * @see com.foxinmy.weixin4j.msg.in.ImageMessage + * @see com.foxinmy.weixin4j.msg.in.VoiceMessage + * @see com.foxinmy.weixin4j.msg.in.VideoMessage + * @see com.foxinmy.weixin4j.msg.in.LocationMessage + * @see com.foxinmy.weixin4j.msg.in.LinkMessage + * @see com.foxinmy.weixin4j.msg.event.ScribeEventMessage + * @see com.foxinmy.weixin4j.msg.event.ScanEventMessage + * @see com.foxinmy.weixin4j.msg.event.LocationEventMessage + * @see com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage + */ + public static BaseMessage xml2msg(String xml) throws DocumentException { + if (StringUtil.isBlank(xml)) + return null; + Document doc = DocumentHelper.parseText(xml); + String type = doc.selectSingleNode("/xml/MsgType").getStringValue(); + if (StringUtil.isBlank(type)) { + return null; + } + XStream xstream = new XStream(); + MessageType messageType = MessageType.valueOf(type.toLowerCase()); + Class extends BaseMessage> messageClass = messageType.getMessageClass(); + if (messageType == MessageType.event) { + type = doc.selectSingleNode("/xml/Event").getStringValue(); + messageClass = EventType.valueOf(type.toLowerCase()).getEventClass(); + } + xstream.alias("xml", messageClass); + xstream.ignoreUnknownElements(); + xstream.autodetectAnnotations(true); + xstream.processAnnotations(messageClass); + return xstream.fromXML(doc.asXML(), messageClass); + } + + /** + * xml消息转换为消息对象 + * + * @param inputStream + * 带消息字符串的输入流 + * @return 消息对象 + * @throws DocumentException + * @see {@link com.foxinmy.weixin4j.WeixinProxy#xml2msg(String)} + */ + public static BaseMessage xml2msg(InputStream inputStream) throws DocumentException { + SAXReader reader = new SAXReader(); + Document doc = reader.read(inputStream); + return xml2msg(doc.asXML()); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java b/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java deleted file mode 100644 index 19fd87e4..00000000 --- a/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.foxinmy.weixin4j.util; - -public class WeixinUtil { - - public static boolean isBlank(String str) { - return str == null || str.isEmpty(); - } -} diff --git a/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java b/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java index 5c0186c6..4a811a6c 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java @@ -9,7 +9,7 @@ import org.junit.Test; import com.foxinmy.weixin4j.WeixinProxy; import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.model.Button; -import com.foxinmy.weixin4j.model.Button.BtnType; +import com.foxinmy.weixin4j.type.ButtonType; /** * 自定义菜单测试 @@ -31,7 +31,7 @@ public class ButtonTest { List btnList = new ArrayList(); Button b = new Button("test"); - b.setType(BtnType.click); + b.setType(ButtonType.click); b.setKey("123"); btnList.add(b); diff --git a/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java b/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java index 8b78305e..bb6bec88 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java @@ -50,7 +50,7 @@ public class GroupTest { @Test public void getid() { try { - System.out.println(weixinProxy.findGroupByOpenId("owGBft_vbBbOaQOmpEUE4xDLeRSU")); + System.out.println(weixinProxy.getGroupByOpenId("owGBft_vbBbOaQOmpEUE4xDLeRSU")); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); diff --git a/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java b/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java new file mode 100644 index 00000000..6d34a733 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java @@ -0,0 +1,22 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Test; + +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.http.HttpRequest; + +public class HttpTest { + private static HttpRequest request; + static { + request = new HttpRequest(); + } + + @Test + public void test(){ + try { + System.out.println(request.get("http://www.baidu.com")); + } catch (WeixinException e) { + e.printStackTrace(); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java b/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java index f907fa3d..d54e649b 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java @@ -31,7 +31,7 @@ public class MediaTest { File file = new File("D:\\test.jpg"); try { System.out.println(weixinProxy.uploadMedia(file, MediaType.image)); - //usAxLEJxFXAjXVlLu_BSw0GvS2YEEoGeelRBybNZBGvMsdxiIcD1F9yBWYd9jVZx + //vvU_AUtovWyfAxQ8J1DsCoNMtK6U_bUmTpe6lpINUOVRLvt_7rtO4zxzBpPgkmay } catch (WeixinException e) { System.out.println(e.getErrorMsg()); } @@ -40,7 +40,7 @@ public class MediaTest { @Test public void download() { try { - System.out.println(weixinProxy.downloadMedia("usAxLEJxFXAjXVlLu_BSw0GvS2YEEoGeelRBybNZBGvMsdxiIcD1F9yBWYd9jVZx", MediaType.image)); + System.out.println(weixinProxy.downloadMedia("vvU_AUtovWyfAxQ8J1DsCoNMtK6U_bUmTpe6lpINUOVRLvt_7rtO4zxzBpPgkmay", MediaType.image)); } catch (WeixinException e) { System.out.println(e.getErrorMsg()); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java new file mode 100644 index 00000000..2cd36584 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java @@ -0,0 +1,194 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Test; + +import com.foxinmy.weixin4j.util.MessageUtil; + +/** + * 接收事件消息格式测试 + * + * @author jy.hu + * @date 2014年3月24日 + * @since JDK 1.7 + */ +public class MessageEventInTest { + + private StringBuilder xmlSb = new StringBuilder(); + + /***************** event message *********************/ + @Test + public void scribe() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void scan() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void scan_scribe() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void location1() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("23.137466"); + xmlSb.append("113.352425"); + xmlSb.append("119.385040"); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_click() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_link() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_scan() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_photo() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("1"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_location() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java index 39269754..fdd40042 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java @@ -1,134 +1,19 @@ package com.foxinmy.weixin4j.test; -import org.junit.Before; import org.junit.Test; -import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.util.MessageUtil; /** - * 接收消息格式测试 + * 接受一般消息格式测试 + * * @author jy.hu * @date 2014年3月24日 * @since JDK 1.7 */ public class MessageInTest { + private StringBuilder xmlSb = new StringBuilder(); - private WeixinProxy weixinProxy; - - @Before - public void init(){ - weixinProxy = new WeixinProxy(); - } - - /***************** event message *********************/ - @Test - public void scribe() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void scan() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - @Test - public void scan_scribe() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void location1() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("23.137466"); - xmlSb.append("113.352425"); - xmlSb.append("119.385040"); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void menu_click() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void menu_link() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } /***************** common message *********************/ @@ -144,7 +29,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -163,7 +48,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -182,7 +67,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -202,7 +87,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -221,7 +106,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -242,7 +127,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -262,7 +147,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java new file mode 100644 index 00000000..8f6a130f --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java @@ -0,0 +1,114 @@ +package com.foxinmy.weixin4j.test; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.model.MpArticle; +import com.foxinmy.weixin4j.type.MediaType; + +/** + * 群发消息 + * + * @className MpNewsTest + * @author jy + * @date 2014年4月27日 + * @since JDK 1.7 + * @see + */ +public class MessageMassTest { + private WeixinProxy weixinProxy; + + @Before + public void init() { + this.weixinProxy = new WeixinProxy(); + } + + @Test + public void uploadArticle() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.uploadArticle(articles); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void uploadVideo() { + try { + weixinProxy.uploadVideo("mediaId", "title", "desc"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massByGroup() { + try { + weixinProxy.massByGroup("123", MediaType.image, "groupId"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massByOpenIds() { + try { + weixinProxy.massByOpenIds("123", MediaType.image, "openIds"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massArticleByGroup() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.massArticleByGroup(articles, "0"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massArticleByOpenIds() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.massArticleByOpenIds(articles, + "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void deleteMass() { + try { + weixinProxy.deleteMassNews("34182"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java index f3be10bb..59aed8de 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java @@ -7,6 +7,7 @@ import org.junit.Test; import com.foxinmy.weixin4j.WeixinProxy; import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.msg.model.Music; import com.foxinmy.weixin4j.msg.notify.ArticleNotify; import com.foxinmy.weixin4j.msg.notify.BaseNotify; import com.foxinmy.weixin4j.msg.notify.ImageNotify; @@ -41,27 +42,29 @@ public class MessageNotifyTest { @Test public void image() { - ImageNotify notify = new ImageNotify("123", "to"); + ImageNotify notify = new ImageNotify("to"); + notify.pushMediaId("123"); System.out.println(notify.toJson()); } @Test public void voice() { - VoiceNotify notify = new VoiceNotify("123", "to"); + VoiceNotify notify = new VoiceNotify("to"); + notify.pushMediaId("123"); System.out.println(notify.toJson()); } @Test public void video() { VideoNotify notify = new VideoNotify("to"); - notify.pushVideo("123", "title", "desc"); + notify.pushVideo("123","m123"); System.out.println(notify.toJson()); } @Test public void music() { MusicNotify notify = new MusicNotify("to"); - notify.pushMusic("title", "desc", "url", "hqUrl", "mediaId"); + notify.pushMusic("url", "hqUrl", "mediaId"); System.out.println(notify.toJson()); } @@ -74,16 +77,27 @@ public class MessageNotifyTest { } @Test - public void send() { - BaseNotify t = new TextNotify("哈哈哈哈", "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + public void send1() { + BaseNotify notify = new TextNotify("哈哈哈哈", "owGBft_vbBbOaQOmpEUE4xDLeRSU"); try { - weixinProxy.sendNotify(t); + weixinProxy.sendNotify(notify); String mediaId = weixinProxy.uploadMedia(new File("D:\\test.jpg"), MediaType.image); - t = new ImageNotify(mediaId, "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + ImageNotify t = new ImageNotify("owGBft_vbBbOaQOmpEUE4xDLeRSU"); + t.pushMediaId(mediaId); weixinProxy.sendNotify(t); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); } } + + @Test + public void send2() { + try { + weixinProxy.sendNotify("to",new Music("thumbMediaId")); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java index 00021aa0..ddb309d4 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java @@ -1,7 +1,9 @@ package com.foxinmy.weixin4j.test; +import org.junit.Before; import org.junit.Test; +import com.foxinmy.weixin4j.msg.BaseMessage; import com.foxinmy.weixin4j.msg.TextMessage; import com.foxinmy.weixin4j.msg.out.ArticleMessage; import com.foxinmy.weixin4j.msg.out.ImageMessage; @@ -17,56 +19,52 @@ import com.foxinmy.weixin4j.msg.out.VoiceMessage; * @since JDK 1.7 */ public class MessageOutTest { + private BaseMessage inMessage; + + @Before + public void init() { + this.inMessage = new TextMessage(); + this.inMessage.setFromUserName("fromusername"); + this.inMessage.setToUserName("tousername"); + } + @Test public void text() { - TextMessage message = new TextMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.setContent("text message"); + TextMessage message = new TextMessage("text", inMessage); System.out.println(message.toXml()); } @Test public void image() { - ImageMessage message = new ImageMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + ImageMessage message = new ImageMessage(inMessage); message.pushMediaId("mediaId"); System.out.println(message.toXml()); } @Test public void voice() { - VoiceMessage message = new VoiceMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + VoiceMessage message = new VoiceMessage(inMessage); message.pushMediaId("mediaId"); System.out.println(message.toXml()); } - + @Test public void video() { - VideoMessage message = new VideoMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.pushVideo("mediaId", "title", "title"); + VideoMessage message = new VideoMessage(inMessage); + message.pushVideo("mediaId"); System.out.println(message.toXml()); } - + @Test public void music() { - MusicMessage message = new MusicMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.pushMusic("title", "desc", "url", "hqurl", "mediaId"); + MusicMessage message = new MusicMessage(inMessage); + message.pushMusic("mediaId"); System.out.println(message.toXml()); } - + @Test public void article() { - ArticleMessage message = new ArticleMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + ArticleMessage message = new ArticleMessage(inMessage); message.pushArticle("title1", "desc1", "picUrl1", "url1"); message.pushArticle("title2", "desc2", "picUrl2", "url2"); System.out.println(message.toXml()); diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java new file mode 100644 index 00000000..b8165a91 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java @@ -0,0 +1,30 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Before; +import org.junit.Test; + +import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.msg.out.TemplateMessage; + +public class MessageTemplTest { + private WeixinProxy weixinProxy; + + @Before + public void init() { + this.weixinProxy = new WeixinProxy(); + } + + @Test + public void test() { + TemplateMessage tplMessage = new TemplateMessage("touser", + "template_id", "url"); + tplMessage.pushData("name", "fox"); + System.out.print(tplMessage.toJson()); + try { + System.out.print(weixinProxy.sendTplMessage(tplMessage)); + } catch (WeixinException e) { + System.out.println(e.getErrorMsg()); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java b/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java deleted file mode 100644 index 5fa1ec67..00000000 --- a/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.foxinmy.weixin4j.test; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; - -import com.foxinmy.weixin4j.WeixinProxy; -import com.foxinmy.weixin4j.exception.WeixinException; -import com.foxinmy.weixin4j.model.MpArticle; -import com.foxinmy.weixin4j.type.MediaType; - -/** - * 群发消息 - * - * @className MpNewsTest - * @author jy - * @date 2014年4月27日 - * @since JDK 1.7 - * @see - */ -public class MpNewsTest { - private WeixinProxy weixinProxy; - - @Before - public void init() { - this.weixinProxy = new WeixinProxy(); - } - - @Test - public void massByGroup(){ - List articles = new ArrayList(); - try { - String thumbMediaId = weixinProxy.uploadMedia(new File("/tmp/test.jpg"), MediaType.image); - articles.add(new MpArticle(thumbMediaId, "title", "content")); - weixinProxy.massNewsByGroup(articles, "0"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } - - @Test - public void massByOpenIds(){ - List articles = new ArrayList(); - try { - String thumbMediaId = weixinProxy.uploadMedia(new File("/tmp/test.jpg"), MediaType.image); - articles.add(new MpArticle(thumbMediaId, "title", "content")); - weixinProxy.massNewsByOpenIds(articles, "owGBft_vbBbOaQOmpEUE4xDLeRSU"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } - - @Test - public void deleteMass(){ - try { - weixinProxy.deleteMassNews("34182"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } -} diff --git a/src/test/java/com/foxinmy/weixin4j/test/QRTest.java b/src/test/java/com/foxinmy/weixin4j/test/QRTest.java index 11934fa9..f18d1aa7 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/QRTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/QRTest.java @@ -25,10 +25,10 @@ public class QRTest { @Test public void temp_qr() { - QRParameter qr = new QRParameter(1200, QRType.QR_SCENE, 1); + QRParameter qr = new QRParameter(1200, QRType.TEMPORARY, 2); try { System.out.println(qr.toJson()); - weixinProxy.getQR(qr); + System.out.println(weixinProxy.getQR(qr)); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); @@ -37,10 +37,10 @@ public class QRTest { @Test public void forever_qr() { - QRParameter qr = new QRParameter(QRType.QR_LIMIT_SCENE, 1); + QRParameter qr = new QRParameter(QRType.PERMANENCE, 1); try { System.out.println(qr.toJson()); - weixinProxy.getQR(qr); + System.out.println(weixinProxy.getQR(qr)); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java b/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java index 37d549d7..a2f8a266 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java @@ -3,7 +3,8 @@ package com.foxinmy.weixin4j.test; import org.junit.Before; import org.junit.Test; -import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.api.token.FileTokenApi; +import com.foxinmy.weixin4j.api.token.TokenApi; import com.foxinmy.weixin4j.exception.WeixinException; /** @@ -14,17 +15,17 @@ import com.foxinmy.weixin4j.exception.WeixinException; * @since JDK 1.7 */ public class TokenTest { - private WeixinProxy weixinProxy; + private TokenApi tokenApi; @Before public void init() { - weixinProxy = new WeixinProxy(); + tokenApi = new FileTokenApi(); } @Test public void getToken() { try { - System.out.println(weixinProxy.getToken()); + System.out.println(tokenApi.getToken()); } catch (WeixinException e) { e.printStackTrace(); }
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 查询客服聊天记录 + */ + public List 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); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/api/QrApi.java b/src/main/java/com/foxinmy/weixin4j/api/QrApi.java new file mode 100644 index 00000000..d006b3dc --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/api/QrApi.java @@ -0,0 +1,115 @@ +package com.foxinmy.weixin4j.api; + +import java.io.File; +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 二维码支持 + */ +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); + } + + /** + * 生成带参数的二维码 + * + * 二维码分为临时跟永久两种,扫描时触发推送带参数事件 + * + * + * @param parameter + * 二维码参数 + * @return 硬盘存储的文件对象 + * @throws WeixinException + * @see 二维码 + * @see com.foxinmy.weixin4j.model.QRParameter + */ + public File getQR(QRParameter parameter) throws WeixinException { + 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; + } + FileOutputStream out = null; + try { + try { + file.createNewFile(); + } catch (IOException e) { + file.getParentFile().mkdirs(); + file.createNewFile(); + } + out = new FileOutputStream(file); + byte[] b = getQRData(parameter); + out.write(b); + } catch (IOException e) { + ; + } finally { + try { + if (out != null) { + out.close(); + } + } catch (IOException e) { + ; + } + } + return file; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/api/TemplApi.java b/src/main/java/com/foxinmy/weixin4j/api/TemplApi.java new file mode 100644 index 00000000..4cb4e922 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/api/TemplApi.java @@ -0,0 +1,49 @@ +package com.foxinmy.weixin4j.api; + +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.msg.BaseResult; +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 TemplApi extends BaseApi { + + private final TokenApi tokenApi; + + public TemplApi(TokenApi tokenApi) { + this.tokenApi = tokenApi; + } + + /** + * 发送模板消息 + * + * @param message + * @return 发送结果 + * @throws WeixinException + * @see 模板消息 + * @see com.foxinmy.weixin4j.msg.out.TemplateMessage + * @seee com.foxinmy.weixin4j.msg.event.TemplatesendjobfinishMessage + */ + public BaseResult sendTplMessage(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(); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/api/UserApi.java b/src/main/java/com/foxinmy/weixin4j/api/UserApi.java new file mode 100644 index 00000000..8ce55535 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/api/UserApi.java @@ -0,0 +1,182 @@ +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.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.msg.BaseResult; +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 获取用户token + * @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 拉取用户信息 + * @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); + } + + /** + * 获取用户信息 + * + * 在关注者与公众号产生消息交互后,公众号可获得关注者的OpenID(加密后的微信号,每个用户对每个公众号的OpenID是唯一的,对于不同公众号, + * 同一用户的openid不同),公众号可通过本接口来根据OpenID获取用户基本信息,包括昵称、头像、性别、所在城市、语言和关注时间 + * + * + * @param openId + * 用户对应的ID + * @return 用户对象 + * @throws WeixinException + * @see 获取用户信息 + * @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 获取关注者列表 + * @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 openIds = JSON.parseArray(following.getDataJson() + .getString("openid"), String.class); + List userList = new ArrayList(); + for (String openId : openIds) { + userList.add(getUser(openId)); + } + following.setUserList(userList); + } + return following; + } + + /** + * 获取用户全部的关注者列表 + * + * 当公众号关注者数量超过10000时,可通过填写next_openid的值,从而多次拉取列表的方式来满足需求, + * 将上一次调用得到的返回中的next_openid值,作为下一次调用中的next_openid值 + * + * + * @return 用户对象集合 + * @throws WeixinException + * @see 获取关注者列表 + * @see com.foxinmy.weixin4j.model.Following + * @see com.foxinmy.weixin4j.api.UserApi#getFollowing(String) + */ + public List getAllFollowing() throws WeixinException { + List userList = new ArrayList(); + 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 设置用户备注名 + */ + public BaseResult updateUserRemark(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(); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/api/token/FileTokenApi.java b/src/main/java/com/foxinmy/weixin4j/api/token/FileTokenApi.java new file mode 100644 index 00000000..ac8a5a1e --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/api/token/FileTokenApi.java @@ -0,0 +1,95 @@ +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 获取token说明 + * @see com.foxinmy.weixin4j.model.Token + */ +public class FileTokenApi implements TokenApi { + + private final HttpRequest request = new HttpRequest(); + + private final String appid; + private final String appsecret; + public FileTokenApi() { + this(ConfigUtil.getValue("app_id"), ConfigUtil.getValue("app_secret")); + } + + public FileTokenApi(String appid, String appsecret) { + this.appid = appid; + this.appsecret = appsecret; + } + + /** + * 获取token + * + * 正常情况下返回{"access_token":"ACCESS_TOKEN","expires_in":7200},否则抛出异常. + * + * + * @return token对象 + * @throws WeixinException + * @see 获取token说明 + * @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; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/api/token/RedisTokenApi.java b/src/main/java/com/foxinmy/weixin4j/api/token/RedisTokenApi.java new file mode 100644 index 00000000..dfc0079d --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/api/token/RedisTokenApi.java @@ -0,0 +1,82 @@ +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 获取token说明 + * @see com.foxinmy.weixin4j.model.Token + */ +public class RedisTokenApi implements TokenApi { + + private final HttpRequest request = new HttpRequest(); + + private final String appid; + private final String appsecret; + private JedisPool jedisPool; + + public RedisTokenApi() { + this(ConfigUtil.getValue("app_id"), ConfigUtil.getValue("app_secret")); + } + + 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; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/api/token/TokenApi.java b/src/main/java/com/foxinmy/weixin4j/api/token/TokenApi.java new file mode 100644 index 00000000..c2c3c351 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/api/token/TokenApi.java @@ -0,0 +1,19 @@ +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.FileTokenApi + * @see com.foxinmy.weixin4j.api.token.RedisTokenApi + */ +public interface TokenApi { + public Token getToken() throws WeixinException; +} diff --git a/src/main/java/com/foxinmy/weixin4j/config.properties b/src/main/java/com/foxinmy/weixin4j/config.properties index 938b23e5..f0f037a2 100644 --- a/src/main/java/com/foxinmy/weixin4j/config.properties +++ b/src/main/java/com/foxinmy/weixin4j/config.properties @@ -15,6 +15,7 @@ api_base_url=https://api.weixin.qq.com/cgi-bin mp_base_url=https://mp.weixin.qq.com/cgi-bin file_base_url=http://file.api.weixin.qq.com/cgi-bin + # \u7f51\u9875\u6388\u6743\u83b7\u53d6\u7528\u6237\u4fe1\u606f user_auth_uri=https://open.weixin.qq.com/connect/oauth2/authorize?appid={app_id}&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect sns_user_token_uri=https://api.weixin.qq.com/sns/oauth2/access_token?appid={app_id}&secret={app_secret}&code=%s&grant_type=authorization_code @@ -23,7 +24,7 @@ sns_user_info_uri=https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid= # \u76f4\u63a5\u83b7\u53d6\u7528\u6237\u4fe1\u606f api_user_info_uri={api_base_url}/user/info?access_token=%s&openid=%s&lang=zh_CN # \u83b7\u53d6\u6211\u7684token -api_token_uri={api_base_url}/token?grant_type=client_credential&appid={app_id}&secret={app_secret} +api_token_uri={api_base_url}/token?grant_type=client_credential&appid=%s&secret=%s # \u83b7\u53d6\u4e8c\u7ef4\u7801 qr_ticket_uri={api_base_url}/qrcode/create?access_token=%s @@ -53,14 +54,25 @@ menu_create_uri={api_base_url}/menu/create?access_token=%s menu_get_uri={api_base_url}/menu/get?access_token=%s # \u5220\u9664\u83dc\u5355 menu_delete_uri={api_base_url}/menu/delete?access_token=%s -# \u4e0a\u4f20\u6d88\u606f -news_upload_uri={api_base_url}/media/uploadnews?access_token=%s +# \u4e0a\u4f20\u56fe\u6587 +article_upload_uri={api_base_url}/media/uploadnews?access_token=%s +# \u4e0a\u4f20\u89c6\u9891 +video_upload_uri={file_base_url}/media/uploadvideo?access_token=%s # \u5206\u7ec4\u7fa4\u53d1 mass_group_uri={api_base_url}/message/mass/sendall?access_token=%s # openId\u7fa4\u53d1 mass_openid_uri={api_base_url}/message/mass/send?access_token=%s # \u5220\u9664\u7fa4\u53d1 mass_delete_uri={api_base_url}/message/mass/delete?access_token=%s +# \u5ba2\u670d\u804a\u5929\u8bb0\u5f55 +custom_record_uri={api_base_url}/customservice/getrecord?access_token=%s +# \u957f\u94fe\u63a5\u8f6c\u77ed\u94fe\u63a5 +shorturl_uri={api_base_url}/shorturl?access_token=%s +# \u8bbe\u7f6e\u5907\u6ce8\u540d +updateremark_uri={api_base_url}/user/info/updateremark?access_token=%s +# \u6a21\u677f\u6d88\u606f +template_send_uri={api_base_url}/message/template/send?access_token=%s + # token\u5b58\u653e\u8def\u5f84 token_path=/tmp/weixin/token diff --git a/src/main/java/com/foxinmy/weixin4j/http/HttpRequest.java b/src/main/java/com/foxinmy/weixin4j/http/HttpRequest.java index 4559afd1..9ecee3e8 100644 --- a/src/main/java/com/foxinmy/weixin4j/http/HttpRequest.java +++ b/src/main/java/com/foxinmy/weixin4j/http/HttpRequest.java @@ -1,53 +1,76 @@ package com.foxinmy.weixin4j.http; -import java.io.IOException; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.util.ArrayList; +import java.util.List; -import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler; -import org.apache.commons.httpclient.Header; -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.HttpStatus; -import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; -import org.apache.commons.httpclient.cookie.CookiePolicy; -import org.apache.commons.httpclient.methods.GetMethod; -import org.apache.commons.httpclient.methods.PostMethod; -import org.apache.commons.httpclient.methods.RequestEntity; -import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity; -import org.apache.commons.httpclient.methods.multipart.Part; -import org.apache.commons.httpclient.params.HttpClientParams; -import org.apache.commons.httpclient.params.HttpConnectionManagerParams; -import org.apache.commons.httpclient.params.HttpMethodParams; +import 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.alibaba.fastjson.JSONObject; import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.msg.BaseResult; +/** + * 调用微信相关接口的HttpRequest,对于其他请求可能并不试用 + * + * @className HttpRequest + * @author jy + * @date 2014年8月21日 + * @since JDK 1.7 + * @see + */ public class HttpRequest { - private final String CONTENT_CHARSET = "UTF-8"; - private final String ERROR_CODE_KEY = "errcode"; - private final String ERROR_MSG_KEY = "errmsg"; - private HttpClient client; + private AbstractHttpClient client; public HttpRequest() { - this(150, 30000, 30000, 1024 * 1024); + this(150, 100, 10000, 10000); } - public HttpRequest(int maxConPerHost, int conTimeOutMs, int soTimeOutMs, int maxSize) { - MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager(); - connectionManager = new MultiThreadedHttpConnectionManager(); - HttpConnectionManagerParams params = connectionManager.getParams(); - params.setDefaultMaxConnectionsPerHost(maxConPerHost); - params.setConnectionTimeout(conTimeOutMs); - params.setSoTimeout(soTimeOutMs); + public HttpRequest(int maxConPerRoute, int maxTotal, int socketTimeout, int connectionTimeout) { + PoolingClientConnectionManager connectionManager = new PoolingClientConnectionManager(); + // 指定IP并发最大数 + connectionManager.setDefaultMaxPerRoute(maxConPerRoute); + // socket最大创建数 + connectionManager.setMaxTotal(maxTotal); - HttpClientParams clientParams = new HttpClientParams(); - clientParams.setCookiePolicy(CookiePolicy.IGNORE_COOKIES); - client = new HttpClient(clientParams, connectionManager); - client.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, CONTENT_CHARSET); + 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 { - Parameter[] empty = null; - return get(url, empty); + return get(url, (Parameter[]) null); } public Response get(String url, Parameter... parameters) throws WeixinException { @@ -60,70 +83,87 @@ public class HttpRequest { sb.append(parameters[i].toGetPara()); } } - return doRequest(new GetMethod(sb.toString())); + return doRequest(new HttpGet(sb.toString())); } public Response post(String url) throws WeixinException { - Parameter[] empty = null; - return post(url, empty); + return post(url, (Parameter[]) null); } public Response post(String url, Parameter... parameters) throws WeixinException { - PostMethod method = new PostMethod(url); + HttpPost method = new HttpPost(url); + List params = new ArrayList(); for (Parameter parameter : parameters) { - method.addParameter(parameter.toPostPara()); + 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); } - public Response post(String url, RequestEntity entity) throws WeixinException { - PostMethod method = new PostMethod(url); - method.setRequestEntity(entity); - return doRequest(method); - } - - public Response post(String url, Part... parts) throws WeixinException { - PostMethod method = new PostMethod(url); - method.getParams().setContentCharset(CONTENT_CHARSET); - MultipartRequestEntity entity = new MultipartRequestEntity(parts, method.getParams()); - method.setRequestEntity(entity); - return doRequest(method); - } - - protected Response doRequest(HttpMethod method) throws WeixinException { - + protected Response doRequest(HttpRequestBase request) throws WeixinException { try { + HttpResponse httpResponse = client.execute(request); + StatusLine statusLine = httpResponse.getStatusLine(); + HttpEntity httpEntity = httpResponse.getEntity(); - method.getParams().setContentCharset(CONTENT_CHARSET); - method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler(3, false)); - int status = client.executeMethod(method); + int status = statusLine.getStatusCode(); if (status != HttpStatus.SC_OK) { throw new WeixinException(status, "request fail"); } - // HttpClient对于要求接受后继服务的请求,象POST和PUT等不能自动处理转发 // 301或者302 if (status == HttpStatus.SC_MOVED_PERMANENTLY || status == HttpStatus.SC_MOVED_TEMPORARILY) { - throw new WeixinException(status, String.format("the page was redirected to %s", method.getResponseHeader("location"))); + throw new WeixinException(status, String.format("the page was redirected to %s", httpResponse.getFirstHeader("location"))); } - Response response = new Response(method.getResponseBodyAsString()); - response.setBody(method.getResponseBody()); + byte[] data = EntityUtils.toByteArray(httpEntity); + Response response = new Response(); + response.setBody(data); response.setStatusCode(status); - response.setStatusText(method.getStatusText()); - response.setStream(method.getResponseBodyAsStream()); + response.setStatusText(statusLine.getReasonPhrase()); + response.setStream(new ByteArrayInputStream(data)); + response.setText(StringUtils.newStringUtf8(data)); - Header contentType = method.getResponseHeader("Content-Type"); - if (contentType.getValue().indexOf("application/json") >= 0 || contentType.getValue().indexOf("text/plain") >= 0) { - JSONObject jsonObj = response.getAsJson(); - if (jsonObj.containsKey(ERROR_CODE_KEY) && jsonObj.getIntValue(ERROR_CODE_KEY) != 0) { - throw new WeixinException(jsonObj.getIntValue(ERROR_CODE_KEY), jsonObj.getString(ERROR_MSG_KEY)); + Header contentType = httpResponse.getFirstHeader(HttpHeaders.CONTENT_TYPE); + if (contentType.getValue().contains(ContentType.APPLICATION_JSON.getMimeType())) { + BaseResult result = response.getAsResult(); + if (result.getErrcode() != 0) { + throw new WeixinException(result.getErrcode(), result.getErrmsg()); } } + EntityUtils.consume(httpEntity); return response; - } catch (IOException e) { + } catch (Exception e) { throw new WeixinException(e.getMessage()); } finally { - method.releaseConnection(); + request.releaseConnection(); } } } diff --git a/src/main/java/com/foxinmy/weixin4j/http/Parameter.java b/src/main/java/com/foxinmy/weixin4j/http/Parameter.java index cacfcd28..ecf69374 100644 --- a/src/main/java/com/foxinmy/weixin4j/http/Parameter.java +++ b/src/main/java/com/foxinmy/weixin4j/http/Parameter.java @@ -2,10 +2,15 @@ package com.foxinmy.weixin4j.http; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; -import org.apache.commons.httpclient.NameValuePair; +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; @@ -36,7 +41,7 @@ public class Parameter { public String toGetPara() { try { - return String.format("&%s=%s", URLEncoder.encode(name, "UTF-8"), URLEncoder.encode(value, "UTF-8")); + return String.format("&%s=%s", name, URLEncoder.encode(value, CHARSET)); } catch (UnsupportedEncodingException e) { return String.format("&%s=%s", name, value); } @@ -44,15 +49,15 @@ public class Parameter { public NameValuePair toPostPara() { try { - return new NameValuePair(URLEncoder.encode(name, "UTF-8"), URLEncoder.encode(value, "UTF-8")); + return new BasicNameValuePair(name, URLEncoder.encode(value, CHARSET)); } catch (UnsupportedEncodingException e) { - return new NameValuePair(name, value); + return new BasicNameValuePair(name, value); } } @Override public String toString() { - return String.format("[Parameter name=%s, value=%s]", name,value); + return String.format("[Parameter name=%s, value=%s]", name, value); } - + } diff --git a/src/main/java/com/foxinmy/weixin4j/http/PartParameter.java b/src/main/java/com/foxinmy/weixin4j/http/PartParameter.java new file mode 100644 index 00000000..c522a8dd --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/http/PartParameter.java @@ -0,0 +1,35 @@ +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 + "]"; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/http/Response.java b/src/main/java/com/foxinmy/weixin4j/http/Response.java index caeec808..b1b2e274 100644 --- a/src/main/java/com/foxinmy/weixin4j/http/Response.java +++ b/src/main/java/com/foxinmy/weixin4j/http/Response.java @@ -11,20 +11,20 @@ import org.dom4j.io.SAXReader; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.foxinmy.weixin4j.WeixinProxy; -import com.foxinmy.weixin4j.msg.ErrorMessage; +import com.foxinmy.weixin4j.msg.BaseResult; import com.thoughtworks.xstream.XStream; public class Response { - private final String ERROR_CODE_KEY = "errcode"; - private final String ERROR_MSG_KEY = "errmsg"; - private String text; private int statusCode; private String statusText; private byte[] body; private InputStream stream; + public Response() { + } + public Response(String text) { this.text = text; } @@ -33,6 +33,10 @@ public class Response { return text; } + public BaseResult getAsResult() { + return JSON.parseObject(text, BaseResult.class); + } + public JSONObject getAsJson() { return JSON.parseObject(text); } @@ -56,24 +60,17 @@ public class Response { * @return * @throws DocumentException */ - public ErrorMessage getErrorMsg() throws DocumentException { - JSONObject jsonObj = getAsJson(); - if (jsonObj.containsKey(ERROR_CODE_KEY)) { + public BaseResult getBaseError() throws DocumentException { + BaseResult result = getAsResult(); + if (result.getErrcode() != 0) { SAXReader reader = new SAXReader(); - Document doc = reader.read(WeixinProxy.class - .getResourceAsStream("error.xml")); - Node node = doc.getRootElement().selectSingleNode( - String.format("error[@code='%d']", - jsonObj.getInteger(ERROR_CODE_KEY))); + Document doc = reader.read(WeixinProxy.class.getResourceAsStream("error.xml")); + Node node = doc.getRootElement().selectSingleNode(String.format("error[@code='%d']", result.getErrcode())); if (node != null) { - return new ErrorMessage(jsonObj.getInteger(ERROR_CODE_KEY), - jsonObj.getString(ERROR_MSG_KEY), node.getStringValue()); + result.setText(node.getStringValue()); } - return new ErrorMessage(jsonObj.getInteger(ERROR_CODE_KEY), - "unknown error", "未知错误"); } - - return new ErrorMessage(0, "request success", ""); + return result; } public String getText() { @@ -124,5 +121,4 @@ public class Response { sb.append(", statusText=").append(statusText).append("]"); return sb.toString(); } - } diff --git a/src/main/java/com/foxinmy/weixin4j/model/AuthResult.java b/src/main/java/com/foxinmy/weixin4j/model/AuthResult.java index 03fec1cb..799534ee 100644 --- a/src/main/java/com/foxinmy/weixin4j/model/AuthResult.java +++ b/src/main/java/com/foxinmy/weixin4j/model/AuthResult.java @@ -4,11 +4,13 @@ import java.io.Serializable; /** * 网页授权结果 + * * @className AuthResult * @author jy.hu * @date 2014年4月8日 * @since JDK 1.7 - * @see 网页授权获取用户基本资料 + * @see 网页授权获取用户基本资料 */ public class AuthResult implements Serializable { @@ -16,11 +18,13 @@ public class AuthResult implements Serializable { /** * 网页授权获取code + * * @className AuthScope * @author jy.hu * @date 2014年4月8日 * @since JDK 1.7 - * @see 获取code + * @see 获取code */ public enum AuthScope { BASE("snsapi_base"), USERINFO("snsapi_userinfo"); @@ -54,6 +58,11 @@ public class AuthResult implements Serializable { this.accessToken = accessToken; } + public AuthResult(String location, AuthCode authCode) { + this.location = location; + this.authCode = authCode; + } + public AuthCode getAuthCode() { return authCode; } diff --git a/src/main/java/com/foxinmy/weixin4j/model/Button.java b/src/main/java/com/foxinmy/weixin4j/model/Button.java index 2c678d76..8c3d89cd 100644 --- a/src/main/java/com/foxinmy/weixin4j/model/Button.java +++ b/src/main/java/com/foxinmy/weixin4j/model/Button.java @@ -5,24 +5,29 @@ import java.util.ArrayList; import java.util.List; import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.type.ButtonType; /** * 菜单按钮 - * 目前自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单,一级菜单最多4个汉字,二级菜单最多7个汉字,多出来的部分将会以"..."代替 - * 请注意,创建自定义菜单后,由于微信客户端缓存,需要24小时微信客户端才会展现出来,建议测试时可以尝试取消关注公众账号后再次关注,则可以看到创建后的效果 + * + * 目前自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单,一级菜单最多4个汉字,二级菜单最多7个汉字,多出来的部分将会以"..."代替 + * 请注意,创建自定义菜单后,由于微信客户端缓存,需要24小时微信客户端才会展现出来,建议测试时可以尝试取消关注公众账号后再次关注,则可以看到创建后的效果 + * + * * @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 BtnType type; - private String key; - private String url; + private ButtonType type; // 菜单的响应动作类型 + private String key; // click等点击类型必须 + private String url; // view类型必须 @JSONField(name = "sub_button") private List subs; @@ -37,7 +42,7 @@ public class Button implements Serializable { public Button(String name, String url) { this.name = name; this.url = url; - this.type = BtnType.view; + this.type = ButtonType.view; } public String getName() { @@ -48,11 +53,11 @@ public class Button implements Serializable { this.name = name; } - public BtnType getType() { + public ButtonType getType() { return type; } - public void setType(BtnType type) { + public void setType(ButtonType type) { this.type = type; } @@ -80,26 +85,12 @@ public class Button implements Serializable { this.subs = subs; } - public void pushSub(Button btn) { + public Button pushSub(Button btn) { if (this.subs == null) { this.subs = new ArrayList(); } this.subs.add(btn); - } - - /** - * 按钮类型 - * click: - * 用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event 的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互; - * view: - * 用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的url值(即网页链接),达到打开网页的目的,建议与网页授权获取用户基本信息接口结合,获得用户的登入个人信息 - * @className BtnType - * @author jy.hu - * @date 2014年4月8日 - * @since JDK 1.7 - */ - public enum BtnType { - click, view + return this; } @Override @@ -119,5 +110,4 @@ public class Button implements Serializable { sb.append("]"); return sb.toString(); } - } diff --git a/src/main/java/com/foxinmy/weixin4j/model/CustomRecord.java b/src/main/java/com/foxinmy/weixin4j/model/CustomRecord.java index ddd7da86..f54e2870 100644 --- a/src/main/java/com/foxinmy/weixin4j/model/CustomRecord.java +++ b/src/main/java/com/foxinmy/weixin4j/model/CustomRecord.java @@ -72,7 +72,6 @@ public class CustomRecord implements Serializable { this.code = code; this.desc = desc; } - public int getCode() { return code; } diff --git a/src/main/java/com/foxinmy/weixin4j/model/MpArticle.java b/src/main/java/com/foxinmy/weixin4j/model/MpArticle.java index 99b6c1eb..2a1d4d64 100644 --- a/src/main/java/com/foxinmy/weixin4j/model/MpArticle.java +++ b/src/main/java/com/foxinmy/weixin4j/model/MpArticle.java @@ -25,6 +25,8 @@ public class MpArticle implements Serializable { 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; } @@ -61,15 +63,31 @@ public class MpArticle implements Serializable { public void setDigest(String digest) { this.digest = digest; } - - public MpArticle(String thumbMediaId, String title,String content) { + 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(); } - } diff --git a/src/main/java/com/foxinmy/weixin4j/model/QRParameter.java b/src/main/java/com/foxinmy/weixin4j/model/QRParameter.java index fe076cfe..32bdafb3 100644 --- a/src/main/java/com/foxinmy/weixin4j/model/QRParameter.java +++ b/src/main/java/com/foxinmy/weixin4j/model/QRParameter.java @@ -7,34 +7,50 @@ import com.thoughtworks.xstream.annotations.XStreamOmitField; /** * 二维码参数对象 - * 目前有2种类型的二维码,分别是临时二维码和永久二维码,前者有过期时间,最大为1800秒,但能够生成较多数量,后者无过期时间,数量较少(目前参数只支持1--100000) + * + * 目前有2种类型的二维码,分别是临时二维码和永久二维码,前者有过期时间,最大为1800秒,但能够生成较多数量,后者无过期时间,数量较少(目前参数只支持1-- + * 100000) + * + * * @className QRParameter * @author jy.hu * @date 2014年4月8日 * @since JDK 1.7 - * @see 生成带参数的二维码 + * @see 生成带参数的二维码 */ public class QRParameter implements Serializable { private static final long serialVersionUID = 6611187606558274253L; public enum QRType { - QR_SCENE, // 临时 - QR_LIMIT_SCENE; // 永久 + TEMPORARY("QR_SCENE"), // 临时 + PERMANENCE("QR_LIMIT_SCENE"); // 永久 + private String name; + + QRType(String name) { + this.name = name; + } + + public String getName() { + return name; + } } - private int expire_seconds; // 该二维码有效时间,以秒为单位。 最大不超过1800。 + @XStreamAlias("expire_seconds") + private int expireSeconds; // 该二维码有效时间,以秒为单位。 最大不超过1800。 @XStreamAlias("action_name") private QRType qrType; // 二维码类型,QR_SCENE为临时,QR_LIMIT_SCENE为永久 @XStreamOmitField - private int scene_id; // 场景值ID,临时二维码时为32位非0整型,永久二维码时最大值为100000(目前参数只支持1--100000) + @XStreamAlias("scene_id") + private int sceneId; // 场景值ID,临时二维码时为32位非0整型,永久二维码时最大值为100000(目前参数只支持1--100000) - public int getExpire_seconds() { - return expire_seconds; + public int getExpireSeconds() { + return expireSeconds; } - public void setExpire_seconds(int expire_seconds) { - this.expire_seconds = expire_seconds; + public void setExpireSeconds(int expireSeconds) { + this.expireSeconds = expireSeconds; } public QRType getQrType() { @@ -45,22 +61,26 @@ public class QRParameter implements Serializable { this.qrType = qrType; } - public int getScene_id() { - return scene_id; + public int getSceneId() { + return sceneId; } - public void setScene_id(int scene_id) { - this.scene_id = scene_id; + public void setSceneId(int sceneId) { + this.sceneId = sceneId; } - public QRParameter(int expire_seconds, QRType qrType, int scene_id) { - this.expire_seconds = expire_seconds; + public QRParameter(int expireSeconds, QRType qrType, int sceneId) { + this.expireSeconds = expireSeconds; this.qrType = qrType; - this.scene_id = scene_id; + this.sceneId = sceneId; } - public QRParameter(QRType action_name, int scene_id) { - this(0, action_name, scene_id); + public QRParameter(QRType qrType, int sceneId) { + this(0, qrType, sceneId); + } + + public QRParameter(int sceneId, int expireSeconds) { + this(0, null, sceneId); } public String toJson() { @@ -74,17 +94,17 @@ public class QRParameter implements Serializable { * "expire_seconds"); } return xstream.toXML(this); */ StringBuilder jsonBuilder = new StringBuilder("{"); - jsonBuilder.append("\"action_name\":\"").append(qrType.name()).append("\""); - if (this.qrType == QRType.QR_SCENE) { - jsonBuilder.append(",\"expire_seconds\":").append(expire_seconds); + jsonBuilder.append("\"action_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}}", scene_id)); + jsonBuilder.append(",\"action_info\":").append(String.format("{\"scene\": {\"scene_id\": %d}}", sceneId)); jsonBuilder.append("}"); return jsonBuilder.toString(); } @Override public String toString() { - return String.format("[QRParameter action_name=%s, expire_seconds=%d, scene_id=%d]", getQrType().name(), getExpire_seconds(), getScene_id()); + return "QRParameter [expireSeconds=" + expireSeconds + ", qrType=" + qrType + ", sceneId=" + sceneId + "]"; } } diff --git a/src/main/java/com/foxinmy/weixin4j/model/Token.java b/src/main/java/com/foxinmy/weixin4j/model/Token.java index 0f9a29fa..abaa2e09 100644 --- a/src/main/java/com/foxinmy/weixin4j/model/Token.java +++ b/src/main/java/com/foxinmy/weixin4j/model/Token.java @@ -2,10 +2,12 @@ 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失效 + * access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token,正常情况下access_token有效期为7200秒, + * 重复获取将导致上次获取的access_token失效 * * @className Token * @author jy.hu @@ -18,25 +20,27 @@ import com.thoughtworks.xstream.annotations.XStreamAlias; public class Token implements Serializable { private static final long serialVersionUID = 1L; - private String access_token; - private int expires_in; + @JSONField(name = "access_token") + private String accessToken; + @JSONField(name = "expires_in") + private int expiresIn; private String openid; private long time; - public String getAccess_token() { - return access_token; + public String getAccessToken() { + return accessToken; } - public void setAccess_token(String access_token) { - this.access_token = access_token; + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; } - public int getExpires_in() { - return expires_in; + public int getExpiresIn() { + return expiresIn; } - public void setExpires_in(int expires_in) { - this.expires_in = expires_in; + public void setExpiresIn(int expiresIn) { + this.expiresIn = expiresIn; } public String getOpenid() { @@ -58,18 +62,13 @@ public class Token implements Serializable { @Override public boolean equals(Object obj) { if (obj instanceof Token) { - return access_token.equals(((Token) obj).getAccess_token()); + return accessToken.equals(((Token) obj).getAccessToken()); } return false; } @Override public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("[Token access_token=").append(access_token); - sb.append(", expires_in=").append(expires_in); - sb.append(", openid=").append(openid); - sb.append(", time=").append(time).append("]"); - return sb.toString(); + return "Token [accessToken=" + accessToken + ", expiresIn=" + expiresIn + ", openid=" + openid + ", time=" + time + "]"; } } diff --git a/src/main/java/com/foxinmy/weixin4j/model/User.java b/src/main/java/com/foxinmy/weixin4j/model/User.java index df89a4dc..9db48888 100644 --- a/src/main/java/com/foxinmy/weixin4j/model/User.java +++ b/src/main/java/com/foxinmy/weixin4j/model/User.java @@ -2,15 +2,19 @@ package com.foxinmy.weixin4j.model; import java.io.Serializable; -import com.foxinmy.weixin4j.util.WeixinUtil; +import org.jsoup.helper.StringUtil; /** * 用户对象 - * 当用户与公众号有交互时,可通过openid获取信息 + * + * 当用户与公众号有交互时,可通过openid获取信息 + * + * * @author jy.hu * @date 2014年4月8日 * @since JDK 1.7 - * @see 获取用户基本资料 + * @see 获取用户基本资料 */ public class User implements Serializable { @@ -27,6 +31,7 @@ public class User implements Serializable { private int subscribe; // 是否关注 private long subscribe_time; // 关注时间 private Lang language; // 使用语言 + private String unionid; // 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段 // 国家地区语言版本 public enum Lang { @@ -92,14 +97,14 @@ public class User implements Serializable { return sex; } - public Gender getGender(){ - if(sex == 1){ + public Gender getGender() { + if (sex == 1) { return Gender.male; - }else if(sex == 2){ + } else if (sex == 2) { return Gender.female; - }else{ + } else { return Gender.unknown; - } + } } public void setSex(int sex) { @@ -135,9 +140,10 @@ public class User implements Serializable { } public String getHeadimgurl(Size size) { - if (!WeixinUtil.isBlank(headimgurl)) { + if (!StringUtil.isBlank(headimgurl)) { StringBuilder sb = new StringBuilder(headimgurl); - return sb.replace(0, (headimgurl.length() - 1), size.getInt() + "").toString(); + return sb.replace(0, (headimgurl.length() - 1), size.getInt() + "") + .toString(); } return ""; } @@ -178,6 +184,14 @@ public class User implements Serializable { 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) { @@ -199,6 +213,7 @@ public class User implements Serializable { 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(); } diff --git a/src/main/java/com/foxinmy/weixin4j/model/UserToken.java b/src/main/java/com/foxinmy/weixin4j/model/UserToken.java index aea3eace..08827e17 100644 --- a/src/main/java/com/foxinmy/weixin4j/model/UserToken.java +++ b/src/main/java/com/foxinmy/weixin4j/model/UserToken.java @@ -1,7 +1,10 @@ package com.foxinmy.weixin4j.model; +import com.alibaba.fastjson.annotation.JSONField; + /** * 用户token 一般通过授权页面获得 + * * @className UserToken * @author jy.hu * @date 2014年4月6日 @@ -13,16 +16,17 @@ public class UserToken extends Token { private static final long serialVersionUID = 1L; - private String refresh_token; + @JSONField(name = "refresh_token") + private String refreshToken; private String scope; - public String getRefresh_token() { - return refresh_token; + public String getRefreshToken() { + return refreshToken; } - public void setRefresh_token(String refresh_token) { - this.refresh_token = refresh_token; + public void setRefreshToken(String refreshToken) { + this.refreshToken = refreshToken; } public String getScope() { @@ -35,13 +39,6 @@ public class UserToken extends Token { @Override public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("[UserToken access_token=").append(super.getAccess_token()); - sb.append(", expires_in=").append(super.getExpires_in()); - sb.append(", openid=").append(super.getOpenid()); - sb.append(", refresh_token=").append(refresh_token); - sb.append(", scope=").append(scope); - sb.append(", time=").append(super.getTime()).append("]"); - return sb.toString(); + return "UserToken [refreshToken=" + refreshToken + ", scope=" + scope + ", getAccessToken()=" + getAccessToken() + ", getExpiresIn()=" + getExpiresIn() + ", getOpenid()=" + getOpenid() + ", getTime()=" + getTime() + "]"; } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/BaseMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/BaseMessage.java index 4f03502b..dbfe975a 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/BaseMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/BaseMessage.java @@ -4,8 +4,6 @@ import java.io.Serializable; import java.io.Writer; import com.foxinmy.weixin4j.type.MessageType; -import com.foxinmy.weixin4j.util.WeixinConfig; -import com.foxinmy.weixin4j.util.WeixinUtil; import com.foxinmy.weixin4j.xml.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; @@ -14,8 +12,11 @@ import com.thoughtworks.xstream.io.json.JsonWriter; /** * 普通消息基类 - * 回复图片等多媒体消息时需要预先上传多媒体文件到微信服务器, - * 假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试 + * + * 回复图片等多媒体消息时需要预先上传多媒体文件到微信服务器, + * 假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试 + * + * * @className BaseMessage * @author jy.hu * @date 2014年4月6日 @@ -24,7 +25,8 @@ import com.thoughtworks.xstream.io.json.JsonWriter; public class BaseMessage implements Serializable { private static final long serialVersionUID = 7761192742840031607L; - + private static XStream xstream; + @XStreamAlias("ToUserName") private String toUserName; // 开发者微信号 @XStreamAlias("FromUserName") @@ -36,10 +38,25 @@ public class BaseMessage implements Serializable { @XStreamAlias("MsgId") private long msgId; // 消息ID + static{ + xstream = new XStream(); + } + 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; } @@ -87,25 +104,35 @@ public class BaseMessage implements Serializable { } return false; } - + + protected XStream getXStream() { + Class extends BaseMessage> targetClass = getMsgType() + .getMessageClass(); + xstream.alias("xml", targetClass); + xstream.autodetectAnnotations(true); + xstream.processAnnotations(targetClass); + xstream.omitField(BaseMessage.class, "msgId"); + return xstream; + } + /** * 消息对象转换为微信服务器接受的xml格式消息 + * * @return xml字符串 */ public String toXml() { - XStream xstream = new XStream(); - xstream.alias("xml", getMsgType().getMessageClass()); + Class extends BaseMessage> targetClass = getMsgType() + .getMessageClass(); + xstream.alias("xml", targetClass); xstream.autodetectAnnotations(true); - xstream.processAnnotations(getMsgType().getMessageClass()); + xstream.processAnnotations(targetClass); xstream.omitField(BaseMessage.class, "msgId"); - if (WeixinUtil.isBlank(fromUserName)) { - setFromUserName(WeixinConfig.getValue("app_openId")); - } return xstream.toXML(this); } /** * 消息对象转换为微信服务器接受的json格式字符串 + * * @return json字符串 */ public String toJson() { @@ -118,9 +145,6 @@ public class BaseMessage implements Serializable { xstream.autodetectAnnotations(true); xstream.processAnnotations(getMsgType().getMessageClass()); xstream.omitField(BaseMessage.class, "msgId"); - if (WeixinUtil.isBlank(fromUserName)) { - setFromUserName(WeixinConfig.getValue("app_openId")); - } return xstream.toXML(this); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/BaseResult.java b/src/main/java/com/foxinmy/weixin4j/msg/BaseResult.java new file mode 100644 index 00000000..0e46f846 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/BaseResult.java @@ -0,0 +1,78 @@ +package com.foxinmy.weixin4j.msg; + +import java.io.Serializable; + +/** + * 调用接口响应值 + * + * @className BaseResult + * @author jy.hu + * @date 2014年9月24日 + * @since JDK 1.7 + * @see 全局返回码 + */ +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 + "]"; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/ErrorMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/ErrorMessage.java deleted file mode 100644 index bb2ac329..00000000 --- a/src/main/java/com/foxinmy/weixin4j/msg/ErrorMessage.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.foxinmy.weixin4j.msg; - -import java.io.Serializable; - -public class ErrorMessage implements Serializable { - - private static final long serialVersionUID = 2539772564331987708L; - - private int code; - private String msg; - private String text; - - public int getCode() { - return code; - } - - public void setCode(int code) { - this.code = code; - } - - public String getMsg() { - return msg; - } - - public void setMsg(String msg) { - this.msg = msg; - } - - public String getText() { - return text; - } - - public void setText(String text) { - this.text = text; - } - - public ErrorMessage(int code, String msg, String text) { - this.code = code; - this.msg = msg; - this.text = text; - } - public ErrorMessage() { - - } - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("[ErrorMessage code=").append(code); - sb.append(", msg=").append(msg); - sb.append(", text=").append(text).append("]"); - return sb.toString(); - } - -} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/TextMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/TextMessage.java index ad167215..43fdcc94 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/TextMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/TextMessage.java @@ -5,12 +5,15 @@ import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 文本消息(接收|回复) + * * @className TextMessage * @author jy.hu * @date 2014年4月6日 * @since JDK 1.7 - * @see 接收文本消息 - * @see 回复文本消息 + * @see 接收文本消息 + * @see 回复文本消息 * @see com.foxinmy.weixin4j.msg.BaseMessage * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ @@ -22,9 +25,8 @@ public class TextMessage extends BaseMessage { super(MessageType.text); } - public TextMessage(String toUserName, String content) { - super(MessageType.text); - setToUserName(toUserName); + public TextMessage(String content, BaseMessage inMessage) { + super(MessageType.text, inMessage); this.content = content; } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/event/LocationEventMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/event/LocationEventMessage.java index ff1091ed..2e7c155c 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/event/LocationEventMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/event/LocationEventMessage.java @@ -3,16 +3,15 @@ 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 上报地理位置事件 - * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see 上报地理位置事件 */ public class LocationEventMessage extends EventMessage { @@ -21,7 +20,7 @@ public class LocationEventMessage extends EventMessage { public LocationEventMessage() { super(EventType.location); } - + @XStreamAlias("Latitude") private String latitude;// 地理位置纬度 @XStreamAlias("Longitude") @@ -33,30 +32,19 @@ public class LocationEventMessage extends EventMessage { return latitude; } - public void setLatitude(String latitude) { - this.latitude = latitude; - } - public String getLongitude() { return longitude; } - public void setLongitude(String longitude) { - this.longitude = longitude; - } - public String getPrecision() { return precision; } - public void setPrecision(String precision) { - this.precision = precision; - } - @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("[LocationEventMessage ,toUserName=").append(super.getToUserName()); + sb.append("[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()); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/event/MassEventMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/event/MassEventMessage.java index 346e7172..c59d187c 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/event/MassEventMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/event/MassEventMessage.java @@ -18,7 +18,7 @@ public class MassEventMessage extends EventMessage { private static final long serialVersionUID = -1660543255873723895L; public MassEventMessage() { - super(EventType.MASSSENDJOBFINISH); + super(EventType.massendjobfinish); } @XStreamAlias("Status") @@ -35,38 +35,28 @@ public class MassEventMessage extends EventMessage { public String getStatus() { return status; } - public void setStatus(String status) { - this.status = status; - } + public int getTotalCount() { return totalCount; } - public void setTotalCount(int totalCount) { - this.totalCount = totalCount; - } + public int getFilterCount() { return filterCount; } - public void setFilterCount(int filterCount) { - this.filterCount = filterCount; - } + public int getSentCount() { return sentCount; } - public void setSentCount(int sentCount) { - this.sentCount = sentCount; - } + public int getErrorCount() { return errorCount; } - public void setErrorCount(int errorCount) { - this.errorCount = errorCount; - } - + @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("[MassEventMessage ,toUserName=").append(super.getToUserName()); + sb.append("[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()); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/event/ScanEventMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/event/ScanEventMessage.java index 9e621530..ccf2a6b8 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/event/ScanEventMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/event/ScanEventMessage.java @@ -3,14 +3,14 @@ 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 扫描二维码事件 - * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see 扫描二维码事件 */ public class ScanEventMessage extends EventMessage { @@ -20,7 +20,7 @@ public class ScanEventMessage extends EventMessage { private static final long serialVersionUID = 8078674062833071562L; private static final String PARA_PREFIX = "qrscene_"; - + @XStreamAlias("EventKey") private String eventKey; // 事件KEY值,是一个32位无符号整数,即创建二维码时的二维码scene_id @XStreamAlias("Ticket") @@ -30,18 +30,10 @@ public class ScanEventMessage extends EventMessage { return eventKey; } - public void setEventKey(String eventKey) { - this.eventKey = eventKey; - } - public String getTicket() { return ticket; } - public void setTicket(String ticket) { - this.ticket = ticket; - } - public String getParameter() { return eventKey.replace(PARA_PREFIX, ""); } @@ -49,7 +41,8 @@ public class ScanEventMessage extends EventMessage { @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("[ScanEventMessage ,toUserName=").append(super.getToUserName()); + 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()); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/event/ScribeEventMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/event/ScribeEventMessage.java index 21053b24..645ab6b6 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/event/ScribeEventMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/event/ScribeEventMessage.java @@ -9,8 +9,6 @@ package com.foxinmy.weixin4j.msg.event; * @date 2014年4月6日 * @since JDK 1.7 * @see 关注/取消关注事件 - * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class ScribeEventMessage extends ScanEventMessage { diff --git a/src/main/java/com/foxinmy/weixin4j/msg/event/TemplatesendjobfinishMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/event/TemplatesendjobfinishMessage.java new file mode 100644 index 00000000..45a9f023 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/event/TemplatesendjobfinishMessage.java @@ -0,0 +1,35 @@ +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 模板消息事件推送 + */ +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 + "]"; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/event/MenuEventMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/event/menu/MenuEventMessage.java similarity index 64% rename from src/main/java/com/foxinmy/weixin4j/msg/event/MenuEventMessage.java rename to src/main/java/com/foxinmy/weixin4j/msg/event/menu/MenuEventMessage.java index f4d3c752..01b3f5d0 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/event/MenuEventMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/event/menu/MenuEventMessage.java @@ -1,17 +1,18 @@ -package com.foxinmy.weixin4j.msg.event; +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 自定义菜单事件 - * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see 菜单事件 */ public class MenuEventMessage extends EventMessage { @@ -28,14 +29,11 @@ public class MenuEventMessage extends EventMessage { return eventKey; } - public void setEventKey(String eventKey) { - this.eventKey = eventKey; - } - @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("[MenuEventMessage ,toUserName=").append(super.getToUserName()); + sb.append("[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()); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/event/menu/MenuLocationEventMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/event/menu/MenuLocationEventMessage.java new file mode 100644 index 00000000..4811681f --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/event/menu/MenuLocationEventMessage.java @@ -0,0 +1,74 @@ +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 弹出地理位置选择事件推送 + */ +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 + "]"; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/event/menu/MenuPhotoEventMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/event/menu/MenuPhotoEventMessage.java new file mode 100644 index 00000000..674303f3 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/event/menu/MenuPhotoEventMessage.java @@ -0,0 +1,63 @@ +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 弹出系统拍照发图的事件推送 + */ +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 items; + + public int getCount() { + return count; + } + + public List 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 + "]"; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/event/menu/MenuScanEventMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/event/menu/MenuScanEventMessage.java new file mode 100644 index 00000000..cc6e4a1e --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/event/menu/MenuScanEventMessage.java @@ -0,0 +1,51 @@ +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 扫码推事件的事件推送 + */ +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 + "]"; + } + +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/in/ImageMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/in/ImageMessage.java index d749b26c..37b5e9c7 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/in/ImageMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/in/ImageMessage.java @@ -6,13 +6,13 @@ import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 图片消息 + * * @className ImageMessage * @author jy.hu * @date 2014年4月6日 * @since JDK 1.7 - * @see 图片消息 - * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see 图片消息 */ public class ImageMessage extends BaseMessage { @@ -21,7 +21,7 @@ public class ImageMessage extends BaseMessage { public ImageMessage() { super(MessageType.image); } - + @XStreamAlias("PicUrl") private String picUrl; // 图片链接 @XStreamAlias("MediaId") @@ -31,18 +31,10 @@ public class ImageMessage extends BaseMessage { return picUrl; } - public void setPicUrl(String picUrl) { - this.picUrl = picUrl; - } - public String getMediaId() { return mediaId; } - public void setMediaId(String mediaId) { - this.mediaId = mediaId; - } - @Override public String toString() { StringBuilder sb = new StringBuilder(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/in/LinkMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/in/LinkMessage.java index 5defa28e..7faca8d8 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/in/LinkMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/in/LinkMessage.java @@ -6,13 +6,13 @@ import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 链接消息 + * * @className LinkMessage * @author jy.hu * @date 2014年4月6日 * @since JDK 1.7 - * @see 链接消息 - * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see 链接消息 */ public class LinkMessage extends BaseMessage { @@ -21,7 +21,7 @@ public class LinkMessage extends BaseMessage { public LinkMessage() { super(MessageType.link); } - + @XStreamAlias("Title") private String title; // 消息标题 @XStreamAlias("Description") @@ -33,26 +33,14 @@ public class LinkMessage extends BaseMessage { return title; } - public void setTitle(String title) { - this.title = title; - } - public String getDescription() { return description; } - public void setDescription(String description) { - this.description = description; - } - public String getUrl() { return url; } - public void setUrl(String url) { - this.url = url; - } - @Override public String toString() { StringBuilder sb = new StringBuilder(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/in/LocationMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/in/LocationMessage.java index 4a883208..70b19da2 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/in/LocationMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/in/LocationMessage.java @@ -6,13 +6,13 @@ import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 地理位置消息 + * * @className LocationMessage * @author jy.hu * @date 2014年4月6日 * @since JDK 1.7 - * @see 地理位置消息 - * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see 地理位置消息 */ public class LocationMessage extends BaseMessage { @@ -23,38 +23,26 @@ public class LocationMessage extends BaseMessage { } @XStreamAlias("Location_X") - private String location_X; // 地理位置维度 + private double x; // 地理位置维度 @XStreamAlias("Location_Y") - private String location_Y; // 地理位置经度 + private double y; // 地理位置经度 @XStreamAlias("Scale") - private String scale; // 地图缩放大小 + private double scale; // 地图缩放大小 @XStreamAlias("Label") private String label; // 地理位置信息 - public String getLocation_X() { - return location_X; + public double getX() { + return x; } - public void setLocation_X(String location_X) { - this.location_X = location_X; + public double getY() { + return y; } - public String getLocation_Y() { - return location_Y; - } - - public void setLocation_Y(String location_Y) { - this.location_Y = location_Y; - } - - public String getScale() { + public double getScale() { return scale; } - public void setScale(String scale) { - this.scale = scale; - } - public String getLabel() { return label; } @@ -66,11 +54,12 @@ public class LocationMessage extends BaseMessage { @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("[LocationMessage ,toUserName=").append(super.getToUserName()); + sb.append("[LocationMessage ,toUserName=") + .append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,location_X=").append(location_X); - sb.append(" ,location_Y=").append(location_Y); + sb.append(" ,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()); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/in/VideoMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/in/VideoMessage.java index ce240885..053c1974 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/in/VideoMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/in/VideoMessage.java @@ -6,13 +6,13 @@ import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 视频消息 + * * @className VideoMessage * @author jy.hu * @date 2014年4月6日 * @since JDK 1.7 - * @see 视频消息 - * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see 视频消息 */ public class VideoMessage extends BaseMessage { @@ -31,18 +31,10 @@ public class VideoMessage extends BaseMessage { return mediaId; } - public void setMediaId(String mediaId) { - this.mediaId = mediaId; - } - public String getThumbMediaId() { return thumbMediaId; } - public void setThumbMediaId(String thumbMediaId) { - this.thumbMediaId = thumbMediaId; - } - @Override public String toString() { StringBuilder sb = new StringBuilder(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/in/VoiceMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/in/VoiceMessage.java index af168e77..57fde9ec 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/in/VoiceMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/in/VoiceMessage.java @@ -6,14 +6,16 @@ import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 语音消息 - * 开通语音识别功能,用户每次发送语音给公众号时,微信会在推送的语音消息XML数据包中,赋值到Recongnition字段. + * + * 开通语音识别功能,用户每次发送语音给公众号时,微信会在推送的语音消息XML数据包中,赋值到Recongnition字段. + * + * * @className VoiceMessage * @author jy.hu * @date 2014年4月6日 * @since JDK 1.7 - * @see 语音消息 - * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see 语音消息 */ public class VoiceMessage extends BaseMessage { @@ -27,7 +29,7 @@ public class VoiceMessage extends BaseMessage { private String mediaId; // 语音消息媒体id,可以调用多媒体文件下载接口拉取数据。 @XStreamAlias("Format") private String format; // 语音格式,如amr,speex等 - + @XStreamAlias("Recognition") private String recognition; // 语音识别结果,UTF8编码 @@ -35,26 +37,14 @@ public class VoiceMessage extends BaseMessage { return recognition; } - public void setRecognition(String recognition) { - this.recognition = recognition; - } - public String getMediaId() { return mediaId; } - public void setMediaId(String mediaId) { - this.mediaId = mediaId; - } - public String getFormat() { return format; } - public void setFormat(String format) { - this.format = format; - } - @Override public String toString() { StringBuilder sb = new StringBuilder(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/model/Article.java b/src/main/java/com/foxinmy/weixin4j/msg/model/Article.java new file mode 100644 index 00000000..28f4c861 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/model/Article.java @@ -0,0 +1,75 @@ +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; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/model/BaseMsg.java b/src/main/java/com/foxinmy/weixin4j/msg/model/BaseMsg.java new file mode 100644 index 00000000..61b5648c --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/model/BaseMsg.java @@ -0,0 +1,33 @@ +package com.foxinmy.weixin4j.msg.model; + +import java.io.Serializable; +import java.io.Writer; + +import com.foxinmy.weixin4j.type.MediaType; +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; + + public abstract MediaType getMediaType(); + + /** + * 客服消息json化,适用于客服消息接口 + * + * @return {"touser": "to","msgtype": "text","text": {"content": "123"}} + */ + public String toNotifyJson() { + 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); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/model/Image.java b/src/main/java/com/foxinmy/weixin4j/msg/model/Image.java new file mode 100644 index 00000000..00197ff5 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/model/Image.java @@ -0,0 +1,38 @@ +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; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/model/Music.java b/src/main/java/com/foxinmy/weixin4j/msg/model/Music.java new file mode 100644 index 00000000..7754c1ed --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/model/Music.java @@ -0,0 +1,93 @@ +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; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/model/Text.java b/src/main/java/com/foxinmy/weixin4j/msg/model/Text.java new file mode 100644 index 00000000..8375e59e --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/model/Text.java @@ -0,0 +1,40 @@ +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; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/model/Video.java b/src/main/java/com/foxinmy/weixin4j/msg/model/Video.java new file mode 100644 index 00000000..3795b714 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/model/Video.java @@ -0,0 +1,88 @@ +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; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/model/Voice.java b/src/main/java/com/foxinmy/weixin4j/msg/model/Voice.java new file mode 100644 index 00000000..c99201a2 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/model/Voice.java @@ -0,0 +1,38 @@ +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; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/notify/ArticleNotify.java b/src/main/java/com/foxinmy/weixin4j/msg/notify/ArticleNotify.java index abb74af7..4fb91621 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/notify/ArticleNotify.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/notify/ArticleNotify.java @@ -3,17 +3,21 @@ 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 客服图文消息 + * @see 客服图文消息 + * @see com.foxinmy.weixin.msg.model.Article * @see com.foxinmy.weixin4j.msg.notify.BaseNotify * @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson() */ @@ -46,60 +50,53 @@ public class ArticleNotify extends BaseNotify { count++; } - private static class News { - @XStreamAlias("articles") - private List<$> articles; - - public News() { - this.articles = new LinkedList<$>(); + public void pushAll(List articles) { + count = articles.size(); + if (articles.size() > MAX_ARTICLE_COUNT) { + count = MAX_ARTICLE_COUNT; + articles = articles.subList(0, count); } - - public void pushArticle(String title, String desc, String picUrl, String url) { - this.articles.add(new $(title, desc, picUrl, url)); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - for ($ item : articles) { - sb.append("{title=").append(item.title); - sb.append(" ,description=").append(item.desc); - sb.append(" ,picUrl=").append(item.picUrl); - sb.append(" ,url=").append(item.url).append("}"); - } - return sb.toString(); + if (this.news == null) { + this.news = new News(); } + this.news.setArticles(articles); } - private static class $ { - private String title; // 图文消息标题 - @XStreamAlias("description") - private String desc; // 图文消息描述 - @XStreamAlias("picurl") - private String picUrl; // 图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200 - @XStreamAlias("url") - private String url; // 点击图文消息跳转链接 + private static class News { + @XStreamAlias("articles") + private List articles; - public $(String title, String desc, String picUrl, String url) { - this.title = title; - this.desc = desc; - this.picUrl = picUrl; - this.url = url; + public News() { + this.articles = new LinkedList(); + } + + public void pushArticle(String title, String desc, String picUrl, + String url) { + this.articles.add(new Article(title, desc, picUrl, url)); + } + + public void setArticles(List articles) { + this.articles = articles; } @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("(article ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,picUrl=").append(picUrl); - sb.append(" ,url=").append(url).append(")"); + 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()); + return String.format( + "[ArticleNotify touser=%s ,msgtype=%s ,articles=%s]", + super.getTouser(), super.getMsgtype().name(), + this.news.toString()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/notify/ImageNotify.java b/src/main/java/com/foxinmy/weixin4j/msg/notify/ImageNotify.java index f9a52263..d2e47096 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/notify/ImageNotify.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/notify/ImageNotify.java @@ -1,14 +1,17 @@ package com.foxinmy.weixin4j.msg.notify; +import com.foxinmy.weixin4j.msg.model.Image; import com.foxinmy.weixin4j.type.MessageType; -import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 客服图片消息 + * * @author jy.hu * @date 2014年4月4日 * @since JDK 1.7 - * @see 客服图片消息 + * @see 客服图片消息 + * @see com.foxinmy.weixin4j.msg.model.Image * @see com.foxinmy.weixin4j.msg.notify.BaseNotify * @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson() */ @@ -20,30 +23,25 @@ public class ImageNotify extends BaseNotify { super(MessageType.image); } - public ImageNotify(String mediaId) { - super(MessageType.image); - this.image = new $(mediaId); + public ImageNotify(String touser) { + super(touser, MessageType.image); } public ImageNotify(String mediaId, String touser) { super(touser, MessageType.image); - this.image = new $(mediaId); + this.pushMediaId(mediaId); } - @XStreamAlias("image") - private $ image; - - private static class $ { - @XStreamAlias("media_id") - private String mediaId; - - public $(String mediaId) { - this.mediaId = 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.mediaId); + return String.format("[ImageNotify touser=%s ,msgtype=%s ,mediaId=%s]", + super.getTouser(), super.getMsgtype().name(), + this.image.getMediaId()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/notify/MusicNotify.java b/src/main/java/com/foxinmy/weixin4j/msg/notify/MusicNotify.java index 6f3e66fa..1e328677 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/notify/MusicNotify.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/notify/MusicNotify.java @@ -1,14 +1,17 @@ package com.foxinmy.weixin4j.msg.notify; +import com.foxinmy.weixin4j.msg.model.Music; import com.foxinmy.weixin4j.type.MessageType; -import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 客服音乐消息 + * * @author jy.hu * @date 2014年4月4日 * @since JDK 1.7 - * @see 客服音乐消息 + * @see 客服音乐消息 + * @see com.foxinmy.weixin4j.msg.model.Music * @see com.foxinmy.weixin4j.msg.notify.BaseNotify * @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson() */ @@ -24,44 +27,20 @@ public class MusicNotify extends BaseNotify { super(touser, MessageType.music); } - public void pushMusic(String title, String desc, String url, String hqUrl, String mediaId) { - this.music = new $(); - this.music.thumbMediaId = mediaId; - this.music.desc = desc; - this.music.hqMusicUrl = hqUrl; - this.music.musicUrl = url; - this.music.title = title; + public void pushMusic(String musicurl, String hqUrl, String mediaId) { + this.music = new Music(null, null, musicurl, hqUrl, mediaId); } - @XStreamAlias("music") - private $ music; - - private static class $ { - private String title; - @XStreamAlias("description") - private String desc; - @XStreamAlias("musicurl") - private String musicUrl; - @XStreamAlias("hqmusicurl") - private String hqMusicUrl; - @XStreamAlias("thumb_media_id") - private String thumbMediaId; - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(music ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,musicURL=").append(musicUrl); - sb.append(" ,hqMusicUrl=").append(hqMusicUrl); - sb.append(" ,thumbMediaId=").append(thumbMediaId).append(")"); - return sb.toString(); - } + private Music music; + public void setMusic(Music music) { + this.music = music; } @Override public String toString() { - return String.format("[VideoNotify touser=%s ,msgtype=%s ,music=%s]", super.getTouser(), super.getMsgtype().name(), this.music.toString()); + return String.format("[MusicNotify touser=%s ,msgtype=%s ,music=%s]", + super.getTouser(), super.getMsgtype().name(), + this.music.toString()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/notify/TextNotify.java b/src/main/java/com/foxinmy/weixin4j/msg/notify/TextNotify.java index edcf2565..6ec09a3a 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/notify/TextNotify.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/notify/TextNotify.java @@ -1,14 +1,17 @@ package com.foxinmy.weixin4j.msg.notify; +import com.foxinmy.weixin4j.msg.model.Text; import com.foxinmy.weixin4j.type.MessageType; -import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 客服文本消息 + * * @author jy.hu * @date 2014年4月4日 * @since JDK 1.7 - * @see 客服文本消息 + * @see 客服文本消息 + * @see com.foxinmy.weixin.msg.model.Text * @see com.foxinmy.weixin4j.msg.notify.BaseNotify * @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson() */ @@ -22,27 +25,24 @@ public class TextNotify extends BaseNotify { public TextNotify(String content) { super(MessageType.text); - this.text = new $(content); + this.text = new Text(content); } public TextNotify(String content, String touser) { super(touser, MessageType.text); - this.text = new $(content); + this.text = new Text(content); } - @XStreamAlias("text") - private $ text; - - private static class $ { - @XStreamAlias("content") - private String content; - - public $(String content) { - this.content = 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.content); + return String.format("[TextNotify touser=%s ,msgtype=%s ,content=%s]", + super.getTouser(), super.getMsgtype().name(), + this.text.getContent()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/notify/VideoNotify.java b/src/main/java/com/foxinmy/weixin4j/msg/notify/VideoNotify.java index d8865910..8e433c03 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/notify/VideoNotify.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/notify/VideoNotify.java @@ -1,14 +1,17 @@ package com.foxinmy.weixin4j.msg.notify; +import com.foxinmy.weixin4j.msg.model.Video; import com.foxinmy.weixin4j.type.MessageType; -import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 客服视频消息 + * * @author jy.hu * @date 2014年4月4日 * @since JDK 1.7 - * @see 客服视频消息 + * @see 客服视频消息 + * @see com.foxinmy.weixin4j.msg.model.Video * @see com.foxinmy.weixin4j.msg.notify.BaseNotify * @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson() */ @@ -23,36 +26,21 @@ public class VideoNotify extends BaseNotify { public VideoNotify(String touser) { super(touser, MessageType.video); } - - public void pushVideo(String mediaId, String title, String desc) { - this.video = new $(mediaId, title, desc); + + public void pushVideo(String mediaId, String thumbMediaId) { + this.video = new Video(mediaId, thumbMediaId); } - @XStreamAlias("video") - private $ video; - - private static class $ { - @XStreamAlias("media_id") - private String mediaId; - private String title; - @XStreamAlias("description") - private String desc; - - public $(String mediaId, String title, String desc) { - this.mediaId = mediaId; - this.title = title; - this.desc = desc; - } - - @Override - public String toString() { - return String.format("(video mediaId=%s ,title=%s ,description=%s)", mediaId, title, desc); - } + 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()); + return String.format("[VideoNotify touser=%s ,msgtype=%s ,video=%s]", + super.getTouser(), super.getMsgtype().name(), + this.video.toString()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/notify/VoiceNotify.java b/src/main/java/com/foxinmy/weixin4j/msg/notify/VoiceNotify.java index 8e0787b6..4cfb7a7f 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/notify/VoiceNotify.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/notify/VoiceNotify.java @@ -1,14 +1,17 @@ package com.foxinmy.weixin4j.msg.notify; +import com.foxinmy.weixin4j.msg.model.Voice; import com.foxinmy.weixin4j.type.MessageType; -import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 客服语音消息 + * * @author jy.hu * @date 2014年4月4日 * @since JDK 1.7 - * @see 客服语音消息 + * @see 客服语音消息 + * @see com.foxinmy.weixin4j.msg.model.Voice * @see com.foxinmy.weixin4j.msg.notify.BaseNotify * @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson() */ @@ -20,30 +23,25 @@ public class VoiceNotify extends BaseNotify { super(MessageType.voice); } - public VoiceNotify(String mediaId) { - super(MessageType.voice); - this.voice = new $(mediaId); + public VoiceNotify(String touser) { + super(touser, MessageType.voice); } public VoiceNotify(String mediaId, String touser) { super(touser, MessageType.voice); - this.voice = new $(mediaId); + this.pushMediaId(mediaId); } - @XStreamAlias("voice") - private $ voice; - - private static class $ { - @XStreamAlias("media_id") - private String mediaId; - - public $(String mediaId) { - this.mediaId = 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.mediaId); + return String.format("[VoiceNotify touser=%s ,msgtype=%s ,mediaId=%s]", + super.getTouser(), super.getMsgtype().name(), + this.voice.getMediaId()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/ArticleMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/ArticleMessage.java index e892aeaa..9c3737a7 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/ArticleMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/ArticleMessage.java @@ -4,36 +4,36 @@ import java.util.LinkedList; import java.util.List; 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 回复图文消息 + * @see 回复图文消息 + * @see com.foxinmy.weixin.msg.model.Article * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class ArticleMessage extends BaseMessage { private static final int MAX_ARTICLE_COUNT = 10; private static final long serialVersionUID = -7331603018352309317L; - public ArticleMessage() { - super(MessageType.news); - } - - public ArticleMessage(String toUserName) { - super(MessageType.news); - super.setToUserName(toUserName); + public ArticleMessage(BaseMessage inMessage) { + super(MessageType.news, inMessage); } @XStreamAlias("ArticleCount") private int count; // 图文消息个数,限制为10条以内 @XStreamAlias("Articles") - private List articles; + private LinkedList articles; public List getArticles() { return this.articles; @@ -44,39 +44,55 @@ public class ArticleMessage extends BaseMessage { return; } if (this.articles == null) { - this.articles = new LinkedList(); + this.articles = new LinkedList(); } this.articles.add(new Article(title, desc, picUrl, url)); - count ++; + count++; } - @XStreamAlias("item") - private static class Article { - @XStreamAlias("Title") - private String title; // 图文消息标题 - @XStreamAlias("Description") - private String desc; // 图文消息描述 - @XStreamAlias("PicUrl") - private String picUrl; // 图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200 - @XStreamAlias("Url") - private String url; // 点击图文消息跳转链接 - - public Article(String title, String desc, String picUrl, String url) { - this.title = title; - this.desc = desc; - this.picUrl = picUrl; - this.url = url; + public void pushFirstArticle(String title, String desc, String picUrl, + String url) { + if (this.articles == null) { + this.articles = new LinkedList(); } + this.articles.addFirst(new Article(title, desc, picUrl, url)); + } - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Article ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,picUrl=").append(picUrl); - sb.append(" ,url=").append(url).append(")"); - return sb.toString(); + public void pushLastArticle(String title, String desc, String picUrl, + String url) { + if (this.articles == null) { + this.articles = new LinkedList(); } + this.articles.addLast(new Article(title, desc, picUrl, url)); + } + + public Article removeLastArticle() { + if (this.articles != null) { + return this.articles.removeLast(); + } + return null; + } + + 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() { + 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 diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java index 2da50a01..fb58ecb8 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java @@ -1,38 +1,50 @@ 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 回复图片消息 + * @see 回复图片消息 + * @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() { - super(MessageType.image); + public ImageMessage(BaseMessage inMessage) { + super(MessageType.image, inMessage); super.getMsgType().setMessageClass(ImageMessage.class); } + 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(); - this.image.mediaId = mediaId; + this.image = new Image(mediaId); } - private static class Image { - @XStreamAlias("MediaId") - private String mediaId; + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Image.class, "mediaId"); + return xstream.toXML(this); } @Override @@ -41,7 +53,7 @@ public class ImageMessage extends BaseMessage { sb.append("[ImageMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,mediaId=").append(this.image.mediaId); + sb.append(" ,mediaId=").append(this.image.getMediaId()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java index c790b9ac..419f32d6 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java @@ -1,74 +1,61 @@ 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 回复音乐消息 + * @see 回复音乐消息 + * @see com.foxinmy.weixin4j.msg.model.Music * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class MusicMessage extends BaseMessage { private static final long serialVersionUID = 4384403772658796395L; - public MusicMessage() { - super(MessageType.music); + public MusicMessage(BaseMessage inMessage) { + super(MessageType.music, inMessage); } @XStreamAlias("Music") private Music music; - public Music getMusic() { - return this.music; + public void pushMusic(String mediaId) { + this.music = new Music(mediaId); } - public void pushMusic(String title, String desc, String url, String hqUrl, String mediaId) { - this.music = new Music(); - this.music.thumbMediaId = mediaId; - this.music.desc = desc; - this.music.hqMusicUrl = hqUrl; - this.music.MusicURL = url; - this.music.title = title; + public void setMusic(Music music) { + this.music = music; } - private static class Music { - @XStreamAlias("Title") - private String title; // 音乐标题 - @XStreamAlias("Description") - private String desc; // 音乐描述 - @XStreamAlias("MusicURL") - private String MusicURL; // 音乐链接 - @XStreamAlias("HQMusicUrl") - private String hqMusicUrl; // 高质量音乐链接,WIFI环境优先使用该链接播放音乐 - @XStreamAlias("ThumbMediaId") - private String thumbMediaId; // 缩略图的媒体id,通过上传多媒体文件,得到的id - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Music ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,musicURL=").append(MusicURL); - sb.append(" ,hqMusicUrl=").append(hqMusicUrl); - sb.append(" ,thumbMediaId=").append(thumbMediaId).append(")"); - return sb.toString(); - } + @Override + public String 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(getMusic().toString()); + sb.append(" ,music=").append(music.toString()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java new file mode 100644 index 00000000..3721504b --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java @@ -0,0 +1,117 @@ +package com.foxinmy.weixin4j.msg.out; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +import com.alibaba.fastjson.JSON; + +/** + * 模板消息 + * + * @className TemplateMessage + * @author jy + * @date 2014年9月29日 + * @since JDK 1.7 + * @see + */ +public class TemplateMessage implements Serializable { + + private static final long serialVersionUID = 7950608393821661436L; + + private String touser; + private String template_id; + private String url; + private String topcolor = "#FF0000"; + private Map data; + + public void pushData(String key, String value) { + this.data.put(key, new Item(value)); + } + + public TemplateMessage(String touser, String template_id, String url) { + this.touser = touser; + this.template_id = template_id; + this.url = url; + this.data = new HashMap(); + } + + private static class Item implements Serializable { + private static final long serialVersionUID = 1L; + private String value; + private String color; + + public Item(String value) { + this(value, "#173177"); + } + + public Item(String value, String color) { + this.value = value; + this.color = color; + } + + public String getValue() { + return value; + } + + public String getColor() { + return color; + } + + @Override + public String toString() { + return "$ [value=" + getValue() + ", color=" + getColor() + "]"; + } + } + + public String getTouser() { + return touser; + } + + public void setTouser(String touser) { + this.touser = touser; + } + + public String getTemplate_id() { + return template_id; + } + + public void setTemplate_id(String template_id) { + this.template_id = template_id; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getTopcolor() { + return topcolor; + } + + public void setTopcolor(String topcolor) { + this.topcolor = topcolor; + } + + public Map getData() { + return data; + } + + public void setData(Map data) { + this.data = data; + } + + @Override + public String toString() { + return "TemplateMessage [touser=" + touser + ", template_id=" + + template_id + ", url=" + url + ", topcolor=" + topcolor + + ", data=" + data + "]"; + } + + public String toJson() { + return JSON.toJSONString(this); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java new file mode 100644 index 00000000..b89621aa --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java @@ -0,0 +1,25 @@ +package com.foxinmy.weixin4j.msg.out; + +import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.type.MessageType; + +/** + * 转移消息到多客服端消息 + * + * @className TransferMessage + * @author jy.hu + * @date 2014年6月28日 + * @since JDK 1.7 + * @see 多客服转移消息 + * @see com.foxinmy.weixin4j.msg.BaseMessage + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + */ +public class TransferMessage extends BaseMessage { + + private static final long serialVersionUID = -5479496746108594940L; + + public TransferMessage(BaseMessage inMessage) { + super(MessageType.transfer_customer_service,inMessage); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java index d16c5a12..d6cdfc91 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java @@ -1,58 +1,52 @@ package com.foxinmy.weixin4j.msg.out; import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.msg.model.Video; import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 回复视频消息 + * * @className VideoMessage * @author jy.hu * @date 2014年4月6日 * @since JDK 1.7 - * @see 回复视频消息 + * @see 回复视频消息 + * @see com.foxinmy.weixin4j.msg.model.Video * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class VideoMessage extends BaseMessage { private static final long serialVersionUID = -1013075358679078381L; - public VideoMessage() { - super(MessageType.video); + public VideoMessage(BaseMessage inMessage) { + super(MessageType.video, inMessage); super.getMsgType().setMessageClass(VideoMessage.class); } @XStreamAlias("Video") private Video video; - public Video getVideo() { - return this.video; + public void pushVideo(String mediaId) { + this.video = new Video(mediaId); } - public void pushVideo(String mediaId, String title, String desc) { - this.video = new Video(); - this.video.desc = desc; - this.video.mediaId = mediaId; - this.video.title = title; + public void setVideo(Video video) { + this.video = video; } - private static class Video { - @XStreamAlias("MediaId") - private String mediaId; - @XStreamAlias("Title") - private String title; - @XStreamAlias("Description") - private String desc; - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Video mediaId=").append(mediaId); - sb.append(" ,title=").append(title); - sb.append(" ,desc=").append(desc).append(")"); - return super.toString(); - } + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Video.class, "mediaId"); + xstream.aliasField("Title", Video.class, "title"); + xstream.aliasField("Description", Video.class, "desc"); + xstream.omitField(Video.class, "thumbMediaId"); + return xstream.toXML(this); } @Override @@ -61,7 +55,7 @@ public class VideoMessage extends BaseMessage { sb.append("[VideoMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,video=").append(getVideo().toString()); + sb.append(" ,video=").append(video.toString()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java index 93052907..dcac1046 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java @@ -1,53 +1,60 @@ package com.foxinmy.weixin4j.msg.out; import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.msg.model.Voice; import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 语音消息 + * * @className VoiceMessage * @author jy.hu * @date 2014年3月23日 * @since JDK 1.7 - * @see 回复语音消息 + * @see 回复语音消息 + * @see com.foxinmy.weixin4j.msg.model.Voice * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class VoiceMessage extends BaseMessage { private static final long serialVersionUID = -7944926238652243793L; - public VoiceMessage() { - super(MessageType.voice); + public VoiceMessage(BaseMessage inMessage) { + super(MessageType.voice, inMessage); super.getMsgType().setMessageClass(VoiceMessage.class); } + + public VoiceMessage(String mediaId, BaseMessage inMessage) { + super(MessageType.voice, inMessage); + super.getMsgType().setMessageClass(VoiceMessage.class); + this.pushMediaId(mediaId); + } + @XStreamAlias("Voice") private Voice voice; - - public Voice getVocie() { - return voice; + + public void pushMediaId(String mediaId) { + this.voice = new Voice(mediaId); } - public void pushMediaId(String mediaId){ - this.voice = new Voice(); - this.voice.setMediaId(mediaId); - } - - private static class Voice { - @XStreamAlias("MediaId") - private String mediaId; - - private void setMediaId(String mediaId) { - this.mediaId = mediaId; - } + + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Voice.class, "mediaId"); + return xstream.toXML(this); } + @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("[VoiceMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,mediaId=").append(getVocie().mediaId); + sb.append(" ,mediaId=").append(voice.getMediaId()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java b/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java new file mode 100644 index 00000000..cf2ab68e --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java @@ -0,0 +1,55 @@ +package com.foxinmy.weixin4j.type; + +/** + * 自定义菜单类型 + * scancode_push 到 location_selec + * 仅支持微信iPhone5.4.1以上版本,和Android5 .4以上版本的微信用户 旧版本微信用户点击后将没有回应 + * 开发者也不能正常接收到事件推送。 + * + * @className ButtonType + * @author jy + * @date 2014年9月30日 + * @since JDK 1.7 + * @see 按钮类型 + */ +public enum ButtonType { + /** + * 点击推事件 用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event + * 的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互; + */ + click, + /** + * 跳转URL 用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的网页URL,可与网页授权获取用户基本信息接口结合,获得用户基本信息。 + */ + view, + /** + * 扫码推事件 用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后显示扫描结果(如果是URL,将进入URL),且会将扫码的结果传给开发者, + * 开发者可以下发消息。 + */ + scancode_push, + /** + * 扫码推事件且弹出“消息接收中”提示框用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后,将扫码的结果传给开发者,同时收起扫一扫工具, + * 然后弹出“消息接收中”提示框,随后可能会收到开发者下发的消息。 + */ + scancode_waitmsg, + /** + * 弹出系统拍照发图用户点击按钮后,微信客户端将调起系统相机,完成拍照操作后,会将拍摄的相片发送给开发者,并推送事件给开发者,同时收起系统相机, + * 随后可能会收到开发者下发的消息。 + */ + pic_sysphoto, + /** + * 弹出拍照或者相册发图用户点击按钮后,微信客户端将弹出选择器供用户选择“拍照”或者“从手机相册选择”。用户选择后即走其他两种流程。 + */ + pic_photo_or_albu, + /** + * 弹出微信相册发图器用户点击按钮后,微信客户端将调起微信相册,完成选择操作后,将选择的相片发送给开发者的服务器,并推送事件给开发者,同时收起相册, + * 随后可能会收到开发者下发的消息。 + */ + pic_weixin, + /** + * 弹出地理位置选择器用户点击按钮后,微信客户端将调起地理位置选择工具,完成选择操作后,将选择的地理位置发送给开发者的服务器,同时收起位置选择工具, + * 随后可能会收到开发者下发的消息。 + */ + location_select; +} diff --git a/src/main/java/com/foxinmy/weixin4j/type/EventType.java b/src/main/java/com/foxinmy/weixin4j/type/EventType.java index a8e864b8..bc85ce90 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/EventType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/EventType.java @@ -3,21 +3,36 @@ package com.foxinmy.weixin4j.type; import com.foxinmy.weixin4j.msg.event.EventMessage; import com.foxinmy.weixin4j.msg.event.LocationEventMessage; import com.foxinmy.weixin4j.msg.event.MassEventMessage; -import com.foxinmy.weixin4j.msg.event.MenuEventMessage; import com.foxinmy.weixin4j.msg.event.ScanEventMessage; import com.foxinmy.weixin4j.msg.event.ScribeEventMessage; +import com.foxinmy.weixin4j.msg.event.TemplatesendjobfinishMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuLocationEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuPhotoEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuScanEventMessage; /** - * * 事件类型 - * @author jy.hu - * + * + * @className EventType + * @author jy + * @date 2014年9月30日 + * @since JDK 1.7 + * @see */ public enum EventType { - subscribe(ScribeEventMessage.class), unsubscribe(ScribeEventMessage.class), - scan(ScanEventMessage.class),click(MenuEventMessage.class),view(MenuEventMessage.class), - location(LocationEventMessage.class),MASSSENDJOBFINISH(MassEventMessage.class); - + subscribe(ScribeEventMessage.class), unsubscribe(ScribeEventMessage.class), scan( + ScanEventMessage.class), scancode_push(MenuScanEventMessage.class), view( + MenuEventMessage.class), scancode_waitmsg( + MenuScanEventMessage.class), pic_sysphoto( + MenuPhotoEventMessage.class), pic_photo_or_album( + MenuPhotoEventMessage.class), pic_weixin( + MenuPhotoEventMessage.class), location_select( + MenuLocationEventMessage.class), click(MenuEventMessage.class), location( + LocationEventMessage.class), massendjobfinish( + MassEventMessage.class), templatesendjobfinish( + TemplatesendjobfinishMessage.class); + private Class extends EventMessage> eventClass; EventType(Class extends EventMessage> eventClass) { diff --git a/src/main/java/com/foxinmy/weixin4j/type/MediaType.java b/src/main/java/com/foxinmy/weixin4j/type/MediaType.java index 1f567181..322ba3ce 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/MediaType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/MediaType.java @@ -6,13 +6,20 @@ package com.foxinmy.weixin4j.type; * 语音(voice):256K,播放长度不超过60s,支持AMR\MP3格式 * 视频(video):1MB,支持MP4格式 * 缩略图(thumb):64KB,支持JPG格式 - * 媒体文件在后台保存时间为3天,即3天后media_id失效 + * + * 媒体文件在后台保存时间为3天,即3天后media_id失效 + * + * * @author jy.hu * @date 2014年4月2日 * @since JDK 1.7 */ public enum MediaType { - image("image/jpeg",".jpg"), voice("binary/octet-stream","amr"), vedio("binary/octet-stream","mp4"), thumb("image/jpeg","jpg"); + image("image/jpeg", "jpg"), voice("binary/octet-stream", "amr"), vedio( + "binary/octet-stream", "mp4"), thumb("image/jpeg", "jpg"), text( + "application/json", ""), music("binary/octet-stream", "mp3"), news( + "application/json", ""), mpnews("application/json", ""), mpvideo( + "binary/octet-stream", ""); MediaType(String contentType, String formatType) { this.contentType = contentType; @@ -26,6 +33,7 @@ public enum MediaType { } private String formatType; + public String getFormatType() { return formatType; } diff --git a/src/main/java/com/foxinmy/weixin4j/type/MessageType.java b/src/main/java/com/foxinmy/weixin4j/type/MessageType.java index 21a7b6dc..a883d993 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/MessageType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/MessageType.java @@ -10,6 +10,7 @@ import com.foxinmy.weixin4j.msg.in.VideoMessage; import com.foxinmy.weixin4j.msg.in.VoiceMessage; import com.foxinmy.weixin4j.msg.out.ArticleMessage; import com.foxinmy.weixin4j.msg.out.MusicMessage; +import com.foxinmy.weixin4j.msg.out.TransferMessage; /** * @@ -20,9 +21,13 @@ import com.foxinmy.weixin4j.msg.out.MusicMessage; */ public enum MessageType { // 接收到的消息类型 - text(TextMessage.class), image(ImageMessage.class), voice(VoiceMessage.class), video(VideoMessage.class), location(LocationMessage.class), link(LinkMessage.class), event(EventMessage.class), + text(TextMessage.class), image(ImageMessage.class), voice( + VoiceMessage.class), video(VideoMessage.class), location( + LocationMessage.class), link(LinkMessage.class), event( + EventMessage.class), // 发送的消息类型 - music(MusicMessage.class), news(ArticleMessage.class); + music(MusicMessage.class), news(ArticleMessage.class), transfer_customer_service( + TransferMessage.class); private Class extends BaseMessage> messageClass; MessageType(Class extends BaseMessage> messageClass) { diff --git a/src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java b/src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java similarity index 91% rename from src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java rename to src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java index f428c33b..b419bd1c 100644 --- a/src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java +++ b/src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java @@ -8,8 +8,8 @@ import java.util.regex.Pattern; import com.foxinmy.weixin4j.WeixinProxy; -public class WeixinConfig { - public WeixinConfig() { +public class ConfigUtil { + public ConfigUtil() { } private static Properties props = new Properties(); @@ -38,7 +38,6 @@ public class WeixinConfig { m.appendTail(sb); return sb.toString(); } - public static void main(String[] args) { System.out.println(getValue("api_token_uri")); } diff --git a/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java b/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java new file mode 100644 index 00000000..60eae107 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java @@ -0,0 +1,67 @@ +package com.foxinmy.weixin4j.util; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.Writer; +import java.nio.charset.Charset; + +/** + * IOUtil + * + * @className IOUtil + * @author jy.hu + * @date 2014年9月22日 + * @since JDK 1.7 + * @see org.apache.commons.io.IOUtils + */ +public class IOUtil { + + private static final int EOF = -1; + private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; + + public static byte[] toByteArray(Reader input) throws IOException { + return toByteArray(input, Charset.defaultCharset()); + } + + public static byte[] toByteArray(Reader input, Charset encoding) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + copy(input, output, encoding); + return output.toByteArray(); + } + + public static void copy(Reader input, OutputStream output, Charset encoding) throws IOException { + OutputStreamWriter out = new OutputStreamWriter(output, encoding); + copyLarge(input, out, new char[DEFAULT_BUFFER_SIZE]); + out.flush(); + } + + public static byte[] toByteArray(InputStream input) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + copyLarge(input, output, new byte[DEFAULT_BUFFER_SIZE]); + return output.toByteArray(); + } + + private static long copyLarge(InputStream input, OutputStream output, byte[] buffer) throws IOException { + long count = 0; + int n = 0; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } + + private static long copyLarge(Reader input, Writer output, char[] buffer) throws IOException { + long count = 0; + int n = 0; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java b/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java new file mode 100644 index 00000000..82a23ef3 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java @@ -0,0 +1,135 @@ +package com.foxinmy.weixin4j.util; + +import java.io.InputStream; +import java.util.Arrays; + +import org.apache.commons.codec.digest.DigestUtils; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.DocumentHelper; +import org.dom4j.io.SAXReader; +import org.jsoup.helper.StringUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.type.EventType; +import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; + +public class MessageUtil { + + private final static Logger log = LoggerFactory.getLogger(MessageUtil.class); + + /** + * 验证微信签名 + * + * @param echostr + * 随机字符串 + * @param timestamp + * 时间戳 + * @param nonce + * 随机数 + * @param signature + * 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数 + * @return 开发者通过检验signature对请求进行相关校验。若确认此次GET请求来自微信服务器 + * 请原样返回echostr参数内容,则接入生效 成为开发者成功,否则接入失败 + * @see 接入指南 + */ + public static String signature(String echostr, String timestamp, String nonce, String signature) { + String app_token = ConfigUtil.getValue("app_token"); + if (StringUtil.isBlank(app_token)) { + log.error("signature fail : token is null!"); + return null; + } + if (StringUtil.isBlank(echostr) || StringUtil.isBlank(timestamp) || StringUtil.isBlank(nonce)) { + log.error("signature fail : invalid parameter!"); + return null; + } + String _signature = null; + try { + String[] a = { app_token, timestamp, nonce }; + Arrays.sort(a); + StringBuilder sb = new StringBuilder(3); + for (String str : a) { + sb.append(str); + } + _signature = DigestUtils.sha1Hex(sb.toString()); + } catch (Exception e) { + log.error("signature error", e); + } + if (signature.equals(_signature)) { + return echostr; + } else { + log.error("signature fail : invalid signature!"); + return null; + } + } + + /** + * xml消息转换为消息对象 + * + * 微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次 + * + * + * @param xml + * 消息字符串 + * @return 消息对象 + * @throws DocumentException + * @see 验证消息的合法性 + * @see 普通消息 + * @see 事件触发 + * @see com.foxinmy.weixin4j.type.MessageType + * @see com.feican.weixin.msg.BaeMessage + * @see com.foxinmy.weixin4j.msg.TextMessage + * @see com.foxinmy.weixin4j.msg.in.ImageMessage + * @see com.foxinmy.weixin4j.msg.in.VoiceMessage + * @see com.foxinmy.weixin4j.msg.in.VideoMessage + * @see com.foxinmy.weixin4j.msg.in.LocationMessage + * @see com.foxinmy.weixin4j.msg.in.LinkMessage + * @see com.foxinmy.weixin4j.msg.event.ScribeEventMessage + * @see com.foxinmy.weixin4j.msg.event.ScanEventMessage + * @see com.foxinmy.weixin4j.msg.event.LocationEventMessage + * @see com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage + */ + public static BaseMessage xml2msg(String xml) throws DocumentException { + if (StringUtil.isBlank(xml)) + return null; + Document doc = DocumentHelper.parseText(xml); + String type = doc.selectSingleNode("/xml/MsgType").getStringValue(); + if (StringUtil.isBlank(type)) { + return null; + } + XStream xstream = new XStream(); + MessageType messageType = MessageType.valueOf(type.toLowerCase()); + Class extends BaseMessage> messageClass = messageType.getMessageClass(); + if (messageType == MessageType.event) { + type = doc.selectSingleNode("/xml/Event").getStringValue(); + messageClass = EventType.valueOf(type.toLowerCase()).getEventClass(); + } + xstream.alias("xml", messageClass); + xstream.ignoreUnknownElements(); + xstream.autodetectAnnotations(true); + xstream.processAnnotations(messageClass); + return xstream.fromXML(doc.asXML(), messageClass); + } + + /** + * xml消息转换为消息对象 + * + * @param inputStream + * 带消息字符串的输入流 + * @return 消息对象 + * @throws DocumentException + * @see {@link com.foxinmy.weixin4j.WeixinProxy#xml2msg(String)} + */ + public static BaseMessage xml2msg(InputStream inputStream) throws DocumentException { + SAXReader reader = new SAXReader(); + Document doc = reader.read(inputStream); + return xml2msg(doc.asXML()); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java b/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java deleted file mode 100644 index 19fd87e4..00000000 --- a/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.foxinmy.weixin4j.util; - -public class WeixinUtil { - - public static boolean isBlank(String str) { - return str == null || str.isEmpty(); - } -} diff --git a/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java b/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java index 5c0186c6..4a811a6c 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java @@ -9,7 +9,7 @@ import org.junit.Test; import com.foxinmy.weixin4j.WeixinProxy; import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.model.Button; -import com.foxinmy.weixin4j.model.Button.BtnType; +import com.foxinmy.weixin4j.type.ButtonType; /** * 自定义菜单测试 @@ -31,7 +31,7 @@ public class ButtonTest { List btnList = new ArrayList(); Button b = new Button("test"); - b.setType(BtnType.click); + b.setType(ButtonType.click); b.setKey("123"); btnList.add(b); diff --git a/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java b/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java index 8b78305e..bb6bec88 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java @@ -50,7 +50,7 @@ public class GroupTest { @Test public void getid() { try { - System.out.println(weixinProxy.findGroupByOpenId("owGBft_vbBbOaQOmpEUE4xDLeRSU")); + System.out.println(weixinProxy.getGroupByOpenId("owGBft_vbBbOaQOmpEUE4xDLeRSU")); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); diff --git a/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java b/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java new file mode 100644 index 00000000..6d34a733 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java @@ -0,0 +1,22 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Test; + +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.http.HttpRequest; + +public class HttpTest { + private static HttpRequest request; + static { + request = new HttpRequest(); + } + + @Test + public void test(){ + try { + System.out.println(request.get("http://www.baidu.com")); + } catch (WeixinException e) { + e.printStackTrace(); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java b/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java index f907fa3d..d54e649b 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java @@ -31,7 +31,7 @@ public class MediaTest { File file = new File("D:\\test.jpg"); try { System.out.println(weixinProxy.uploadMedia(file, MediaType.image)); - //usAxLEJxFXAjXVlLu_BSw0GvS2YEEoGeelRBybNZBGvMsdxiIcD1F9yBWYd9jVZx + //vvU_AUtovWyfAxQ8J1DsCoNMtK6U_bUmTpe6lpINUOVRLvt_7rtO4zxzBpPgkmay } catch (WeixinException e) { System.out.println(e.getErrorMsg()); } @@ -40,7 +40,7 @@ public class MediaTest { @Test public void download() { try { - System.out.println(weixinProxy.downloadMedia("usAxLEJxFXAjXVlLu_BSw0GvS2YEEoGeelRBybNZBGvMsdxiIcD1F9yBWYd9jVZx", MediaType.image)); + System.out.println(weixinProxy.downloadMedia("vvU_AUtovWyfAxQ8J1DsCoNMtK6U_bUmTpe6lpINUOVRLvt_7rtO4zxzBpPgkmay", MediaType.image)); } catch (WeixinException e) { System.out.println(e.getErrorMsg()); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java new file mode 100644 index 00000000..2cd36584 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java @@ -0,0 +1,194 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Test; + +import com.foxinmy.weixin4j.util.MessageUtil; + +/** + * 接收事件消息格式测试 + * + * @author jy.hu + * @date 2014年3月24日 + * @since JDK 1.7 + */ +public class MessageEventInTest { + + private StringBuilder xmlSb = new StringBuilder(); + + /***************** event message *********************/ + @Test + public void scribe() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void scan() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void scan_scribe() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void location1() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("23.137466"); + xmlSb.append("113.352425"); + xmlSb.append("119.385040"); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_click() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_link() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_scan() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_photo() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("1"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_location() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java index 39269754..fdd40042 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java @@ -1,134 +1,19 @@ package com.foxinmy.weixin4j.test; -import org.junit.Before; import org.junit.Test; -import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.util.MessageUtil; /** - * 接收消息格式测试 + * 接受一般消息格式测试 + * * @author jy.hu * @date 2014年3月24日 * @since JDK 1.7 */ public class MessageInTest { + private StringBuilder xmlSb = new StringBuilder(); - private WeixinProxy weixinProxy; - - @Before - public void init(){ - weixinProxy = new WeixinProxy(); - } - - /***************** event message *********************/ - @Test - public void scribe() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void scan() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - @Test - public void scan_scribe() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void location1() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("23.137466"); - xmlSb.append("113.352425"); - xmlSb.append("119.385040"); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void menu_click() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void menu_link() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } /***************** common message *********************/ @@ -144,7 +29,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -163,7 +48,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -182,7 +67,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -202,7 +87,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -221,7 +106,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -242,7 +127,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -262,7 +147,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java new file mode 100644 index 00000000..8f6a130f --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java @@ -0,0 +1,114 @@ +package com.foxinmy.weixin4j.test; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.model.MpArticle; +import com.foxinmy.weixin4j.type.MediaType; + +/** + * 群发消息 + * + * @className MpNewsTest + * @author jy + * @date 2014年4月27日 + * @since JDK 1.7 + * @see + */ +public class MessageMassTest { + private WeixinProxy weixinProxy; + + @Before + public void init() { + this.weixinProxy = new WeixinProxy(); + } + + @Test + public void uploadArticle() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.uploadArticle(articles); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void uploadVideo() { + try { + weixinProxy.uploadVideo("mediaId", "title", "desc"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massByGroup() { + try { + weixinProxy.massByGroup("123", MediaType.image, "groupId"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massByOpenIds() { + try { + weixinProxy.massByOpenIds("123", MediaType.image, "openIds"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massArticleByGroup() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.massArticleByGroup(articles, "0"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massArticleByOpenIds() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.massArticleByOpenIds(articles, + "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void deleteMass() { + try { + weixinProxy.deleteMassNews("34182"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java index f3be10bb..59aed8de 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java @@ -7,6 +7,7 @@ import org.junit.Test; import com.foxinmy.weixin4j.WeixinProxy; import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.msg.model.Music; import com.foxinmy.weixin4j.msg.notify.ArticleNotify; import com.foxinmy.weixin4j.msg.notify.BaseNotify; import com.foxinmy.weixin4j.msg.notify.ImageNotify; @@ -41,27 +42,29 @@ public class MessageNotifyTest { @Test public void image() { - ImageNotify notify = new ImageNotify("123", "to"); + ImageNotify notify = new ImageNotify("to"); + notify.pushMediaId("123"); System.out.println(notify.toJson()); } @Test public void voice() { - VoiceNotify notify = new VoiceNotify("123", "to"); + VoiceNotify notify = new VoiceNotify("to"); + notify.pushMediaId("123"); System.out.println(notify.toJson()); } @Test public void video() { VideoNotify notify = new VideoNotify("to"); - notify.pushVideo("123", "title", "desc"); + notify.pushVideo("123","m123"); System.out.println(notify.toJson()); } @Test public void music() { MusicNotify notify = new MusicNotify("to"); - notify.pushMusic("title", "desc", "url", "hqUrl", "mediaId"); + notify.pushMusic("url", "hqUrl", "mediaId"); System.out.println(notify.toJson()); } @@ -74,16 +77,27 @@ public class MessageNotifyTest { } @Test - public void send() { - BaseNotify t = new TextNotify("哈哈哈哈", "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + public void send1() { + BaseNotify notify = new TextNotify("哈哈哈哈", "owGBft_vbBbOaQOmpEUE4xDLeRSU"); try { - weixinProxy.sendNotify(t); + weixinProxy.sendNotify(notify); String mediaId = weixinProxy.uploadMedia(new File("D:\\test.jpg"), MediaType.image); - t = new ImageNotify(mediaId, "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + ImageNotify t = new ImageNotify("owGBft_vbBbOaQOmpEUE4xDLeRSU"); + t.pushMediaId(mediaId); weixinProxy.sendNotify(t); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); } } + + @Test + public void send2() { + try { + weixinProxy.sendNotify("to",new Music("thumbMediaId")); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java index 00021aa0..ddb309d4 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java @@ -1,7 +1,9 @@ package com.foxinmy.weixin4j.test; +import org.junit.Before; import org.junit.Test; +import com.foxinmy.weixin4j.msg.BaseMessage; import com.foxinmy.weixin4j.msg.TextMessage; import com.foxinmy.weixin4j.msg.out.ArticleMessage; import com.foxinmy.weixin4j.msg.out.ImageMessage; @@ -17,56 +19,52 @@ import com.foxinmy.weixin4j.msg.out.VoiceMessage; * @since JDK 1.7 */ public class MessageOutTest { + private BaseMessage inMessage; + + @Before + public void init() { + this.inMessage = new TextMessage(); + this.inMessage.setFromUserName("fromusername"); + this.inMessage.setToUserName("tousername"); + } + @Test public void text() { - TextMessage message = new TextMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.setContent("text message"); + TextMessage message = new TextMessage("text", inMessage); System.out.println(message.toXml()); } @Test public void image() { - ImageMessage message = new ImageMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + ImageMessage message = new ImageMessage(inMessage); message.pushMediaId("mediaId"); System.out.println(message.toXml()); } @Test public void voice() { - VoiceMessage message = new VoiceMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + VoiceMessage message = new VoiceMessage(inMessage); message.pushMediaId("mediaId"); System.out.println(message.toXml()); } - + @Test public void video() { - VideoMessage message = new VideoMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.pushVideo("mediaId", "title", "title"); + VideoMessage message = new VideoMessage(inMessage); + message.pushVideo("mediaId"); System.out.println(message.toXml()); } - + @Test public void music() { - MusicMessage message = new MusicMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.pushMusic("title", "desc", "url", "hqurl", "mediaId"); + MusicMessage message = new MusicMessage(inMessage); + message.pushMusic("mediaId"); System.out.println(message.toXml()); } - + @Test public void article() { - ArticleMessage message = new ArticleMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + ArticleMessage message = new ArticleMessage(inMessage); message.pushArticle("title1", "desc1", "picUrl1", "url1"); message.pushArticle("title2", "desc2", "picUrl2", "url2"); System.out.println(message.toXml()); diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java new file mode 100644 index 00000000..b8165a91 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java @@ -0,0 +1,30 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Before; +import org.junit.Test; + +import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.msg.out.TemplateMessage; + +public class MessageTemplTest { + private WeixinProxy weixinProxy; + + @Before + public void init() { + this.weixinProxy = new WeixinProxy(); + } + + @Test + public void test() { + TemplateMessage tplMessage = new TemplateMessage("touser", + "template_id", "url"); + tplMessage.pushData("name", "fox"); + System.out.print(tplMessage.toJson()); + try { + System.out.print(weixinProxy.sendTplMessage(tplMessage)); + } catch (WeixinException e) { + System.out.println(e.getErrorMsg()); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java b/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java deleted file mode 100644 index 5fa1ec67..00000000 --- a/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.foxinmy.weixin4j.test; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; - -import com.foxinmy.weixin4j.WeixinProxy; -import com.foxinmy.weixin4j.exception.WeixinException; -import com.foxinmy.weixin4j.model.MpArticle; -import com.foxinmy.weixin4j.type.MediaType; - -/** - * 群发消息 - * - * @className MpNewsTest - * @author jy - * @date 2014年4月27日 - * @since JDK 1.7 - * @see - */ -public class MpNewsTest { - private WeixinProxy weixinProxy; - - @Before - public void init() { - this.weixinProxy = new WeixinProxy(); - } - - @Test - public void massByGroup(){ - List articles = new ArrayList(); - try { - String thumbMediaId = weixinProxy.uploadMedia(new File("/tmp/test.jpg"), MediaType.image); - articles.add(new MpArticle(thumbMediaId, "title", "content")); - weixinProxy.massNewsByGroup(articles, "0"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } - - @Test - public void massByOpenIds(){ - List articles = new ArrayList(); - try { - String thumbMediaId = weixinProxy.uploadMedia(new File("/tmp/test.jpg"), MediaType.image); - articles.add(new MpArticle(thumbMediaId, "title", "content")); - weixinProxy.massNewsByOpenIds(articles, "owGBft_vbBbOaQOmpEUE4xDLeRSU"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } - - @Test - public void deleteMass(){ - try { - weixinProxy.deleteMassNews("34182"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } -} diff --git a/src/test/java/com/foxinmy/weixin4j/test/QRTest.java b/src/test/java/com/foxinmy/weixin4j/test/QRTest.java index 11934fa9..f18d1aa7 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/QRTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/QRTest.java @@ -25,10 +25,10 @@ public class QRTest { @Test public void temp_qr() { - QRParameter qr = new QRParameter(1200, QRType.QR_SCENE, 1); + QRParameter qr = new QRParameter(1200, QRType.TEMPORARY, 2); try { System.out.println(qr.toJson()); - weixinProxy.getQR(qr); + System.out.println(weixinProxy.getQR(qr)); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); @@ -37,10 +37,10 @@ public class QRTest { @Test public void forever_qr() { - QRParameter qr = new QRParameter(QRType.QR_LIMIT_SCENE, 1); + QRParameter qr = new QRParameter(QRType.PERMANENCE, 1); try { System.out.println(qr.toJson()); - weixinProxy.getQR(qr); + System.out.println(weixinProxy.getQR(qr)); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java b/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java index 37d549d7..a2f8a266 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java @@ -3,7 +3,8 @@ package com.foxinmy.weixin4j.test; import org.junit.Before; import org.junit.Test; -import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.api.token.FileTokenApi; +import com.foxinmy.weixin4j.api.token.TokenApi; import com.foxinmy.weixin4j.exception.WeixinException; /** @@ -14,17 +15,17 @@ import com.foxinmy.weixin4j.exception.WeixinException; * @since JDK 1.7 */ public class TokenTest { - private WeixinProxy weixinProxy; + private TokenApi tokenApi; @Before public void init() { - weixinProxy = new WeixinProxy(); + tokenApi = new FileTokenApi(); } @Test public void getToken() { try { - System.out.println(weixinProxy.getToken()); + System.out.println(tokenApi.getToken()); } catch (WeixinException e) { e.printStackTrace(); }
articles) { + count = articles.size(); + if (articles.size() > MAX_ARTICLE_COUNT) { + count = MAX_ARTICLE_COUNT; + articles = articles.subList(0, count); } - - public void pushArticle(String title, String desc, String picUrl, String url) { - this.articles.add(new $(title, desc, picUrl, url)); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - for ($ item : articles) { - sb.append("{title=").append(item.title); - sb.append(" ,description=").append(item.desc); - sb.append(" ,picUrl=").append(item.picUrl); - sb.append(" ,url=").append(item.url).append("}"); - } - return sb.toString(); + if (this.news == null) { + this.news = new News(); } + this.news.setArticles(articles); } - private static class $ { - private String title; // 图文消息标题 - @XStreamAlias("description") - private String desc; // 图文消息描述 - @XStreamAlias("picurl") - private String picUrl; // 图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200 - @XStreamAlias("url") - private String url; // 点击图文消息跳转链接 + private static class News { + @XStreamAlias("articles") + private List articles; - public $(String title, String desc, String picUrl, String url) { - this.title = title; - this.desc = desc; - this.picUrl = picUrl; - this.url = url; + public News() { + this.articles = new LinkedList(); + } + + public void pushArticle(String title, String desc, String picUrl, + String url) { + this.articles.add(new Article(title, desc, picUrl, url)); + } + + public void setArticles(List articles) { + this.articles = articles; } @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("(article ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,picUrl=").append(picUrl); - sb.append(" ,url=").append(url).append(")"); + 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()); + return String.format( + "[ArticleNotify touser=%s ,msgtype=%s ,articles=%s]", + super.getTouser(), super.getMsgtype().name(), + this.news.toString()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/notify/ImageNotify.java b/src/main/java/com/foxinmy/weixin4j/msg/notify/ImageNotify.java index f9a52263..d2e47096 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/notify/ImageNotify.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/notify/ImageNotify.java @@ -1,14 +1,17 @@ package com.foxinmy.weixin4j.msg.notify; +import com.foxinmy.weixin4j.msg.model.Image; import com.foxinmy.weixin4j.type.MessageType; -import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 客服图片消息 + * * @author jy.hu * @date 2014年4月4日 * @since JDK 1.7 - * @see 客服图片消息 + * @see 客服图片消息 + * @see com.foxinmy.weixin4j.msg.model.Image * @see com.foxinmy.weixin4j.msg.notify.BaseNotify * @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson() */ @@ -20,30 +23,25 @@ public class ImageNotify extends BaseNotify { super(MessageType.image); } - public ImageNotify(String mediaId) { - super(MessageType.image); - this.image = new $(mediaId); + public ImageNotify(String touser) { + super(touser, MessageType.image); } public ImageNotify(String mediaId, String touser) { super(touser, MessageType.image); - this.image = new $(mediaId); + this.pushMediaId(mediaId); } - @XStreamAlias("image") - private $ image; - - private static class $ { - @XStreamAlias("media_id") - private String mediaId; - - public $(String mediaId) { - this.mediaId = 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.mediaId); + return String.format("[ImageNotify touser=%s ,msgtype=%s ,mediaId=%s]", + super.getTouser(), super.getMsgtype().name(), + this.image.getMediaId()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/notify/MusicNotify.java b/src/main/java/com/foxinmy/weixin4j/msg/notify/MusicNotify.java index 6f3e66fa..1e328677 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/notify/MusicNotify.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/notify/MusicNotify.java @@ -1,14 +1,17 @@ package com.foxinmy.weixin4j.msg.notify; +import com.foxinmy.weixin4j.msg.model.Music; import com.foxinmy.weixin4j.type.MessageType; -import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 客服音乐消息 + * * @author jy.hu * @date 2014年4月4日 * @since JDK 1.7 - * @see 客服音乐消息 + * @see 客服音乐消息 + * @see com.foxinmy.weixin4j.msg.model.Music * @see com.foxinmy.weixin4j.msg.notify.BaseNotify * @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson() */ @@ -24,44 +27,20 @@ public class MusicNotify extends BaseNotify { super(touser, MessageType.music); } - public void pushMusic(String title, String desc, String url, String hqUrl, String mediaId) { - this.music = new $(); - this.music.thumbMediaId = mediaId; - this.music.desc = desc; - this.music.hqMusicUrl = hqUrl; - this.music.musicUrl = url; - this.music.title = title; + public void pushMusic(String musicurl, String hqUrl, String mediaId) { + this.music = new Music(null, null, musicurl, hqUrl, mediaId); } - @XStreamAlias("music") - private $ music; - - private static class $ { - private String title; - @XStreamAlias("description") - private String desc; - @XStreamAlias("musicurl") - private String musicUrl; - @XStreamAlias("hqmusicurl") - private String hqMusicUrl; - @XStreamAlias("thumb_media_id") - private String thumbMediaId; - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(music ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,musicURL=").append(musicUrl); - sb.append(" ,hqMusicUrl=").append(hqMusicUrl); - sb.append(" ,thumbMediaId=").append(thumbMediaId).append(")"); - return sb.toString(); - } + private Music music; + public void setMusic(Music music) { + this.music = music; } @Override public String toString() { - return String.format("[VideoNotify touser=%s ,msgtype=%s ,music=%s]", super.getTouser(), super.getMsgtype().name(), this.music.toString()); + return String.format("[MusicNotify touser=%s ,msgtype=%s ,music=%s]", + super.getTouser(), super.getMsgtype().name(), + this.music.toString()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/notify/TextNotify.java b/src/main/java/com/foxinmy/weixin4j/msg/notify/TextNotify.java index edcf2565..6ec09a3a 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/notify/TextNotify.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/notify/TextNotify.java @@ -1,14 +1,17 @@ package com.foxinmy.weixin4j.msg.notify; +import com.foxinmy.weixin4j.msg.model.Text; import com.foxinmy.weixin4j.type.MessageType; -import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 客服文本消息 + * * @author jy.hu * @date 2014年4月4日 * @since JDK 1.7 - * @see 客服文本消息 + * @see 客服文本消息 + * @see com.foxinmy.weixin.msg.model.Text * @see com.foxinmy.weixin4j.msg.notify.BaseNotify * @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson() */ @@ -22,27 +25,24 @@ public class TextNotify extends BaseNotify { public TextNotify(String content) { super(MessageType.text); - this.text = new $(content); + this.text = new Text(content); } public TextNotify(String content, String touser) { super(touser, MessageType.text); - this.text = new $(content); + this.text = new Text(content); } - @XStreamAlias("text") - private $ text; - - private static class $ { - @XStreamAlias("content") - private String content; - - public $(String content) { - this.content = 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.content); + return String.format("[TextNotify touser=%s ,msgtype=%s ,content=%s]", + super.getTouser(), super.getMsgtype().name(), + this.text.getContent()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/notify/VideoNotify.java b/src/main/java/com/foxinmy/weixin4j/msg/notify/VideoNotify.java index d8865910..8e433c03 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/notify/VideoNotify.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/notify/VideoNotify.java @@ -1,14 +1,17 @@ package com.foxinmy.weixin4j.msg.notify; +import com.foxinmy.weixin4j.msg.model.Video; import com.foxinmy.weixin4j.type.MessageType; -import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 客服视频消息 + * * @author jy.hu * @date 2014年4月4日 * @since JDK 1.7 - * @see 客服视频消息 + * @see 客服视频消息 + * @see com.foxinmy.weixin4j.msg.model.Video * @see com.foxinmy.weixin4j.msg.notify.BaseNotify * @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson() */ @@ -23,36 +26,21 @@ public class VideoNotify extends BaseNotify { public VideoNotify(String touser) { super(touser, MessageType.video); } - - public void pushVideo(String mediaId, String title, String desc) { - this.video = new $(mediaId, title, desc); + + public void pushVideo(String mediaId, String thumbMediaId) { + this.video = new Video(mediaId, thumbMediaId); } - @XStreamAlias("video") - private $ video; - - private static class $ { - @XStreamAlias("media_id") - private String mediaId; - private String title; - @XStreamAlias("description") - private String desc; - - public $(String mediaId, String title, String desc) { - this.mediaId = mediaId; - this.title = title; - this.desc = desc; - } - - @Override - public String toString() { - return String.format("(video mediaId=%s ,title=%s ,description=%s)", mediaId, title, desc); - } + 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()); + return String.format("[VideoNotify touser=%s ,msgtype=%s ,video=%s]", + super.getTouser(), super.getMsgtype().name(), + this.video.toString()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/notify/VoiceNotify.java b/src/main/java/com/foxinmy/weixin4j/msg/notify/VoiceNotify.java index 8e0787b6..4cfb7a7f 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/notify/VoiceNotify.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/notify/VoiceNotify.java @@ -1,14 +1,17 @@ package com.foxinmy.weixin4j.msg.notify; +import com.foxinmy.weixin4j.msg.model.Voice; import com.foxinmy.weixin4j.type.MessageType; -import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 客服语音消息 + * * @author jy.hu * @date 2014年4月4日 * @since JDK 1.7 - * @see 客服语音消息 + * @see 客服语音消息 + * @see com.foxinmy.weixin4j.msg.model.Voice * @see com.foxinmy.weixin4j.msg.notify.BaseNotify * @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson() */ @@ -20,30 +23,25 @@ public class VoiceNotify extends BaseNotify { super(MessageType.voice); } - public VoiceNotify(String mediaId) { - super(MessageType.voice); - this.voice = new $(mediaId); + public VoiceNotify(String touser) { + super(touser, MessageType.voice); } public VoiceNotify(String mediaId, String touser) { super(touser, MessageType.voice); - this.voice = new $(mediaId); + this.pushMediaId(mediaId); } - @XStreamAlias("voice") - private $ voice; - - private static class $ { - @XStreamAlias("media_id") - private String mediaId; - - public $(String mediaId) { - this.mediaId = 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.mediaId); + return String.format("[VoiceNotify touser=%s ,msgtype=%s ,mediaId=%s]", + super.getTouser(), super.getMsgtype().name(), + this.voice.getMediaId()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/ArticleMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/ArticleMessage.java index e892aeaa..9c3737a7 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/ArticleMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/ArticleMessage.java @@ -4,36 +4,36 @@ import java.util.LinkedList; import java.util.List; 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 回复图文消息 + * @see 回复图文消息 + * @see com.foxinmy.weixin.msg.model.Article * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class ArticleMessage extends BaseMessage { private static final int MAX_ARTICLE_COUNT = 10; private static final long serialVersionUID = -7331603018352309317L; - public ArticleMessage() { - super(MessageType.news); - } - - public ArticleMessage(String toUserName) { - super(MessageType.news); - super.setToUserName(toUserName); + public ArticleMessage(BaseMessage inMessage) { + super(MessageType.news, inMessage); } @XStreamAlias("ArticleCount") private int count; // 图文消息个数,限制为10条以内 @XStreamAlias("Articles") - private List articles; + private LinkedList articles; public List getArticles() { return this.articles; @@ -44,39 +44,55 @@ public class ArticleMessage extends BaseMessage { return; } if (this.articles == null) { - this.articles = new LinkedList(); + this.articles = new LinkedList(); } this.articles.add(new Article(title, desc, picUrl, url)); - count ++; + count++; } - @XStreamAlias("item") - private static class Article { - @XStreamAlias("Title") - private String title; // 图文消息标题 - @XStreamAlias("Description") - private String desc; // 图文消息描述 - @XStreamAlias("PicUrl") - private String picUrl; // 图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200 - @XStreamAlias("Url") - private String url; // 点击图文消息跳转链接 - - public Article(String title, String desc, String picUrl, String url) { - this.title = title; - this.desc = desc; - this.picUrl = picUrl; - this.url = url; + public void pushFirstArticle(String title, String desc, String picUrl, + String url) { + if (this.articles == null) { + this.articles = new LinkedList(); } + this.articles.addFirst(new Article(title, desc, picUrl, url)); + } - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Article ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,picUrl=").append(picUrl); - sb.append(" ,url=").append(url).append(")"); - return sb.toString(); + public void pushLastArticle(String title, String desc, String picUrl, + String url) { + if (this.articles == null) { + this.articles = new LinkedList(); } + this.articles.addLast(new Article(title, desc, picUrl, url)); + } + + public Article removeLastArticle() { + if (this.articles != null) { + return this.articles.removeLast(); + } + return null; + } + + 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() { + 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 diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java index 2da50a01..fb58ecb8 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java @@ -1,38 +1,50 @@ 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 回复图片消息 + * @see 回复图片消息 + * @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() { - super(MessageType.image); + public ImageMessage(BaseMessage inMessage) { + super(MessageType.image, inMessage); super.getMsgType().setMessageClass(ImageMessage.class); } + 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(); - this.image.mediaId = mediaId; + this.image = new Image(mediaId); } - private static class Image { - @XStreamAlias("MediaId") - private String mediaId; + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Image.class, "mediaId"); + return xstream.toXML(this); } @Override @@ -41,7 +53,7 @@ public class ImageMessage extends BaseMessage { sb.append("[ImageMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,mediaId=").append(this.image.mediaId); + sb.append(" ,mediaId=").append(this.image.getMediaId()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java index c790b9ac..419f32d6 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java @@ -1,74 +1,61 @@ 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 回复音乐消息 + * @see 回复音乐消息 + * @see com.foxinmy.weixin4j.msg.model.Music * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class MusicMessage extends BaseMessage { private static final long serialVersionUID = 4384403772658796395L; - public MusicMessage() { - super(MessageType.music); + public MusicMessage(BaseMessage inMessage) { + super(MessageType.music, inMessage); } @XStreamAlias("Music") private Music music; - public Music getMusic() { - return this.music; + public void pushMusic(String mediaId) { + this.music = new Music(mediaId); } - public void pushMusic(String title, String desc, String url, String hqUrl, String mediaId) { - this.music = new Music(); - this.music.thumbMediaId = mediaId; - this.music.desc = desc; - this.music.hqMusicUrl = hqUrl; - this.music.MusicURL = url; - this.music.title = title; + public void setMusic(Music music) { + this.music = music; } - private static class Music { - @XStreamAlias("Title") - private String title; // 音乐标题 - @XStreamAlias("Description") - private String desc; // 音乐描述 - @XStreamAlias("MusicURL") - private String MusicURL; // 音乐链接 - @XStreamAlias("HQMusicUrl") - private String hqMusicUrl; // 高质量音乐链接,WIFI环境优先使用该链接播放音乐 - @XStreamAlias("ThumbMediaId") - private String thumbMediaId; // 缩略图的媒体id,通过上传多媒体文件,得到的id - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Music ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,musicURL=").append(MusicURL); - sb.append(" ,hqMusicUrl=").append(hqMusicUrl); - sb.append(" ,thumbMediaId=").append(thumbMediaId).append(")"); - return sb.toString(); - } + @Override + public String 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(getMusic().toString()); + sb.append(" ,music=").append(music.toString()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java new file mode 100644 index 00000000..3721504b --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java @@ -0,0 +1,117 @@ +package com.foxinmy.weixin4j.msg.out; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +import com.alibaba.fastjson.JSON; + +/** + * 模板消息 + * + * @className TemplateMessage + * @author jy + * @date 2014年9月29日 + * @since JDK 1.7 + * @see + */ +public class TemplateMessage implements Serializable { + + private static final long serialVersionUID = 7950608393821661436L; + + private String touser; + private String template_id; + private String url; + private String topcolor = "#FF0000"; + private Map data; + + public void pushData(String key, String value) { + this.data.put(key, new Item(value)); + } + + public TemplateMessage(String touser, String template_id, String url) { + this.touser = touser; + this.template_id = template_id; + this.url = url; + this.data = new HashMap(); + } + + private static class Item implements Serializable { + private static final long serialVersionUID = 1L; + private String value; + private String color; + + public Item(String value) { + this(value, "#173177"); + } + + public Item(String value, String color) { + this.value = value; + this.color = color; + } + + public String getValue() { + return value; + } + + public String getColor() { + return color; + } + + @Override + public String toString() { + return "$ [value=" + getValue() + ", color=" + getColor() + "]"; + } + } + + public String getTouser() { + return touser; + } + + public void setTouser(String touser) { + this.touser = touser; + } + + public String getTemplate_id() { + return template_id; + } + + public void setTemplate_id(String template_id) { + this.template_id = template_id; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getTopcolor() { + return topcolor; + } + + public void setTopcolor(String topcolor) { + this.topcolor = topcolor; + } + + public Map getData() { + return data; + } + + public void setData(Map data) { + this.data = data; + } + + @Override + public String toString() { + return "TemplateMessage [touser=" + touser + ", template_id=" + + template_id + ", url=" + url + ", topcolor=" + topcolor + + ", data=" + data + "]"; + } + + public String toJson() { + return JSON.toJSONString(this); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java new file mode 100644 index 00000000..b89621aa --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java @@ -0,0 +1,25 @@ +package com.foxinmy.weixin4j.msg.out; + +import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.type.MessageType; + +/** + * 转移消息到多客服端消息 + * + * @className TransferMessage + * @author jy.hu + * @date 2014年6月28日 + * @since JDK 1.7 + * @see 多客服转移消息 + * @see com.foxinmy.weixin4j.msg.BaseMessage + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + */ +public class TransferMessage extends BaseMessage { + + private static final long serialVersionUID = -5479496746108594940L; + + public TransferMessage(BaseMessage inMessage) { + super(MessageType.transfer_customer_service,inMessage); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java index d16c5a12..d6cdfc91 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java @@ -1,58 +1,52 @@ package com.foxinmy.weixin4j.msg.out; import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.msg.model.Video; import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 回复视频消息 + * * @className VideoMessage * @author jy.hu * @date 2014年4月6日 * @since JDK 1.7 - * @see 回复视频消息 + * @see 回复视频消息 + * @see com.foxinmy.weixin4j.msg.model.Video * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class VideoMessage extends BaseMessage { private static final long serialVersionUID = -1013075358679078381L; - public VideoMessage() { - super(MessageType.video); + public VideoMessage(BaseMessage inMessage) { + super(MessageType.video, inMessage); super.getMsgType().setMessageClass(VideoMessage.class); } @XStreamAlias("Video") private Video video; - public Video getVideo() { - return this.video; + public void pushVideo(String mediaId) { + this.video = new Video(mediaId); } - public void pushVideo(String mediaId, String title, String desc) { - this.video = new Video(); - this.video.desc = desc; - this.video.mediaId = mediaId; - this.video.title = title; + public void setVideo(Video video) { + this.video = video; } - private static class Video { - @XStreamAlias("MediaId") - private String mediaId; - @XStreamAlias("Title") - private String title; - @XStreamAlias("Description") - private String desc; - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Video mediaId=").append(mediaId); - sb.append(" ,title=").append(title); - sb.append(" ,desc=").append(desc).append(")"); - return super.toString(); - } + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Video.class, "mediaId"); + xstream.aliasField("Title", Video.class, "title"); + xstream.aliasField("Description", Video.class, "desc"); + xstream.omitField(Video.class, "thumbMediaId"); + return xstream.toXML(this); } @Override @@ -61,7 +55,7 @@ public class VideoMessage extends BaseMessage { sb.append("[VideoMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,video=").append(getVideo().toString()); + sb.append(" ,video=").append(video.toString()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java index 93052907..dcac1046 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java @@ -1,53 +1,60 @@ package com.foxinmy.weixin4j.msg.out; import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.msg.model.Voice; import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 语音消息 + * * @className VoiceMessage * @author jy.hu * @date 2014年3月23日 * @since JDK 1.7 - * @see 回复语音消息 + * @see 回复语音消息 + * @see com.foxinmy.weixin4j.msg.model.Voice * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class VoiceMessage extends BaseMessage { private static final long serialVersionUID = -7944926238652243793L; - public VoiceMessage() { - super(MessageType.voice); + public VoiceMessage(BaseMessage inMessage) { + super(MessageType.voice, inMessage); super.getMsgType().setMessageClass(VoiceMessage.class); } + + public VoiceMessage(String mediaId, BaseMessage inMessage) { + super(MessageType.voice, inMessage); + super.getMsgType().setMessageClass(VoiceMessage.class); + this.pushMediaId(mediaId); + } + @XStreamAlias("Voice") private Voice voice; - - public Voice getVocie() { - return voice; + + public void pushMediaId(String mediaId) { + this.voice = new Voice(mediaId); } - public void pushMediaId(String mediaId){ - this.voice = new Voice(); - this.voice.setMediaId(mediaId); - } - - private static class Voice { - @XStreamAlias("MediaId") - private String mediaId; - - private void setMediaId(String mediaId) { - this.mediaId = mediaId; - } + + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Voice.class, "mediaId"); + return xstream.toXML(this); } + @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("[VoiceMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,mediaId=").append(getVocie().mediaId); + sb.append(" ,mediaId=").append(voice.getMediaId()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java b/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java new file mode 100644 index 00000000..cf2ab68e --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java @@ -0,0 +1,55 @@ +package com.foxinmy.weixin4j.type; + +/** + * 自定义菜单类型 + * scancode_push 到 location_selec + * 仅支持微信iPhone5.4.1以上版本,和Android5 .4以上版本的微信用户 旧版本微信用户点击后将没有回应 + * 开发者也不能正常接收到事件推送。 + * + * @className ButtonType + * @author jy + * @date 2014年9月30日 + * @since JDK 1.7 + * @see 按钮类型 + */ +public enum ButtonType { + /** + * 点击推事件 用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event + * 的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互; + */ + click, + /** + * 跳转URL 用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的网页URL,可与网页授权获取用户基本信息接口结合,获得用户基本信息。 + */ + view, + /** + * 扫码推事件 用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后显示扫描结果(如果是URL,将进入URL),且会将扫码的结果传给开发者, + * 开发者可以下发消息。 + */ + scancode_push, + /** + * 扫码推事件且弹出“消息接收中”提示框用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后,将扫码的结果传给开发者,同时收起扫一扫工具, + * 然后弹出“消息接收中”提示框,随后可能会收到开发者下发的消息。 + */ + scancode_waitmsg, + /** + * 弹出系统拍照发图用户点击按钮后,微信客户端将调起系统相机,完成拍照操作后,会将拍摄的相片发送给开发者,并推送事件给开发者,同时收起系统相机, + * 随后可能会收到开发者下发的消息。 + */ + pic_sysphoto, + /** + * 弹出拍照或者相册发图用户点击按钮后,微信客户端将弹出选择器供用户选择“拍照”或者“从手机相册选择”。用户选择后即走其他两种流程。 + */ + pic_photo_or_albu, + /** + * 弹出微信相册发图器用户点击按钮后,微信客户端将调起微信相册,完成选择操作后,将选择的相片发送给开发者的服务器,并推送事件给开发者,同时收起相册, + * 随后可能会收到开发者下发的消息。 + */ + pic_weixin, + /** + * 弹出地理位置选择器用户点击按钮后,微信客户端将调起地理位置选择工具,完成选择操作后,将选择的地理位置发送给开发者的服务器,同时收起位置选择工具, + * 随后可能会收到开发者下发的消息。 + */ + location_select; +} diff --git a/src/main/java/com/foxinmy/weixin4j/type/EventType.java b/src/main/java/com/foxinmy/weixin4j/type/EventType.java index a8e864b8..bc85ce90 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/EventType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/EventType.java @@ -3,21 +3,36 @@ package com.foxinmy.weixin4j.type; import com.foxinmy.weixin4j.msg.event.EventMessage; import com.foxinmy.weixin4j.msg.event.LocationEventMessage; import com.foxinmy.weixin4j.msg.event.MassEventMessage; -import com.foxinmy.weixin4j.msg.event.MenuEventMessage; import com.foxinmy.weixin4j.msg.event.ScanEventMessage; import com.foxinmy.weixin4j.msg.event.ScribeEventMessage; +import com.foxinmy.weixin4j.msg.event.TemplatesendjobfinishMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuLocationEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuPhotoEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuScanEventMessage; /** - * * 事件类型 - * @author jy.hu - * + * + * @className EventType + * @author jy + * @date 2014年9月30日 + * @since JDK 1.7 + * @see */ public enum EventType { - subscribe(ScribeEventMessage.class), unsubscribe(ScribeEventMessage.class), - scan(ScanEventMessage.class),click(MenuEventMessage.class),view(MenuEventMessage.class), - location(LocationEventMessage.class),MASSSENDJOBFINISH(MassEventMessage.class); - + subscribe(ScribeEventMessage.class), unsubscribe(ScribeEventMessage.class), scan( + ScanEventMessage.class), scancode_push(MenuScanEventMessage.class), view( + MenuEventMessage.class), scancode_waitmsg( + MenuScanEventMessage.class), pic_sysphoto( + MenuPhotoEventMessage.class), pic_photo_or_album( + MenuPhotoEventMessage.class), pic_weixin( + MenuPhotoEventMessage.class), location_select( + MenuLocationEventMessage.class), click(MenuEventMessage.class), location( + LocationEventMessage.class), massendjobfinish( + MassEventMessage.class), templatesendjobfinish( + TemplatesendjobfinishMessage.class); + private Class extends EventMessage> eventClass; EventType(Class extends EventMessage> eventClass) { diff --git a/src/main/java/com/foxinmy/weixin4j/type/MediaType.java b/src/main/java/com/foxinmy/weixin4j/type/MediaType.java index 1f567181..322ba3ce 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/MediaType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/MediaType.java @@ -6,13 +6,20 @@ package com.foxinmy.weixin4j.type; * 语音(voice):256K,播放长度不超过60s,支持AMR\MP3格式 * 视频(video):1MB,支持MP4格式 * 缩略图(thumb):64KB,支持JPG格式 - * 媒体文件在后台保存时间为3天,即3天后media_id失效 + * + * 媒体文件在后台保存时间为3天,即3天后media_id失效 + * + * * @author jy.hu * @date 2014年4月2日 * @since JDK 1.7 */ public enum MediaType { - image("image/jpeg",".jpg"), voice("binary/octet-stream","amr"), vedio("binary/octet-stream","mp4"), thumb("image/jpeg","jpg"); + image("image/jpeg", "jpg"), voice("binary/octet-stream", "amr"), vedio( + "binary/octet-stream", "mp4"), thumb("image/jpeg", "jpg"), text( + "application/json", ""), music("binary/octet-stream", "mp3"), news( + "application/json", ""), mpnews("application/json", ""), mpvideo( + "binary/octet-stream", ""); MediaType(String contentType, String formatType) { this.contentType = contentType; @@ -26,6 +33,7 @@ public enum MediaType { } private String formatType; + public String getFormatType() { return formatType; } diff --git a/src/main/java/com/foxinmy/weixin4j/type/MessageType.java b/src/main/java/com/foxinmy/weixin4j/type/MessageType.java index 21a7b6dc..a883d993 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/MessageType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/MessageType.java @@ -10,6 +10,7 @@ import com.foxinmy.weixin4j.msg.in.VideoMessage; import com.foxinmy.weixin4j.msg.in.VoiceMessage; import com.foxinmy.weixin4j.msg.out.ArticleMessage; import com.foxinmy.weixin4j.msg.out.MusicMessage; +import com.foxinmy.weixin4j.msg.out.TransferMessage; /** * @@ -20,9 +21,13 @@ import com.foxinmy.weixin4j.msg.out.MusicMessage; */ public enum MessageType { // 接收到的消息类型 - text(TextMessage.class), image(ImageMessage.class), voice(VoiceMessage.class), video(VideoMessage.class), location(LocationMessage.class), link(LinkMessage.class), event(EventMessage.class), + text(TextMessage.class), image(ImageMessage.class), voice( + VoiceMessage.class), video(VideoMessage.class), location( + LocationMessage.class), link(LinkMessage.class), event( + EventMessage.class), // 发送的消息类型 - music(MusicMessage.class), news(ArticleMessage.class); + music(MusicMessage.class), news(ArticleMessage.class), transfer_customer_service( + TransferMessage.class); private Class extends BaseMessage> messageClass; MessageType(Class extends BaseMessage> messageClass) { diff --git a/src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java b/src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java similarity index 91% rename from src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java rename to src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java index f428c33b..b419bd1c 100644 --- a/src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java +++ b/src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java @@ -8,8 +8,8 @@ import java.util.regex.Pattern; import com.foxinmy.weixin4j.WeixinProxy; -public class WeixinConfig { - public WeixinConfig() { +public class ConfigUtil { + public ConfigUtil() { } private static Properties props = new Properties(); @@ -38,7 +38,6 @@ public class WeixinConfig { m.appendTail(sb); return sb.toString(); } - public static void main(String[] args) { System.out.println(getValue("api_token_uri")); } diff --git a/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java b/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java new file mode 100644 index 00000000..60eae107 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java @@ -0,0 +1,67 @@ +package com.foxinmy.weixin4j.util; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.Writer; +import java.nio.charset.Charset; + +/** + * IOUtil + * + * @className IOUtil + * @author jy.hu + * @date 2014年9月22日 + * @since JDK 1.7 + * @see org.apache.commons.io.IOUtils + */ +public class IOUtil { + + private static final int EOF = -1; + private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; + + public static byte[] toByteArray(Reader input) throws IOException { + return toByteArray(input, Charset.defaultCharset()); + } + + public static byte[] toByteArray(Reader input, Charset encoding) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + copy(input, output, encoding); + return output.toByteArray(); + } + + public static void copy(Reader input, OutputStream output, Charset encoding) throws IOException { + OutputStreamWriter out = new OutputStreamWriter(output, encoding); + copyLarge(input, out, new char[DEFAULT_BUFFER_SIZE]); + out.flush(); + } + + public static byte[] toByteArray(InputStream input) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + copyLarge(input, output, new byte[DEFAULT_BUFFER_SIZE]); + return output.toByteArray(); + } + + private static long copyLarge(InputStream input, OutputStream output, byte[] buffer) throws IOException { + long count = 0; + int n = 0; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } + + private static long copyLarge(Reader input, Writer output, char[] buffer) throws IOException { + long count = 0; + int n = 0; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java b/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java new file mode 100644 index 00000000..82a23ef3 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java @@ -0,0 +1,135 @@ +package com.foxinmy.weixin4j.util; + +import java.io.InputStream; +import java.util.Arrays; + +import org.apache.commons.codec.digest.DigestUtils; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.DocumentHelper; +import org.dom4j.io.SAXReader; +import org.jsoup.helper.StringUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.type.EventType; +import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; + +public class MessageUtil { + + private final static Logger log = LoggerFactory.getLogger(MessageUtil.class); + + /** + * 验证微信签名 + * + * @param echostr + * 随机字符串 + * @param timestamp + * 时间戳 + * @param nonce + * 随机数 + * @param signature + * 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数 + * @return 开发者通过检验signature对请求进行相关校验。若确认此次GET请求来自微信服务器 + * 请原样返回echostr参数内容,则接入生效 成为开发者成功,否则接入失败 + * @see 接入指南 + */ + public static String signature(String echostr, String timestamp, String nonce, String signature) { + String app_token = ConfigUtil.getValue("app_token"); + if (StringUtil.isBlank(app_token)) { + log.error("signature fail : token is null!"); + return null; + } + if (StringUtil.isBlank(echostr) || StringUtil.isBlank(timestamp) || StringUtil.isBlank(nonce)) { + log.error("signature fail : invalid parameter!"); + return null; + } + String _signature = null; + try { + String[] a = { app_token, timestamp, nonce }; + Arrays.sort(a); + StringBuilder sb = new StringBuilder(3); + for (String str : a) { + sb.append(str); + } + _signature = DigestUtils.sha1Hex(sb.toString()); + } catch (Exception e) { + log.error("signature error", e); + } + if (signature.equals(_signature)) { + return echostr; + } else { + log.error("signature fail : invalid signature!"); + return null; + } + } + + /** + * xml消息转换为消息对象 + * + * 微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次 + * + * + * @param xml + * 消息字符串 + * @return 消息对象 + * @throws DocumentException + * @see 验证消息的合法性 + * @see 普通消息 + * @see 事件触发 + * @see com.foxinmy.weixin4j.type.MessageType + * @see com.feican.weixin.msg.BaeMessage + * @see com.foxinmy.weixin4j.msg.TextMessage + * @see com.foxinmy.weixin4j.msg.in.ImageMessage + * @see com.foxinmy.weixin4j.msg.in.VoiceMessage + * @see com.foxinmy.weixin4j.msg.in.VideoMessage + * @see com.foxinmy.weixin4j.msg.in.LocationMessage + * @see com.foxinmy.weixin4j.msg.in.LinkMessage + * @see com.foxinmy.weixin4j.msg.event.ScribeEventMessage + * @see com.foxinmy.weixin4j.msg.event.ScanEventMessage + * @see com.foxinmy.weixin4j.msg.event.LocationEventMessage + * @see com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage + */ + public static BaseMessage xml2msg(String xml) throws DocumentException { + if (StringUtil.isBlank(xml)) + return null; + Document doc = DocumentHelper.parseText(xml); + String type = doc.selectSingleNode("/xml/MsgType").getStringValue(); + if (StringUtil.isBlank(type)) { + return null; + } + XStream xstream = new XStream(); + MessageType messageType = MessageType.valueOf(type.toLowerCase()); + Class extends BaseMessage> messageClass = messageType.getMessageClass(); + if (messageType == MessageType.event) { + type = doc.selectSingleNode("/xml/Event").getStringValue(); + messageClass = EventType.valueOf(type.toLowerCase()).getEventClass(); + } + xstream.alias("xml", messageClass); + xstream.ignoreUnknownElements(); + xstream.autodetectAnnotations(true); + xstream.processAnnotations(messageClass); + return xstream.fromXML(doc.asXML(), messageClass); + } + + /** + * xml消息转换为消息对象 + * + * @param inputStream + * 带消息字符串的输入流 + * @return 消息对象 + * @throws DocumentException + * @see {@link com.foxinmy.weixin4j.WeixinProxy#xml2msg(String)} + */ + public static BaseMessage xml2msg(InputStream inputStream) throws DocumentException { + SAXReader reader = new SAXReader(); + Document doc = reader.read(inputStream); + return xml2msg(doc.asXML()); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java b/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java deleted file mode 100644 index 19fd87e4..00000000 --- a/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.foxinmy.weixin4j.util; - -public class WeixinUtil { - - public static boolean isBlank(String str) { - return str == null || str.isEmpty(); - } -} diff --git a/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java b/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java index 5c0186c6..4a811a6c 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java @@ -9,7 +9,7 @@ import org.junit.Test; import com.foxinmy.weixin4j.WeixinProxy; import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.model.Button; -import com.foxinmy.weixin4j.model.Button.BtnType; +import com.foxinmy.weixin4j.type.ButtonType; /** * 自定义菜单测试 @@ -31,7 +31,7 @@ public class ButtonTest { List btnList = new ArrayList(); Button b = new Button("test"); - b.setType(BtnType.click); + b.setType(ButtonType.click); b.setKey("123"); btnList.add(b); diff --git a/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java b/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java index 8b78305e..bb6bec88 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java @@ -50,7 +50,7 @@ public class GroupTest { @Test public void getid() { try { - System.out.println(weixinProxy.findGroupByOpenId("owGBft_vbBbOaQOmpEUE4xDLeRSU")); + System.out.println(weixinProxy.getGroupByOpenId("owGBft_vbBbOaQOmpEUE4xDLeRSU")); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); diff --git a/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java b/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java new file mode 100644 index 00000000..6d34a733 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java @@ -0,0 +1,22 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Test; + +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.http.HttpRequest; + +public class HttpTest { + private static HttpRequest request; + static { + request = new HttpRequest(); + } + + @Test + public void test(){ + try { + System.out.println(request.get("http://www.baidu.com")); + } catch (WeixinException e) { + e.printStackTrace(); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java b/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java index f907fa3d..d54e649b 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java @@ -31,7 +31,7 @@ public class MediaTest { File file = new File("D:\\test.jpg"); try { System.out.println(weixinProxy.uploadMedia(file, MediaType.image)); - //usAxLEJxFXAjXVlLu_BSw0GvS2YEEoGeelRBybNZBGvMsdxiIcD1F9yBWYd9jVZx + //vvU_AUtovWyfAxQ8J1DsCoNMtK6U_bUmTpe6lpINUOVRLvt_7rtO4zxzBpPgkmay } catch (WeixinException e) { System.out.println(e.getErrorMsg()); } @@ -40,7 +40,7 @@ public class MediaTest { @Test public void download() { try { - System.out.println(weixinProxy.downloadMedia("usAxLEJxFXAjXVlLu_BSw0GvS2YEEoGeelRBybNZBGvMsdxiIcD1F9yBWYd9jVZx", MediaType.image)); + System.out.println(weixinProxy.downloadMedia("vvU_AUtovWyfAxQ8J1DsCoNMtK6U_bUmTpe6lpINUOVRLvt_7rtO4zxzBpPgkmay", MediaType.image)); } catch (WeixinException e) { System.out.println(e.getErrorMsg()); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java new file mode 100644 index 00000000..2cd36584 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java @@ -0,0 +1,194 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Test; + +import com.foxinmy.weixin4j.util.MessageUtil; + +/** + * 接收事件消息格式测试 + * + * @author jy.hu + * @date 2014年3月24日 + * @since JDK 1.7 + */ +public class MessageEventInTest { + + private StringBuilder xmlSb = new StringBuilder(); + + /***************** event message *********************/ + @Test + public void scribe() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void scan() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void scan_scribe() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void location1() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("23.137466"); + xmlSb.append("113.352425"); + xmlSb.append("119.385040"); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_click() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_link() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_scan() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_photo() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("1"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_location() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java index 39269754..fdd40042 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java @@ -1,134 +1,19 @@ package com.foxinmy.weixin4j.test; -import org.junit.Before; import org.junit.Test; -import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.util.MessageUtil; /** - * 接收消息格式测试 + * 接受一般消息格式测试 + * * @author jy.hu * @date 2014年3月24日 * @since JDK 1.7 */ public class MessageInTest { + private StringBuilder xmlSb = new StringBuilder(); - private WeixinProxy weixinProxy; - - @Before - public void init(){ - weixinProxy = new WeixinProxy(); - } - - /***************** event message *********************/ - @Test - public void scribe() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void scan() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - @Test - public void scan_scribe() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void location1() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("23.137466"); - xmlSb.append("113.352425"); - xmlSb.append("119.385040"); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void menu_click() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void menu_link() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } /***************** common message *********************/ @@ -144,7 +29,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -163,7 +48,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -182,7 +67,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -202,7 +87,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -221,7 +106,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -242,7 +127,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -262,7 +147,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java new file mode 100644 index 00000000..8f6a130f --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java @@ -0,0 +1,114 @@ +package com.foxinmy.weixin4j.test; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.model.MpArticle; +import com.foxinmy.weixin4j.type.MediaType; + +/** + * 群发消息 + * + * @className MpNewsTest + * @author jy + * @date 2014年4月27日 + * @since JDK 1.7 + * @see + */ +public class MessageMassTest { + private WeixinProxy weixinProxy; + + @Before + public void init() { + this.weixinProxy = new WeixinProxy(); + } + + @Test + public void uploadArticle() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.uploadArticle(articles); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void uploadVideo() { + try { + weixinProxy.uploadVideo("mediaId", "title", "desc"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massByGroup() { + try { + weixinProxy.massByGroup("123", MediaType.image, "groupId"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massByOpenIds() { + try { + weixinProxy.massByOpenIds("123", MediaType.image, "openIds"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massArticleByGroup() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.massArticleByGroup(articles, "0"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massArticleByOpenIds() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.massArticleByOpenIds(articles, + "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void deleteMass() { + try { + weixinProxy.deleteMassNews("34182"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java index f3be10bb..59aed8de 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java @@ -7,6 +7,7 @@ import org.junit.Test; import com.foxinmy.weixin4j.WeixinProxy; import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.msg.model.Music; import com.foxinmy.weixin4j.msg.notify.ArticleNotify; import com.foxinmy.weixin4j.msg.notify.BaseNotify; import com.foxinmy.weixin4j.msg.notify.ImageNotify; @@ -41,27 +42,29 @@ public class MessageNotifyTest { @Test public void image() { - ImageNotify notify = new ImageNotify("123", "to"); + ImageNotify notify = new ImageNotify("to"); + notify.pushMediaId("123"); System.out.println(notify.toJson()); } @Test public void voice() { - VoiceNotify notify = new VoiceNotify("123", "to"); + VoiceNotify notify = new VoiceNotify("to"); + notify.pushMediaId("123"); System.out.println(notify.toJson()); } @Test public void video() { VideoNotify notify = new VideoNotify("to"); - notify.pushVideo("123", "title", "desc"); + notify.pushVideo("123","m123"); System.out.println(notify.toJson()); } @Test public void music() { MusicNotify notify = new MusicNotify("to"); - notify.pushMusic("title", "desc", "url", "hqUrl", "mediaId"); + notify.pushMusic("url", "hqUrl", "mediaId"); System.out.println(notify.toJson()); } @@ -74,16 +77,27 @@ public class MessageNotifyTest { } @Test - public void send() { - BaseNotify t = new TextNotify("哈哈哈哈", "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + public void send1() { + BaseNotify notify = new TextNotify("哈哈哈哈", "owGBft_vbBbOaQOmpEUE4xDLeRSU"); try { - weixinProxy.sendNotify(t); + weixinProxy.sendNotify(notify); String mediaId = weixinProxy.uploadMedia(new File("D:\\test.jpg"), MediaType.image); - t = new ImageNotify(mediaId, "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + ImageNotify t = new ImageNotify("owGBft_vbBbOaQOmpEUE4xDLeRSU"); + t.pushMediaId(mediaId); weixinProxy.sendNotify(t); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); } } + + @Test + public void send2() { + try { + weixinProxy.sendNotify("to",new Music("thumbMediaId")); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java index 00021aa0..ddb309d4 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java @@ -1,7 +1,9 @@ package com.foxinmy.weixin4j.test; +import org.junit.Before; import org.junit.Test; +import com.foxinmy.weixin4j.msg.BaseMessage; import com.foxinmy.weixin4j.msg.TextMessage; import com.foxinmy.weixin4j.msg.out.ArticleMessage; import com.foxinmy.weixin4j.msg.out.ImageMessage; @@ -17,56 +19,52 @@ import com.foxinmy.weixin4j.msg.out.VoiceMessage; * @since JDK 1.7 */ public class MessageOutTest { + private BaseMessage inMessage; + + @Before + public void init() { + this.inMessage = new TextMessage(); + this.inMessage.setFromUserName("fromusername"); + this.inMessage.setToUserName("tousername"); + } + @Test public void text() { - TextMessage message = new TextMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.setContent("text message"); + TextMessage message = new TextMessage("text", inMessage); System.out.println(message.toXml()); } @Test public void image() { - ImageMessage message = new ImageMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + ImageMessage message = new ImageMessage(inMessage); message.pushMediaId("mediaId"); System.out.println(message.toXml()); } @Test public void voice() { - VoiceMessage message = new VoiceMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + VoiceMessage message = new VoiceMessage(inMessage); message.pushMediaId("mediaId"); System.out.println(message.toXml()); } - + @Test public void video() { - VideoMessage message = new VideoMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.pushVideo("mediaId", "title", "title"); + VideoMessage message = new VideoMessage(inMessage); + message.pushVideo("mediaId"); System.out.println(message.toXml()); } - + @Test public void music() { - MusicMessage message = new MusicMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.pushMusic("title", "desc", "url", "hqurl", "mediaId"); + MusicMessage message = new MusicMessage(inMessage); + message.pushMusic("mediaId"); System.out.println(message.toXml()); } - + @Test public void article() { - ArticleMessage message = new ArticleMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + ArticleMessage message = new ArticleMessage(inMessage); message.pushArticle("title1", "desc1", "picUrl1", "url1"); message.pushArticle("title2", "desc2", "picUrl2", "url2"); System.out.println(message.toXml()); diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java new file mode 100644 index 00000000..b8165a91 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java @@ -0,0 +1,30 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Before; +import org.junit.Test; + +import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.msg.out.TemplateMessage; + +public class MessageTemplTest { + private WeixinProxy weixinProxy; + + @Before + public void init() { + this.weixinProxy = new WeixinProxy(); + } + + @Test + public void test() { + TemplateMessage tplMessage = new TemplateMessage("touser", + "template_id", "url"); + tplMessage.pushData("name", "fox"); + System.out.print(tplMessage.toJson()); + try { + System.out.print(weixinProxy.sendTplMessage(tplMessage)); + } catch (WeixinException e) { + System.out.println(e.getErrorMsg()); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java b/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java deleted file mode 100644 index 5fa1ec67..00000000 --- a/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.foxinmy.weixin4j.test; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; - -import com.foxinmy.weixin4j.WeixinProxy; -import com.foxinmy.weixin4j.exception.WeixinException; -import com.foxinmy.weixin4j.model.MpArticle; -import com.foxinmy.weixin4j.type.MediaType; - -/** - * 群发消息 - * - * @className MpNewsTest - * @author jy - * @date 2014年4月27日 - * @since JDK 1.7 - * @see - */ -public class MpNewsTest { - private WeixinProxy weixinProxy; - - @Before - public void init() { - this.weixinProxy = new WeixinProxy(); - } - - @Test - public void massByGroup(){ - List articles = new ArrayList(); - try { - String thumbMediaId = weixinProxy.uploadMedia(new File("/tmp/test.jpg"), MediaType.image); - articles.add(new MpArticle(thumbMediaId, "title", "content")); - weixinProxy.massNewsByGroup(articles, "0"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } - - @Test - public void massByOpenIds(){ - List articles = new ArrayList(); - try { - String thumbMediaId = weixinProxy.uploadMedia(new File("/tmp/test.jpg"), MediaType.image); - articles.add(new MpArticle(thumbMediaId, "title", "content")); - weixinProxy.massNewsByOpenIds(articles, "owGBft_vbBbOaQOmpEUE4xDLeRSU"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } - - @Test - public void deleteMass(){ - try { - weixinProxy.deleteMassNews("34182"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } -} diff --git a/src/test/java/com/foxinmy/weixin4j/test/QRTest.java b/src/test/java/com/foxinmy/weixin4j/test/QRTest.java index 11934fa9..f18d1aa7 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/QRTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/QRTest.java @@ -25,10 +25,10 @@ public class QRTest { @Test public void temp_qr() { - QRParameter qr = new QRParameter(1200, QRType.QR_SCENE, 1); + QRParameter qr = new QRParameter(1200, QRType.TEMPORARY, 2); try { System.out.println(qr.toJson()); - weixinProxy.getQR(qr); + System.out.println(weixinProxy.getQR(qr)); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); @@ -37,10 +37,10 @@ public class QRTest { @Test public void forever_qr() { - QRParameter qr = new QRParameter(QRType.QR_LIMIT_SCENE, 1); + QRParameter qr = new QRParameter(QRType.PERMANENCE, 1); try { System.out.println(qr.toJson()); - weixinProxy.getQR(qr); + System.out.println(weixinProxy.getQR(qr)); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java b/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java index 37d549d7..a2f8a266 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java @@ -3,7 +3,8 @@ package com.foxinmy.weixin4j.test; import org.junit.Before; import org.junit.Test; -import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.api.token.FileTokenApi; +import com.foxinmy.weixin4j.api.token.TokenApi; import com.foxinmy.weixin4j.exception.WeixinException; /** @@ -14,17 +15,17 @@ import com.foxinmy.weixin4j.exception.WeixinException; * @since JDK 1.7 */ public class TokenTest { - private WeixinProxy weixinProxy; + private TokenApi tokenApi; @Before public void init() { - weixinProxy = new WeixinProxy(); + tokenApi = new FileTokenApi(); } @Test public void getToken() { try { - System.out.println(weixinProxy.getToken()); + System.out.println(tokenApi.getToken()); } catch (WeixinException e) { e.printStackTrace(); }
articles; - public $(String title, String desc, String picUrl, String url) { - this.title = title; - this.desc = desc; - this.picUrl = picUrl; - this.url = url; + public News() { + this.articles = new LinkedList(); + } + + public void pushArticle(String title, String desc, String picUrl, + String url) { + this.articles.add(new Article(title, desc, picUrl, url)); + } + + public void setArticles(List articles) { + this.articles = articles; } @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("(article ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,picUrl=").append(picUrl); - sb.append(" ,url=").append(url).append(")"); + 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()); + return String.format( + "[ArticleNotify touser=%s ,msgtype=%s ,articles=%s]", + super.getTouser(), super.getMsgtype().name(), + this.news.toString()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/notify/ImageNotify.java b/src/main/java/com/foxinmy/weixin4j/msg/notify/ImageNotify.java index f9a52263..d2e47096 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/notify/ImageNotify.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/notify/ImageNotify.java @@ -1,14 +1,17 @@ package com.foxinmy.weixin4j.msg.notify; +import com.foxinmy.weixin4j.msg.model.Image; import com.foxinmy.weixin4j.type.MessageType; -import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 客服图片消息 + * * @author jy.hu * @date 2014年4月4日 * @since JDK 1.7 - * @see 客服图片消息 + * @see 客服图片消息 + * @see com.foxinmy.weixin4j.msg.model.Image * @see com.foxinmy.weixin4j.msg.notify.BaseNotify * @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson() */ @@ -20,30 +23,25 @@ public class ImageNotify extends BaseNotify { super(MessageType.image); } - public ImageNotify(String mediaId) { - super(MessageType.image); - this.image = new $(mediaId); + public ImageNotify(String touser) { + super(touser, MessageType.image); } public ImageNotify(String mediaId, String touser) { super(touser, MessageType.image); - this.image = new $(mediaId); + this.pushMediaId(mediaId); } - @XStreamAlias("image") - private $ image; - - private static class $ { - @XStreamAlias("media_id") - private String mediaId; - - public $(String mediaId) { - this.mediaId = 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.mediaId); + return String.format("[ImageNotify touser=%s ,msgtype=%s ,mediaId=%s]", + super.getTouser(), super.getMsgtype().name(), + this.image.getMediaId()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/notify/MusicNotify.java b/src/main/java/com/foxinmy/weixin4j/msg/notify/MusicNotify.java index 6f3e66fa..1e328677 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/notify/MusicNotify.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/notify/MusicNotify.java @@ -1,14 +1,17 @@ package com.foxinmy.weixin4j.msg.notify; +import com.foxinmy.weixin4j.msg.model.Music; import com.foxinmy.weixin4j.type.MessageType; -import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 客服音乐消息 + * * @author jy.hu * @date 2014年4月4日 * @since JDK 1.7 - * @see 客服音乐消息 + * @see 客服音乐消息 + * @see com.foxinmy.weixin4j.msg.model.Music * @see com.foxinmy.weixin4j.msg.notify.BaseNotify * @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson() */ @@ -24,44 +27,20 @@ public class MusicNotify extends BaseNotify { super(touser, MessageType.music); } - public void pushMusic(String title, String desc, String url, String hqUrl, String mediaId) { - this.music = new $(); - this.music.thumbMediaId = mediaId; - this.music.desc = desc; - this.music.hqMusicUrl = hqUrl; - this.music.musicUrl = url; - this.music.title = title; + public void pushMusic(String musicurl, String hqUrl, String mediaId) { + this.music = new Music(null, null, musicurl, hqUrl, mediaId); } - @XStreamAlias("music") - private $ music; - - private static class $ { - private String title; - @XStreamAlias("description") - private String desc; - @XStreamAlias("musicurl") - private String musicUrl; - @XStreamAlias("hqmusicurl") - private String hqMusicUrl; - @XStreamAlias("thumb_media_id") - private String thumbMediaId; - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(music ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,musicURL=").append(musicUrl); - sb.append(" ,hqMusicUrl=").append(hqMusicUrl); - sb.append(" ,thumbMediaId=").append(thumbMediaId).append(")"); - return sb.toString(); - } + private Music music; + public void setMusic(Music music) { + this.music = music; } @Override public String toString() { - return String.format("[VideoNotify touser=%s ,msgtype=%s ,music=%s]", super.getTouser(), super.getMsgtype().name(), this.music.toString()); + return String.format("[MusicNotify touser=%s ,msgtype=%s ,music=%s]", + super.getTouser(), super.getMsgtype().name(), + this.music.toString()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/notify/TextNotify.java b/src/main/java/com/foxinmy/weixin4j/msg/notify/TextNotify.java index edcf2565..6ec09a3a 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/notify/TextNotify.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/notify/TextNotify.java @@ -1,14 +1,17 @@ package com.foxinmy.weixin4j.msg.notify; +import com.foxinmy.weixin4j.msg.model.Text; import com.foxinmy.weixin4j.type.MessageType; -import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 客服文本消息 + * * @author jy.hu * @date 2014年4月4日 * @since JDK 1.7 - * @see 客服文本消息 + * @see 客服文本消息 + * @see com.foxinmy.weixin.msg.model.Text * @see com.foxinmy.weixin4j.msg.notify.BaseNotify * @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson() */ @@ -22,27 +25,24 @@ public class TextNotify extends BaseNotify { public TextNotify(String content) { super(MessageType.text); - this.text = new $(content); + this.text = new Text(content); } public TextNotify(String content, String touser) { super(touser, MessageType.text); - this.text = new $(content); + this.text = new Text(content); } - @XStreamAlias("text") - private $ text; - - private static class $ { - @XStreamAlias("content") - private String content; - - public $(String content) { - this.content = 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.content); + return String.format("[TextNotify touser=%s ,msgtype=%s ,content=%s]", + super.getTouser(), super.getMsgtype().name(), + this.text.getContent()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/notify/VideoNotify.java b/src/main/java/com/foxinmy/weixin4j/msg/notify/VideoNotify.java index d8865910..8e433c03 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/notify/VideoNotify.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/notify/VideoNotify.java @@ -1,14 +1,17 @@ package com.foxinmy.weixin4j.msg.notify; +import com.foxinmy.weixin4j.msg.model.Video; import com.foxinmy.weixin4j.type.MessageType; -import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 客服视频消息 + * * @author jy.hu * @date 2014年4月4日 * @since JDK 1.7 - * @see 客服视频消息 + * @see 客服视频消息 + * @see com.foxinmy.weixin4j.msg.model.Video * @see com.foxinmy.weixin4j.msg.notify.BaseNotify * @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson() */ @@ -23,36 +26,21 @@ public class VideoNotify extends BaseNotify { public VideoNotify(String touser) { super(touser, MessageType.video); } - - public void pushVideo(String mediaId, String title, String desc) { - this.video = new $(mediaId, title, desc); + + public void pushVideo(String mediaId, String thumbMediaId) { + this.video = new Video(mediaId, thumbMediaId); } - @XStreamAlias("video") - private $ video; - - private static class $ { - @XStreamAlias("media_id") - private String mediaId; - private String title; - @XStreamAlias("description") - private String desc; - - public $(String mediaId, String title, String desc) { - this.mediaId = mediaId; - this.title = title; - this.desc = desc; - } - - @Override - public String toString() { - return String.format("(video mediaId=%s ,title=%s ,description=%s)", mediaId, title, desc); - } + 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()); + return String.format("[VideoNotify touser=%s ,msgtype=%s ,video=%s]", + super.getTouser(), super.getMsgtype().name(), + this.video.toString()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/notify/VoiceNotify.java b/src/main/java/com/foxinmy/weixin4j/msg/notify/VoiceNotify.java index 8e0787b6..4cfb7a7f 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/notify/VoiceNotify.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/notify/VoiceNotify.java @@ -1,14 +1,17 @@ package com.foxinmy.weixin4j.msg.notify; +import com.foxinmy.weixin4j.msg.model.Voice; import com.foxinmy.weixin4j.type.MessageType; -import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 客服语音消息 + * * @author jy.hu * @date 2014年4月4日 * @since JDK 1.7 - * @see 客服语音消息 + * @see 客服语音消息 + * @see com.foxinmy.weixin4j.msg.model.Voice * @see com.foxinmy.weixin4j.msg.notify.BaseNotify * @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson() */ @@ -20,30 +23,25 @@ public class VoiceNotify extends BaseNotify { super(MessageType.voice); } - public VoiceNotify(String mediaId) { - super(MessageType.voice); - this.voice = new $(mediaId); + public VoiceNotify(String touser) { + super(touser, MessageType.voice); } public VoiceNotify(String mediaId, String touser) { super(touser, MessageType.voice); - this.voice = new $(mediaId); + this.pushMediaId(mediaId); } - @XStreamAlias("voice") - private $ voice; - - private static class $ { - @XStreamAlias("media_id") - private String mediaId; - - public $(String mediaId) { - this.mediaId = 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.mediaId); + return String.format("[VoiceNotify touser=%s ,msgtype=%s ,mediaId=%s]", + super.getTouser(), super.getMsgtype().name(), + this.voice.getMediaId()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/ArticleMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/ArticleMessage.java index e892aeaa..9c3737a7 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/ArticleMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/ArticleMessage.java @@ -4,36 +4,36 @@ import java.util.LinkedList; import java.util.List; 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 回复图文消息 + * @see 回复图文消息 + * @see com.foxinmy.weixin.msg.model.Article * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class ArticleMessage extends BaseMessage { private static final int MAX_ARTICLE_COUNT = 10; private static final long serialVersionUID = -7331603018352309317L; - public ArticleMessage() { - super(MessageType.news); - } - - public ArticleMessage(String toUserName) { - super(MessageType.news); - super.setToUserName(toUserName); + public ArticleMessage(BaseMessage inMessage) { + super(MessageType.news, inMessage); } @XStreamAlias("ArticleCount") private int count; // 图文消息个数,限制为10条以内 @XStreamAlias("Articles") - private List articles; + private LinkedList articles; public List getArticles() { return this.articles; @@ -44,39 +44,55 @@ public class ArticleMessage extends BaseMessage { return; } if (this.articles == null) { - this.articles = new LinkedList(); + this.articles = new LinkedList(); } this.articles.add(new Article(title, desc, picUrl, url)); - count ++; + count++; } - @XStreamAlias("item") - private static class Article { - @XStreamAlias("Title") - private String title; // 图文消息标题 - @XStreamAlias("Description") - private String desc; // 图文消息描述 - @XStreamAlias("PicUrl") - private String picUrl; // 图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200 - @XStreamAlias("Url") - private String url; // 点击图文消息跳转链接 - - public Article(String title, String desc, String picUrl, String url) { - this.title = title; - this.desc = desc; - this.picUrl = picUrl; - this.url = url; + public void pushFirstArticle(String title, String desc, String picUrl, + String url) { + if (this.articles == null) { + this.articles = new LinkedList(); } + this.articles.addFirst(new Article(title, desc, picUrl, url)); + } - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Article ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,picUrl=").append(picUrl); - sb.append(" ,url=").append(url).append(")"); - return sb.toString(); + public void pushLastArticle(String title, String desc, String picUrl, + String url) { + if (this.articles == null) { + this.articles = new LinkedList(); } + this.articles.addLast(new Article(title, desc, picUrl, url)); + } + + public Article removeLastArticle() { + if (this.articles != null) { + return this.articles.removeLast(); + } + return null; + } + + 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() { + 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 diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java index 2da50a01..fb58ecb8 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java @@ -1,38 +1,50 @@ 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 回复图片消息 + * @see 回复图片消息 + * @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() { - super(MessageType.image); + public ImageMessage(BaseMessage inMessage) { + super(MessageType.image, inMessage); super.getMsgType().setMessageClass(ImageMessage.class); } + 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(); - this.image.mediaId = mediaId; + this.image = new Image(mediaId); } - private static class Image { - @XStreamAlias("MediaId") - private String mediaId; + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Image.class, "mediaId"); + return xstream.toXML(this); } @Override @@ -41,7 +53,7 @@ public class ImageMessage extends BaseMessage { sb.append("[ImageMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,mediaId=").append(this.image.mediaId); + sb.append(" ,mediaId=").append(this.image.getMediaId()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java index c790b9ac..419f32d6 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java @@ -1,74 +1,61 @@ 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 回复音乐消息 + * @see 回复音乐消息 + * @see com.foxinmy.weixin4j.msg.model.Music * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class MusicMessage extends BaseMessage { private static final long serialVersionUID = 4384403772658796395L; - public MusicMessage() { - super(MessageType.music); + public MusicMessage(BaseMessage inMessage) { + super(MessageType.music, inMessage); } @XStreamAlias("Music") private Music music; - public Music getMusic() { - return this.music; + public void pushMusic(String mediaId) { + this.music = new Music(mediaId); } - public void pushMusic(String title, String desc, String url, String hqUrl, String mediaId) { - this.music = new Music(); - this.music.thumbMediaId = mediaId; - this.music.desc = desc; - this.music.hqMusicUrl = hqUrl; - this.music.MusicURL = url; - this.music.title = title; + public void setMusic(Music music) { + this.music = music; } - private static class Music { - @XStreamAlias("Title") - private String title; // 音乐标题 - @XStreamAlias("Description") - private String desc; // 音乐描述 - @XStreamAlias("MusicURL") - private String MusicURL; // 音乐链接 - @XStreamAlias("HQMusicUrl") - private String hqMusicUrl; // 高质量音乐链接,WIFI环境优先使用该链接播放音乐 - @XStreamAlias("ThumbMediaId") - private String thumbMediaId; // 缩略图的媒体id,通过上传多媒体文件,得到的id - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Music ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,musicURL=").append(MusicURL); - sb.append(" ,hqMusicUrl=").append(hqMusicUrl); - sb.append(" ,thumbMediaId=").append(thumbMediaId).append(")"); - return sb.toString(); - } + @Override + public String 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(getMusic().toString()); + sb.append(" ,music=").append(music.toString()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java new file mode 100644 index 00000000..3721504b --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java @@ -0,0 +1,117 @@ +package com.foxinmy.weixin4j.msg.out; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +import com.alibaba.fastjson.JSON; + +/** + * 模板消息 + * + * @className TemplateMessage + * @author jy + * @date 2014年9月29日 + * @since JDK 1.7 + * @see + */ +public class TemplateMessage implements Serializable { + + private static final long serialVersionUID = 7950608393821661436L; + + private String touser; + private String template_id; + private String url; + private String topcolor = "#FF0000"; + private Map data; + + public void pushData(String key, String value) { + this.data.put(key, new Item(value)); + } + + public TemplateMessage(String touser, String template_id, String url) { + this.touser = touser; + this.template_id = template_id; + this.url = url; + this.data = new HashMap(); + } + + private static class Item implements Serializable { + private static final long serialVersionUID = 1L; + private String value; + private String color; + + public Item(String value) { + this(value, "#173177"); + } + + public Item(String value, String color) { + this.value = value; + this.color = color; + } + + public String getValue() { + return value; + } + + public String getColor() { + return color; + } + + @Override + public String toString() { + return "$ [value=" + getValue() + ", color=" + getColor() + "]"; + } + } + + public String getTouser() { + return touser; + } + + public void setTouser(String touser) { + this.touser = touser; + } + + public String getTemplate_id() { + return template_id; + } + + public void setTemplate_id(String template_id) { + this.template_id = template_id; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getTopcolor() { + return topcolor; + } + + public void setTopcolor(String topcolor) { + this.topcolor = topcolor; + } + + public Map getData() { + return data; + } + + public void setData(Map data) { + this.data = data; + } + + @Override + public String toString() { + return "TemplateMessage [touser=" + touser + ", template_id=" + + template_id + ", url=" + url + ", topcolor=" + topcolor + + ", data=" + data + "]"; + } + + public String toJson() { + return JSON.toJSONString(this); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java new file mode 100644 index 00000000..b89621aa --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java @@ -0,0 +1,25 @@ +package com.foxinmy.weixin4j.msg.out; + +import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.type.MessageType; + +/** + * 转移消息到多客服端消息 + * + * @className TransferMessage + * @author jy.hu + * @date 2014年6月28日 + * @since JDK 1.7 + * @see 多客服转移消息 + * @see com.foxinmy.weixin4j.msg.BaseMessage + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + */ +public class TransferMessage extends BaseMessage { + + private static final long serialVersionUID = -5479496746108594940L; + + public TransferMessage(BaseMessage inMessage) { + super(MessageType.transfer_customer_service,inMessage); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java index d16c5a12..d6cdfc91 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java @@ -1,58 +1,52 @@ package com.foxinmy.weixin4j.msg.out; import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.msg.model.Video; import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 回复视频消息 + * * @className VideoMessage * @author jy.hu * @date 2014年4月6日 * @since JDK 1.7 - * @see 回复视频消息 + * @see 回复视频消息 + * @see com.foxinmy.weixin4j.msg.model.Video * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class VideoMessage extends BaseMessage { private static final long serialVersionUID = -1013075358679078381L; - public VideoMessage() { - super(MessageType.video); + public VideoMessage(BaseMessage inMessage) { + super(MessageType.video, inMessage); super.getMsgType().setMessageClass(VideoMessage.class); } @XStreamAlias("Video") private Video video; - public Video getVideo() { - return this.video; + public void pushVideo(String mediaId) { + this.video = new Video(mediaId); } - public void pushVideo(String mediaId, String title, String desc) { - this.video = new Video(); - this.video.desc = desc; - this.video.mediaId = mediaId; - this.video.title = title; + public void setVideo(Video video) { + this.video = video; } - private static class Video { - @XStreamAlias("MediaId") - private String mediaId; - @XStreamAlias("Title") - private String title; - @XStreamAlias("Description") - private String desc; - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Video mediaId=").append(mediaId); - sb.append(" ,title=").append(title); - sb.append(" ,desc=").append(desc).append(")"); - return super.toString(); - } + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Video.class, "mediaId"); + xstream.aliasField("Title", Video.class, "title"); + xstream.aliasField("Description", Video.class, "desc"); + xstream.omitField(Video.class, "thumbMediaId"); + return xstream.toXML(this); } @Override @@ -61,7 +55,7 @@ public class VideoMessage extends BaseMessage { sb.append("[VideoMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,video=").append(getVideo().toString()); + sb.append(" ,video=").append(video.toString()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java index 93052907..dcac1046 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java @@ -1,53 +1,60 @@ package com.foxinmy.weixin4j.msg.out; import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.msg.model.Voice; import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 语音消息 + * * @className VoiceMessage * @author jy.hu * @date 2014年3月23日 * @since JDK 1.7 - * @see 回复语音消息 + * @see 回复语音消息 + * @see com.foxinmy.weixin4j.msg.model.Voice * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class VoiceMessage extends BaseMessage { private static final long serialVersionUID = -7944926238652243793L; - public VoiceMessage() { - super(MessageType.voice); + public VoiceMessage(BaseMessage inMessage) { + super(MessageType.voice, inMessage); super.getMsgType().setMessageClass(VoiceMessage.class); } + + public VoiceMessage(String mediaId, BaseMessage inMessage) { + super(MessageType.voice, inMessage); + super.getMsgType().setMessageClass(VoiceMessage.class); + this.pushMediaId(mediaId); + } + @XStreamAlias("Voice") private Voice voice; - - public Voice getVocie() { - return voice; + + public void pushMediaId(String mediaId) { + this.voice = new Voice(mediaId); } - public void pushMediaId(String mediaId){ - this.voice = new Voice(); - this.voice.setMediaId(mediaId); - } - - private static class Voice { - @XStreamAlias("MediaId") - private String mediaId; - - private void setMediaId(String mediaId) { - this.mediaId = mediaId; - } + + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Voice.class, "mediaId"); + return xstream.toXML(this); } + @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("[VoiceMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,mediaId=").append(getVocie().mediaId); + sb.append(" ,mediaId=").append(voice.getMediaId()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java b/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java new file mode 100644 index 00000000..cf2ab68e --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java @@ -0,0 +1,55 @@ +package com.foxinmy.weixin4j.type; + +/** + * 自定义菜单类型 + * scancode_push 到 location_selec + * 仅支持微信iPhone5.4.1以上版本,和Android5 .4以上版本的微信用户 旧版本微信用户点击后将没有回应 + * 开发者也不能正常接收到事件推送。 + * + * @className ButtonType + * @author jy + * @date 2014年9月30日 + * @since JDK 1.7 + * @see 按钮类型 + */ +public enum ButtonType { + /** + * 点击推事件 用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event + * 的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互; + */ + click, + /** + * 跳转URL 用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的网页URL,可与网页授权获取用户基本信息接口结合,获得用户基本信息。 + */ + view, + /** + * 扫码推事件 用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后显示扫描结果(如果是URL,将进入URL),且会将扫码的结果传给开发者, + * 开发者可以下发消息。 + */ + scancode_push, + /** + * 扫码推事件且弹出“消息接收中”提示框用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后,将扫码的结果传给开发者,同时收起扫一扫工具, + * 然后弹出“消息接收中”提示框,随后可能会收到开发者下发的消息。 + */ + scancode_waitmsg, + /** + * 弹出系统拍照发图用户点击按钮后,微信客户端将调起系统相机,完成拍照操作后,会将拍摄的相片发送给开发者,并推送事件给开发者,同时收起系统相机, + * 随后可能会收到开发者下发的消息。 + */ + pic_sysphoto, + /** + * 弹出拍照或者相册发图用户点击按钮后,微信客户端将弹出选择器供用户选择“拍照”或者“从手机相册选择”。用户选择后即走其他两种流程。 + */ + pic_photo_or_albu, + /** + * 弹出微信相册发图器用户点击按钮后,微信客户端将调起微信相册,完成选择操作后,将选择的相片发送给开发者的服务器,并推送事件给开发者,同时收起相册, + * 随后可能会收到开发者下发的消息。 + */ + pic_weixin, + /** + * 弹出地理位置选择器用户点击按钮后,微信客户端将调起地理位置选择工具,完成选择操作后,将选择的地理位置发送给开发者的服务器,同时收起位置选择工具, + * 随后可能会收到开发者下发的消息。 + */ + location_select; +} diff --git a/src/main/java/com/foxinmy/weixin4j/type/EventType.java b/src/main/java/com/foxinmy/weixin4j/type/EventType.java index a8e864b8..bc85ce90 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/EventType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/EventType.java @@ -3,21 +3,36 @@ package com.foxinmy.weixin4j.type; import com.foxinmy.weixin4j.msg.event.EventMessage; import com.foxinmy.weixin4j.msg.event.LocationEventMessage; import com.foxinmy.weixin4j.msg.event.MassEventMessage; -import com.foxinmy.weixin4j.msg.event.MenuEventMessage; import com.foxinmy.weixin4j.msg.event.ScanEventMessage; import com.foxinmy.weixin4j.msg.event.ScribeEventMessage; +import com.foxinmy.weixin4j.msg.event.TemplatesendjobfinishMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuLocationEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuPhotoEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuScanEventMessage; /** - * * 事件类型 - * @author jy.hu - * + * + * @className EventType + * @author jy + * @date 2014年9月30日 + * @since JDK 1.7 + * @see */ public enum EventType { - subscribe(ScribeEventMessage.class), unsubscribe(ScribeEventMessage.class), - scan(ScanEventMessage.class),click(MenuEventMessage.class),view(MenuEventMessage.class), - location(LocationEventMessage.class),MASSSENDJOBFINISH(MassEventMessage.class); - + subscribe(ScribeEventMessage.class), unsubscribe(ScribeEventMessage.class), scan( + ScanEventMessage.class), scancode_push(MenuScanEventMessage.class), view( + MenuEventMessage.class), scancode_waitmsg( + MenuScanEventMessage.class), pic_sysphoto( + MenuPhotoEventMessage.class), pic_photo_or_album( + MenuPhotoEventMessage.class), pic_weixin( + MenuPhotoEventMessage.class), location_select( + MenuLocationEventMessage.class), click(MenuEventMessage.class), location( + LocationEventMessage.class), massendjobfinish( + MassEventMessage.class), templatesendjobfinish( + TemplatesendjobfinishMessage.class); + private Class extends EventMessage> eventClass; EventType(Class extends EventMessage> eventClass) { diff --git a/src/main/java/com/foxinmy/weixin4j/type/MediaType.java b/src/main/java/com/foxinmy/weixin4j/type/MediaType.java index 1f567181..322ba3ce 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/MediaType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/MediaType.java @@ -6,13 +6,20 @@ package com.foxinmy.weixin4j.type; * 语音(voice):256K,播放长度不超过60s,支持AMR\MP3格式 * 视频(video):1MB,支持MP4格式 * 缩略图(thumb):64KB,支持JPG格式 - * 媒体文件在后台保存时间为3天,即3天后media_id失效 + * + * 媒体文件在后台保存时间为3天,即3天后media_id失效 + * + * * @author jy.hu * @date 2014年4月2日 * @since JDK 1.7 */ public enum MediaType { - image("image/jpeg",".jpg"), voice("binary/octet-stream","amr"), vedio("binary/octet-stream","mp4"), thumb("image/jpeg","jpg"); + image("image/jpeg", "jpg"), voice("binary/octet-stream", "amr"), vedio( + "binary/octet-stream", "mp4"), thumb("image/jpeg", "jpg"), text( + "application/json", ""), music("binary/octet-stream", "mp3"), news( + "application/json", ""), mpnews("application/json", ""), mpvideo( + "binary/octet-stream", ""); MediaType(String contentType, String formatType) { this.contentType = contentType; @@ -26,6 +33,7 @@ public enum MediaType { } private String formatType; + public String getFormatType() { return formatType; } diff --git a/src/main/java/com/foxinmy/weixin4j/type/MessageType.java b/src/main/java/com/foxinmy/weixin4j/type/MessageType.java index 21a7b6dc..a883d993 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/MessageType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/MessageType.java @@ -10,6 +10,7 @@ import com.foxinmy.weixin4j.msg.in.VideoMessage; import com.foxinmy.weixin4j.msg.in.VoiceMessage; import com.foxinmy.weixin4j.msg.out.ArticleMessage; import com.foxinmy.weixin4j.msg.out.MusicMessage; +import com.foxinmy.weixin4j.msg.out.TransferMessage; /** * @@ -20,9 +21,13 @@ import com.foxinmy.weixin4j.msg.out.MusicMessage; */ public enum MessageType { // 接收到的消息类型 - text(TextMessage.class), image(ImageMessage.class), voice(VoiceMessage.class), video(VideoMessage.class), location(LocationMessage.class), link(LinkMessage.class), event(EventMessage.class), + text(TextMessage.class), image(ImageMessage.class), voice( + VoiceMessage.class), video(VideoMessage.class), location( + LocationMessage.class), link(LinkMessage.class), event( + EventMessage.class), // 发送的消息类型 - music(MusicMessage.class), news(ArticleMessage.class); + music(MusicMessage.class), news(ArticleMessage.class), transfer_customer_service( + TransferMessage.class); private Class extends BaseMessage> messageClass; MessageType(Class extends BaseMessage> messageClass) { diff --git a/src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java b/src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java similarity index 91% rename from src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java rename to src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java index f428c33b..b419bd1c 100644 --- a/src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java +++ b/src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java @@ -8,8 +8,8 @@ import java.util.regex.Pattern; import com.foxinmy.weixin4j.WeixinProxy; -public class WeixinConfig { - public WeixinConfig() { +public class ConfigUtil { + public ConfigUtil() { } private static Properties props = new Properties(); @@ -38,7 +38,6 @@ public class WeixinConfig { m.appendTail(sb); return sb.toString(); } - public static void main(String[] args) { System.out.println(getValue("api_token_uri")); } diff --git a/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java b/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java new file mode 100644 index 00000000..60eae107 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java @@ -0,0 +1,67 @@ +package com.foxinmy.weixin4j.util; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.Writer; +import java.nio.charset.Charset; + +/** + * IOUtil + * + * @className IOUtil + * @author jy.hu + * @date 2014年9月22日 + * @since JDK 1.7 + * @see org.apache.commons.io.IOUtils + */ +public class IOUtil { + + private static final int EOF = -1; + private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; + + public static byte[] toByteArray(Reader input) throws IOException { + return toByteArray(input, Charset.defaultCharset()); + } + + public static byte[] toByteArray(Reader input, Charset encoding) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + copy(input, output, encoding); + return output.toByteArray(); + } + + public static void copy(Reader input, OutputStream output, Charset encoding) throws IOException { + OutputStreamWriter out = new OutputStreamWriter(output, encoding); + copyLarge(input, out, new char[DEFAULT_BUFFER_SIZE]); + out.flush(); + } + + public static byte[] toByteArray(InputStream input) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + copyLarge(input, output, new byte[DEFAULT_BUFFER_SIZE]); + return output.toByteArray(); + } + + private static long copyLarge(InputStream input, OutputStream output, byte[] buffer) throws IOException { + long count = 0; + int n = 0; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } + + private static long copyLarge(Reader input, Writer output, char[] buffer) throws IOException { + long count = 0; + int n = 0; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java b/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java new file mode 100644 index 00000000..82a23ef3 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java @@ -0,0 +1,135 @@ +package com.foxinmy.weixin4j.util; + +import java.io.InputStream; +import java.util.Arrays; + +import org.apache.commons.codec.digest.DigestUtils; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.DocumentHelper; +import org.dom4j.io.SAXReader; +import org.jsoup.helper.StringUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.type.EventType; +import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; + +public class MessageUtil { + + private final static Logger log = LoggerFactory.getLogger(MessageUtil.class); + + /** + * 验证微信签名 + * + * @param echostr + * 随机字符串 + * @param timestamp + * 时间戳 + * @param nonce + * 随机数 + * @param signature + * 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数 + * @return 开发者通过检验signature对请求进行相关校验。若确认此次GET请求来自微信服务器 + * 请原样返回echostr参数内容,则接入生效 成为开发者成功,否则接入失败 + * @see 接入指南 + */ + public static String signature(String echostr, String timestamp, String nonce, String signature) { + String app_token = ConfigUtil.getValue("app_token"); + if (StringUtil.isBlank(app_token)) { + log.error("signature fail : token is null!"); + return null; + } + if (StringUtil.isBlank(echostr) || StringUtil.isBlank(timestamp) || StringUtil.isBlank(nonce)) { + log.error("signature fail : invalid parameter!"); + return null; + } + String _signature = null; + try { + String[] a = { app_token, timestamp, nonce }; + Arrays.sort(a); + StringBuilder sb = new StringBuilder(3); + for (String str : a) { + sb.append(str); + } + _signature = DigestUtils.sha1Hex(sb.toString()); + } catch (Exception e) { + log.error("signature error", e); + } + if (signature.equals(_signature)) { + return echostr; + } else { + log.error("signature fail : invalid signature!"); + return null; + } + } + + /** + * xml消息转换为消息对象 + * + * 微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次 + * + * + * @param xml + * 消息字符串 + * @return 消息对象 + * @throws DocumentException + * @see 验证消息的合法性 + * @see 普通消息 + * @see 事件触发 + * @see com.foxinmy.weixin4j.type.MessageType + * @see com.feican.weixin.msg.BaeMessage + * @see com.foxinmy.weixin4j.msg.TextMessage + * @see com.foxinmy.weixin4j.msg.in.ImageMessage + * @see com.foxinmy.weixin4j.msg.in.VoiceMessage + * @see com.foxinmy.weixin4j.msg.in.VideoMessage + * @see com.foxinmy.weixin4j.msg.in.LocationMessage + * @see com.foxinmy.weixin4j.msg.in.LinkMessage + * @see com.foxinmy.weixin4j.msg.event.ScribeEventMessage + * @see com.foxinmy.weixin4j.msg.event.ScanEventMessage + * @see com.foxinmy.weixin4j.msg.event.LocationEventMessage + * @see com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage + */ + public static BaseMessage xml2msg(String xml) throws DocumentException { + if (StringUtil.isBlank(xml)) + return null; + Document doc = DocumentHelper.parseText(xml); + String type = doc.selectSingleNode("/xml/MsgType").getStringValue(); + if (StringUtil.isBlank(type)) { + return null; + } + XStream xstream = new XStream(); + MessageType messageType = MessageType.valueOf(type.toLowerCase()); + Class extends BaseMessage> messageClass = messageType.getMessageClass(); + if (messageType == MessageType.event) { + type = doc.selectSingleNode("/xml/Event").getStringValue(); + messageClass = EventType.valueOf(type.toLowerCase()).getEventClass(); + } + xstream.alias("xml", messageClass); + xstream.ignoreUnknownElements(); + xstream.autodetectAnnotations(true); + xstream.processAnnotations(messageClass); + return xstream.fromXML(doc.asXML(), messageClass); + } + + /** + * xml消息转换为消息对象 + * + * @param inputStream + * 带消息字符串的输入流 + * @return 消息对象 + * @throws DocumentException + * @see {@link com.foxinmy.weixin4j.WeixinProxy#xml2msg(String)} + */ + public static BaseMessage xml2msg(InputStream inputStream) throws DocumentException { + SAXReader reader = new SAXReader(); + Document doc = reader.read(inputStream); + return xml2msg(doc.asXML()); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java b/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java deleted file mode 100644 index 19fd87e4..00000000 --- a/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.foxinmy.weixin4j.util; - -public class WeixinUtil { - - public static boolean isBlank(String str) { - return str == null || str.isEmpty(); - } -} diff --git a/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java b/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java index 5c0186c6..4a811a6c 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java @@ -9,7 +9,7 @@ import org.junit.Test; import com.foxinmy.weixin4j.WeixinProxy; import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.model.Button; -import com.foxinmy.weixin4j.model.Button.BtnType; +import com.foxinmy.weixin4j.type.ButtonType; /** * 自定义菜单测试 @@ -31,7 +31,7 @@ public class ButtonTest { List btnList = new ArrayList(); Button b = new Button("test"); - b.setType(BtnType.click); + b.setType(ButtonType.click); b.setKey("123"); btnList.add(b); diff --git a/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java b/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java index 8b78305e..bb6bec88 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java @@ -50,7 +50,7 @@ public class GroupTest { @Test public void getid() { try { - System.out.println(weixinProxy.findGroupByOpenId("owGBft_vbBbOaQOmpEUE4xDLeRSU")); + System.out.println(weixinProxy.getGroupByOpenId("owGBft_vbBbOaQOmpEUE4xDLeRSU")); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); diff --git a/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java b/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java new file mode 100644 index 00000000..6d34a733 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java @@ -0,0 +1,22 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Test; + +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.http.HttpRequest; + +public class HttpTest { + private static HttpRequest request; + static { + request = new HttpRequest(); + } + + @Test + public void test(){ + try { + System.out.println(request.get("http://www.baidu.com")); + } catch (WeixinException e) { + e.printStackTrace(); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java b/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java index f907fa3d..d54e649b 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java @@ -31,7 +31,7 @@ public class MediaTest { File file = new File("D:\\test.jpg"); try { System.out.println(weixinProxy.uploadMedia(file, MediaType.image)); - //usAxLEJxFXAjXVlLu_BSw0GvS2YEEoGeelRBybNZBGvMsdxiIcD1F9yBWYd9jVZx + //vvU_AUtovWyfAxQ8J1DsCoNMtK6U_bUmTpe6lpINUOVRLvt_7rtO4zxzBpPgkmay } catch (WeixinException e) { System.out.println(e.getErrorMsg()); } @@ -40,7 +40,7 @@ public class MediaTest { @Test public void download() { try { - System.out.println(weixinProxy.downloadMedia("usAxLEJxFXAjXVlLu_BSw0GvS2YEEoGeelRBybNZBGvMsdxiIcD1F9yBWYd9jVZx", MediaType.image)); + System.out.println(weixinProxy.downloadMedia("vvU_AUtovWyfAxQ8J1DsCoNMtK6U_bUmTpe6lpINUOVRLvt_7rtO4zxzBpPgkmay", MediaType.image)); } catch (WeixinException e) { System.out.println(e.getErrorMsg()); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java new file mode 100644 index 00000000..2cd36584 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java @@ -0,0 +1,194 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Test; + +import com.foxinmy.weixin4j.util.MessageUtil; + +/** + * 接收事件消息格式测试 + * + * @author jy.hu + * @date 2014年3月24日 + * @since JDK 1.7 + */ +public class MessageEventInTest { + + private StringBuilder xmlSb = new StringBuilder(); + + /***************** event message *********************/ + @Test + public void scribe() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void scan() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void scan_scribe() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void location1() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("23.137466"); + xmlSb.append("113.352425"); + xmlSb.append("119.385040"); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_click() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_link() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_scan() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_photo() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("1"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_location() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java index 39269754..fdd40042 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java @@ -1,134 +1,19 @@ package com.foxinmy.weixin4j.test; -import org.junit.Before; import org.junit.Test; -import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.util.MessageUtil; /** - * 接收消息格式测试 + * 接受一般消息格式测试 + * * @author jy.hu * @date 2014年3月24日 * @since JDK 1.7 */ public class MessageInTest { + private StringBuilder xmlSb = new StringBuilder(); - private WeixinProxy weixinProxy; - - @Before - public void init(){ - weixinProxy = new WeixinProxy(); - } - - /***************** event message *********************/ - @Test - public void scribe() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void scan() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - @Test - public void scan_scribe() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void location1() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("23.137466"); - xmlSb.append("113.352425"); - xmlSb.append("119.385040"); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void menu_click() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void menu_link() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } /***************** common message *********************/ @@ -144,7 +29,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -163,7 +48,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -182,7 +67,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -202,7 +87,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -221,7 +106,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -242,7 +127,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -262,7 +147,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java new file mode 100644 index 00000000..8f6a130f --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java @@ -0,0 +1,114 @@ +package com.foxinmy.weixin4j.test; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.model.MpArticle; +import com.foxinmy.weixin4j.type.MediaType; + +/** + * 群发消息 + * + * @className MpNewsTest + * @author jy + * @date 2014年4月27日 + * @since JDK 1.7 + * @see + */ +public class MessageMassTest { + private WeixinProxy weixinProxy; + + @Before + public void init() { + this.weixinProxy = new WeixinProxy(); + } + + @Test + public void uploadArticle() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.uploadArticle(articles); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void uploadVideo() { + try { + weixinProxy.uploadVideo("mediaId", "title", "desc"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massByGroup() { + try { + weixinProxy.massByGroup("123", MediaType.image, "groupId"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massByOpenIds() { + try { + weixinProxy.massByOpenIds("123", MediaType.image, "openIds"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massArticleByGroup() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.massArticleByGroup(articles, "0"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massArticleByOpenIds() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.massArticleByOpenIds(articles, + "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void deleteMass() { + try { + weixinProxy.deleteMassNews("34182"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java index f3be10bb..59aed8de 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java @@ -7,6 +7,7 @@ import org.junit.Test; import com.foxinmy.weixin4j.WeixinProxy; import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.msg.model.Music; import com.foxinmy.weixin4j.msg.notify.ArticleNotify; import com.foxinmy.weixin4j.msg.notify.BaseNotify; import com.foxinmy.weixin4j.msg.notify.ImageNotify; @@ -41,27 +42,29 @@ public class MessageNotifyTest { @Test public void image() { - ImageNotify notify = new ImageNotify("123", "to"); + ImageNotify notify = new ImageNotify("to"); + notify.pushMediaId("123"); System.out.println(notify.toJson()); } @Test public void voice() { - VoiceNotify notify = new VoiceNotify("123", "to"); + VoiceNotify notify = new VoiceNotify("to"); + notify.pushMediaId("123"); System.out.println(notify.toJson()); } @Test public void video() { VideoNotify notify = new VideoNotify("to"); - notify.pushVideo("123", "title", "desc"); + notify.pushVideo("123","m123"); System.out.println(notify.toJson()); } @Test public void music() { MusicNotify notify = new MusicNotify("to"); - notify.pushMusic("title", "desc", "url", "hqUrl", "mediaId"); + notify.pushMusic("url", "hqUrl", "mediaId"); System.out.println(notify.toJson()); } @@ -74,16 +77,27 @@ public class MessageNotifyTest { } @Test - public void send() { - BaseNotify t = new TextNotify("哈哈哈哈", "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + public void send1() { + BaseNotify notify = new TextNotify("哈哈哈哈", "owGBft_vbBbOaQOmpEUE4xDLeRSU"); try { - weixinProxy.sendNotify(t); + weixinProxy.sendNotify(notify); String mediaId = weixinProxy.uploadMedia(new File("D:\\test.jpg"), MediaType.image); - t = new ImageNotify(mediaId, "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + ImageNotify t = new ImageNotify("owGBft_vbBbOaQOmpEUE4xDLeRSU"); + t.pushMediaId(mediaId); weixinProxy.sendNotify(t); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); } } + + @Test + public void send2() { + try { + weixinProxy.sendNotify("to",new Music("thumbMediaId")); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java index 00021aa0..ddb309d4 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java @@ -1,7 +1,9 @@ package com.foxinmy.weixin4j.test; +import org.junit.Before; import org.junit.Test; +import com.foxinmy.weixin4j.msg.BaseMessage; import com.foxinmy.weixin4j.msg.TextMessage; import com.foxinmy.weixin4j.msg.out.ArticleMessage; import com.foxinmy.weixin4j.msg.out.ImageMessage; @@ -17,56 +19,52 @@ import com.foxinmy.weixin4j.msg.out.VoiceMessage; * @since JDK 1.7 */ public class MessageOutTest { + private BaseMessage inMessage; + + @Before + public void init() { + this.inMessage = new TextMessage(); + this.inMessage.setFromUserName("fromusername"); + this.inMessage.setToUserName("tousername"); + } + @Test public void text() { - TextMessage message = new TextMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.setContent("text message"); + TextMessage message = new TextMessage("text", inMessage); System.out.println(message.toXml()); } @Test public void image() { - ImageMessage message = new ImageMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + ImageMessage message = new ImageMessage(inMessage); message.pushMediaId("mediaId"); System.out.println(message.toXml()); } @Test public void voice() { - VoiceMessage message = new VoiceMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + VoiceMessage message = new VoiceMessage(inMessage); message.pushMediaId("mediaId"); System.out.println(message.toXml()); } - + @Test public void video() { - VideoMessage message = new VideoMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.pushVideo("mediaId", "title", "title"); + VideoMessage message = new VideoMessage(inMessage); + message.pushVideo("mediaId"); System.out.println(message.toXml()); } - + @Test public void music() { - MusicMessage message = new MusicMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.pushMusic("title", "desc", "url", "hqurl", "mediaId"); + MusicMessage message = new MusicMessage(inMessage); + message.pushMusic("mediaId"); System.out.println(message.toXml()); } - + @Test public void article() { - ArticleMessage message = new ArticleMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + ArticleMessage message = new ArticleMessage(inMessage); message.pushArticle("title1", "desc1", "picUrl1", "url1"); message.pushArticle("title2", "desc2", "picUrl2", "url2"); System.out.println(message.toXml()); diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java new file mode 100644 index 00000000..b8165a91 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java @@ -0,0 +1,30 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Before; +import org.junit.Test; + +import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.msg.out.TemplateMessage; + +public class MessageTemplTest { + private WeixinProxy weixinProxy; + + @Before + public void init() { + this.weixinProxy = new WeixinProxy(); + } + + @Test + public void test() { + TemplateMessage tplMessage = new TemplateMessage("touser", + "template_id", "url"); + tplMessage.pushData("name", "fox"); + System.out.print(tplMessage.toJson()); + try { + System.out.print(weixinProxy.sendTplMessage(tplMessage)); + } catch (WeixinException e) { + System.out.println(e.getErrorMsg()); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java b/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java deleted file mode 100644 index 5fa1ec67..00000000 --- a/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.foxinmy.weixin4j.test; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; - -import com.foxinmy.weixin4j.WeixinProxy; -import com.foxinmy.weixin4j.exception.WeixinException; -import com.foxinmy.weixin4j.model.MpArticle; -import com.foxinmy.weixin4j.type.MediaType; - -/** - * 群发消息 - * - * @className MpNewsTest - * @author jy - * @date 2014年4月27日 - * @since JDK 1.7 - * @see - */ -public class MpNewsTest { - private WeixinProxy weixinProxy; - - @Before - public void init() { - this.weixinProxy = new WeixinProxy(); - } - - @Test - public void massByGroup(){ - List articles = new ArrayList(); - try { - String thumbMediaId = weixinProxy.uploadMedia(new File("/tmp/test.jpg"), MediaType.image); - articles.add(new MpArticle(thumbMediaId, "title", "content")); - weixinProxy.massNewsByGroup(articles, "0"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } - - @Test - public void massByOpenIds(){ - List articles = new ArrayList(); - try { - String thumbMediaId = weixinProxy.uploadMedia(new File("/tmp/test.jpg"), MediaType.image); - articles.add(new MpArticle(thumbMediaId, "title", "content")); - weixinProxy.massNewsByOpenIds(articles, "owGBft_vbBbOaQOmpEUE4xDLeRSU"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } - - @Test - public void deleteMass(){ - try { - weixinProxy.deleteMassNews("34182"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } -} diff --git a/src/test/java/com/foxinmy/weixin4j/test/QRTest.java b/src/test/java/com/foxinmy/weixin4j/test/QRTest.java index 11934fa9..f18d1aa7 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/QRTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/QRTest.java @@ -25,10 +25,10 @@ public class QRTest { @Test public void temp_qr() { - QRParameter qr = new QRParameter(1200, QRType.QR_SCENE, 1); + QRParameter qr = new QRParameter(1200, QRType.TEMPORARY, 2); try { System.out.println(qr.toJson()); - weixinProxy.getQR(qr); + System.out.println(weixinProxy.getQR(qr)); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); @@ -37,10 +37,10 @@ public class QRTest { @Test public void forever_qr() { - QRParameter qr = new QRParameter(QRType.QR_LIMIT_SCENE, 1); + QRParameter qr = new QRParameter(QRType.PERMANENCE, 1); try { System.out.println(qr.toJson()); - weixinProxy.getQR(qr); + System.out.println(weixinProxy.getQR(qr)); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java b/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java index 37d549d7..a2f8a266 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java @@ -3,7 +3,8 @@ package com.foxinmy.weixin4j.test; import org.junit.Before; import org.junit.Test; -import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.api.token.FileTokenApi; +import com.foxinmy.weixin4j.api.token.TokenApi; import com.foxinmy.weixin4j.exception.WeixinException; /** @@ -14,17 +15,17 @@ import com.foxinmy.weixin4j.exception.WeixinException; * @since JDK 1.7 */ public class TokenTest { - private WeixinProxy weixinProxy; + private TokenApi tokenApi; @Before public void init() { - weixinProxy = new WeixinProxy(); + tokenApi = new FileTokenApi(); } @Test public void getToken() { try { - System.out.println(weixinProxy.getToken()); + System.out.println(tokenApi.getToken()); } catch (WeixinException e) { e.printStackTrace(); }
(); + } + + public void pushArticle(String title, String desc, String picUrl, + String url) { + this.articles.add(new Article(title, desc, picUrl, url)); + } + + public void setArticles(List articles) { + this.articles = articles; } @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("(article ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,picUrl=").append(picUrl); - sb.append(" ,url=").append(url).append(")"); + 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()); + return String.format( + "[ArticleNotify touser=%s ,msgtype=%s ,articles=%s]", + super.getTouser(), super.getMsgtype().name(), + this.news.toString()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/notify/ImageNotify.java b/src/main/java/com/foxinmy/weixin4j/msg/notify/ImageNotify.java index f9a52263..d2e47096 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/notify/ImageNotify.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/notify/ImageNotify.java @@ -1,14 +1,17 @@ package com.foxinmy.weixin4j.msg.notify; +import com.foxinmy.weixin4j.msg.model.Image; import com.foxinmy.weixin4j.type.MessageType; -import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 客服图片消息 + * * @author jy.hu * @date 2014年4月4日 * @since JDK 1.7 - * @see 客服图片消息 + * @see 客服图片消息 + * @see com.foxinmy.weixin4j.msg.model.Image * @see com.foxinmy.weixin4j.msg.notify.BaseNotify * @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson() */ @@ -20,30 +23,25 @@ public class ImageNotify extends BaseNotify { super(MessageType.image); } - public ImageNotify(String mediaId) { - super(MessageType.image); - this.image = new $(mediaId); + public ImageNotify(String touser) { + super(touser, MessageType.image); } public ImageNotify(String mediaId, String touser) { super(touser, MessageType.image); - this.image = new $(mediaId); + this.pushMediaId(mediaId); } - @XStreamAlias("image") - private $ image; - - private static class $ { - @XStreamAlias("media_id") - private String mediaId; - - public $(String mediaId) { - this.mediaId = 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.mediaId); + return String.format("[ImageNotify touser=%s ,msgtype=%s ,mediaId=%s]", + super.getTouser(), super.getMsgtype().name(), + this.image.getMediaId()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/notify/MusicNotify.java b/src/main/java/com/foxinmy/weixin4j/msg/notify/MusicNotify.java index 6f3e66fa..1e328677 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/notify/MusicNotify.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/notify/MusicNotify.java @@ -1,14 +1,17 @@ package com.foxinmy.weixin4j.msg.notify; +import com.foxinmy.weixin4j.msg.model.Music; import com.foxinmy.weixin4j.type.MessageType; -import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 客服音乐消息 + * * @author jy.hu * @date 2014年4月4日 * @since JDK 1.7 - * @see 客服音乐消息 + * @see 客服音乐消息 + * @see com.foxinmy.weixin4j.msg.model.Music * @see com.foxinmy.weixin4j.msg.notify.BaseNotify * @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson() */ @@ -24,44 +27,20 @@ public class MusicNotify extends BaseNotify { super(touser, MessageType.music); } - public void pushMusic(String title, String desc, String url, String hqUrl, String mediaId) { - this.music = new $(); - this.music.thumbMediaId = mediaId; - this.music.desc = desc; - this.music.hqMusicUrl = hqUrl; - this.music.musicUrl = url; - this.music.title = title; + public void pushMusic(String musicurl, String hqUrl, String mediaId) { + this.music = new Music(null, null, musicurl, hqUrl, mediaId); } - @XStreamAlias("music") - private $ music; - - private static class $ { - private String title; - @XStreamAlias("description") - private String desc; - @XStreamAlias("musicurl") - private String musicUrl; - @XStreamAlias("hqmusicurl") - private String hqMusicUrl; - @XStreamAlias("thumb_media_id") - private String thumbMediaId; - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(music ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,musicURL=").append(musicUrl); - sb.append(" ,hqMusicUrl=").append(hqMusicUrl); - sb.append(" ,thumbMediaId=").append(thumbMediaId).append(")"); - return sb.toString(); - } + private Music music; + public void setMusic(Music music) { + this.music = music; } @Override public String toString() { - return String.format("[VideoNotify touser=%s ,msgtype=%s ,music=%s]", super.getTouser(), super.getMsgtype().name(), this.music.toString()); + return String.format("[MusicNotify touser=%s ,msgtype=%s ,music=%s]", + super.getTouser(), super.getMsgtype().name(), + this.music.toString()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/notify/TextNotify.java b/src/main/java/com/foxinmy/weixin4j/msg/notify/TextNotify.java index edcf2565..6ec09a3a 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/notify/TextNotify.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/notify/TextNotify.java @@ -1,14 +1,17 @@ package com.foxinmy.weixin4j.msg.notify; +import com.foxinmy.weixin4j.msg.model.Text; import com.foxinmy.weixin4j.type.MessageType; -import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 客服文本消息 + * * @author jy.hu * @date 2014年4月4日 * @since JDK 1.7 - * @see 客服文本消息 + * @see 客服文本消息 + * @see com.foxinmy.weixin.msg.model.Text * @see com.foxinmy.weixin4j.msg.notify.BaseNotify * @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson() */ @@ -22,27 +25,24 @@ public class TextNotify extends BaseNotify { public TextNotify(String content) { super(MessageType.text); - this.text = new $(content); + this.text = new Text(content); } public TextNotify(String content, String touser) { super(touser, MessageType.text); - this.text = new $(content); + this.text = new Text(content); } - @XStreamAlias("text") - private $ text; - - private static class $ { - @XStreamAlias("content") - private String content; - - public $(String content) { - this.content = 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.content); + return String.format("[TextNotify touser=%s ,msgtype=%s ,content=%s]", + super.getTouser(), super.getMsgtype().name(), + this.text.getContent()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/notify/VideoNotify.java b/src/main/java/com/foxinmy/weixin4j/msg/notify/VideoNotify.java index d8865910..8e433c03 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/notify/VideoNotify.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/notify/VideoNotify.java @@ -1,14 +1,17 @@ package com.foxinmy.weixin4j.msg.notify; +import com.foxinmy.weixin4j.msg.model.Video; import com.foxinmy.weixin4j.type.MessageType; -import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 客服视频消息 + * * @author jy.hu * @date 2014年4月4日 * @since JDK 1.7 - * @see 客服视频消息 + * @see 客服视频消息 + * @see com.foxinmy.weixin4j.msg.model.Video * @see com.foxinmy.weixin4j.msg.notify.BaseNotify * @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson() */ @@ -23,36 +26,21 @@ public class VideoNotify extends BaseNotify { public VideoNotify(String touser) { super(touser, MessageType.video); } - - public void pushVideo(String mediaId, String title, String desc) { - this.video = new $(mediaId, title, desc); + + public void pushVideo(String mediaId, String thumbMediaId) { + this.video = new Video(mediaId, thumbMediaId); } - @XStreamAlias("video") - private $ video; - - private static class $ { - @XStreamAlias("media_id") - private String mediaId; - private String title; - @XStreamAlias("description") - private String desc; - - public $(String mediaId, String title, String desc) { - this.mediaId = mediaId; - this.title = title; - this.desc = desc; - } - - @Override - public String toString() { - return String.format("(video mediaId=%s ,title=%s ,description=%s)", mediaId, title, desc); - } + 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()); + return String.format("[VideoNotify touser=%s ,msgtype=%s ,video=%s]", + super.getTouser(), super.getMsgtype().name(), + this.video.toString()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/notify/VoiceNotify.java b/src/main/java/com/foxinmy/weixin4j/msg/notify/VoiceNotify.java index 8e0787b6..4cfb7a7f 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/notify/VoiceNotify.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/notify/VoiceNotify.java @@ -1,14 +1,17 @@ package com.foxinmy.weixin4j.msg.notify; +import com.foxinmy.weixin4j.msg.model.Voice; import com.foxinmy.weixin4j.type.MessageType; -import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 客服语音消息 + * * @author jy.hu * @date 2014年4月4日 * @since JDK 1.7 - * @see 客服语音消息 + * @see 客服语音消息 + * @see com.foxinmy.weixin4j.msg.model.Voice * @see com.foxinmy.weixin4j.msg.notify.BaseNotify * @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson() */ @@ -20,30 +23,25 @@ public class VoiceNotify extends BaseNotify { super(MessageType.voice); } - public VoiceNotify(String mediaId) { - super(MessageType.voice); - this.voice = new $(mediaId); + public VoiceNotify(String touser) { + super(touser, MessageType.voice); } public VoiceNotify(String mediaId, String touser) { super(touser, MessageType.voice); - this.voice = new $(mediaId); + this.pushMediaId(mediaId); } - @XStreamAlias("voice") - private $ voice; - - private static class $ { - @XStreamAlias("media_id") - private String mediaId; - - public $(String mediaId) { - this.mediaId = 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.mediaId); + return String.format("[VoiceNotify touser=%s ,msgtype=%s ,mediaId=%s]", + super.getTouser(), super.getMsgtype().name(), + this.voice.getMediaId()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/ArticleMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/ArticleMessage.java index e892aeaa..9c3737a7 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/ArticleMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/ArticleMessage.java @@ -4,36 +4,36 @@ import java.util.LinkedList; import java.util.List; 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 回复图文消息 + * @see 回复图文消息 + * @see com.foxinmy.weixin.msg.model.Article * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class ArticleMessage extends BaseMessage { private static final int MAX_ARTICLE_COUNT = 10; private static final long serialVersionUID = -7331603018352309317L; - public ArticleMessage() { - super(MessageType.news); - } - - public ArticleMessage(String toUserName) { - super(MessageType.news); - super.setToUserName(toUserName); + public ArticleMessage(BaseMessage inMessage) { + super(MessageType.news, inMessage); } @XStreamAlias("ArticleCount") private int count; // 图文消息个数,限制为10条以内 @XStreamAlias("Articles") - private List articles; + private LinkedList articles; public List getArticles() { return this.articles; @@ -44,39 +44,55 @@ public class ArticleMessage extends BaseMessage { return; } if (this.articles == null) { - this.articles = new LinkedList(); + this.articles = new LinkedList(); } this.articles.add(new Article(title, desc, picUrl, url)); - count ++; + count++; } - @XStreamAlias("item") - private static class Article { - @XStreamAlias("Title") - private String title; // 图文消息标题 - @XStreamAlias("Description") - private String desc; // 图文消息描述 - @XStreamAlias("PicUrl") - private String picUrl; // 图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200 - @XStreamAlias("Url") - private String url; // 点击图文消息跳转链接 - - public Article(String title, String desc, String picUrl, String url) { - this.title = title; - this.desc = desc; - this.picUrl = picUrl; - this.url = url; + public void pushFirstArticle(String title, String desc, String picUrl, + String url) { + if (this.articles == null) { + this.articles = new LinkedList(); } + this.articles.addFirst(new Article(title, desc, picUrl, url)); + } - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Article ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,picUrl=").append(picUrl); - sb.append(" ,url=").append(url).append(")"); - return sb.toString(); + public void pushLastArticle(String title, String desc, String picUrl, + String url) { + if (this.articles == null) { + this.articles = new LinkedList(); } + this.articles.addLast(new Article(title, desc, picUrl, url)); + } + + public Article removeLastArticle() { + if (this.articles != null) { + return this.articles.removeLast(); + } + return null; + } + + 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() { + 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 diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java index 2da50a01..fb58ecb8 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java @@ -1,38 +1,50 @@ 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 回复图片消息 + * @see 回复图片消息 + * @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() { - super(MessageType.image); + public ImageMessage(BaseMessage inMessage) { + super(MessageType.image, inMessage); super.getMsgType().setMessageClass(ImageMessage.class); } + 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(); - this.image.mediaId = mediaId; + this.image = new Image(mediaId); } - private static class Image { - @XStreamAlias("MediaId") - private String mediaId; + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Image.class, "mediaId"); + return xstream.toXML(this); } @Override @@ -41,7 +53,7 @@ public class ImageMessage extends BaseMessage { sb.append("[ImageMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,mediaId=").append(this.image.mediaId); + sb.append(" ,mediaId=").append(this.image.getMediaId()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java index c790b9ac..419f32d6 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java @@ -1,74 +1,61 @@ 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 回复音乐消息 + * @see 回复音乐消息 + * @see com.foxinmy.weixin4j.msg.model.Music * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class MusicMessage extends BaseMessage { private static final long serialVersionUID = 4384403772658796395L; - public MusicMessage() { - super(MessageType.music); + public MusicMessage(BaseMessage inMessage) { + super(MessageType.music, inMessage); } @XStreamAlias("Music") private Music music; - public Music getMusic() { - return this.music; + public void pushMusic(String mediaId) { + this.music = new Music(mediaId); } - public void pushMusic(String title, String desc, String url, String hqUrl, String mediaId) { - this.music = new Music(); - this.music.thumbMediaId = mediaId; - this.music.desc = desc; - this.music.hqMusicUrl = hqUrl; - this.music.MusicURL = url; - this.music.title = title; + public void setMusic(Music music) { + this.music = music; } - private static class Music { - @XStreamAlias("Title") - private String title; // 音乐标题 - @XStreamAlias("Description") - private String desc; // 音乐描述 - @XStreamAlias("MusicURL") - private String MusicURL; // 音乐链接 - @XStreamAlias("HQMusicUrl") - private String hqMusicUrl; // 高质量音乐链接,WIFI环境优先使用该链接播放音乐 - @XStreamAlias("ThumbMediaId") - private String thumbMediaId; // 缩略图的媒体id,通过上传多媒体文件,得到的id - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Music ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,musicURL=").append(MusicURL); - sb.append(" ,hqMusicUrl=").append(hqMusicUrl); - sb.append(" ,thumbMediaId=").append(thumbMediaId).append(")"); - return sb.toString(); - } + @Override + public String 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(getMusic().toString()); + sb.append(" ,music=").append(music.toString()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java new file mode 100644 index 00000000..3721504b --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java @@ -0,0 +1,117 @@ +package com.foxinmy.weixin4j.msg.out; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +import com.alibaba.fastjson.JSON; + +/** + * 模板消息 + * + * @className TemplateMessage + * @author jy + * @date 2014年9月29日 + * @since JDK 1.7 + * @see + */ +public class TemplateMessage implements Serializable { + + private static final long serialVersionUID = 7950608393821661436L; + + private String touser; + private String template_id; + private String url; + private String topcolor = "#FF0000"; + private Map data; + + public void pushData(String key, String value) { + this.data.put(key, new Item(value)); + } + + public TemplateMessage(String touser, String template_id, String url) { + this.touser = touser; + this.template_id = template_id; + this.url = url; + this.data = new HashMap(); + } + + private static class Item implements Serializable { + private static final long serialVersionUID = 1L; + private String value; + private String color; + + public Item(String value) { + this(value, "#173177"); + } + + public Item(String value, String color) { + this.value = value; + this.color = color; + } + + public String getValue() { + return value; + } + + public String getColor() { + return color; + } + + @Override + public String toString() { + return "$ [value=" + getValue() + ", color=" + getColor() + "]"; + } + } + + public String getTouser() { + return touser; + } + + public void setTouser(String touser) { + this.touser = touser; + } + + public String getTemplate_id() { + return template_id; + } + + public void setTemplate_id(String template_id) { + this.template_id = template_id; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getTopcolor() { + return topcolor; + } + + public void setTopcolor(String topcolor) { + this.topcolor = topcolor; + } + + public Map getData() { + return data; + } + + public void setData(Map data) { + this.data = data; + } + + @Override + public String toString() { + return "TemplateMessage [touser=" + touser + ", template_id=" + + template_id + ", url=" + url + ", topcolor=" + topcolor + + ", data=" + data + "]"; + } + + public String toJson() { + return JSON.toJSONString(this); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java new file mode 100644 index 00000000..b89621aa --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java @@ -0,0 +1,25 @@ +package com.foxinmy.weixin4j.msg.out; + +import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.type.MessageType; + +/** + * 转移消息到多客服端消息 + * + * @className TransferMessage + * @author jy.hu + * @date 2014年6月28日 + * @since JDK 1.7 + * @see 多客服转移消息 + * @see com.foxinmy.weixin4j.msg.BaseMessage + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + */ +public class TransferMessage extends BaseMessage { + + private static final long serialVersionUID = -5479496746108594940L; + + public TransferMessage(BaseMessage inMessage) { + super(MessageType.transfer_customer_service,inMessage); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java index d16c5a12..d6cdfc91 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java @@ -1,58 +1,52 @@ package com.foxinmy.weixin4j.msg.out; import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.msg.model.Video; import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 回复视频消息 + * * @className VideoMessage * @author jy.hu * @date 2014年4月6日 * @since JDK 1.7 - * @see 回复视频消息 + * @see 回复视频消息 + * @see com.foxinmy.weixin4j.msg.model.Video * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class VideoMessage extends BaseMessage { private static final long serialVersionUID = -1013075358679078381L; - public VideoMessage() { - super(MessageType.video); + public VideoMessage(BaseMessage inMessage) { + super(MessageType.video, inMessage); super.getMsgType().setMessageClass(VideoMessage.class); } @XStreamAlias("Video") private Video video; - public Video getVideo() { - return this.video; + public void pushVideo(String mediaId) { + this.video = new Video(mediaId); } - public void pushVideo(String mediaId, String title, String desc) { - this.video = new Video(); - this.video.desc = desc; - this.video.mediaId = mediaId; - this.video.title = title; + public void setVideo(Video video) { + this.video = video; } - private static class Video { - @XStreamAlias("MediaId") - private String mediaId; - @XStreamAlias("Title") - private String title; - @XStreamAlias("Description") - private String desc; - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Video mediaId=").append(mediaId); - sb.append(" ,title=").append(title); - sb.append(" ,desc=").append(desc).append(")"); - return super.toString(); - } + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Video.class, "mediaId"); + xstream.aliasField("Title", Video.class, "title"); + xstream.aliasField("Description", Video.class, "desc"); + xstream.omitField(Video.class, "thumbMediaId"); + return xstream.toXML(this); } @Override @@ -61,7 +55,7 @@ public class VideoMessage extends BaseMessage { sb.append("[VideoMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,video=").append(getVideo().toString()); + sb.append(" ,video=").append(video.toString()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java index 93052907..dcac1046 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java @@ -1,53 +1,60 @@ package com.foxinmy.weixin4j.msg.out; import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.msg.model.Voice; import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 语音消息 + * * @className VoiceMessage * @author jy.hu * @date 2014年3月23日 * @since JDK 1.7 - * @see 回复语音消息 + * @see 回复语音消息 + * @see com.foxinmy.weixin4j.msg.model.Voice * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class VoiceMessage extends BaseMessage { private static final long serialVersionUID = -7944926238652243793L; - public VoiceMessage() { - super(MessageType.voice); + public VoiceMessage(BaseMessage inMessage) { + super(MessageType.voice, inMessage); super.getMsgType().setMessageClass(VoiceMessage.class); } + + public VoiceMessage(String mediaId, BaseMessage inMessage) { + super(MessageType.voice, inMessage); + super.getMsgType().setMessageClass(VoiceMessage.class); + this.pushMediaId(mediaId); + } + @XStreamAlias("Voice") private Voice voice; - - public Voice getVocie() { - return voice; + + public void pushMediaId(String mediaId) { + this.voice = new Voice(mediaId); } - public void pushMediaId(String mediaId){ - this.voice = new Voice(); - this.voice.setMediaId(mediaId); - } - - private static class Voice { - @XStreamAlias("MediaId") - private String mediaId; - - private void setMediaId(String mediaId) { - this.mediaId = mediaId; - } + + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Voice.class, "mediaId"); + return xstream.toXML(this); } + @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("[VoiceMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,mediaId=").append(getVocie().mediaId); + sb.append(" ,mediaId=").append(voice.getMediaId()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java b/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java new file mode 100644 index 00000000..cf2ab68e --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java @@ -0,0 +1,55 @@ +package com.foxinmy.weixin4j.type; + +/** + * 自定义菜单类型 + * scancode_push 到 location_selec + * 仅支持微信iPhone5.4.1以上版本,和Android5 .4以上版本的微信用户 旧版本微信用户点击后将没有回应 + * 开发者也不能正常接收到事件推送。 + * + * @className ButtonType + * @author jy + * @date 2014年9月30日 + * @since JDK 1.7 + * @see 按钮类型 + */ +public enum ButtonType { + /** + * 点击推事件 用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event + * 的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互; + */ + click, + /** + * 跳转URL 用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的网页URL,可与网页授权获取用户基本信息接口结合,获得用户基本信息。 + */ + view, + /** + * 扫码推事件 用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后显示扫描结果(如果是URL,将进入URL),且会将扫码的结果传给开发者, + * 开发者可以下发消息。 + */ + scancode_push, + /** + * 扫码推事件且弹出“消息接收中”提示框用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后,将扫码的结果传给开发者,同时收起扫一扫工具, + * 然后弹出“消息接收中”提示框,随后可能会收到开发者下发的消息。 + */ + scancode_waitmsg, + /** + * 弹出系统拍照发图用户点击按钮后,微信客户端将调起系统相机,完成拍照操作后,会将拍摄的相片发送给开发者,并推送事件给开发者,同时收起系统相机, + * 随后可能会收到开发者下发的消息。 + */ + pic_sysphoto, + /** + * 弹出拍照或者相册发图用户点击按钮后,微信客户端将弹出选择器供用户选择“拍照”或者“从手机相册选择”。用户选择后即走其他两种流程。 + */ + pic_photo_or_albu, + /** + * 弹出微信相册发图器用户点击按钮后,微信客户端将调起微信相册,完成选择操作后,将选择的相片发送给开发者的服务器,并推送事件给开发者,同时收起相册, + * 随后可能会收到开发者下发的消息。 + */ + pic_weixin, + /** + * 弹出地理位置选择器用户点击按钮后,微信客户端将调起地理位置选择工具,完成选择操作后,将选择的地理位置发送给开发者的服务器,同时收起位置选择工具, + * 随后可能会收到开发者下发的消息。 + */ + location_select; +} diff --git a/src/main/java/com/foxinmy/weixin4j/type/EventType.java b/src/main/java/com/foxinmy/weixin4j/type/EventType.java index a8e864b8..bc85ce90 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/EventType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/EventType.java @@ -3,21 +3,36 @@ package com.foxinmy.weixin4j.type; import com.foxinmy.weixin4j.msg.event.EventMessage; import com.foxinmy.weixin4j.msg.event.LocationEventMessage; import com.foxinmy.weixin4j.msg.event.MassEventMessage; -import com.foxinmy.weixin4j.msg.event.MenuEventMessage; import com.foxinmy.weixin4j.msg.event.ScanEventMessage; import com.foxinmy.weixin4j.msg.event.ScribeEventMessage; +import com.foxinmy.weixin4j.msg.event.TemplatesendjobfinishMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuLocationEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuPhotoEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuScanEventMessage; /** - * * 事件类型 - * @author jy.hu - * + * + * @className EventType + * @author jy + * @date 2014年9月30日 + * @since JDK 1.7 + * @see */ public enum EventType { - subscribe(ScribeEventMessage.class), unsubscribe(ScribeEventMessage.class), - scan(ScanEventMessage.class),click(MenuEventMessage.class),view(MenuEventMessage.class), - location(LocationEventMessage.class),MASSSENDJOBFINISH(MassEventMessage.class); - + subscribe(ScribeEventMessage.class), unsubscribe(ScribeEventMessage.class), scan( + ScanEventMessage.class), scancode_push(MenuScanEventMessage.class), view( + MenuEventMessage.class), scancode_waitmsg( + MenuScanEventMessage.class), pic_sysphoto( + MenuPhotoEventMessage.class), pic_photo_or_album( + MenuPhotoEventMessage.class), pic_weixin( + MenuPhotoEventMessage.class), location_select( + MenuLocationEventMessage.class), click(MenuEventMessage.class), location( + LocationEventMessage.class), massendjobfinish( + MassEventMessage.class), templatesendjobfinish( + TemplatesendjobfinishMessage.class); + private Class extends EventMessage> eventClass; EventType(Class extends EventMessage> eventClass) { diff --git a/src/main/java/com/foxinmy/weixin4j/type/MediaType.java b/src/main/java/com/foxinmy/weixin4j/type/MediaType.java index 1f567181..322ba3ce 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/MediaType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/MediaType.java @@ -6,13 +6,20 @@ package com.foxinmy.weixin4j.type; * 语音(voice):256K,播放长度不超过60s,支持AMR\MP3格式 * 视频(video):1MB,支持MP4格式 * 缩略图(thumb):64KB,支持JPG格式 - * 媒体文件在后台保存时间为3天,即3天后media_id失效 + * + * 媒体文件在后台保存时间为3天,即3天后media_id失效 + * + * * @author jy.hu * @date 2014年4月2日 * @since JDK 1.7 */ public enum MediaType { - image("image/jpeg",".jpg"), voice("binary/octet-stream","amr"), vedio("binary/octet-stream","mp4"), thumb("image/jpeg","jpg"); + image("image/jpeg", "jpg"), voice("binary/octet-stream", "amr"), vedio( + "binary/octet-stream", "mp4"), thumb("image/jpeg", "jpg"), text( + "application/json", ""), music("binary/octet-stream", "mp3"), news( + "application/json", ""), mpnews("application/json", ""), mpvideo( + "binary/octet-stream", ""); MediaType(String contentType, String formatType) { this.contentType = contentType; @@ -26,6 +33,7 @@ public enum MediaType { } private String formatType; + public String getFormatType() { return formatType; } diff --git a/src/main/java/com/foxinmy/weixin4j/type/MessageType.java b/src/main/java/com/foxinmy/weixin4j/type/MessageType.java index 21a7b6dc..a883d993 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/MessageType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/MessageType.java @@ -10,6 +10,7 @@ import com.foxinmy.weixin4j.msg.in.VideoMessage; import com.foxinmy.weixin4j.msg.in.VoiceMessage; import com.foxinmy.weixin4j.msg.out.ArticleMessage; import com.foxinmy.weixin4j.msg.out.MusicMessage; +import com.foxinmy.weixin4j.msg.out.TransferMessage; /** * @@ -20,9 +21,13 @@ import com.foxinmy.weixin4j.msg.out.MusicMessage; */ public enum MessageType { // 接收到的消息类型 - text(TextMessage.class), image(ImageMessage.class), voice(VoiceMessage.class), video(VideoMessage.class), location(LocationMessage.class), link(LinkMessage.class), event(EventMessage.class), + text(TextMessage.class), image(ImageMessage.class), voice( + VoiceMessage.class), video(VideoMessage.class), location( + LocationMessage.class), link(LinkMessage.class), event( + EventMessage.class), // 发送的消息类型 - music(MusicMessage.class), news(ArticleMessage.class); + music(MusicMessage.class), news(ArticleMessage.class), transfer_customer_service( + TransferMessage.class); private Class extends BaseMessage> messageClass; MessageType(Class extends BaseMessage> messageClass) { diff --git a/src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java b/src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java similarity index 91% rename from src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java rename to src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java index f428c33b..b419bd1c 100644 --- a/src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java +++ b/src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java @@ -8,8 +8,8 @@ import java.util.regex.Pattern; import com.foxinmy.weixin4j.WeixinProxy; -public class WeixinConfig { - public WeixinConfig() { +public class ConfigUtil { + public ConfigUtil() { } private static Properties props = new Properties(); @@ -38,7 +38,6 @@ public class WeixinConfig { m.appendTail(sb); return sb.toString(); } - public static void main(String[] args) { System.out.println(getValue("api_token_uri")); } diff --git a/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java b/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java new file mode 100644 index 00000000..60eae107 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java @@ -0,0 +1,67 @@ +package com.foxinmy.weixin4j.util; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.Writer; +import java.nio.charset.Charset; + +/** + * IOUtil + * + * @className IOUtil + * @author jy.hu + * @date 2014年9月22日 + * @since JDK 1.7 + * @see org.apache.commons.io.IOUtils + */ +public class IOUtil { + + private static final int EOF = -1; + private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; + + public static byte[] toByteArray(Reader input) throws IOException { + return toByteArray(input, Charset.defaultCharset()); + } + + public static byte[] toByteArray(Reader input, Charset encoding) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + copy(input, output, encoding); + return output.toByteArray(); + } + + public static void copy(Reader input, OutputStream output, Charset encoding) throws IOException { + OutputStreamWriter out = new OutputStreamWriter(output, encoding); + copyLarge(input, out, new char[DEFAULT_BUFFER_SIZE]); + out.flush(); + } + + public static byte[] toByteArray(InputStream input) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + copyLarge(input, output, new byte[DEFAULT_BUFFER_SIZE]); + return output.toByteArray(); + } + + private static long copyLarge(InputStream input, OutputStream output, byte[] buffer) throws IOException { + long count = 0; + int n = 0; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } + + private static long copyLarge(Reader input, Writer output, char[] buffer) throws IOException { + long count = 0; + int n = 0; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java b/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java new file mode 100644 index 00000000..82a23ef3 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java @@ -0,0 +1,135 @@ +package com.foxinmy.weixin4j.util; + +import java.io.InputStream; +import java.util.Arrays; + +import org.apache.commons.codec.digest.DigestUtils; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.DocumentHelper; +import org.dom4j.io.SAXReader; +import org.jsoup.helper.StringUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.type.EventType; +import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; + +public class MessageUtil { + + private final static Logger log = LoggerFactory.getLogger(MessageUtil.class); + + /** + * 验证微信签名 + * + * @param echostr + * 随机字符串 + * @param timestamp + * 时间戳 + * @param nonce + * 随机数 + * @param signature + * 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数 + * @return 开发者通过检验signature对请求进行相关校验。若确认此次GET请求来自微信服务器 + * 请原样返回echostr参数内容,则接入生效 成为开发者成功,否则接入失败 + * @see 接入指南 + */ + public static String signature(String echostr, String timestamp, String nonce, String signature) { + String app_token = ConfigUtil.getValue("app_token"); + if (StringUtil.isBlank(app_token)) { + log.error("signature fail : token is null!"); + return null; + } + if (StringUtil.isBlank(echostr) || StringUtil.isBlank(timestamp) || StringUtil.isBlank(nonce)) { + log.error("signature fail : invalid parameter!"); + return null; + } + String _signature = null; + try { + String[] a = { app_token, timestamp, nonce }; + Arrays.sort(a); + StringBuilder sb = new StringBuilder(3); + for (String str : a) { + sb.append(str); + } + _signature = DigestUtils.sha1Hex(sb.toString()); + } catch (Exception e) { + log.error("signature error", e); + } + if (signature.equals(_signature)) { + return echostr; + } else { + log.error("signature fail : invalid signature!"); + return null; + } + } + + /** + * xml消息转换为消息对象 + * + * 微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次 + * + * + * @param xml + * 消息字符串 + * @return 消息对象 + * @throws DocumentException + * @see 验证消息的合法性 + * @see 普通消息 + * @see 事件触发 + * @see com.foxinmy.weixin4j.type.MessageType + * @see com.feican.weixin.msg.BaeMessage + * @see com.foxinmy.weixin4j.msg.TextMessage + * @see com.foxinmy.weixin4j.msg.in.ImageMessage + * @see com.foxinmy.weixin4j.msg.in.VoiceMessage + * @see com.foxinmy.weixin4j.msg.in.VideoMessage + * @see com.foxinmy.weixin4j.msg.in.LocationMessage + * @see com.foxinmy.weixin4j.msg.in.LinkMessage + * @see com.foxinmy.weixin4j.msg.event.ScribeEventMessage + * @see com.foxinmy.weixin4j.msg.event.ScanEventMessage + * @see com.foxinmy.weixin4j.msg.event.LocationEventMessage + * @see com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage + */ + public static BaseMessage xml2msg(String xml) throws DocumentException { + if (StringUtil.isBlank(xml)) + return null; + Document doc = DocumentHelper.parseText(xml); + String type = doc.selectSingleNode("/xml/MsgType").getStringValue(); + if (StringUtil.isBlank(type)) { + return null; + } + XStream xstream = new XStream(); + MessageType messageType = MessageType.valueOf(type.toLowerCase()); + Class extends BaseMessage> messageClass = messageType.getMessageClass(); + if (messageType == MessageType.event) { + type = doc.selectSingleNode("/xml/Event").getStringValue(); + messageClass = EventType.valueOf(type.toLowerCase()).getEventClass(); + } + xstream.alias("xml", messageClass); + xstream.ignoreUnknownElements(); + xstream.autodetectAnnotations(true); + xstream.processAnnotations(messageClass); + return xstream.fromXML(doc.asXML(), messageClass); + } + + /** + * xml消息转换为消息对象 + * + * @param inputStream + * 带消息字符串的输入流 + * @return 消息对象 + * @throws DocumentException + * @see {@link com.foxinmy.weixin4j.WeixinProxy#xml2msg(String)} + */ + public static BaseMessage xml2msg(InputStream inputStream) throws DocumentException { + SAXReader reader = new SAXReader(); + Document doc = reader.read(inputStream); + return xml2msg(doc.asXML()); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java b/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java deleted file mode 100644 index 19fd87e4..00000000 --- a/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.foxinmy.weixin4j.util; - -public class WeixinUtil { - - public static boolean isBlank(String str) { - return str == null || str.isEmpty(); - } -} diff --git a/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java b/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java index 5c0186c6..4a811a6c 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java @@ -9,7 +9,7 @@ import org.junit.Test; import com.foxinmy.weixin4j.WeixinProxy; import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.model.Button; -import com.foxinmy.weixin4j.model.Button.BtnType; +import com.foxinmy.weixin4j.type.ButtonType; /** * 自定义菜单测试 @@ -31,7 +31,7 @@ public class ButtonTest { List btnList = new ArrayList(); Button b = new Button("test"); - b.setType(BtnType.click); + b.setType(ButtonType.click); b.setKey("123"); btnList.add(b); diff --git a/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java b/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java index 8b78305e..bb6bec88 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java @@ -50,7 +50,7 @@ public class GroupTest { @Test public void getid() { try { - System.out.println(weixinProxy.findGroupByOpenId("owGBft_vbBbOaQOmpEUE4xDLeRSU")); + System.out.println(weixinProxy.getGroupByOpenId("owGBft_vbBbOaQOmpEUE4xDLeRSU")); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); diff --git a/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java b/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java new file mode 100644 index 00000000..6d34a733 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java @@ -0,0 +1,22 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Test; + +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.http.HttpRequest; + +public class HttpTest { + private static HttpRequest request; + static { + request = new HttpRequest(); + } + + @Test + public void test(){ + try { + System.out.println(request.get("http://www.baidu.com")); + } catch (WeixinException e) { + e.printStackTrace(); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java b/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java index f907fa3d..d54e649b 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java @@ -31,7 +31,7 @@ public class MediaTest { File file = new File("D:\\test.jpg"); try { System.out.println(weixinProxy.uploadMedia(file, MediaType.image)); - //usAxLEJxFXAjXVlLu_BSw0GvS2YEEoGeelRBybNZBGvMsdxiIcD1F9yBWYd9jVZx + //vvU_AUtovWyfAxQ8J1DsCoNMtK6U_bUmTpe6lpINUOVRLvt_7rtO4zxzBpPgkmay } catch (WeixinException e) { System.out.println(e.getErrorMsg()); } @@ -40,7 +40,7 @@ public class MediaTest { @Test public void download() { try { - System.out.println(weixinProxy.downloadMedia("usAxLEJxFXAjXVlLu_BSw0GvS2YEEoGeelRBybNZBGvMsdxiIcD1F9yBWYd9jVZx", MediaType.image)); + System.out.println(weixinProxy.downloadMedia("vvU_AUtovWyfAxQ8J1DsCoNMtK6U_bUmTpe6lpINUOVRLvt_7rtO4zxzBpPgkmay", MediaType.image)); } catch (WeixinException e) { System.out.println(e.getErrorMsg()); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java new file mode 100644 index 00000000..2cd36584 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java @@ -0,0 +1,194 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Test; + +import com.foxinmy.weixin4j.util.MessageUtil; + +/** + * 接收事件消息格式测试 + * + * @author jy.hu + * @date 2014年3月24日 + * @since JDK 1.7 + */ +public class MessageEventInTest { + + private StringBuilder xmlSb = new StringBuilder(); + + /***************** event message *********************/ + @Test + public void scribe() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void scan() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void scan_scribe() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void location1() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("23.137466"); + xmlSb.append("113.352425"); + xmlSb.append("119.385040"); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_click() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_link() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_scan() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_photo() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("1"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_location() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java index 39269754..fdd40042 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java @@ -1,134 +1,19 @@ package com.foxinmy.weixin4j.test; -import org.junit.Before; import org.junit.Test; -import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.util.MessageUtil; /** - * 接收消息格式测试 + * 接受一般消息格式测试 + * * @author jy.hu * @date 2014年3月24日 * @since JDK 1.7 */ public class MessageInTest { + private StringBuilder xmlSb = new StringBuilder(); - private WeixinProxy weixinProxy; - - @Before - public void init(){ - weixinProxy = new WeixinProxy(); - } - - /***************** event message *********************/ - @Test - public void scribe() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void scan() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - @Test - public void scan_scribe() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void location1() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("23.137466"); - xmlSb.append("113.352425"); - xmlSb.append("119.385040"); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void menu_click() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void menu_link() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } /***************** common message *********************/ @@ -144,7 +29,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -163,7 +48,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -182,7 +67,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -202,7 +87,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -221,7 +106,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -242,7 +127,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -262,7 +147,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java new file mode 100644 index 00000000..8f6a130f --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java @@ -0,0 +1,114 @@ +package com.foxinmy.weixin4j.test; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.model.MpArticle; +import com.foxinmy.weixin4j.type.MediaType; + +/** + * 群发消息 + * + * @className MpNewsTest + * @author jy + * @date 2014年4月27日 + * @since JDK 1.7 + * @see + */ +public class MessageMassTest { + private WeixinProxy weixinProxy; + + @Before + public void init() { + this.weixinProxy = new WeixinProxy(); + } + + @Test + public void uploadArticle() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.uploadArticle(articles); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void uploadVideo() { + try { + weixinProxy.uploadVideo("mediaId", "title", "desc"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massByGroup() { + try { + weixinProxy.massByGroup("123", MediaType.image, "groupId"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massByOpenIds() { + try { + weixinProxy.massByOpenIds("123", MediaType.image, "openIds"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massArticleByGroup() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.massArticleByGroup(articles, "0"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massArticleByOpenIds() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.massArticleByOpenIds(articles, + "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void deleteMass() { + try { + weixinProxy.deleteMassNews("34182"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java index f3be10bb..59aed8de 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java @@ -7,6 +7,7 @@ import org.junit.Test; import com.foxinmy.weixin4j.WeixinProxy; import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.msg.model.Music; import com.foxinmy.weixin4j.msg.notify.ArticleNotify; import com.foxinmy.weixin4j.msg.notify.BaseNotify; import com.foxinmy.weixin4j.msg.notify.ImageNotify; @@ -41,27 +42,29 @@ public class MessageNotifyTest { @Test public void image() { - ImageNotify notify = new ImageNotify("123", "to"); + ImageNotify notify = new ImageNotify("to"); + notify.pushMediaId("123"); System.out.println(notify.toJson()); } @Test public void voice() { - VoiceNotify notify = new VoiceNotify("123", "to"); + VoiceNotify notify = new VoiceNotify("to"); + notify.pushMediaId("123"); System.out.println(notify.toJson()); } @Test public void video() { VideoNotify notify = new VideoNotify("to"); - notify.pushVideo("123", "title", "desc"); + notify.pushVideo("123","m123"); System.out.println(notify.toJson()); } @Test public void music() { MusicNotify notify = new MusicNotify("to"); - notify.pushMusic("title", "desc", "url", "hqUrl", "mediaId"); + notify.pushMusic("url", "hqUrl", "mediaId"); System.out.println(notify.toJson()); } @@ -74,16 +77,27 @@ public class MessageNotifyTest { } @Test - public void send() { - BaseNotify t = new TextNotify("哈哈哈哈", "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + public void send1() { + BaseNotify notify = new TextNotify("哈哈哈哈", "owGBft_vbBbOaQOmpEUE4xDLeRSU"); try { - weixinProxy.sendNotify(t); + weixinProxy.sendNotify(notify); String mediaId = weixinProxy.uploadMedia(new File("D:\\test.jpg"), MediaType.image); - t = new ImageNotify(mediaId, "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + ImageNotify t = new ImageNotify("owGBft_vbBbOaQOmpEUE4xDLeRSU"); + t.pushMediaId(mediaId); weixinProxy.sendNotify(t); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); } } + + @Test + public void send2() { + try { + weixinProxy.sendNotify("to",new Music("thumbMediaId")); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java index 00021aa0..ddb309d4 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java @@ -1,7 +1,9 @@ package com.foxinmy.weixin4j.test; +import org.junit.Before; import org.junit.Test; +import com.foxinmy.weixin4j.msg.BaseMessage; import com.foxinmy.weixin4j.msg.TextMessage; import com.foxinmy.weixin4j.msg.out.ArticleMessage; import com.foxinmy.weixin4j.msg.out.ImageMessage; @@ -17,56 +19,52 @@ import com.foxinmy.weixin4j.msg.out.VoiceMessage; * @since JDK 1.7 */ public class MessageOutTest { + private BaseMessage inMessage; + + @Before + public void init() { + this.inMessage = new TextMessage(); + this.inMessage.setFromUserName("fromusername"); + this.inMessage.setToUserName("tousername"); + } + @Test public void text() { - TextMessage message = new TextMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.setContent("text message"); + TextMessage message = new TextMessage("text", inMessage); System.out.println(message.toXml()); } @Test public void image() { - ImageMessage message = new ImageMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + ImageMessage message = new ImageMessage(inMessage); message.pushMediaId("mediaId"); System.out.println(message.toXml()); } @Test public void voice() { - VoiceMessage message = new VoiceMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + VoiceMessage message = new VoiceMessage(inMessage); message.pushMediaId("mediaId"); System.out.println(message.toXml()); } - + @Test public void video() { - VideoMessage message = new VideoMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.pushVideo("mediaId", "title", "title"); + VideoMessage message = new VideoMessage(inMessage); + message.pushVideo("mediaId"); System.out.println(message.toXml()); } - + @Test public void music() { - MusicMessage message = new MusicMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.pushMusic("title", "desc", "url", "hqurl", "mediaId"); + MusicMessage message = new MusicMessage(inMessage); + message.pushMusic("mediaId"); System.out.println(message.toXml()); } - + @Test public void article() { - ArticleMessage message = new ArticleMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + ArticleMessage message = new ArticleMessage(inMessage); message.pushArticle("title1", "desc1", "picUrl1", "url1"); message.pushArticle("title2", "desc2", "picUrl2", "url2"); System.out.println(message.toXml()); diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java new file mode 100644 index 00000000..b8165a91 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java @@ -0,0 +1,30 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Before; +import org.junit.Test; + +import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.msg.out.TemplateMessage; + +public class MessageTemplTest { + private WeixinProxy weixinProxy; + + @Before + public void init() { + this.weixinProxy = new WeixinProxy(); + } + + @Test + public void test() { + TemplateMessage tplMessage = new TemplateMessage("touser", + "template_id", "url"); + tplMessage.pushData("name", "fox"); + System.out.print(tplMessage.toJson()); + try { + System.out.print(weixinProxy.sendTplMessage(tplMessage)); + } catch (WeixinException e) { + System.out.println(e.getErrorMsg()); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java b/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java deleted file mode 100644 index 5fa1ec67..00000000 --- a/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.foxinmy.weixin4j.test; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; - -import com.foxinmy.weixin4j.WeixinProxy; -import com.foxinmy.weixin4j.exception.WeixinException; -import com.foxinmy.weixin4j.model.MpArticle; -import com.foxinmy.weixin4j.type.MediaType; - -/** - * 群发消息 - * - * @className MpNewsTest - * @author jy - * @date 2014年4月27日 - * @since JDK 1.7 - * @see - */ -public class MpNewsTest { - private WeixinProxy weixinProxy; - - @Before - public void init() { - this.weixinProxy = new WeixinProxy(); - } - - @Test - public void massByGroup(){ - List articles = new ArrayList(); - try { - String thumbMediaId = weixinProxy.uploadMedia(new File("/tmp/test.jpg"), MediaType.image); - articles.add(new MpArticle(thumbMediaId, "title", "content")); - weixinProxy.massNewsByGroup(articles, "0"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } - - @Test - public void massByOpenIds(){ - List articles = new ArrayList(); - try { - String thumbMediaId = weixinProxy.uploadMedia(new File("/tmp/test.jpg"), MediaType.image); - articles.add(new MpArticle(thumbMediaId, "title", "content")); - weixinProxy.massNewsByOpenIds(articles, "owGBft_vbBbOaQOmpEUE4xDLeRSU"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } - - @Test - public void deleteMass(){ - try { - weixinProxy.deleteMassNews("34182"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } -} diff --git a/src/test/java/com/foxinmy/weixin4j/test/QRTest.java b/src/test/java/com/foxinmy/weixin4j/test/QRTest.java index 11934fa9..f18d1aa7 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/QRTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/QRTest.java @@ -25,10 +25,10 @@ public class QRTest { @Test public void temp_qr() { - QRParameter qr = new QRParameter(1200, QRType.QR_SCENE, 1); + QRParameter qr = new QRParameter(1200, QRType.TEMPORARY, 2); try { System.out.println(qr.toJson()); - weixinProxy.getQR(qr); + System.out.println(weixinProxy.getQR(qr)); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); @@ -37,10 +37,10 @@ public class QRTest { @Test public void forever_qr() { - QRParameter qr = new QRParameter(QRType.QR_LIMIT_SCENE, 1); + QRParameter qr = new QRParameter(QRType.PERMANENCE, 1); try { System.out.println(qr.toJson()); - weixinProxy.getQR(qr); + System.out.println(weixinProxy.getQR(qr)); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java b/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java index 37d549d7..a2f8a266 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java @@ -3,7 +3,8 @@ package com.foxinmy.weixin4j.test; import org.junit.Before; import org.junit.Test; -import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.api.token.FileTokenApi; +import com.foxinmy.weixin4j.api.token.TokenApi; import com.foxinmy.weixin4j.exception.WeixinException; /** @@ -14,17 +15,17 @@ import com.foxinmy.weixin4j.exception.WeixinException; * @since JDK 1.7 */ public class TokenTest { - private WeixinProxy weixinProxy; + private TokenApi tokenApi; @Before public void init() { - weixinProxy = new WeixinProxy(); + tokenApi = new FileTokenApi(); } @Test public void getToken() { try { - System.out.println(weixinProxy.getToken()); + System.out.println(tokenApi.getToken()); } catch (WeixinException e) { e.printStackTrace(); }
articles) { + this.articles = articles; } @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("(article ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,picUrl=").append(picUrl); - sb.append(" ,url=").append(url).append(")"); + 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()); + return String.format( + "[ArticleNotify touser=%s ,msgtype=%s ,articles=%s]", + super.getTouser(), super.getMsgtype().name(), + this.news.toString()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/notify/ImageNotify.java b/src/main/java/com/foxinmy/weixin4j/msg/notify/ImageNotify.java index f9a52263..d2e47096 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/notify/ImageNotify.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/notify/ImageNotify.java @@ -1,14 +1,17 @@ package com.foxinmy.weixin4j.msg.notify; +import com.foxinmy.weixin4j.msg.model.Image; import com.foxinmy.weixin4j.type.MessageType; -import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 客服图片消息 + * * @author jy.hu * @date 2014年4月4日 * @since JDK 1.7 - * @see 客服图片消息 + * @see 客服图片消息 + * @see com.foxinmy.weixin4j.msg.model.Image * @see com.foxinmy.weixin4j.msg.notify.BaseNotify * @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson() */ @@ -20,30 +23,25 @@ public class ImageNotify extends BaseNotify { super(MessageType.image); } - public ImageNotify(String mediaId) { - super(MessageType.image); - this.image = new $(mediaId); + public ImageNotify(String touser) { + super(touser, MessageType.image); } public ImageNotify(String mediaId, String touser) { super(touser, MessageType.image); - this.image = new $(mediaId); + this.pushMediaId(mediaId); } - @XStreamAlias("image") - private $ image; - - private static class $ { - @XStreamAlias("media_id") - private String mediaId; - - public $(String mediaId) { - this.mediaId = 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.mediaId); + return String.format("[ImageNotify touser=%s ,msgtype=%s ,mediaId=%s]", + super.getTouser(), super.getMsgtype().name(), + this.image.getMediaId()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/notify/MusicNotify.java b/src/main/java/com/foxinmy/weixin4j/msg/notify/MusicNotify.java index 6f3e66fa..1e328677 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/notify/MusicNotify.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/notify/MusicNotify.java @@ -1,14 +1,17 @@ package com.foxinmy.weixin4j.msg.notify; +import com.foxinmy.weixin4j.msg.model.Music; import com.foxinmy.weixin4j.type.MessageType; -import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 客服音乐消息 + * * @author jy.hu * @date 2014年4月4日 * @since JDK 1.7 - * @see 客服音乐消息 + * @see 客服音乐消息 + * @see com.foxinmy.weixin4j.msg.model.Music * @see com.foxinmy.weixin4j.msg.notify.BaseNotify * @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson() */ @@ -24,44 +27,20 @@ public class MusicNotify extends BaseNotify { super(touser, MessageType.music); } - public void pushMusic(String title, String desc, String url, String hqUrl, String mediaId) { - this.music = new $(); - this.music.thumbMediaId = mediaId; - this.music.desc = desc; - this.music.hqMusicUrl = hqUrl; - this.music.musicUrl = url; - this.music.title = title; + public void pushMusic(String musicurl, String hqUrl, String mediaId) { + this.music = new Music(null, null, musicurl, hqUrl, mediaId); } - @XStreamAlias("music") - private $ music; - - private static class $ { - private String title; - @XStreamAlias("description") - private String desc; - @XStreamAlias("musicurl") - private String musicUrl; - @XStreamAlias("hqmusicurl") - private String hqMusicUrl; - @XStreamAlias("thumb_media_id") - private String thumbMediaId; - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(music ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,musicURL=").append(musicUrl); - sb.append(" ,hqMusicUrl=").append(hqMusicUrl); - sb.append(" ,thumbMediaId=").append(thumbMediaId).append(")"); - return sb.toString(); - } + private Music music; + public void setMusic(Music music) { + this.music = music; } @Override public String toString() { - return String.format("[VideoNotify touser=%s ,msgtype=%s ,music=%s]", super.getTouser(), super.getMsgtype().name(), this.music.toString()); + return String.format("[MusicNotify touser=%s ,msgtype=%s ,music=%s]", + super.getTouser(), super.getMsgtype().name(), + this.music.toString()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/notify/TextNotify.java b/src/main/java/com/foxinmy/weixin4j/msg/notify/TextNotify.java index edcf2565..6ec09a3a 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/notify/TextNotify.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/notify/TextNotify.java @@ -1,14 +1,17 @@ package com.foxinmy.weixin4j.msg.notify; +import com.foxinmy.weixin4j.msg.model.Text; import com.foxinmy.weixin4j.type.MessageType; -import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 客服文本消息 + * * @author jy.hu * @date 2014年4月4日 * @since JDK 1.7 - * @see 客服文本消息 + * @see 客服文本消息 + * @see com.foxinmy.weixin.msg.model.Text * @see com.foxinmy.weixin4j.msg.notify.BaseNotify * @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson() */ @@ -22,27 +25,24 @@ public class TextNotify extends BaseNotify { public TextNotify(String content) { super(MessageType.text); - this.text = new $(content); + this.text = new Text(content); } public TextNotify(String content, String touser) { super(touser, MessageType.text); - this.text = new $(content); + this.text = new Text(content); } - @XStreamAlias("text") - private $ text; - - private static class $ { - @XStreamAlias("content") - private String content; - - public $(String content) { - this.content = 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.content); + return String.format("[TextNotify touser=%s ,msgtype=%s ,content=%s]", + super.getTouser(), super.getMsgtype().name(), + this.text.getContent()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/notify/VideoNotify.java b/src/main/java/com/foxinmy/weixin4j/msg/notify/VideoNotify.java index d8865910..8e433c03 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/notify/VideoNotify.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/notify/VideoNotify.java @@ -1,14 +1,17 @@ package com.foxinmy.weixin4j.msg.notify; +import com.foxinmy.weixin4j.msg.model.Video; import com.foxinmy.weixin4j.type.MessageType; -import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 客服视频消息 + * * @author jy.hu * @date 2014年4月4日 * @since JDK 1.7 - * @see 客服视频消息 + * @see 客服视频消息 + * @see com.foxinmy.weixin4j.msg.model.Video * @see com.foxinmy.weixin4j.msg.notify.BaseNotify * @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson() */ @@ -23,36 +26,21 @@ public class VideoNotify extends BaseNotify { public VideoNotify(String touser) { super(touser, MessageType.video); } - - public void pushVideo(String mediaId, String title, String desc) { - this.video = new $(mediaId, title, desc); + + public void pushVideo(String mediaId, String thumbMediaId) { + this.video = new Video(mediaId, thumbMediaId); } - @XStreamAlias("video") - private $ video; - - private static class $ { - @XStreamAlias("media_id") - private String mediaId; - private String title; - @XStreamAlias("description") - private String desc; - - public $(String mediaId, String title, String desc) { - this.mediaId = mediaId; - this.title = title; - this.desc = desc; - } - - @Override - public String toString() { - return String.format("(video mediaId=%s ,title=%s ,description=%s)", mediaId, title, desc); - } + 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()); + return String.format("[VideoNotify touser=%s ,msgtype=%s ,video=%s]", + super.getTouser(), super.getMsgtype().name(), + this.video.toString()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/notify/VoiceNotify.java b/src/main/java/com/foxinmy/weixin4j/msg/notify/VoiceNotify.java index 8e0787b6..4cfb7a7f 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/notify/VoiceNotify.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/notify/VoiceNotify.java @@ -1,14 +1,17 @@ package com.foxinmy.weixin4j.msg.notify; +import com.foxinmy.weixin4j.msg.model.Voice; import com.foxinmy.weixin4j.type.MessageType; -import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 客服语音消息 + * * @author jy.hu * @date 2014年4月4日 * @since JDK 1.7 - * @see 客服语音消息 + * @see 客服语音消息 + * @see com.foxinmy.weixin4j.msg.model.Voice * @see com.foxinmy.weixin4j.msg.notify.BaseNotify * @see com.foxinmy.weixin4j.msg.notify.BaseNotify#toJson() */ @@ -20,30 +23,25 @@ public class VoiceNotify extends BaseNotify { super(MessageType.voice); } - public VoiceNotify(String mediaId) { - super(MessageType.voice); - this.voice = new $(mediaId); + public VoiceNotify(String touser) { + super(touser, MessageType.voice); } public VoiceNotify(String mediaId, String touser) { super(touser, MessageType.voice); - this.voice = new $(mediaId); + this.pushMediaId(mediaId); } - @XStreamAlias("voice") - private $ voice; - - private static class $ { - @XStreamAlias("media_id") - private String mediaId; - - public $(String mediaId) { - this.mediaId = 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.mediaId); + return String.format("[VoiceNotify touser=%s ,msgtype=%s ,mediaId=%s]", + super.getTouser(), super.getMsgtype().name(), + this.voice.getMediaId()); } } diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/ArticleMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/ArticleMessage.java index e892aeaa..9c3737a7 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/ArticleMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/ArticleMessage.java @@ -4,36 +4,36 @@ import java.util.LinkedList; import java.util.List; 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 回复图文消息 + * @see 回复图文消息 + * @see com.foxinmy.weixin.msg.model.Article * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class ArticleMessage extends BaseMessage { private static final int MAX_ARTICLE_COUNT = 10; private static final long serialVersionUID = -7331603018352309317L; - public ArticleMessage() { - super(MessageType.news); - } - - public ArticleMessage(String toUserName) { - super(MessageType.news); - super.setToUserName(toUserName); + public ArticleMessage(BaseMessage inMessage) { + super(MessageType.news, inMessage); } @XStreamAlias("ArticleCount") private int count; // 图文消息个数,限制为10条以内 @XStreamAlias("Articles") - private List articles; + private LinkedList articles; public List getArticles() { return this.articles; @@ -44,39 +44,55 @@ public class ArticleMessage extends BaseMessage { return; } if (this.articles == null) { - this.articles = new LinkedList(); + this.articles = new LinkedList(); } this.articles.add(new Article(title, desc, picUrl, url)); - count ++; + count++; } - @XStreamAlias("item") - private static class Article { - @XStreamAlias("Title") - private String title; // 图文消息标题 - @XStreamAlias("Description") - private String desc; // 图文消息描述 - @XStreamAlias("PicUrl") - private String picUrl; // 图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200 - @XStreamAlias("Url") - private String url; // 点击图文消息跳转链接 - - public Article(String title, String desc, String picUrl, String url) { - this.title = title; - this.desc = desc; - this.picUrl = picUrl; - this.url = url; + public void pushFirstArticle(String title, String desc, String picUrl, + String url) { + if (this.articles == null) { + this.articles = new LinkedList(); } + this.articles.addFirst(new Article(title, desc, picUrl, url)); + } - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Article ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,picUrl=").append(picUrl); - sb.append(" ,url=").append(url).append(")"); - return sb.toString(); + public void pushLastArticle(String title, String desc, String picUrl, + String url) { + if (this.articles == null) { + this.articles = new LinkedList(); } + this.articles.addLast(new Article(title, desc, picUrl, url)); + } + + public Article removeLastArticle() { + if (this.articles != null) { + return this.articles.removeLast(); + } + return null; + } + + 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() { + 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 diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java index 2da50a01..fb58ecb8 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java @@ -1,38 +1,50 @@ 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 回复图片消息 + * @see 回复图片消息 + * @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() { - super(MessageType.image); + public ImageMessage(BaseMessage inMessage) { + super(MessageType.image, inMessage); super.getMsgType().setMessageClass(ImageMessage.class); } + 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(); - this.image.mediaId = mediaId; + this.image = new Image(mediaId); } - private static class Image { - @XStreamAlias("MediaId") - private String mediaId; + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Image.class, "mediaId"); + return xstream.toXML(this); } @Override @@ -41,7 +53,7 @@ public class ImageMessage extends BaseMessage { sb.append("[ImageMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,mediaId=").append(this.image.mediaId); + sb.append(" ,mediaId=").append(this.image.getMediaId()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java index c790b9ac..419f32d6 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java @@ -1,74 +1,61 @@ 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 回复音乐消息 + * @see 回复音乐消息 + * @see com.foxinmy.weixin4j.msg.model.Music * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class MusicMessage extends BaseMessage { private static final long serialVersionUID = 4384403772658796395L; - public MusicMessage() { - super(MessageType.music); + public MusicMessage(BaseMessage inMessage) { + super(MessageType.music, inMessage); } @XStreamAlias("Music") private Music music; - public Music getMusic() { - return this.music; + public void pushMusic(String mediaId) { + this.music = new Music(mediaId); } - public void pushMusic(String title, String desc, String url, String hqUrl, String mediaId) { - this.music = new Music(); - this.music.thumbMediaId = mediaId; - this.music.desc = desc; - this.music.hqMusicUrl = hqUrl; - this.music.MusicURL = url; - this.music.title = title; + public void setMusic(Music music) { + this.music = music; } - private static class Music { - @XStreamAlias("Title") - private String title; // 音乐标题 - @XStreamAlias("Description") - private String desc; // 音乐描述 - @XStreamAlias("MusicURL") - private String MusicURL; // 音乐链接 - @XStreamAlias("HQMusicUrl") - private String hqMusicUrl; // 高质量音乐链接,WIFI环境优先使用该链接播放音乐 - @XStreamAlias("ThumbMediaId") - private String thumbMediaId; // 缩略图的媒体id,通过上传多媒体文件,得到的id - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Music ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,musicURL=").append(MusicURL); - sb.append(" ,hqMusicUrl=").append(hqMusicUrl); - sb.append(" ,thumbMediaId=").append(thumbMediaId).append(")"); - return sb.toString(); - } + @Override + public String 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(getMusic().toString()); + sb.append(" ,music=").append(music.toString()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java new file mode 100644 index 00000000..3721504b --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java @@ -0,0 +1,117 @@ +package com.foxinmy.weixin4j.msg.out; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +import com.alibaba.fastjson.JSON; + +/** + * 模板消息 + * + * @className TemplateMessage + * @author jy + * @date 2014年9月29日 + * @since JDK 1.7 + * @see + */ +public class TemplateMessage implements Serializable { + + private static final long serialVersionUID = 7950608393821661436L; + + private String touser; + private String template_id; + private String url; + private String topcolor = "#FF0000"; + private Map data; + + public void pushData(String key, String value) { + this.data.put(key, new Item(value)); + } + + public TemplateMessage(String touser, String template_id, String url) { + this.touser = touser; + this.template_id = template_id; + this.url = url; + this.data = new HashMap(); + } + + private static class Item implements Serializable { + private static final long serialVersionUID = 1L; + private String value; + private String color; + + public Item(String value) { + this(value, "#173177"); + } + + public Item(String value, String color) { + this.value = value; + this.color = color; + } + + public String getValue() { + return value; + } + + public String getColor() { + return color; + } + + @Override + public String toString() { + return "$ [value=" + getValue() + ", color=" + getColor() + "]"; + } + } + + public String getTouser() { + return touser; + } + + public void setTouser(String touser) { + this.touser = touser; + } + + public String getTemplate_id() { + return template_id; + } + + public void setTemplate_id(String template_id) { + this.template_id = template_id; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getTopcolor() { + return topcolor; + } + + public void setTopcolor(String topcolor) { + this.topcolor = topcolor; + } + + public Map getData() { + return data; + } + + public void setData(Map data) { + this.data = data; + } + + @Override + public String toString() { + return "TemplateMessage [touser=" + touser + ", template_id=" + + template_id + ", url=" + url + ", topcolor=" + topcolor + + ", data=" + data + "]"; + } + + public String toJson() { + return JSON.toJSONString(this); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java new file mode 100644 index 00000000..b89621aa --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java @@ -0,0 +1,25 @@ +package com.foxinmy.weixin4j.msg.out; + +import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.type.MessageType; + +/** + * 转移消息到多客服端消息 + * + * @className TransferMessage + * @author jy.hu + * @date 2014年6月28日 + * @since JDK 1.7 + * @see 多客服转移消息 + * @see com.foxinmy.weixin4j.msg.BaseMessage + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + */ +public class TransferMessage extends BaseMessage { + + private static final long serialVersionUID = -5479496746108594940L; + + public TransferMessage(BaseMessage inMessage) { + super(MessageType.transfer_customer_service,inMessage); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java index d16c5a12..d6cdfc91 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java @@ -1,58 +1,52 @@ package com.foxinmy.weixin4j.msg.out; import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.msg.model.Video; import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 回复视频消息 + * * @className VideoMessage * @author jy.hu * @date 2014年4月6日 * @since JDK 1.7 - * @see 回复视频消息 + * @see 回复视频消息 + * @see com.foxinmy.weixin4j.msg.model.Video * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class VideoMessage extends BaseMessage { private static final long serialVersionUID = -1013075358679078381L; - public VideoMessage() { - super(MessageType.video); + public VideoMessage(BaseMessage inMessage) { + super(MessageType.video, inMessage); super.getMsgType().setMessageClass(VideoMessage.class); } @XStreamAlias("Video") private Video video; - public Video getVideo() { - return this.video; + public void pushVideo(String mediaId) { + this.video = new Video(mediaId); } - public void pushVideo(String mediaId, String title, String desc) { - this.video = new Video(); - this.video.desc = desc; - this.video.mediaId = mediaId; - this.video.title = title; + public void setVideo(Video video) { + this.video = video; } - private static class Video { - @XStreamAlias("MediaId") - private String mediaId; - @XStreamAlias("Title") - private String title; - @XStreamAlias("Description") - private String desc; - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Video mediaId=").append(mediaId); - sb.append(" ,title=").append(title); - sb.append(" ,desc=").append(desc).append(")"); - return super.toString(); - } + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Video.class, "mediaId"); + xstream.aliasField("Title", Video.class, "title"); + xstream.aliasField("Description", Video.class, "desc"); + xstream.omitField(Video.class, "thumbMediaId"); + return xstream.toXML(this); } @Override @@ -61,7 +55,7 @@ public class VideoMessage extends BaseMessage { sb.append("[VideoMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,video=").append(getVideo().toString()); + sb.append(" ,video=").append(video.toString()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java index 93052907..dcac1046 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java @@ -1,53 +1,60 @@ package com.foxinmy.weixin4j.msg.out; import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.msg.model.Voice; import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 语音消息 + * * @className VoiceMessage * @author jy.hu * @date 2014年3月23日 * @since JDK 1.7 - * @see 回复语音消息 + * @see 回复语音消息 + * @see com.foxinmy.weixin4j.msg.model.Voice * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class VoiceMessage extends BaseMessage { private static final long serialVersionUID = -7944926238652243793L; - public VoiceMessage() { - super(MessageType.voice); + public VoiceMessage(BaseMessage inMessage) { + super(MessageType.voice, inMessage); super.getMsgType().setMessageClass(VoiceMessage.class); } + + public VoiceMessage(String mediaId, BaseMessage inMessage) { + super(MessageType.voice, inMessage); + super.getMsgType().setMessageClass(VoiceMessage.class); + this.pushMediaId(mediaId); + } + @XStreamAlias("Voice") private Voice voice; - - public Voice getVocie() { - return voice; + + public void pushMediaId(String mediaId) { + this.voice = new Voice(mediaId); } - public void pushMediaId(String mediaId){ - this.voice = new Voice(); - this.voice.setMediaId(mediaId); - } - - private static class Voice { - @XStreamAlias("MediaId") - private String mediaId; - - private void setMediaId(String mediaId) { - this.mediaId = mediaId; - } + + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Voice.class, "mediaId"); + return xstream.toXML(this); } + @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("[VoiceMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,mediaId=").append(getVocie().mediaId); + sb.append(" ,mediaId=").append(voice.getMediaId()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java b/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java new file mode 100644 index 00000000..cf2ab68e --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java @@ -0,0 +1,55 @@ +package com.foxinmy.weixin4j.type; + +/** + * 自定义菜单类型 + * scancode_push 到 location_selec + * 仅支持微信iPhone5.4.1以上版本,和Android5 .4以上版本的微信用户 旧版本微信用户点击后将没有回应 + * 开发者也不能正常接收到事件推送。 + * + * @className ButtonType + * @author jy + * @date 2014年9月30日 + * @since JDK 1.7 + * @see 按钮类型 + */ +public enum ButtonType { + /** + * 点击推事件 用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event + * 的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互; + */ + click, + /** + * 跳转URL 用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的网页URL,可与网页授权获取用户基本信息接口结合,获得用户基本信息。 + */ + view, + /** + * 扫码推事件 用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后显示扫描结果(如果是URL,将进入URL),且会将扫码的结果传给开发者, + * 开发者可以下发消息。 + */ + scancode_push, + /** + * 扫码推事件且弹出“消息接收中”提示框用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后,将扫码的结果传给开发者,同时收起扫一扫工具, + * 然后弹出“消息接收中”提示框,随后可能会收到开发者下发的消息。 + */ + scancode_waitmsg, + /** + * 弹出系统拍照发图用户点击按钮后,微信客户端将调起系统相机,完成拍照操作后,会将拍摄的相片发送给开发者,并推送事件给开发者,同时收起系统相机, + * 随后可能会收到开发者下发的消息。 + */ + pic_sysphoto, + /** + * 弹出拍照或者相册发图用户点击按钮后,微信客户端将弹出选择器供用户选择“拍照”或者“从手机相册选择”。用户选择后即走其他两种流程。 + */ + pic_photo_or_albu, + /** + * 弹出微信相册发图器用户点击按钮后,微信客户端将调起微信相册,完成选择操作后,将选择的相片发送给开发者的服务器,并推送事件给开发者,同时收起相册, + * 随后可能会收到开发者下发的消息。 + */ + pic_weixin, + /** + * 弹出地理位置选择器用户点击按钮后,微信客户端将调起地理位置选择工具,完成选择操作后,将选择的地理位置发送给开发者的服务器,同时收起位置选择工具, + * 随后可能会收到开发者下发的消息。 + */ + location_select; +} diff --git a/src/main/java/com/foxinmy/weixin4j/type/EventType.java b/src/main/java/com/foxinmy/weixin4j/type/EventType.java index a8e864b8..bc85ce90 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/EventType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/EventType.java @@ -3,21 +3,36 @@ package com.foxinmy.weixin4j.type; import com.foxinmy.weixin4j.msg.event.EventMessage; import com.foxinmy.weixin4j.msg.event.LocationEventMessage; import com.foxinmy.weixin4j.msg.event.MassEventMessage; -import com.foxinmy.weixin4j.msg.event.MenuEventMessage; import com.foxinmy.weixin4j.msg.event.ScanEventMessage; import com.foxinmy.weixin4j.msg.event.ScribeEventMessage; +import com.foxinmy.weixin4j.msg.event.TemplatesendjobfinishMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuLocationEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuPhotoEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuScanEventMessage; /** - * * 事件类型 - * @author jy.hu - * + * + * @className EventType + * @author jy + * @date 2014年9月30日 + * @since JDK 1.7 + * @see */ public enum EventType { - subscribe(ScribeEventMessage.class), unsubscribe(ScribeEventMessage.class), - scan(ScanEventMessage.class),click(MenuEventMessage.class),view(MenuEventMessage.class), - location(LocationEventMessage.class),MASSSENDJOBFINISH(MassEventMessage.class); - + subscribe(ScribeEventMessage.class), unsubscribe(ScribeEventMessage.class), scan( + ScanEventMessage.class), scancode_push(MenuScanEventMessage.class), view( + MenuEventMessage.class), scancode_waitmsg( + MenuScanEventMessage.class), pic_sysphoto( + MenuPhotoEventMessage.class), pic_photo_or_album( + MenuPhotoEventMessage.class), pic_weixin( + MenuPhotoEventMessage.class), location_select( + MenuLocationEventMessage.class), click(MenuEventMessage.class), location( + LocationEventMessage.class), massendjobfinish( + MassEventMessage.class), templatesendjobfinish( + TemplatesendjobfinishMessage.class); + private Class extends EventMessage> eventClass; EventType(Class extends EventMessage> eventClass) { diff --git a/src/main/java/com/foxinmy/weixin4j/type/MediaType.java b/src/main/java/com/foxinmy/weixin4j/type/MediaType.java index 1f567181..322ba3ce 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/MediaType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/MediaType.java @@ -6,13 +6,20 @@ package com.foxinmy.weixin4j.type; * 语音(voice):256K,播放长度不超过60s,支持AMR\MP3格式 * 视频(video):1MB,支持MP4格式 * 缩略图(thumb):64KB,支持JPG格式 - * 媒体文件在后台保存时间为3天,即3天后media_id失效 + * + * 媒体文件在后台保存时间为3天,即3天后media_id失效 + * + * * @author jy.hu * @date 2014年4月2日 * @since JDK 1.7 */ public enum MediaType { - image("image/jpeg",".jpg"), voice("binary/octet-stream","amr"), vedio("binary/octet-stream","mp4"), thumb("image/jpeg","jpg"); + image("image/jpeg", "jpg"), voice("binary/octet-stream", "amr"), vedio( + "binary/octet-stream", "mp4"), thumb("image/jpeg", "jpg"), text( + "application/json", ""), music("binary/octet-stream", "mp3"), news( + "application/json", ""), mpnews("application/json", ""), mpvideo( + "binary/octet-stream", ""); MediaType(String contentType, String formatType) { this.contentType = contentType; @@ -26,6 +33,7 @@ public enum MediaType { } private String formatType; + public String getFormatType() { return formatType; } diff --git a/src/main/java/com/foxinmy/weixin4j/type/MessageType.java b/src/main/java/com/foxinmy/weixin4j/type/MessageType.java index 21a7b6dc..a883d993 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/MessageType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/MessageType.java @@ -10,6 +10,7 @@ import com.foxinmy.weixin4j.msg.in.VideoMessage; import com.foxinmy.weixin4j.msg.in.VoiceMessage; import com.foxinmy.weixin4j.msg.out.ArticleMessage; import com.foxinmy.weixin4j.msg.out.MusicMessage; +import com.foxinmy.weixin4j.msg.out.TransferMessage; /** * @@ -20,9 +21,13 @@ import com.foxinmy.weixin4j.msg.out.MusicMessage; */ public enum MessageType { // 接收到的消息类型 - text(TextMessage.class), image(ImageMessage.class), voice(VoiceMessage.class), video(VideoMessage.class), location(LocationMessage.class), link(LinkMessage.class), event(EventMessage.class), + text(TextMessage.class), image(ImageMessage.class), voice( + VoiceMessage.class), video(VideoMessage.class), location( + LocationMessage.class), link(LinkMessage.class), event( + EventMessage.class), // 发送的消息类型 - music(MusicMessage.class), news(ArticleMessage.class); + music(MusicMessage.class), news(ArticleMessage.class), transfer_customer_service( + TransferMessage.class); private Class extends BaseMessage> messageClass; MessageType(Class extends BaseMessage> messageClass) { diff --git a/src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java b/src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java similarity index 91% rename from src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java rename to src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java index f428c33b..b419bd1c 100644 --- a/src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java +++ b/src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java @@ -8,8 +8,8 @@ import java.util.regex.Pattern; import com.foxinmy.weixin4j.WeixinProxy; -public class WeixinConfig { - public WeixinConfig() { +public class ConfigUtil { + public ConfigUtil() { } private static Properties props = new Properties(); @@ -38,7 +38,6 @@ public class WeixinConfig { m.appendTail(sb); return sb.toString(); } - public static void main(String[] args) { System.out.println(getValue("api_token_uri")); } diff --git a/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java b/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java new file mode 100644 index 00000000..60eae107 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java @@ -0,0 +1,67 @@ +package com.foxinmy.weixin4j.util; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.Writer; +import java.nio.charset.Charset; + +/** + * IOUtil + * + * @className IOUtil + * @author jy.hu + * @date 2014年9月22日 + * @since JDK 1.7 + * @see org.apache.commons.io.IOUtils + */ +public class IOUtil { + + private static final int EOF = -1; + private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; + + public static byte[] toByteArray(Reader input) throws IOException { + return toByteArray(input, Charset.defaultCharset()); + } + + public static byte[] toByteArray(Reader input, Charset encoding) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + copy(input, output, encoding); + return output.toByteArray(); + } + + public static void copy(Reader input, OutputStream output, Charset encoding) throws IOException { + OutputStreamWriter out = new OutputStreamWriter(output, encoding); + copyLarge(input, out, new char[DEFAULT_BUFFER_SIZE]); + out.flush(); + } + + public static byte[] toByteArray(InputStream input) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + copyLarge(input, output, new byte[DEFAULT_BUFFER_SIZE]); + return output.toByteArray(); + } + + private static long copyLarge(InputStream input, OutputStream output, byte[] buffer) throws IOException { + long count = 0; + int n = 0; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } + + private static long copyLarge(Reader input, Writer output, char[] buffer) throws IOException { + long count = 0; + int n = 0; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java b/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java new file mode 100644 index 00000000..82a23ef3 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java @@ -0,0 +1,135 @@ +package com.foxinmy.weixin4j.util; + +import java.io.InputStream; +import java.util.Arrays; + +import org.apache.commons.codec.digest.DigestUtils; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.DocumentHelper; +import org.dom4j.io.SAXReader; +import org.jsoup.helper.StringUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.type.EventType; +import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; + +public class MessageUtil { + + private final static Logger log = LoggerFactory.getLogger(MessageUtil.class); + + /** + * 验证微信签名 + * + * @param echostr + * 随机字符串 + * @param timestamp + * 时间戳 + * @param nonce + * 随机数 + * @param signature + * 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数 + * @return 开发者通过检验signature对请求进行相关校验。若确认此次GET请求来自微信服务器 + * 请原样返回echostr参数内容,则接入生效 成为开发者成功,否则接入失败 + * @see 接入指南 + */ + public static String signature(String echostr, String timestamp, String nonce, String signature) { + String app_token = ConfigUtil.getValue("app_token"); + if (StringUtil.isBlank(app_token)) { + log.error("signature fail : token is null!"); + return null; + } + if (StringUtil.isBlank(echostr) || StringUtil.isBlank(timestamp) || StringUtil.isBlank(nonce)) { + log.error("signature fail : invalid parameter!"); + return null; + } + String _signature = null; + try { + String[] a = { app_token, timestamp, nonce }; + Arrays.sort(a); + StringBuilder sb = new StringBuilder(3); + for (String str : a) { + sb.append(str); + } + _signature = DigestUtils.sha1Hex(sb.toString()); + } catch (Exception e) { + log.error("signature error", e); + } + if (signature.equals(_signature)) { + return echostr; + } else { + log.error("signature fail : invalid signature!"); + return null; + } + } + + /** + * xml消息转换为消息对象 + * + * 微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次 + * + * + * @param xml + * 消息字符串 + * @return 消息对象 + * @throws DocumentException + * @see 验证消息的合法性 + * @see 普通消息 + * @see 事件触发 + * @see com.foxinmy.weixin4j.type.MessageType + * @see com.feican.weixin.msg.BaeMessage + * @see com.foxinmy.weixin4j.msg.TextMessage + * @see com.foxinmy.weixin4j.msg.in.ImageMessage + * @see com.foxinmy.weixin4j.msg.in.VoiceMessage + * @see com.foxinmy.weixin4j.msg.in.VideoMessage + * @see com.foxinmy.weixin4j.msg.in.LocationMessage + * @see com.foxinmy.weixin4j.msg.in.LinkMessage + * @see com.foxinmy.weixin4j.msg.event.ScribeEventMessage + * @see com.foxinmy.weixin4j.msg.event.ScanEventMessage + * @see com.foxinmy.weixin4j.msg.event.LocationEventMessage + * @see com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage + */ + public static BaseMessage xml2msg(String xml) throws DocumentException { + if (StringUtil.isBlank(xml)) + return null; + Document doc = DocumentHelper.parseText(xml); + String type = doc.selectSingleNode("/xml/MsgType").getStringValue(); + if (StringUtil.isBlank(type)) { + return null; + } + XStream xstream = new XStream(); + MessageType messageType = MessageType.valueOf(type.toLowerCase()); + Class extends BaseMessage> messageClass = messageType.getMessageClass(); + if (messageType == MessageType.event) { + type = doc.selectSingleNode("/xml/Event").getStringValue(); + messageClass = EventType.valueOf(type.toLowerCase()).getEventClass(); + } + xstream.alias("xml", messageClass); + xstream.ignoreUnknownElements(); + xstream.autodetectAnnotations(true); + xstream.processAnnotations(messageClass); + return xstream.fromXML(doc.asXML(), messageClass); + } + + /** + * xml消息转换为消息对象 + * + * @param inputStream + * 带消息字符串的输入流 + * @return 消息对象 + * @throws DocumentException + * @see {@link com.foxinmy.weixin4j.WeixinProxy#xml2msg(String)} + */ + public static BaseMessage xml2msg(InputStream inputStream) throws DocumentException { + SAXReader reader = new SAXReader(); + Document doc = reader.read(inputStream); + return xml2msg(doc.asXML()); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java b/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java deleted file mode 100644 index 19fd87e4..00000000 --- a/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.foxinmy.weixin4j.util; - -public class WeixinUtil { - - public static boolean isBlank(String str) { - return str == null || str.isEmpty(); - } -} diff --git a/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java b/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java index 5c0186c6..4a811a6c 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java @@ -9,7 +9,7 @@ import org.junit.Test; import com.foxinmy.weixin4j.WeixinProxy; import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.model.Button; -import com.foxinmy.weixin4j.model.Button.BtnType; +import com.foxinmy.weixin4j.type.ButtonType; /** * 自定义菜单测试 @@ -31,7 +31,7 @@ public class ButtonTest { List btnList = new ArrayList(); Button b = new Button("test"); - b.setType(BtnType.click); + b.setType(ButtonType.click); b.setKey("123"); btnList.add(b); diff --git a/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java b/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java index 8b78305e..bb6bec88 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java @@ -50,7 +50,7 @@ public class GroupTest { @Test public void getid() { try { - System.out.println(weixinProxy.findGroupByOpenId("owGBft_vbBbOaQOmpEUE4xDLeRSU")); + System.out.println(weixinProxy.getGroupByOpenId("owGBft_vbBbOaQOmpEUE4xDLeRSU")); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); diff --git a/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java b/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java new file mode 100644 index 00000000..6d34a733 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java @@ -0,0 +1,22 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Test; + +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.http.HttpRequest; + +public class HttpTest { + private static HttpRequest request; + static { + request = new HttpRequest(); + } + + @Test + public void test(){ + try { + System.out.println(request.get("http://www.baidu.com")); + } catch (WeixinException e) { + e.printStackTrace(); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java b/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java index f907fa3d..d54e649b 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java @@ -31,7 +31,7 @@ public class MediaTest { File file = new File("D:\\test.jpg"); try { System.out.println(weixinProxy.uploadMedia(file, MediaType.image)); - //usAxLEJxFXAjXVlLu_BSw0GvS2YEEoGeelRBybNZBGvMsdxiIcD1F9yBWYd9jVZx + //vvU_AUtovWyfAxQ8J1DsCoNMtK6U_bUmTpe6lpINUOVRLvt_7rtO4zxzBpPgkmay } catch (WeixinException e) { System.out.println(e.getErrorMsg()); } @@ -40,7 +40,7 @@ public class MediaTest { @Test public void download() { try { - System.out.println(weixinProxy.downloadMedia("usAxLEJxFXAjXVlLu_BSw0GvS2YEEoGeelRBybNZBGvMsdxiIcD1F9yBWYd9jVZx", MediaType.image)); + System.out.println(weixinProxy.downloadMedia("vvU_AUtovWyfAxQ8J1DsCoNMtK6U_bUmTpe6lpINUOVRLvt_7rtO4zxzBpPgkmay", MediaType.image)); } catch (WeixinException e) { System.out.println(e.getErrorMsg()); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java new file mode 100644 index 00000000..2cd36584 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java @@ -0,0 +1,194 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Test; + +import com.foxinmy.weixin4j.util.MessageUtil; + +/** + * 接收事件消息格式测试 + * + * @author jy.hu + * @date 2014年3月24日 + * @since JDK 1.7 + */ +public class MessageEventInTest { + + private StringBuilder xmlSb = new StringBuilder(); + + /***************** event message *********************/ + @Test + public void scribe() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void scan() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void scan_scribe() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void location1() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("23.137466"); + xmlSb.append("113.352425"); + xmlSb.append("119.385040"); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_click() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_link() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_scan() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_photo() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("1"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_location() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java index 39269754..fdd40042 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java @@ -1,134 +1,19 @@ package com.foxinmy.weixin4j.test; -import org.junit.Before; import org.junit.Test; -import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.util.MessageUtil; /** - * 接收消息格式测试 + * 接受一般消息格式测试 + * * @author jy.hu * @date 2014年3月24日 * @since JDK 1.7 */ public class MessageInTest { + private StringBuilder xmlSb = new StringBuilder(); - private WeixinProxy weixinProxy; - - @Before - public void init(){ - weixinProxy = new WeixinProxy(); - } - - /***************** event message *********************/ - @Test - public void scribe() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void scan() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - @Test - public void scan_scribe() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void location1() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("23.137466"); - xmlSb.append("113.352425"); - xmlSb.append("119.385040"); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void menu_click() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void menu_link() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } /***************** common message *********************/ @@ -144,7 +29,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -163,7 +48,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -182,7 +67,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -202,7 +87,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -221,7 +106,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -242,7 +127,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -262,7 +147,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java new file mode 100644 index 00000000..8f6a130f --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java @@ -0,0 +1,114 @@ +package com.foxinmy.weixin4j.test; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.model.MpArticle; +import com.foxinmy.weixin4j.type.MediaType; + +/** + * 群发消息 + * + * @className MpNewsTest + * @author jy + * @date 2014年4月27日 + * @since JDK 1.7 + * @see + */ +public class MessageMassTest { + private WeixinProxy weixinProxy; + + @Before + public void init() { + this.weixinProxy = new WeixinProxy(); + } + + @Test + public void uploadArticle() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.uploadArticle(articles); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void uploadVideo() { + try { + weixinProxy.uploadVideo("mediaId", "title", "desc"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massByGroup() { + try { + weixinProxy.massByGroup("123", MediaType.image, "groupId"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massByOpenIds() { + try { + weixinProxy.massByOpenIds("123", MediaType.image, "openIds"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massArticleByGroup() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.massArticleByGroup(articles, "0"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massArticleByOpenIds() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.massArticleByOpenIds(articles, + "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void deleteMass() { + try { + weixinProxy.deleteMassNews("34182"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java index f3be10bb..59aed8de 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java @@ -7,6 +7,7 @@ import org.junit.Test; import com.foxinmy.weixin4j.WeixinProxy; import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.msg.model.Music; import com.foxinmy.weixin4j.msg.notify.ArticleNotify; import com.foxinmy.weixin4j.msg.notify.BaseNotify; import com.foxinmy.weixin4j.msg.notify.ImageNotify; @@ -41,27 +42,29 @@ public class MessageNotifyTest { @Test public void image() { - ImageNotify notify = new ImageNotify("123", "to"); + ImageNotify notify = new ImageNotify("to"); + notify.pushMediaId("123"); System.out.println(notify.toJson()); } @Test public void voice() { - VoiceNotify notify = new VoiceNotify("123", "to"); + VoiceNotify notify = new VoiceNotify("to"); + notify.pushMediaId("123"); System.out.println(notify.toJson()); } @Test public void video() { VideoNotify notify = new VideoNotify("to"); - notify.pushVideo("123", "title", "desc"); + notify.pushVideo("123","m123"); System.out.println(notify.toJson()); } @Test public void music() { MusicNotify notify = new MusicNotify("to"); - notify.pushMusic("title", "desc", "url", "hqUrl", "mediaId"); + notify.pushMusic("url", "hqUrl", "mediaId"); System.out.println(notify.toJson()); } @@ -74,16 +77,27 @@ public class MessageNotifyTest { } @Test - public void send() { - BaseNotify t = new TextNotify("哈哈哈哈", "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + public void send1() { + BaseNotify notify = new TextNotify("哈哈哈哈", "owGBft_vbBbOaQOmpEUE4xDLeRSU"); try { - weixinProxy.sendNotify(t); + weixinProxy.sendNotify(notify); String mediaId = weixinProxy.uploadMedia(new File("D:\\test.jpg"), MediaType.image); - t = new ImageNotify(mediaId, "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + ImageNotify t = new ImageNotify("owGBft_vbBbOaQOmpEUE4xDLeRSU"); + t.pushMediaId(mediaId); weixinProxy.sendNotify(t); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); } } + + @Test + public void send2() { + try { + weixinProxy.sendNotify("to",new Music("thumbMediaId")); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java index 00021aa0..ddb309d4 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java @@ -1,7 +1,9 @@ package com.foxinmy.weixin4j.test; +import org.junit.Before; import org.junit.Test; +import com.foxinmy.weixin4j.msg.BaseMessage; import com.foxinmy.weixin4j.msg.TextMessage; import com.foxinmy.weixin4j.msg.out.ArticleMessage; import com.foxinmy.weixin4j.msg.out.ImageMessage; @@ -17,56 +19,52 @@ import com.foxinmy.weixin4j.msg.out.VoiceMessage; * @since JDK 1.7 */ public class MessageOutTest { + private BaseMessage inMessage; + + @Before + public void init() { + this.inMessage = new TextMessage(); + this.inMessage.setFromUserName("fromusername"); + this.inMessage.setToUserName("tousername"); + } + @Test public void text() { - TextMessage message = new TextMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.setContent("text message"); + TextMessage message = new TextMessage("text", inMessage); System.out.println(message.toXml()); } @Test public void image() { - ImageMessage message = new ImageMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + ImageMessage message = new ImageMessage(inMessage); message.pushMediaId("mediaId"); System.out.println(message.toXml()); } @Test public void voice() { - VoiceMessage message = new VoiceMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + VoiceMessage message = new VoiceMessage(inMessage); message.pushMediaId("mediaId"); System.out.println(message.toXml()); } - + @Test public void video() { - VideoMessage message = new VideoMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.pushVideo("mediaId", "title", "title"); + VideoMessage message = new VideoMessage(inMessage); + message.pushVideo("mediaId"); System.out.println(message.toXml()); } - + @Test public void music() { - MusicMessage message = new MusicMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.pushMusic("title", "desc", "url", "hqurl", "mediaId"); + MusicMessage message = new MusicMessage(inMessage); + message.pushMusic("mediaId"); System.out.println(message.toXml()); } - + @Test public void article() { - ArticleMessage message = new ArticleMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + ArticleMessage message = new ArticleMessage(inMessage); message.pushArticle("title1", "desc1", "picUrl1", "url1"); message.pushArticle("title2", "desc2", "picUrl2", "url2"); System.out.println(message.toXml()); diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java new file mode 100644 index 00000000..b8165a91 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java @@ -0,0 +1,30 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Before; +import org.junit.Test; + +import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.msg.out.TemplateMessage; + +public class MessageTemplTest { + private WeixinProxy weixinProxy; + + @Before + public void init() { + this.weixinProxy = new WeixinProxy(); + } + + @Test + public void test() { + TemplateMessage tplMessage = new TemplateMessage("touser", + "template_id", "url"); + tplMessage.pushData("name", "fox"); + System.out.print(tplMessage.toJson()); + try { + System.out.print(weixinProxy.sendTplMessage(tplMessage)); + } catch (WeixinException e) { + System.out.println(e.getErrorMsg()); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java b/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java deleted file mode 100644 index 5fa1ec67..00000000 --- a/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.foxinmy.weixin4j.test; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; - -import com.foxinmy.weixin4j.WeixinProxy; -import com.foxinmy.weixin4j.exception.WeixinException; -import com.foxinmy.weixin4j.model.MpArticle; -import com.foxinmy.weixin4j.type.MediaType; - -/** - * 群发消息 - * - * @className MpNewsTest - * @author jy - * @date 2014年4月27日 - * @since JDK 1.7 - * @see - */ -public class MpNewsTest { - private WeixinProxy weixinProxy; - - @Before - public void init() { - this.weixinProxy = new WeixinProxy(); - } - - @Test - public void massByGroup(){ - List articles = new ArrayList(); - try { - String thumbMediaId = weixinProxy.uploadMedia(new File("/tmp/test.jpg"), MediaType.image); - articles.add(new MpArticle(thumbMediaId, "title", "content")); - weixinProxy.massNewsByGroup(articles, "0"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } - - @Test - public void massByOpenIds(){ - List articles = new ArrayList(); - try { - String thumbMediaId = weixinProxy.uploadMedia(new File("/tmp/test.jpg"), MediaType.image); - articles.add(new MpArticle(thumbMediaId, "title", "content")); - weixinProxy.massNewsByOpenIds(articles, "owGBft_vbBbOaQOmpEUE4xDLeRSU"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } - - @Test - public void deleteMass(){ - try { - weixinProxy.deleteMassNews("34182"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } -} diff --git a/src/test/java/com/foxinmy/weixin4j/test/QRTest.java b/src/test/java/com/foxinmy/weixin4j/test/QRTest.java index 11934fa9..f18d1aa7 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/QRTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/QRTest.java @@ -25,10 +25,10 @@ public class QRTest { @Test public void temp_qr() { - QRParameter qr = new QRParameter(1200, QRType.QR_SCENE, 1); + QRParameter qr = new QRParameter(1200, QRType.TEMPORARY, 2); try { System.out.println(qr.toJson()); - weixinProxy.getQR(qr); + System.out.println(weixinProxy.getQR(qr)); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); @@ -37,10 +37,10 @@ public class QRTest { @Test public void forever_qr() { - QRParameter qr = new QRParameter(QRType.QR_LIMIT_SCENE, 1); + QRParameter qr = new QRParameter(QRType.PERMANENCE, 1); try { System.out.println(qr.toJson()); - weixinProxy.getQR(qr); + System.out.println(weixinProxy.getQR(qr)); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java b/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java index 37d549d7..a2f8a266 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java @@ -3,7 +3,8 @@ package com.foxinmy.weixin4j.test; import org.junit.Before; import org.junit.Test; -import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.api.token.FileTokenApi; +import com.foxinmy.weixin4j.api.token.TokenApi; import com.foxinmy.weixin4j.exception.WeixinException; /** @@ -14,17 +15,17 @@ import com.foxinmy.weixin4j.exception.WeixinException; * @since JDK 1.7 */ public class TokenTest { - private WeixinProxy weixinProxy; + private TokenApi tokenApi; @Before public void init() { - weixinProxy = new WeixinProxy(); + tokenApi = new FileTokenApi(); } @Test public void getToken() { try { - System.out.println(weixinProxy.getToken()); + System.out.println(tokenApi.getToken()); } catch (WeixinException e) { e.printStackTrace(); }
articles; + private LinkedList articles; public List getArticles() { return this.articles; @@ -44,39 +44,55 @@ public class ArticleMessage extends BaseMessage { return; } if (this.articles == null) { - this.articles = new LinkedList(); + this.articles = new LinkedList(); } this.articles.add(new Article(title, desc, picUrl, url)); - count ++; + count++; } - @XStreamAlias("item") - private static class Article { - @XStreamAlias("Title") - private String title; // 图文消息标题 - @XStreamAlias("Description") - private String desc; // 图文消息描述 - @XStreamAlias("PicUrl") - private String picUrl; // 图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200 - @XStreamAlias("Url") - private String url; // 点击图文消息跳转链接 - - public Article(String title, String desc, String picUrl, String url) { - this.title = title; - this.desc = desc; - this.picUrl = picUrl; - this.url = url; + public void pushFirstArticle(String title, String desc, String picUrl, + String url) { + if (this.articles == null) { + this.articles = new LinkedList(); } + this.articles.addFirst(new Article(title, desc, picUrl, url)); + } - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Article ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,picUrl=").append(picUrl); - sb.append(" ,url=").append(url).append(")"); - return sb.toString(); + public void pushLastArticle(String title, String desc, String picUrl, + String url) { + if (this.articles == null) { + this.articles = new LinkedList(); } + this.articles.addLast(new Article(title, desc, picUrl, url)); + } + + public Article removeLastArticle() { + if (this.articles != null) { + return this.articles.removeLast(); + } + return null; + } + + 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() { + 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 diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java index 2da50a01..fb58ecb8 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java @@ -1,38 +1,50 @@ 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 回复图片消息 + * @see 回复图片消息 + * @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() { - super(MessageType.image); + public ImageMessage(BaseMessage inMessage) { + super(MessageType.image, inMessage); super.getMsgType().setMessageClass(ImageMessage.class); } + 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(); - this.image.mediaId = mediaId; + this.image = new Image(mediaId); } - private static class Image { - @XStreamAlias("MediaId") - private String mediaId; + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Image.class, "mediaId"); + return xstream.toXML(this); } @Override @@ -41,7 +53,7 @@ public class ImageMessage extends BaseMessage { sb.append("[ImageMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,mediaId=").append(this.image.mediaId); + sb.append(" ,mediaId=").append(this.image.getMediaId()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java index c790b9ac..419f32d6 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java @@ -1,74 +1,61 @@ 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 回复音乐消息 + * @see 回复音乐消息 + * @see com.foxinmy.weixin4j.msg.model.Music * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class MusicMessage extends BaseMessage { private static final long serialVersionUID = 4384403772658796395L; - public MusicMessage() { - super(MessageType.music); + public MusicMessage(BaseMessage inMessage) { + super(MessageType.music, inMessage); } @XStreamAlias("Music") private Music music; - public Music getMusic() { - return this.music; + public void pushMusic(String mediaId) { + this.music = new Music(mediaId); } - public void pushMusic(String title, String desc, String url, String hqUrl, String mediaId) { - this.music = new Music(); - this.music.thumbMediaId = mediaId; - this.music.desc = desc; - this.music.hqMusicUrl = hqUrl; - this.music.MusicURL = url; - this.music.title = title; + public void setMusic(Music music) { + this.music = music; } - private static class Music { - @XStreamAlias("Title") - private String title; // 音乐标题 - @XStreamAlias("Description") - private String desc; // 音乐描述 - @XStreamAlias("MusicURL") - private String MusicURL; // 音乐链接 - @XStreamAlias("HQMusicUrl") - private String hqMusicUrl; // 高质量音乐链接,WIFI环境优先使用该链接播放音乐 - @XStreamAlias("ThumbMediaId") - private String thumbMediaId; // 缩略图的媒体id,通过上传多媒体文件,得到的id - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Music ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,musicURL=").append(MusicURL); - sb.append(" ,hqMusicUrl=").append(hqMusicUrl); - sb.append(" ,thumbMediaId=").append(thumbMediaId).append(")"); - return sb.toString(); - } + @Override + public String 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(getMusic().toString()); + sb.append(" ,music=").append(music.toString()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java new file mode 100644 index 00000000..3721504b --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java @@ -0,0 +1,117 @@ +package com.foxinmy.weixin4j.msg.out; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +import com.alibaba.fastjson.JSON; + +/** + * 模板消息 + * + * @className TemplateMessage + * @author jy + * @date 2014年9月29日 + * @since JDK 1.7 + * @see + */ +public class TemplateMessage implements Serializable { + + private static final long serialVersionUID = 7950608393821661436L; + + private String touser; + private String template_id; + private String url; + private String topcolor = "#FF0000"; + private Map data; + + public void pushData(String key, String value) { + this.data.put(key, new Item(value)); + } + + public TemplateMessage(String touser, String template_id, String url) { + this.touser = touser; + this.template_id = template_id; + this.url = url; + this.data = new HashMap(); + } + + private static class Item implements Serializable { + private static final long serialVersionUID = 1L; + private String value; + private String color; + + public Item(String value) { + this(value, "#173177"); + } + + public Item(String value, String color) { + this.value = value; + this.color = color; + } + + public String getValue() { + return value; + } + + public String getColor() { + return color; + } + + @Override + public String toString() { + return "$ [value=" + getValue() + ", color=" + getColor() + "]"; + } + } + + public String getTouser() { + return touser; + } + + public void setTouser(String touser) { + this.touser = touser; + } + + public String getTemplate_id() { + return template_id; + } + + public void setTemplate_id(String template_id) { + this.template_id = template_id; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getTopcolor() { + return topcolor; + } + + public void setTopcolor(String topcolor) { + this.topcolor = topcolor; + } + + public Map getData() { + return data; + } + + public void setData(Map data) { + this.data = data; + } + + @Override + public String toString() { + return "TemplateMessage [touser=" + touser + ", template_id=" + + template_id + ", url=" + url + ", topcolor=" + topcolor + + ", data=" + data + "]"; + } + + public String toJson() { + return JSON.toJSONString(this); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java new file mode 100644 index 00000000..b89621aa --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java @@ -0,0 +1,25 @@ +package com.foxinmy.weixin4j.msg.out; + +import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.type.MessageType; + +/** + * 转移消息到多客服端消息 + * + * @className TransferMessage + * @author jy.hu + * @date 2014年6月28日 + * @since JDK 1.7 + * @see 多客服转移消息 + * @see com.foxinmy.weixin4j.msg.BaseMessage + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + */ +public class TransferMessage extends BaseMessage { + + private static final long serialVersionUID = -5479496746108594940L; + + public TransferMessage(BaseMessage inMessage) { + super(MessageType.transfer_customer_service,inMessage); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java index d16c5a12..d6cdfc91 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java @@ -1,58 +1,52 @@ package com.foxinmy.weixin4j.msg.out; import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.msg.model.Video; import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 回复视频消息 + * * @className VideoMessage * @author jy.hu * @date 2014年4月6日 * @since JDK 1.7 - * @see 回复视频消息 + * @see 回复视频消息 + * @see com.foxinmy.weixin4j.msg.model.Video * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class VideoMessage extends BaseMessage { private static final long serialVersionUID = -1013075358679078381L; - public VideoMessage() { - super(MessageType.video); + public VideoMessage(BaseMessage inMessage) { + super(MessageType.video, inMessage); super.getMsgType().setMessageClass(VideoMessage.class); } @XStreamAlias("Video") private Video video; - public Video getVideo() { - return this.video; + public void pushVideo(String mediaId) { + this.video = new Video(mediaId); } - public void pushVideo(String mediaId, String title, String desc) { - this.video = new Video(); - this.video.desc = desc; - this.video.mediaId = mediaId; - this.video.title = title; + public void setVideo(Video video) { + this.video = video; } - private static class Video { - @XStreamAlias("MediaId") - private String mediaId; - @XStreamAlias("Title") - private String title; - @XStreamAlias("Description") - private String desc; - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Video mediaId=").append(mediaId); - sb.append(" ,title=").append(title); - sb.append(" ,desc=").append(desc).append(")"); - return super.toString(); - } + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Video.class, "mediaId"); + xstream.aliasField("Title", Video.class, "title"); + xstream.aliasField("Description", Video.class, "desc"); + xstream.omitField(Video.class, "thumbMediaId"); + return xstream.toXML(this); } @Override @@ -61,7 +55,7 @@ public class VideoMessage extends BaseMessage { sb.append("[VideoMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,video=").append(getVideo().toString()); + sb.append(" ,video=").append(video.toString()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java index 93052907..dcac1046 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java @@ -1,53 +1,60 @@ package com.foxinmy.weixin4j.msg.out; import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.msg.model.Voice; import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 语音消息 + * * @className VoiceMessage * @author jy.hu * @date 2014年3月23日 * @since JDK 1.7 - * @see 回复语音消息 + * @see 回复语音消息 + * @see com.foxinmy.weixin4j.msg.model.Voice * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class VoiceMessage extends BaseMessage { private static final long serialVersionUID = -7944926238652243793L; - public VoiceMessage() { - super(MessageType.voice); + public VoiceMessage(BaseMessage inMessage) { + super(MessageType.voice, inMessage); super.getMsgType().setMessageClass(VoiceMessage.class); } + + public VoiceMessage(String mediaId, BaseMessage inMessage) { + super(MessageType.voice, inMessage); + super.getMsgType().setMessageClass(VoiceMessage.class); + this.pushMediaId(mediaId); + } + @XStreamAlias("Voice") private Voice voice; - - public Voice getVocie() { - return voice; + + public void pushMediaId(String mediaId) { + this.voice = new Voice(mediaId); } - public void pushMediaId(String mediaId){ - this.voice = new Voice(); - this.voice.setMediaId(mediaId); - } - - private static class Voice { - @XStreamAlias("MediaId") - private String mediaId; - - private void setMediaId(String mediaId) { - this.mediaId = mediaId; - } + + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Voice.class, "mediaId"); + return xstream.toXML(this); } + @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("[VoiceMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,mediaId=").append(getVocie().mediaId); + sb.append(" ,mediaId=").append(voice.getMediaId()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java b/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java new file mode 100644 index 00000000..cf2ab68e --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java @@ -0,0 +1,55 @@ +package com.foxinmy.weixin4j.type; + +/** + * 自定义菜单类型 + * scancode_push 到 location_selec + * 仅支持微信iPhone5.4.1以上版本,和Android5 .4以上版本的微信用户 旧版本微信用户点击后将没有回应 + * 开发者也不能正常接收到事件推送。 + * + * @className ButtonType + * @author jy + * @date 2014年9月30日 + * @since JDK 1.7 + * @see 按钮类型 + */ +public enum ButtonType { + /** + * 点击推事件 用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event + * 的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互; + */ + click, + /** + * 跳转URL 用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的网页URL,可与网页授权获取用户基本信息接口结合,获得用户基本信息。 + */ + view, + /** + * 扫码推事件 用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后显示扫描结果(如果是URL,将进入URL),且会将扫码的结果传给开发者, + * 开发者可以下发消息。 + */ + scancode_push, + /** + * 扫码推事件且弹出“消息接收中”提示框用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后,将扫码的结果传给开发者,同时收起扫一扫工具, + * 然后弹出“消息接收中”提示框,随后可能会收到开发者下发的消息。 + */ + scancode_waitmsg, + /** + * 弹出系统拍照发图用户点击按钮后,微信客户端将调起系统相机,完成拍照操作后,会将拍摄的相片发送给开发者,并推送事件给开发者,同时收起系统相机, + * 随后可能会收到开发者下发的消息。 + */ + pic_sysphoto, + /** + * 弹出拍照或者相册发图用户点击按钮后,微信客户端将弹出选择器供用户选择“拍照”或者“从手机相册选择”。用户选择后即走其他两种流程。 + */ + pic_photo_or_albu, + /** + * 弹出微信相册发图器用户点击按钮后,微信客户端将调起微信相册,完成选择操作后,将选择的相片发送给开发者的服务器,并推送事件给开发者,同时收起相册, + * 随后可能会收到开发者下发的消息。 + */ + pic_weixin, + /** + * 弹出地理位置选择器用户点击按钮后,微信客户端将调起地理位置选择工具,完成选择操作后,将选择的地理位置发送给开发者的服务器,同时收起位置选择工具, + * 随后可能会收到开发者下发的消息。 + */ + location_select; +} diff --git a/src/main/java/com/foxinmy/weixin4j/type/EventType.java b/src/main/java/com/foxinmy/weixin4j/type/EventType.java index a8e864b8..bc85ce90 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/EventType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/EventType.java @@ -3,21 +3,36 @@ package com.foxinmy.weixin4j.type; import com.foxinmy.weixin4j.msg.event.EventMessage; import com.foxinmy.weixin4j.msg.event.LocationEventMessage; import com.foxinmy.weixin4j.msg.event.MassEventMessage; -import com.foxinmy.weixin4j.msg.event.MenuEventMessage; import com.foxinmy.weixin4j.msg.event.ScanEventMessage; import com.foxinmy.weixin4j.msg.event.ScribeEventMessage; +import com.foxinmy.weixin4j.msg.event.TemplatesendjobfinishMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuLocationEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuPhotoEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuScanEventMessage; /** - * * 事件类型 - * @author jy.hu - * + * + * @className EventType + * @author jy + * @date 2014年9月30日 + * @since JDK 1.7 + * @see */ public enum EventType { - subscribe(ScribeEventMessage.class), unsubscribe(ScribeEventMessage.class), - scan(ScanEventMessage.class),click(MenuEventMessage.class),view(MenuEventMessage.class), - location(LocationEventMessage.class),MASSSENDJOBFINISH(MassEventMessage.class); - + subscribe(ScribeEventMessage.class), unsubscribe(ScribeEventMessage.class), scan( + ScanEventMessage.class), scancode_push(MenuScanEventMessage.class), view( + MenuEventMessage.class), scancode_waitmsg( + MenuScanEventMessage.class), pic_sysphoto( + MenuPhotoEventMessage.class), pic_photo_or_album( + MenuPhotoEventMessage.class), pic_weixin( + MenuPhotoEventMessage.class), location_select( + MenuLocationEventMessage.class), click(MenuEventMessage.class), location( + LocationEventMessage.class), massendjobfinish( + MassEventMessage.class), templatesendjobfinish( + TemplatesendjobfinishMessage.class); + private Class extends EventMessage> eventClass; EventType(Class extends EventMessage> eventClass) { diff --git a/src/main/java/com/foxinmy/weixin4j/type/MediaType.java b/src/main/java/com/foxinmy/weixin4j/type/MediaType.java index 1f567181..322ba3ce 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/MediaType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/MediaType.java @@ -6,13 +6,20 @@ package com.foxinmy.weixin4j.type; * 语音(voice):256K,播放长度不超过60s,支持AMR\MP3格式 * 视频(video):1MB,支持MP4格式 * 缩略图(thumb):64KB,支持JPG格式 - * 媒体文件在后台保存时间为3天,即3天后media_id失效 + * + * 媒体文件在后台保存时间为3天,即3天后media_id失效 + * + * * @author jy.hu * @date 2014年4月2日 * @since JDK 1.7 */ public enum MediaType { - image("image/jpeg",".jpg"), voice("binary/octet-stream","amr"), vedio("binary/octet-stream","mp4"), thumb("image/jpeg","jpg"); + image("image/jpeg", "jpg"), voice("binary/octet-stream", "amr"), vedio( + "binary/octet-stream", "mp4"), thumb("image/jpeg", "jpg"), text( + "application/json", ""), music("binary/octet-stream", "mp3"), news( + "application/json", ""), mpnews("application/json", ""), mpvideo( + "binary/octet-stream", ""); MediaType(String contentType, String formatType) { this.contentType = contentType; @@ -26,6 +33,7 @@ public enum MediaType { } private String formatType; + public String getFormatType() { return formatType; } diff --git a/src/main/java/com/foxinmy/weixin4j/type/MessageType.java b/src/main/java/com/foxinmy/weixin4j/type/MessageType.java index 21a7b6dc..a883d993 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/MessageType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/MessageType.java @@ -10,6 +10,7 @@ import com.foxinmy.weixin4j.msg.in.VideoMessage; import com.foxinmy.weixin4j.msg.in.VoiceMessage; import com.foxinmy.weixin4j.msg.out.ArticleMessage; import com.foxinmy.weixin4j.msg.out.MusicMessage; +import com.foxinmy.weixin4j.msg.out.TransferMessage; /** * @@ -20,9 +21,13 @@ import com.foxinmy.weixin4j.msg.out.MusicMessage; */ public enum MessageType { // 接收到的消息类型 - text(TextMessage.class), image(ImageMessage.class), voice(VoiceMessage.class), video(VideoMessage.class), location(LocationMessage.class), link(LinkMessage.class), event(EventMessage.class), + text(TextMessage.class), image(ImageMessage.class), voice( + VoiceMessage.class), video(VideoMessage.class), location( + LocationMessage.class), link(LinkMessage.class), event( + EventMessage.class), // 发送的消息类型 - music(MusicMessage.class), news(ArticleMessage.class); + music(MusicMessage.class), news(ArticleMessage.class), transfer_customer_service( + TransferMessage.class); private Class extends BaseMessage> messageClass; MessageType(Class extends BaseMessage> messageClass) { diff --git a/src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java b/src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java similarity index 91% rename from src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java rename to src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java index f428c33b..b419bd1c 100644 --- a/src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java +++ b/src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java @@ -8,8 +8,8 @@ import java.util.regex.Pattern; import com.foxinmy.weixin4j.WeixinProxy; -public class WeixinConfig { - public WeixinConfig() { +public class ConfigUtil { + public ConfigUtil() { } private static Properties props = new Properties(); @@ -38,7 +38,6 @@ public class WeixinConfig { m.appendTail(sb); return sb.toString(); } - public static void main(String[] args) { System.out.println(getValue("api_token_uri")); } diff --git a/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java b/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java new file mode 100644 index 00000000..60eae107 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java @@ -0,0 +1,67 @@ +package com.foxinmy.weixin4j.util; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.Writer; +import java.nio.charset.Charset; + +/** + * IOUtil + * + * @className IOUtil + * @author jy.hu + * @date 2014年9月22日 + * @since JDK 1.7 + * @see org.apache.commons.io.IOUtils + */ +public class IOUtil { + + private static final int EOF = -1; + private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; + + public static byte[] toByteArray(Reader input) throws IOException { + return toByteArray(input, Charset.defaultCharset()); + } + + public static byte[] toByteArray(Reader input, Charset encoding) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + copy(input, output, encoding); + return output.toByteArray(); + } + + public static void copy(Reader input, OutputStream output, Charset encoding) throws IOException { + OutputStreamWriter out = new OutputStreamWriter(output, encoding); + copyLarge(input, out, new char[DEFAULT_BUFFER_SIZE]); + out.flush(); + } + + public static byte[] toByteArray(InputStream input) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + copyLarge(input, output, new byte[DEFAULT_BUFFER_SIZE]); + return output.toByteArray(); + } + + private static long copyLarge(InputStream input, OutputStream output, byte[] buffer) throws IOException { + long count = 0; + int n = 0; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } + + private static long copyLarge(Reader input, Writer output, char[] buffer) throws IOException { + long count = 0; + int n = 0; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java b/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java new file mode 100644 index 00000000..82a23ef3 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java @@ -0,0 +1,135 @@ +package com.foxinmy.weixin4j.util; + +import java.io.InputStream; +import java.util.Arrays; + +import org.apache.commons.codec.digest.DigestUtils; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.DocumentHelper; +import org.dom4j.io.SAXReader; +import org.jsoup.helper.StringUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.type.EventType; +import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; + +public class MessageUtil { + + private final static Logger log = LoggerFactory.getLogger(MessageUtil.class); + + /** + * 验证微信签名 + * + * @param echostr + * 随机字符串 + * @param timestamp + * 时间戳 + * @param nonce + * 随机数 + * @param signature + * 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数 + * @return 开发者通过检验signature对请求进行相关校验。若确认此次GET请求来自微信服务器 + * 请原样返回echostr参数内容,则接入生效 成为开发者成功,否则接入失败 + * @see 接入指南 + */ + public static String signature(String echostr, String timestamp, String nonce, String signature) { + String app_token = ConfigUtil.getValue("app_token"); + if (StringUtil.isBlank(app_token)) { + log.error("signature fail : token is null!"); + return null; + } + if (StringUtil.isBlank(echostr) || StringUtil.isBlank(timestamp) || StringUtil.isBlank(nonce)) { + log.error("signature fail : invalid parameter!"); + return null; + } + String _signature = null; + try { + String[] a = { app_token, timestamp, nonce }; + Arrays.sort(a); + StringBuilder sb = new StringBuilder(3); + for (String str : a) { + sb.append(str); + } + _signature = DigestUtils.sha1Hex(sb.toString()); + } catch (Exception e) { + log.error("signature error", e); + } + if (signature.equals(_signature)) { + return echostr; + } else { + log.error("signature fail : invalid signature!"); + return null; + } + } + + /** + * xml消息转换为消息对象 + * + * 微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次 + * + * + * @param xml + * 消息字符串 + * @return 消息对象 + * @throws DocumentException + * @see 验证消息的合法性 + * @see 普通消息 + * @see 事件触发 + * @see com.foxinmy.weixin4j.type.MessageType + * @see com.feican.weixin.msg.BaeMessage + * @see com.foxinmy.weixin4j.msg.TextMessage + * @see com.foxinmy.weixin4j.msg.in.ImageMessage + * @see com.foxinmy.weixin4j.msg.in.VoiceMessage + * @see com.foxinmy.weixin4j.msg.in.VideoMessage + * @see com.foxinmy.weixin4j.msg.in.LocationMessage + * @see com.foxinmy.weixin4j.msg.in.LinkMessage + * @see com.foxinmy.weixin4j.msg.event.ScribeEventMessage + * @see com.foxinmy.weixin4j.msg.event.ScanEventMessage + * @see com.foxinmy.weixin4j.msg.event.LocationEventMessage + * @see com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage + */ + public static BaseMessage xml2msg(String xml) throws DocumentException { + if (StringUtil.isBlank(xml)) + return null; + Document doc = DocumentHelper.parseText(xml); + String type = doc.selectSingleNode("/xml/MsgType").getStringValue(); + if (StringUtil.isBlank(type)) { + return null; + } + XStream xstream = new XStream(); + MessageType messageType = MessageType.valueOf(type.toLowerCase()); + Class extends BaseMessage> messageClass = messageType.getMessageClass(); + if (messageType == MessageType.event) { + type = doc.selectSingleNode("/xml/Event").getStringValue(); + messageClass = EventType.valueOf(type.toLowerCase()).getEventClass(); + } + xstream.alias("xml", messageClass); + xstream.ignoreUnknownElements(); + xstream.autodetectAnnotations(true); + xstream.processAnnotations(messageClass); + return xstream.fromXML(doc.asXML(), messageClass); + } + + /** + * xml消息转换为消息对象 + * + * @param inputStream + * 带消息字符串的输入流 + * @return 消息对象 + * @throws DocumentException + * @see {@link com.foxinmy.weixin4j.WeixinProxy#xml2msg(String)} + */ + public static BaseMessage xml2msg(InputStream inputStream) throws DocumentException { + SAXReader reader = new SAXReader(); + Document doc = reader.read(inputStream); + return xml2msg(doc.asXML()); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java b/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java deleted file mode 100644 index 19fd87e4..00000000 --- a/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.foxinmy.weixin4j.util; - -public class WeixinUtil { - - public static boolean isBlank(String str) { - return str == null || str.isEmpty(); - } -} diff --git a/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java b/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java index 5c0186c6..4a811a6c 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java @@ -9,7 +9,7 @@ import org.junit.Test; import com.foxinmy.weixin4j.WeixinProxy; import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.model.Button; -import com.foxinmy.weixin4j.model.Button.BtnType; +import com.foxinmy.weixin4j.type.ButtonType; /** * 自定义菜单测试 @@ -31,7 +31,7 @@ public class ButtonTest { List btnList = new ArrayList(); Button b = new Button("test"); - b.setType(BtnType.click); + b.setType(ButtonType.click); b.setKey("123"); btnList.add(b); diff --git a/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java b/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java index 8b78305e..bb6bec88 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java @@ -50,7 +50,7 @@ public class GroupTest { @Test public void getid() { try { - System.out.println(weixinProxy.findGroupByOpenId("owGBft_vbBbOaQOmpEUE4xDLeRSU")); + System.out.println(weixinProxy.getGroupByOpenId("owGBft_vbBbOaQOmpEUE4xDLeRSU")); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); diff --git a/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java b/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java new file mode 100644 index 00000000..6d34a733 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java @@ -0,0 +1,22 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Test; + +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.http.HttpRequest; + +public class HttpTest { + private static HttpRequest request; + static { + request = new HttpRequest(); + } + + @Test + public void test(){ + try { + System.out.println(request.get("http://www.baidu.com")); + } catch (WeixinException e) { + e.printStackTrace(); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java b/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java index f907fa3d..d54e649b 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java @@ -31,7 +31,7 @@ public class MediaTest { File file = new File("D:\\test.jpg"); try { System.out.println(weixinProxy.uploadMedia(file, MediaType.image)); - //usAxLEJxFXAjXVlLu_BSw0GvS2YEEoGeelRBybNZBGvMsdxiIcD1F9yBWYd9jVZx + //vvU_AUtovWyfAxQ8J1DsCoNMtK6U_bUmTpe6lpINUOVRLvt_7rtO4zxzBpPgkmay } catch (WeixinException e) { System.out.println(e.getErrorMsg()); } @@ -40,7 +40,7 @@ public class MediaTest { @Test public void download() { try { - System.out.println(weixinProxy.downloadMedia("usAxLEJxFXAjXVlLu_BSw0GvS2YEEoGeelRBybNZBGvMsdxiIcD1F9yBWYd9jVZx", MediaType.image)); + System.out.println(weixinProxy.downloadMedia("vvU_AUtovWyfAxQ8J1DsCoNMtK6U_bUmTpe6lpINUOVRLvt_7rtO4zxzBpPgkmay", MediaType.image)); } catch (WeixinException e) { System.out.println(e.getErrorMsg()); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java new file mode 100644 index 00000000..2cd36584 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java @@ -0,0 +1,194 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Test; + +import com.foxinmy.weixin4j.util.MessageUtil; + +/** + * 接收事件消息格式测试 + * + * @author jy.hu + * @date 2014年3月24日 + * @since JDK 1.7 + */ +public class MessageEventInTest { + + private StringBuilder xmlSb = new StringBuilder(); + + /***************** event message *********************/ + @Test + public void scribe() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void scan() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void scan_scribe() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void location1() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("23.137466"); + xmlSb.append("113.352425"); + xmlSb.append("119.385040"); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_click() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_link() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_scan() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_photo() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("1"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_location() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java index 39269754..fdd40042 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java @@ -1,134 +1,19 @@ package com.foxinmy.weixin4j.test; -import org.junit.Before; import org.junit.Test; -import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.util.MessageUtil; /** - * 接收消息格式测试 + * 接受一般消息格式测试 + * * @author jy.hu * @date 2014年3月24日 * @since JDK 1.7 */ public class MessageInTest { + private StringBuilder xmlSb = new StringBuilder(); - private WeixinProxy weixinProxy; - - @Before - public void init(){ - weixinProxy = new WeixinProxy(); - } - - /***************** event message *********************/ - @Test - public void scribe() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void scan() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - @Test - public void scan_scribe() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void location1() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("23.137466"); - xmlSb.append("113.352425"); - xmlSb.append("119.385040"); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void menu_click() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void menu_link() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } /***************** common message *********************/ @@ -144,7 +29,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -163,7 +48,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -182,7 +67,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -202,7 +87,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -221,7 +106,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -242,7 +127,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -262,7 +147,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java new file mode 100644 index 00000000..8f6a130f --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java @@ -0,0 +1,114 @@ +package com.foxinmy.weixin4j.test; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.model.MpArticle; +import com.foxinmy.weixin4j.type.MediaType; + +/** + * 群发消息 + * + * @className MpNewsTest + * @author jy + * @date 2014年4月27日 + * @since JDK 1.7 + * @see + */ +public class MessageMassTest { + private WeixinProxy weixinProxy; + + @Before + public void init() { + this.weixinProxy = new WeixinProxy(); + } + + @Test + public void uploadArticle() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.uploadArticle(articles); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void uploadVideo() { + try { + weixinProxy.uploadVideo("mediaId", "title", "desc"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massByGroup() { + try { + weixinProxy.massByGroup("123", MediaType.image, "groupId"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massByOpenIds() { + try { + weixinProxy.massByOpenIds("123", MediaType.image, "openIds"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massArticleByGroup() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.massArticleByGroup(articles, "0"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massArticleByOpenIds() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.massArticleByOpenIds(articles, + "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void deleteMass() { + try { + weixinProxy.deleteMassNews("34182"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java index f3be10bb..59aed8de 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java @@ -7,6 +7,7 @@ import org.junit.Test; import com.foxinmy.weixin4j.WeixinProxy; import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.msg.model.Music; import com.foxinmy.weixin4j.msg.notify.ArticleNotify; import com.foxinmy.weixin4j.msg.notify.BaseNotify; import com.foxinmy.weixin4j.msg.notify.ImageNotify; @@ -41,27 +42,29 @@ public class MessageNotifyTest { @Test public void image() { - ImageNotify notify = new ImageNotify("123", "to"); + ImageNotify notify = new ImageNotify("to"); + notify.pushMediaId("123"); System.out.println(notify.toJson()); } @Test public void voice() { - VoiceNotify notify = new VoiceNotify("123", "to"); + VoiceNotify notify = new VoiceNotify("to"); + notify.pushMediaId("123"); System.out.println(notify.toJson()); } @Test public void video() { VideoNotify notify = new VideoNotify("to"); - notify.pushVideo("123", "title", "desc"); + notify.pushVideo("123","m123"); System.out.println(notify.toJson()); } @Test public void music() { MusicNotify notify = new MusicNotify("to"); - notify.pushMusic("title", "desc", "url", "hqUrl", "mediaId"); + notify.pushMusic("url", "hqUrl", "mediaId"); System.out.println(notify.toJson()); } @@ -74,16 +77,27 @@ public class MessageNotifyTest { } @Test - public void send() { - BaseNotify t = new TextNotify("哈哈哈哈", "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + public void send1() { + BaseNotify notify = new TextNotify("哈哈哈哈", "owGBft_vbBbOaQOmpEUE4xDLeRSU"); try { - weixinProxy.sendNotify(t); + weixinProxy.sendNotify(notify); String mediaId = weixinProxy.uploadMedia(new File("D:\\test.jpg"), MediaType.image); - t = new ImageNotify(mediaId, "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + ImageNotify t = new ImageNotify("owGBft_vbBbOaQOmpEUE4xDLeRSU"); + t.pushMediaId(mediaId); weixinProxy.sendNotify(t); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); } } + + @Test + public void send2() { + try { + weixinProxy.sendNotify("to",new Music("thumbMediaId")); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java index 00021aa0..ddb309d4 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java @@ -1,7 +1,9 @@ package com.foxinmy.weixin4j.test; +import org.junit.Before; import org.junit.Test; +import com.foxinmy.weixin4j.msg.BaseMessage; import com.foxinmy.weixin4j.msg.TextMessage; import com.foxinmy.weixin4j.msg.out.ArticleMessage; import com.foxinmy.weixin4j.msg.out.ImageMessage; @@ -17,56 +19,52 @@ import com.foxinmy.weixin4j.msg.out.VoiceMessage; * @since JDK 1.7 */ public class MessageOutTest { + private BaseMessage inMessage; + + @Before + public void init() { + this.inMessage = new TextMessage(); + this.inMessage.setFromUserName("fromusername"); + this.inMessage.setToUserName("tousername"); + } + @Test public void text() { - TextMessage message = new TextMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.setContent("text message"); + TextMessage message = new TextMessage("text", inMessage); System.out.println(message.toXml()); } @Test public void image() { - ImageMessage message = new ImageMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + ImageMessage message = new ImageMessage(inMessage); message.pushMediaId("mediaId"); System.out.println(message.toXml()); } @Test public void voice() { - VoiceMessage message = new VoiceMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + VoiceMessage message = new VoiceMessage(inMessage); message.pushMediaId("mediaId"); System.out.println(message.toXml()); } - + @Test public void video() { - VideoMessage message = new VideoMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.pushVideo("mediaId", "title", "title"); + VideoMessage message = new VideoMessage(inMessage); + message.pushVideo("mediaId"); System.out.println(message.toXml()); } - + @Test public void music() { - MusicMessage message = new MusicMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.pushMusic("title", "desc", "url", "hqurl", "mediaId"); + MusicMessage message = new MusicMessage(inMessage); + message.pushMusic("mediaId"); System.out.println(message.toXml()); } - + @Test public void article() { - ArticleMessage message = new ArticleMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + ArticleMessage message = new ArticleMessage(inMessage); message.pushArticle("title1", "desc1", "picUrl1", "url1"); message.pushArticle("title2", "desc2", "picUrl2", "url2"); System.out.println(message.toXml()); diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java new file mode 100644 index 00000000..b8165a91 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java @@ -0,0 +1,30 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Before; +import org.junit.Test; + +import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.msg.out.TemplateMessage; + +public class MessageTemplTest { + private WeixinProxy weixinProxy; + + @Before + public void init() { + this.weixinProxy = new WeixinProxy(); + } + + @Test + public void test() { + TemplateMessage tplMessage = new TemplateMessage("touser", + "template_id", "url"); + tplMessage.pushData("name", "fox"); + System.out.print(tplMessage.toJson()); + try { + System.out.print(weixinProxy.sendTplMessage(tplMessage)); + } catch (WeixinException e) { + System.out.println(e.getErrorMsg()); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java b/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java deleted file mode 100644 index 5fa1ec67..00000000 --- a/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.foxinmy.weixin4j.test; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; - -import com.foxinmy.weixin4j.WeixinProxy; -import com.foxinmy.weixin4j.exception.WeixinException; -import com.foxinmy.weixin4j.model.MpArticle; -import com.foxinmy.weixin4j.type.MediaType; - -/** - * 群发消息 - * - * @className MpNewsTest - * @author jy - * @date 2014年4月27日 - * @since JDK 1.7 - * @see - */ -public class MpNewsTest { - private WeixinProxy weixinProxy; - - @Before - public void init() { - this.weixinProxy = new WeixinProxy(); - } - - @Test - public void massByGroup(){ - List articles = new ArrayList(); - try { - String thumbMediaId = weixinProxy.uploadMedia(new File("/tmp/test.jpg"), MediaType.image); - articles.add(new MpArticle(thumbMediaId, "title", "content")); - weixinProxy.massNewsByGroup(articles, "0"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } - - @Test - public void massByOpenIds(){ - List articles = new ArrayList(); - try { - String thumbMediaId = weixinProxy.uploadMedia(new File("/tmp/test.jpg"), MediaType.image); - articles.add(new MpArticle(thumbMediaId, "title", "content")); - weixinProxy.massNewsByOpenIds(articles, "owGBft_vbBbOaQOmpEUE4xDLeRSU"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } - - @Test - public void deleteMass(){ - try { - weixinProxy.deleteMassNews("34182"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } -} diff --git a/src/test/java/com/foxinmy/weixin4j/test/QRTest.java b/src/test/java/com/foxinmy/weixin4j/test/QRTest.java index 11934fa9..f18d1aa7 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/QRTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/QRTest.java @@ -25,10 +25,10 @@ public class QRTest { @Test public void temp_qr() { - QRParameter qr = new QRParameter(1200, QRType.QR_SCENE, 1); + QRParameter qr = new QRParameter(1200, QRType.TEMPORARY, 2); try { System.out.println(qr.toJson()); - weixinProxy.getQR(qr); + System.out.println(weixinProxy.getQR(qr)); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); @@ -37,10 +37,10 @@ public class QRTest { @Test public void forever_qr() { - QRParameter qr = new QRParameter(QRType.QR_LIMIT_SCENE, 1); + QRParameter qr = new QRParameter(QRType.PERMANENCE, 1); try { System.out.println(qr.toJson()); - weixinProxy.getQR(qr); + System.out.println(weixinProxy.getQR(qr)); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java b/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java index 37d549d7..a2f8a266 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java @@ -3,7 +3,8 @@ package com.foxinmy.weixin4j.test; import org.junit.Before; import org.junit.Test; -import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.api.token.FileTokenApi; +import com.foxinmy.weixin4j.api.token.TokenApi; import com.foxinmy.weixin4j.exception.WeixinException; /** @@ -14,17 +15,17 @@ import com.foxinmy.weixin4j.exception.WeixinException; * @since JDK 1.7 */ public class TokenTest { - private WeixinProxy weixinProxy; + private TokenApi tokenApi; @Before public void init() { - weixinProxy = new WeixinProxy(); + tokenApi = new FileTokenApi(); } @Test public void getToken() { try { - System.out.println(weixinProxy.getToken()); + System.out.println(tokenApi.getToken()); } catch (WeixinException e) { e.printStackTrace(); }
articles; public List getArticles() { return this.articles; @@ -44,39 +44,55 @@ public class ArticleMessage extends BaseMessage { return; } if (this.articles == null) { - this.articles = new LinkedList(); + this.articles = new LinkedList(); } this.articles.add(new Article(title, desc, picUrl, url)); - count ++; + count++; } - @XStreamAlias("item") - private static class Article { - @XStreamAlias("Title") - private String title; // 图文消息标题 - @XStreamAlias("Description") - private String desc; // 图文消息描述 - @XStreamAlias("PicUrl") - private String picUrl; // 图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200 - @XStreamAlias("Url") - private String url; // 点击图文消息跳转链接 - - public Article(String title, String desc, String picUrl, String url) { - this.title = title; - this.desc = desc; - this.picUrl = picUrl; - this.url = url; + public void pushFirstArticle(String title, String desc, String picUrl, + String url) { + if (this.articles == null) { + this.articles = new LinkedList(); } + this.articles.addFirst(new Article(title, desc, picUrl, url)); + } - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Article ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,picUrl=").append(picUrl); - sb.append(" ,url=").append(url).append(")"); - return sb.toString(); + public void pushLastArticle(String title, String desc, String picUrl, + String url) { + if (this.articles == null) { + this.articles = new LinkedList(); } + this.articles.addLast(new Article(title, desc, picUrl, url)); + } + + public Article removeLastArticle() { + if (this.articles != null) { + return this.articles.removeLast(); + } + return null; + } + + 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() { + 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 diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java index 2da50a01..fb58ecb8 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java @@ -1,38 +1,50 @@ 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 回复图片消息 + * @see 回复图片消息 + * @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() { - super(MessageType.image); + public ImageMessage(BaseMessage inMessage) { + super(MessageType.image, inMessage); super.getMsgType().setMessageClass(ImageMessage.class); } + 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(); - this.image.mediaId = mediaId; + this.image = new Image(mediaId); } - private static class Image { - @XStreamAlias("MediaId") - private String mediaId; + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Image.class, "mediaId"); + return xstream.toXML(this); } @Override @@ -41,7 +53,7 @@ public class ImageMessage extends BaseMessage { sb.append("[ImageMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,mediaId=").append(this.image.mediaId); + sb.append(" ,mediaId=").append(this.image.getMediaId()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java index c790b9ac..419f32d6 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java @@ -1,74 +1,61 @@ 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 回复音乐消息 + * @see 回复音乐消息 + * @see com.foxinmy.weixin4j.msg.model.Music * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class MusicMessage extends BaseMessage { private static final long serialVersionUID = 4384403772658796395L; - public MusicMessage() { - super(MessageType.music); + public MusicMessage(BaseMessage inMessage) { + super(MessageType.music, inMessage); } @XStreamAlias("Music") private Music music; - public Music getMusic() { - return this.music; + public void pushMusic(String mediaId) { + this.music = new Music(mediaId); } - public void pushMusic(String title, String desc, String url, String hqUrl, String mediaId) { - this.music = new Music(); - this.music.thumbMediaId = mediaId; - this.music.desc = desc; - this.music.hqMusicUrl = hqUrl; - this.music.MusicURL = url; - this.music.title = title; + public void setMusic(Music music) { + this.music = music; } - private static class Music { - @XStreamAlias("Title") - private String title; // 音乐标题 - @XStreamAlias("Description") - private String desc; // 音乐描述 - @XStreamAlias("MusicURL") - private String MusicURL; // 音乐链接 - @XStreamAlias("HQMusicUrl") - private String hqMusicUrl; // 高质量音乐链接,WIFI环境优先使用该链接播放音乐 - @XStreamAlias("ThumbMediaId") - private String thumbMediaId; // 缩略图的媒体id,通过上传多媒体文件,得到的id - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Music ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,musicURL=").append(MusicURL); - sb.append(" ,hqMusicUrl=").append(hqMusicUrl); - sb.append(" ,thumbMediaId=").append(thumbMediaId).append(")"); - return sb.toString(); - } + @Override + public String 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(getMusic().toString()); + sb.append(" ,music=").append(music.toString()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java new file mode 100644 index 00000000..3721504b --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java @@ -0,0 +1,117 @@ +package com.foxinmy.weixin4j.msg.out; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +import com.alibaba.fastjson.JSON; + +/** + * 模板消息 + * + * @className TemplateMessage + * @author jy + * @date 2014年9月29日 + * @since JDK 1.7 + * @see + */ +public class TemplateMessage implements Serializable { + + private static final long serialVersionUID = 7950608393821661436L; + + private String touser; + private String template_id; + private String url; + private String topcolor = "#FF0000"; + private Map data; + + public void pushData(String key, String value) { + this.data.put(key, new Item(value)); + } + + public TemplateMessage(String touser, String template_id, String url) { + this.touser = touser; + this.template_id = template_id; + this.url = url; + this.data = new HashMap(); + } + + private static class Item implements Serializable { + private static final long serialVersionUID = 1L; + private String value; + private String color; + + public Item(String value) { + this(value, "#173177"); + } + + public Item(String value, String color) { + this.value = value; + this.color = color; + } + + public String getValue() { + return value; + } + + public String getColor() { + return color; + } + + @Override + public String toString() { + return "$ [value=" + getValue() + ", color=" + getColor() + "]"; + } + } + + public String getTouser() { + return touser; + } + + public void setTouser(String touser) { + this.touser = touser; + } + + public String getTemplate_id() { + return template_id; + } + + public void setTemplate_id(String template_id) { + this.template_id = template_id; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getTopcolor() { + return topcolor; + } + + public void setTopcolor(String topcolor) { + this.topcolor = topcolor; + } + + public Map getData() { + return data; + } + + public void setData(Map data) { + this.data = data; + } + + @Override + public String toString() { + return "TemplateMessage [touser=" + touser + ", template_id=" + + template_id + ", url=" + url + ", topcolor=" + topcolor + + ", data=" + data + "]"; + } + + public String toJson() { + return JSON.toJSONString(this); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java new file mode 100644 index 00000000..b89621aa --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java @@ -0,0 +1,25 @@ +package com.foxinmy.weixin4j.msg.out; + +import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.type.MessageType; + +/** + * 转移消息到多客服端消息 + * + * @className TransferMessage + * @author jy.hu + * @date 2014年6月28日 + * @since JDK 1.7 + * @see 多客服转移消息 + * @see com.foxinmy.weixin4j.msg.BaseMessage + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + */ +public class TransferMessage extends BaseMessage { + + private static final long serialVersionUID = -5479496746108594940L; + + public TransferMessage(BaseMessage inMessage) { + super(MessageType.transfer_customer_service,inMessage); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java index d16c5a12..d6cdfc91 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java @@ -1,58 +1,52 @@ package com.foxinmy.weixin4j.msg.out; import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.msg.model.Video; import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 回复视频消息 + * * @className VideoMessage * @author jy.hu * @date 2014年4月6日 * @since JDK 1.7 - * @see 回复视频消息 + * @see 回复视频消息 + * @see com.foxinmy.weixin4j.msg.model.Video * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class VideoMessage extends BaseMessage { private static final long serialVersionUID = -1013075358679078381L; - public VideoMessage() { - super(MessageType.video); + public VideoMessage(BaseMessage inMessage) { + super(MessageType.video, inMessage); super.getMsgType().setMessageClass(VideoMessage.class); } @XStreamAlias("Video") private Video video; - public Video getVideo() { - return this.video; + public void pushVideo(String mediaId) { + this.video = new Video(mediaId); } - public void pushVideo(String mediaId, String title, String desc) { - this.video = new Video(); - this.video.desc = desc; - this.video.mediaId = mediaId; - this.video.title = title; + public void setVideo(Video video) { + this.video = video; } - private static class Video { - @XStreamAlias("MediaId") - private String mediaId; - @XStreamAlias("Title") - private String title; - @XStreamAlias("Description") - private String desc; - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Video mediaId=").append(mediaId); - sb.append(" ,title=").append(title); - sb.append(" ,desc=").append(desc).append(")"); - return super.toString(); - } + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Video.class, "mediaId"); + xstream.aliasField("Title", Video.class, "title"); + xstream.aliasField("Description", Video.class, "desc"); + xstream.omitField(Video.class, "thumbMediaId"); + return xstream.toXML(this); } @Override @@ -61,7 +55,7 @@ public class VideoMessage extends BaseMessage { sb.append("[VideoMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,video=").append(getVideo().toString()); + sb.append(" ,video=").append(video.toString()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java index 93052907..dcac1046 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java @@ -1,53 +1,60 @@ package com.foxinmy.weixin4j.msg.out; import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.msg.model.Voice; import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 语音消息 + * * @className VoiceMessage * @author jy.hu * @date 2014年3月23日 * @since JDK 1.7 - * @see 回复语音消息 + * @see 回复语音消息 + * @see com.foxinmy.weixin4j.msg.model.Voice * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class VoiceMessage extends BaseMessage { private static final long serialVersionUID = -7944926238652243793L; - public VoiceMessage() { - super(MessageType.voice); + public VoiceMessage(BaseMessage inMessage) { + super(MessageType.voice, inMessage); super.getMsgType().setMessageClass(VoiceMessage.class); } + + public VoiceMessage(String mediaId, BaseMessage inMessage) { + super(MessageType.voice, inMessage); + super.getMsgType().setMessageClass(VoiceMessage.class); + this.pushMediaId(mediaId); + } + @XStreamAlias("Voice") private Voice voice; - - public Voice getVocie() { - return voice; + + public void pushMediaId(String mediaId) { + this.voice = new Voice(mediaId); } - public void pushMediaId(String mediaId){ - this.voice = new Voice(); - this.voice.setMediaId(mediaId); - } - - private static class Voice { - @XStreamAlias("MediaId") - private String mediaId; - - private void setMediaId(String mediaId) { - this.mediaId = mediaId; - } + + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Voice.class, "mediaId"); + return xstream.toXML(this); } + @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("[VoiceMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,mediaId=").append(getVocie().mediaId); + sb.append(" ,mediaId=").append(voice.getMediaId()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java b/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java new file mode 100644 index 00000000..cf2ab68e --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java @@ -0,0 +1,55 @@ +package com.foxinmy.weixin4j.type; + +/** + * 自定义菜单类型 + * scancode_push 到 location_selec + * 仅支持微信iPhone5.4.1以上版本,和Android5 .4以上版本的微信用户 旧版本微信用户点击后将没有回应 + * 开发者也不能正常接收到事件推送。 + * + * @className ButtonType + * @author jy + * @date 2014年9月30日 + * @since JDK 1.7 + * @see 按钮类型 + */ +public enum ButtonType { + /** + * 点击推事件 用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event + * 的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互; + */ + click, + /** + * 跳转URL 用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的网页URL,可与网页授权获取用户基本信息接口结合,获得用户基本信息。 + */ + view, + /** + * 扫码推事件 用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后显示扫描结果(如果是URL,将进入URL),且会将扫码的结果传给开发者, + * 开发者可以下发消息。 + */ + scancode_push, + /** + * 扫码推事件且弹出“消息接收中”提示框用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后,将扫码的结果传给开发者,同时收起扫一扫工具, + * 然后弹出“消息接收中”提示框,随后可能会收到开发者下发的消息。 + */ + scancode_waitmsg, + /** + * 弹出系统拍照发图用户点击按钮后,微信客户端将调起系统相机,完成拍照操作后,会将拍摄的相片发送给开发者,并推送事件给开发者,同时收起系统相机, + * 随后可能会收到开发者下发的消息。 + */ + pic_sysphoto, + /** + * 弹出拍照或者相册发图用户点击按钮后,微信客户端将弹出选择器供用户选择“拍照”或者“从手机相册选择”。用户选择后即走其他两种流程。 + */ + pic_photo_or_albu, + /** + * 弹出微信相册发图器用户点击按钮后,微信客户端将调起微信相册,完成选择操作后,将选择的相片发送给开发者的服务器,并推送事件给开发者,同时收起相册, + * 随后可能会收到开发者下发的消息。 + */ + pic_weixin, + /** + * 弹出地理位置选择器用户点击按钮后,微信客户端将调起地理位置选择工具,完成选择操作后,将选择的地理位置发送给开发者的服务器,同时收起位置选择工具, + * 随后可能会收到开发者下发的消息。 + */ + location_select; +} diff --git a/src/main/java/com/foxinmy/weixin4j/type/EventType.java b/src/main/java/com/foxinmy/weixin4j/type/EventType.java index a8e864b8..bc85ce90 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/EventType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/EventType.java @@ -3,21 +3,36 @@ package com.foxinmy.weixin4j.type; import com.foxinmy.weixin4j.msg.event.EventMessage; import com.foxinmy.weixin4j.msg.event.LocationEventMessage; import com.foxinmy.weixin4j.msg.event.MassEventMessage; -import com.foxinmy.weixin4j.msg.event.MenuEventMessage; import com.foxinmy.weixin4j.msg.event.ScanEventMessage; import com.foxinmy.weixin4j.msg.event.ScribeEventMessage; +import com.foxinmy.weixin4j.msg.event.TemplatesendjobfinishMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuLocationEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuPhotoEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuScanEventMessage; /** - * * 事件类型 - * @author jy.hu - * + * + * @className EventType + * @author jy + * @date 2014年9月30日 + * @since JDK 1.7 + * @see */ public enum EventType { - subscribe(ScribeEventMessage.class), unsubscribe(ScribeEventMessage.class), - scan(ScanEventMessage.class),click(MenuEventMessage.class),view(MenuEventMessage.class), - location(LocationEventMessage.class),MASSSENDJOBFINISH(MassEventMessage.class); - + subscribe(ScribeEventMessage.class), unsubscribe(ScribeEventMessage.class), scan( + ScanEventMessage.class), scancode_push(MenuScanEventMessage.class), view( + MenuEventMessage.class), scancode_waitmsg( + MenuScanEventMessage.class), pic_sysphoto( + MenuPhotoEventMessage.class), pic_photo_or_album( + MenuPhotoEventMessage.class), pic_weixin( + MenuPhotoEventMessage.class), location_select( + MenuLocationEventMessage.class), click(MenuEventMessage.class), location( + LocationEventMessage.class), massendjobfinish( + MassEventMessage.class), templatesendjobfinish( + TemplatesendjobfinishMessage.class); + private Class extends EventMessage> eventClass; EventType(Class extends EventMessage> eventClass) { diff --git a/src/main/java/com/foxinmy/weixin4j/type/MediaType.java b/src/main/java/com/foxinmy/weixin4j/type/MediaType.java index 1f567181..322ba3ce 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/MediaType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/MediaType.java @@ -6,13 +6,20 @@ package com.foxinmy.weixin4j.type; * 语音(voice):256K,播放长度不超过60s,支持AMR\MP3格式 * 视频(video):1MB,支持MP4格式 * 缩略图(thumb):64KB,支持JPG格式 - * 媒体文件在后台保存时间为3天,即3天后media_id失效 + * + * 媒体文件在后台保存时间为3天,即3天后media_id失效 + * + * * @author jy.hu * @date 2014年4月2日 * @since JDK 1.7 */ public enum MediaType { - image("image/jpeg",".jpg"), voice("binary/octet-stream","amr"), vedio("binary/octet-stream","mp4"), thumb("image/jpeg","jpg"); + image("image/jpeg", "jpg"), voice("binary/octet-stream", "amr"), vedio( + "binary/octet-stream", "mp4"), thumb("image/jpeg", "jpg"), text( + "application/json", ""), music("binary/octet-stream", "mp3"), news( + "application/json", ""), mpnews("application/json", ""), mpvideo( + "binary/octet-stream", ""); MediaType(String contentType, String formatType) { this.contentType = contentType; @@ -26,6 +33,7 @@ public enum MediaType { } private String formatType; + public String getFormatType() { return formatType; } diff --git a/src/main/java/com/foxinmy/weixin4j/type/MessageType.java b/src/main/java/com/foxinmy/weixin4j/type/MessageType.java index 21a7b6dc..a883d993 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/MessageType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/MessageType.java @@ -10,6 +10,7 @@ import com.foxinmy.weixin4j.msg.in.VideoMessage; import com.foxinmy.weixin4j.msg.in.VoiceMessage; import com.foxinmy.weixin4j.msg.out.ArticleMessage; import com.foxinmy.weixin4j.msg.out.MusicMessage; +import com.foxinmy.weixin4j.msg.out.TransferMessage; /** * @@ -20,9 +21,13 @@ import com.foxinmy.weixin4j.msg.out.MusicMessage; */ public enum MessageType { // 接收到的消息类型 - text(TextMessage.class), image(ImageMessage.class), voice(VoiceMessage.class), video(VideoMessage.class), location(LocationMessage.class), link(LinkMessage.class), event(EventMessage.class), + text(TextMessage.class), image(ImageMessage.class), voice( + VoiceMessage.class), video(VideoMessage.class), location( + LocationMessage.class), link(LinkMessage.class), event( + EventMessage.class), // 发送的消息类型 - music(MusicMessage.class), news(ArticleMessage.class); + music(MusicMessage.class), news(ArticleMessage.class), transfer_customer_service( + TransferMessage.class); private Class extends BaseMessage> messageClass; MessageType(Class extends BaseMessage> messageClass) { diff --git a/src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java b/src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java similarity index 91% rename from src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java rename to src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java index f428c33b..b419bd1c 100644 --- a/src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java +++ b/src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java @@ -8,8 +8,8 @@ import java.util.regex.Pattern; import com.foxinmy.weixin4j.WeixinProxy; -public class WeixinConfig { - public WeixinConfig() { +public class ConfigUtil { + public ConfigUtil() { } private static Properties props = new Properties(); @@ -38,7 +38,6 @@ public class WeixinConfig { m.appendTail(sb); return sb.toString(); } - public static void main(String[] args) { System.out.println(getValue("api_token_uri")); } diff --git a/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java b/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java new file mode 100644 index 00000000..60eae107 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java @@ -0,0 +1,67 @@ +package com.foxinmy.weixin4j.util; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.Writer; +import java.nio.charset.Charset; + +/** + * IOUtil + * + * @className IOUtil + * @author jy.hu + * @date 2014年9月22日 + * @since JDK 1.7 + * @see org.apache.commons.io.IOUtils + */ +public class IOUtil { + + private static final int EOF = -1; + private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; + + public static byte[] toByteArray(Reader input) throws IOException { + return toByteArray(input, Charset.defaultCharset()); + } + + public static byte[] toByteArray(Reader input, Charset encoding) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + copy(input, output, encoding); + return output.toByteArray(); + } + + public static void copy(Reader input, OutputStream output, Charset encoding) throws IOException { + OutputStreamWriter out = new OutputStreamWriter(output, encoding); + copyLarge(input, out, new char[DEFAULT_BUFFER_SIZE]); + out.flush(); + } + + public static byte[] toByteArray(InputStream input) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + copyLarge(input, output, new byte[DEFAULT_BUFFER_SIZE]); + return output.toByteArray(); + } + + private static long copyLarge(InputStream input, OutputStream output, byte[] buffer) throws IOException { + long count = 0; + int n = 0; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } + + private static long copyLarge(Reader input, Writer output, char[] buffer) throws IOException { + long count = 0; + int n = 0; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java b/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java new file mode 100644 index 00000000..82a23ef3 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java @@ -0,0 +1,135 @@ +package com.foxinmy.weixin4j.util; + +import java.io.InputStream; +import java.util.Arrays; + +import org.apache.commons.codec.digest.DigestUtils; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.DocumentHelper; +import org.dom4j.io.SAXReader; +import org.jsoup.helper.StringUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.type.EventType; +import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; + +public class MessageUtil { + + private final static Logger log = LoggerFactory.getLogger(MessageUtil.class); + + /** + * 验证微信签名 + * + * @param echostr + * 随机字符串 + * @param timestamp + * 时间戳 + * @param nonce + * 随机数 + * @param signature + * 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数 + * @return 开发者通过检验signature对请求进行相关校验。若确认此次GET请求来自微信服务器 + * 请原样返回echostr参数内容,则接入生效 成为开发者成功,否则接入失败 + * @see 接入指南 + */ + public static String signature(String echostr, String timestamp, String nonce, String signature) { + String app_token = ConfigUtil.getValue("app_token"); + if (StringUtil.isBlank(app_token)) { + log.error("signature fail : token is null!"); + return null; + } + if (StringUtil.isBlank(echostr) || StringUtil.isBlank(timestamp) || StringUtil.isBlank(nonce)) { + log.error("signature fail : invalid parameter!"); + return null; + } + String _signature = null; + try { + String[] a = { app_token, timestamp, nonce }; + Arrays.sort(a); + StringBuilder sb = new StringBuilder(3); + for (String str : a) { + sb.append(str); + } + _signature = DigestUtils.sha1Hex(sb.toString()); + } catch (Exception e) { + log.error("signature error", e); + } + if (signature.equals(_signature)) { + return echostr; + } else { + log.error("signature fail : invalid signature!"); + return null; + } + } + + /** + * xml消息转换为消息对象 + * + * 微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次 + * + * + * @param xml + * 消息字符串 + * @return 消息对象 + * @throws DocumentException + * @see 验证消息的合法性 + * @see 普通消息 + * @see 事件触发 + * @see com.foxinmy.weixin4j.type.MessageType + * @see com.feican.weixin.msg.BaeMessage + * @see com.foxinmy.weixin4j.msg.TextMessage + * @see com.foxinmy.weixin4j.msg.in.ImageMessage + * @see com.foxinmy.weixin4j.msg.in.VoiceMessage + * @see com.foxinmy.weixin4j.msg.in.VideoMessage + * @see com.foxinmy.weixin4j.msg.in.LocationMessage + * @see com.foxinmy.weixin4j.msg.in.LinkMessage + * @see com.foxinmy.weixin4j.msg.event.ScribeEventMessage + * @see com.foxinmy.weixin4j.msg.event.ScanEventMessage + * @see com.foxinmy.weixin4j.msg.event.LocationEventMessage + * @see com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage + */ + public static BaseMessage xml2msg(String xml) throws DocumentException { + if (StringUtil.isBlank(xml)) + return null; + Document doc = DocumentHelper.parseText(xml); + String type = doc.selectSingleNode("/xml/MsgType").getStringValue(); + if (StringUtil.isBlank(type)) { + return null; + } + XStream xstream = new XStream(); + MessageType messageType = MessageType.valueOf(type.toLowerCase()); + Class extends BaseMessage> messageClass = messageType.getMessageClass(); + if (messageType == MessageType.event) { + type = doc.selectSingleNode("/xml/Event").getStringValue(); + messageClass = EventType.valueOf(type.toLowerCase()).getEventClass(); + } + xstream.alias("xml", messageClass); + xstream.ignoreUnknownElements(); + xstream.autodetectAnnotations(true); + xstream.processAnnotations(messageClass); + return xstream.fromXML(doc.asXML(), messageClass); + } + + /** + * xml消息转换为消息对象 + * + * @param inputStream + * 带消息字符串的输入流 + * @return 消息对象 + * @throws DocumentException + * @see {@link com.foxinmy.weixin4j.WeixinProxy#xml2msg(String)} + */ + public static BaseMessage xml2msg(InputStream inputStream) throws DocumentException { + SAXReader reader = new SAXReader(); + Document doc = reader.read(inputStream); + return xml2msg(doc.asXML()); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java b/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java deleted file mode 100644 index 19fd87e4..00000000 --- a/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.foxinmy.weixin4j.util; - -public class WeixinUtil { - - public static boolean isBlank(String str) { - return str == null || str.isEmpty(); - } -} diff --git a/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java b/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java index 5c0186c6..4a811a6c 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java @@ -9,7 +9,7 @@ import org.junit.Test; import com.foxinmy.weixin4j.WeixinProxy; import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.model.Button; -import com.foxinmy.weixin4j.model.Button.BtnType; +import com.foxinmy.weixin4j.type.ButtonType; /** * 自定义菜单测试 @@ -31,7 +31,7 @@ public class ButtonTest { List btnList = new ArrayList(); Button b = new Button("test"); - b.setType(BtnType.click); + b.setType(ButtonType.click); b.setKey("123"); btnList.add(b); diff --git a/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java b/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java index 8b78305e..bb6bec88 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java @@ -50,7 +50,7 @@ public class GroupTest { @Test public void getid() { try { - System.out.println(weixinProxy.findGroupByOpenId("owGBft_vbBbOaQOmpEUE4xDLeRSU")); + System.out.println(weixinProxy.getGroupByOpenId("owGBft_vbBbOaQOmpEUE4xDLeRSU")); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); diff --git a/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java b/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java new file mode 100644 index 00000000..6d34a733 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java @@ -0,0 +1,22 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Test; + +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.http.HttpRequest; + +public class HttpTest { + private static HttpRequest request; + static { + request = new HttpRequest(); + } + + @Test + public void test(){ + try { + System.out.println(request.get("http://www.baidu.com")); + } catch (WeixinException e) { + e.printStackTrace(); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java b/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java index f907fa3d..d54e649b 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java @@ -31,7 +31,7 @@ public class MediaTest { File file = new File("D:\\test.jpg"); try { System.out.println(weixinProxy.uploadMedia(file, MediaType.image)); - //usAxLEJxFXAjXVlLu_BSw0GvS2YEEoGeelRBybNZBGvMsdxiIcD1F9yBWYd9jVZx + //vvU_AUtovWyfAxQ8J1DsCoNMtK6U_bUmTpe6lpINUOVRLvt_7rtO4zxzBpPgkmay } catch (WeixinException e) { System.out.println(e.getErrorMsg()); } @@ -40,7 +40,7 @@ public class MediaTest { @Test public void download() { try { - System.out.println(weixinProxy.downloadMedia("usAxLEJxFXAjXVlLu_BSw0GvS2YEEoGeelRBybNZBGvMsdxiIcD1F9yBWYd9jVZx", MediaType.image)); + System.out.println(weixinProxy.downloadMedia("vvU_AUtovWyfAxQ8J1DsCoNMtK6U_bUmTpe6lpINUOVRLvt_7rtO4zxzBpPgkmay", MediaType.image)); } catch (WeixinException e) { System.out.println(e.getErrorMsg()); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java new file mode 100644 index 00000000..2cd36584 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java @@ -0,0 +1,194 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Test; + +import com.foxinmy.weixin4j.util.MessageUtil; + +/** + * 接收事件消息格式测试 + * + * @author jy.hu + * @date 2014年3月24日 + * @since JDK 1.7 + */ +public class MessageEventInTest { + + private StringBuilder xmlSb = new StringBuilder(); + + /***************** event message *********************/ + @Test + public void scribe() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void scan() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void scan_scribe() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void location1() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("23.137466"); + xmlSb.append("113.352425"); + xmlSb.append("119.385040"); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_click() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_link() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_scan() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_photo() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("1"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_location() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java index 39269754..fdd40042 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java @@ -1,134 +1,19 @@ package com.foxinmy.weixin4j.test; -import org.junit.Before; import org.junit.Test; -import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.util.MessageUtil; /** - * 接收消息格式测试 + * 接受一般消息格式测试 + * * @author jy.hu * @date 2014年3月24日 * @since JDK 1.7 */ public class MessageInTest { + private StringBuilder xmlSb = new StringBuilder(); - private WeixinProxy weixinProxy; - - @Before - public void init(){ - weixinProxy = new WeixinProxy(); - } - - /***************** event message *********************/ - @Test - public void scribe() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void scan() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - @Test - public void scan_scribe() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void location1() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("23.137466"); - xmlSb.append("113.352425"); - xmlSb.append("119.385040"); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void menu_click() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void menu_link() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } /***************** common message *********************/ @@ -144,7 +29,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -163,7 +48,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -182,7 +67,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -202,7 +87,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -221,7 +106,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -242,7 +127,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -262,7 +147,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java new file mode 100644 index 00000000..8f6a130f --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java @@ -0,0 +1,114 @@ +package com.foxinmy.weixin4j.test; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.model.MpArticle; +import com.foxinmy.weixin4j.type.MediaType; + +/** + * 群发消息 + * + * @className MpNewsTest + * @author jy + * @date 2014年4月27日 + * @since JDK 1.7 + * @see + */ +public class MessageMassTest { + private WeixinProxy weixinProxy; + + @Before + public void init() { + this.weixinProxy = new WeixinProxy(); + } + + @Test + public void uploadArticle() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.uploadArticle(articles); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void uploadVideo() { + try { + weixinProxy.uploadVideo("mediaId", "title", "desc"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massByGroup() { + try { + weixinProxy.massByGroup("123", MediaType.image, "groupId"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massByOpenIds() { + try { + weixinProxy.massByOpenIds("123", MediaType.image, "openIds"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massArticleByGroup() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.massArticleByGroup(articles, "0"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massArticleByOpenIds() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.massArticleByOpenIds(articles, + "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void deleteMass() { + try { + weixinProxy.deleteMassNews("34182"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java index f3be10bb..59aed8de 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java @@ -7,6 +7,7 @@ import org.junit.Test; import com.foxinmy.weixin4j.WeixinProxy; import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.msg.model.Music; import com.foxinmy.weixin4j.msg.notify.ArticleNotify; import com.foxinmy.weixin4j.msg.notify.BaseNotify; import com.foxinmy.weixin4j.msg.notify.ImageNotify; @@ -41,27 +42,29 @@ public class MessageNotifyTest { @Test public void image() { - ImageNotify notify = new ImageNotify("123", "to"); + ImageNotify notify = new ImageNotify("to"); + notify.pushMediaId("123"); System.out.println(notify.toJson()); } @Test public void voice() { - VoiceNotify notify = new VoiceNotify("123", "to"); + VoiceNotify notify = new VoiceNotify("to"); + notify.pushMediaId("123"); System.out.println(notify.toJson()); } @Test public void video() { VideoNotify notify = new VideoNotify("to"); - notify.pushVideo("123", "title", "desc"); + notify.pushVideo("123","m123"); System.out.println(notify.toJson()); } @Test public void music() { MusicNotify notify = new MusicNotify("to"); - notify.pushMusic("title", "desc", "url", "hqUrl", "mediaId"); + notify.pushMusic("url", "hqUrl", "mediaId"); System.out.println(notify.toJson()); } @@ -74,16 +77,27 @@ public class MessageNotifyTest { } @Test - public void send() { - BaseNotify t = new TextNotify("哈哈哈哈", "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + public void send1() { + BaseNotify notify = new TextNotify("哈哈哈哈", "owGBft_vbBbOaQOmpEUE4xDLeRSU"); try { - weixinProxy.sendNotify(t); + weixinProxy.sendNotify(notify); String mediaId = weixinProxy.uploadMedia(new File("D:\\test.jpg"), MediaType.image); - t = new ImageNotify(mediaId, "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + ImageNotify t = new ImageNotify("owGBft_vbBbOaQOmpEUE4xDLeRSU"); + t.pushMediaId(mediaId); weixinProxy.sendNotify(t); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); } } + + @Test + public void send2() { + try { + weixinProxy.sendNotify("to",new Music("thumbMediaId")); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java index 00021aa0..ddb309d4 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java @@ -1,7 +1,9 @@ package com.foxinmy.weixin4j.test; +import org.junit.Before; import org.junit.Test; +import com.foxinmy.weixin4j.msg.BaseMessage; import com.foxinmy.weixin4j.msg.TextMessage; import com.foxinmy.weixin4j.msg.out.ArticleMessage; import com.foxinmy.weixin4j.msg.out.ImageMessage; @@ -17,56 +19,52 @@ import com.foxinmy.weixin4j.msg.out.VoiceMessage; * @since JDK 1.7 */ public class MessageOutTest { + private BaseMessage inMessage; + + @Before + public void init() { + this.inMessage = new TextMessage(); + this.inMessage.setFromUserName("fromusername"); + this.inMessage.setToUserName("tousername"); + } + @Test public void text() { - TextMessage message = new TextMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.setContent("text message"); + TextMessage message = new TextMessage("text", inMessage); System.out.println(message.toXml()); } @Test public void image() { - ImageMessage message = new ImageMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + ImageMessage message = new ImageMessage(inMessage); message.pushMediaId("mediaId"); System.out.println(message.toXml()); } @Test public void voice() { - VoiceMessage message = new VoiceMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + VoiceMessage message = new VoiceMessage(inMessage); message.pushMediaId("mediaId"); System.out.println(message.toXml()); } - + @Test public void video() { - VideoMessage message = new VideoMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.pushVideo("mediaId", "title", "title"); + VideoMessage message = new VideoMessage(inMessage); + message.pushVideo("mediaId"); System.out.println(message.toXml()); } - + @Test public void music() { - MusicMessage message = new MusicMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.pushMusic("title", "desc", "url", "hqurl", "mediaId"); + MusicMessage message = new MusicMessage(inMessage); + message.pushMusic("mediaId"); System.out.println(message.toXml()); } - + @Test public void article() { - ArticleMessage message = new ArticleMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + ArticleMessage message = new ArticleMessage(inMessage); message.pushArticle("title1", "desc1", "picUrl1", "url1"); message.pushArticle("title2", "desc2", "picUrl2", "url2"); System.out.println(message.toXml()); diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java new file mode 100644 index 00000000..b8165a91 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java @@ -0,0 +1,30 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Before; +import org.junit.Test; + +import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.msg.out.TemplateMessage; + +public class MessageTemplTest { + private WeixinProxy weixinProxy; + + @Before + public void init() { + this.weixinProxy = new WeixinProxy(); + } + + @Test + public void test() { + TemplateMessage tplMessage = new TemplateMessage("touser", + "template_id", "url"); + tplMessage.pushData("name", "fox"); + System.out.print(tplMessage.toJson()); + try { + System.out.print(weixinProxy.sendTplMessage(tplMessage)); + } catch (WeixinException e) { + System.out.println(e.getErrorMsg()); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java b/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java deleted file mode 100644 index 5fa1ec67..00000000 --- a/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.foxinmy.weixin4j.test; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; - -import com.foxinmy.weixin4j.WeixinProxy; -import com.foxinmy.weixin4j.exception.WeixinException; -import com.foxinmy.weixin4j.model.MpArticle; -import com.foxinmy.weixin4j.type.MediaType; - -/** - * 群发消息 - * - * @className MpNewsTest - * @author jy - * @date 2014年4月27日 - * @since JDK 1.7 - * @see - */ -public class MpNewsTest { - private WeixinProxy weixinProxy; - - @Before - public void init() { - this.weixinProxy = new WeixinProxy(); - } - - @Test - public void massByGroup(){ - List articles = new ArrayList(); - try { - String thumbMediaId = weixinProxy.uploadMedia(new File("/tmp/test.jpg"), MediaType.image); - articles.add(new MpArticle(thumbMediaId, "title", "content")); - weixinProxy.massNewsByGroup(articles, "0"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } - - @Test - public void massByOpenIds(){ - List articles = new ArrayList(); - try { - String thumbMediaId = weixinProxy.uploadMedia(new File("/tmp/test.jpg"), MediaType.image); - articles.add(new MpArticle(thumbMediaId, "title", "content")); - weixinProxy.massNewsByOpenIds(articles, "owGBft_vbBbOaQOmpEUE4xDLeRSU"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } - - @Test - public void deleteMass(){ - try { - weixinProxy.deleteMassNews("34182"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } -} diff --git a/src/test/java/com/foxinmy/weixin4j/test/QRTest.java b/src/test/java/com/foxinmy/weixin4j/test/QRTest.java index 11934fa9..f18d1aa7 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/QRTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/QRTest.java @@ -25,10 +25,10 @@ public class QRTest { @Test public void temp_qr() { - QRParameter qr = new QRParameter(1200, QRType.QR_SCENE, 1); + QRParameter qr = new QRParameter(1200, QRType.TEMPORARY, 2); try { System.out.println(qr.toJson()); - weixinProxy.getQR(qr); + System.out.println(weixinProxy.getQR(qr)); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); @@ -37,10 +37,10 @@ public class QRTest { @Test public void forever_qr() { - QRParameter qr = new QRParameter(QRType.QR_LIMIT_SCENE, 1); + QRParameter qr = new QRParameter(QRType.PERMANENCE, 1); try { System.out.println(qr.toJson()); - weixinProxy.getQR(qr); + System.out.println(weixinProxy.getQR(qr)); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java b/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java index 37d549d7..a2f8a266 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java @@ -3,7 +3,8 @@ package com.foxinmy.weixin4j.test; import org.junit.Before; import org.junit.Test; -import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.api.token.FileTokenApi; +import com.foxinmy.weixin4j.api.token.TokenApi; import com.foxinmy.weixin4j.exception.WeixinException; /** @@ -14,17 +15,17 @@ import com.foxinmy.weixin4j.exception.WeixinException; * @since JDK 1.7 */ public class TokenTest { - private WeixinProxy weixinProxy; + private TokenApi tokenApi; @Before public void init() { - weixinProxy = new WeixinProxy(); + tokenApi = new FileTokenApi(); } @Test public void getToken() { try { - System.out.println(weixinProxy.getToken()); + System.out.println(tokenApi.getToken()); } catch (WeixinException e) { e.printStackTrace(); }
getArticles() { return this.articles; @@ -44,39 +44,55 @@ public class ArticleMessage extends BaseMessage { return; } if (this.articles == null) { - this.articles = new LinkedList(); + this.articles = new LinkedList(); } this.articles.add(new Article(title, desc, picUrl, url)); - count ++; + count++; } - @XStreamAlias("item") - private static class Article { - @XStreamAlias("Title") - private String title; // 图文消息标题 - @XStreamAlias("Description") - private String desc; // 图文消息描述 - @XStreamAlias("PicUrl") - private String picUrl; // 图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200 - @XStreamAlias("Url") - private String url; // 点击图文消息跳转链接 - - public Article(String title, String desc, String picUrl, String url) { - this.title = title; - this.desc = desc; - this.picUrl = picUrl; - this.url = url; + public void pushFirstArticle(String title, String desc, String picUrl, + String url) { + if (this.articles == null) { + this.articles = new LinkedList(); } + this.articles.addFirst(new Article(title, desc, picUrl, url)); + } - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Article ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,picUrl=").append(picUrl); - sb.append(" ,url=").append(url).append(")"); - return sb.toString(); + public void pushLastArticle(String title, String desc, String picUrl, + String url) { + if (this.articles == null) { + this.articles = new LinkedList(); } + this.articles.addLast(new Article(title, desc, picUrl, url)); + } + + public Article removeLastArticle() { + if (this.articles != null) { + return this.articles.removeLast(); + } + return null; + } + + 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() { + 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 diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java index 2da50a01..fb58ecb8 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java @@ -1,38 +1,50 @@ 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 回复图片消息 + * @see 回复图片消息 + * @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() { - super(MessageType.image); + public ImageMessage(BaseMessage inMessage) { + super(MessageType.image, inMessage); super.getMsgType().setMessageClass(ImageMessage.class); } + 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(); - this.image.mediaId = mediaId; + this.image = new Image(mediaId); } - private static class Image { - @XStreamAlias("MediaId") - private String mediaId; + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Image.class, "mediaId"); + return xstream.toXML(this); } @Override @@ -41,7 +53,7 @@ public class ImageMessage extends BaseMessage { sb.append("[ImageMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,mediaId=").append(this.image.mediaId); + sb.append(" ,mediaId=").append(this.image.getMediaId()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java index c790b9ac..419f32d6 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java @@ -1,74 +1,61 @@ 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 回复音乐消息 + * @see 回复音乐消息 + * @see com.foxinmy.weixin4j.msg.model.Music * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class MusicMessage extends BaseMessage { private static final long serialVersionUID = 4384403772658796395L; - public MusicMessage() { - super(MessageType.music); + public MusicMessage(BaseMessage inMessage) { + super(MessageType.music, inMessage); } @XStreamAlias("Music") private Music music; - public Music getMusic() { - return this.music; + public void pushMusic(String mediaId) { + this.music = new Music(mediaId); } - public void pushMusic(String title, String desc, String url, String hqUrl, String mediaId) { - this.music = new Music(); - this.music.thumbMediaId = mediaId; - this.music.desc = desc; - this.music.hqMusicUrl = hqUrl; - this.music.MusicURL = url; - this.music.title = title; + public void setMusic(Music music) { + this.music = music; } - private static class Music { - @XStreamAlias("Title") - private String title; // 音乐标题 - @XStreamAlias("Description") - private String desc; // 音乐描述 - @XStreamAlias("MusicURL") - private String MusicURL; // 音乐链接 - @XStreamAlias("HQMusicUrl") - private String hqMusicUrl; // 高质量音乐链接,WIFI环境优先使用该链接播放音乐 - @XStreamAlias("ThumbMediaId") - private String thumbMediaId; // 缩略图的媒体id,通过上传多媒体文件,得到的id - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Music ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,musicURL=").append(MusicURL); - sb.append(" ,hqMusicUrl=").append(hqMusicUrl); - sb.append(" ,thumbMediaId=").append(thumbMediaId).append(")"); - return sb.toString(); - } + @Override + public String 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(getMusic().toString()); + sb.append(" ,music=").append(music.toString()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java new file mode 100644 index 00000000..3721504b --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java @@ -0,0 +1,117 @@ +package com.foxinmy.weixin4j.msg.out; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +import com.alibaba.fastjson.JSON; + +/** + * 模板消息 + * + * @className TemplateMessage + * @author jy + * @date 2014年9月29日 + * @since JDK 1.7 + * @see + */ +public class TemplateMessage implements Serializable { + + private static final long serialVersionUID = 7950608393821661436L; + + private String touser; + private String template_id; + private String url; + private String topcolor = "#FF0000"; + private Map data; + + public void pushData(String key, String value) { + this.data.put(key, new Item(value)); + } + + public TemplateMessage(String touser, String template_id, String url) { + this.touser = touser; + this.template_id = template_id; + this.url = url; + this.data = new HashMap(); + } + + private static class Item implements Serializable { + private static final long serialVersionUID = 1L; + private String value; + private String color; + + public Item(String value) { + this(value, "#173177"); + } + + public Item(String value, String color) { + this.value = value; + this.color = color; + } + + public String getValue() { + return value; + } + + public String getColor() { + return color; + } + + @Override + public String toString() { + return "$ [value=" + getValue() + ", color=" + getColor() + "]"; + } + } + + public String getTouser() { + return touser; + } + + public void setTouser(String touser) { + this.touser = touser; + } + + public String getTemplate_id() { + return template_id; + } + + public void setTemplate_id(String template_id) { + this.template_id = template_id; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getTopcolor() { + return topcolor; + } + + public void setTopcolor(String topcolor) { + this.topcolor = topcolor; + } + + public Map getData() { + return data; + } + + public void setData(Map data) { + this.data = data; + } + + @Override + public String toString() { + return "TemplateMessage [touser=" + touser + ", template_id=" + + template_id + ", url=" + url + ", topcolor=" + topcolor + + ", data=" + data + "]"; + } + + public String toJson() { + return JSON.toJSONString(this); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java new file mode 100644 index 00000000..b89621aa --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java @@ -0,0 +1,25 @@ +package com.foxinmy.weixin4j.msg.out; + +import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.type.MessageType; + +/** + * 转移消息到多客服端消息 + * + * @className TransferMessage + * @author jy.hu + * @date 2014年6月28日 + * @since JDK 1.7 + * @see 多客服转移消息 + * @see com.foxinmy.weixin4j.msg.BaseMessage + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + */ +public class TransferMessage extends BaseMessage { + + private static final long serialVersionUID = -5479496746108594940L; + + public TransferMessage(BaseMessage inMessage) { + super(MessageType.transfer_customer_service,inMessage); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java index d16c5a12..d6cdfc91 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java @@ -1,58 +1,52 @@ package com.foxinmy.weixin4j.msg.out; import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.msg.model.Video; import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 回复视频消息 + * * @className VideoMessage * @author jy.hu * @date 2014年4月6日 * @since JDK 1.7 - * @see 回复视频消息 + * @see 回复视频消息 + * @see com.foxinmy.weixin4j.msg.model.Video * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class VideoMessage extends BaseMessage { private static final long serialVersionUID = -1013075358679078381L; - public VideoMessage() { - super(MessageType.video); + public VideoMessage(BaseMessage inMessage) { + super(MessageType.video, inMessage); super.getMsgType().setMessageClass(VideoMessage.class); } @XStreamAlias("Video") private Video video; - public Video getVideo() { - return this.video; + public void pushVideo(String mediaId) { + this.video = new Video(mediaId); } - public void pushVideo(String mediaId, String title, String desc) { - this.video = new Video(); - this.video.desc = desc; - this.video.mediaId = mediaId; - this.video.title = title; + public void setVideo(Video video) { + this.video = video; } - private static class Video { - @XStreamAlias("MediaId") - private String mediaId; - @XStreamAlias("Title") - private String title; - @XStreamAlias("Description") - private String desc; - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Video mediaId=").append(mediaId); - sb.append(" ,title=").append(title); - sb.append(" ,desc=").append(desc).append(")"); - return super.toString(); - } + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Video.class, "mediaId"); + xstream.aliasField("Title", Video.class, "title"); + xstream.aliasField("Description", Video.class, "desc"); + xstream.omitField(Video.class, "thumbMediaId"); + return xstream.toXML(this); } @Override @@ -61,7 +55,7 @@ public class VideoMessage extends BaseMessage { sb.append("[VideoMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,video=").append(getVideo().toString()); + sb.append(" ,video=").append(video.toString()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java index 93052907..dcac1046 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java @@ -1,53 +1,60 @@ package com.foxinmy.weixin4j.msg.out; import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.msg.model.Voice; import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 语音消息 + * * @className VoiceMessage * @author jy.hu * @date 2014年3月23日 * @since JDK 1.7 - * @see 回复语音消息 + * @see 回复语音消息 + * @see com.foxinmy.weixin4j.msg.model.Voice * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class VoiceMessage extends BaseMessage { private static final long serialVersionUID = -7944926238652243793L; - public VoiceMessage() { - super(MessageType.voice); + public VoiceMessage(BaseMessage inMessage) { + super(MessageType.voice, inMessage); super.getMsgType().setMessageClass(VoiceMessage.class); } + + public VoiceMessage(String mediaId, BaseMessage inMessage) { + super(MessageType.voice, inMessage); + super.getMsgType().setMessageClass(VoiceMessage.class); + this.pushMediaId(mediaId); + } + @XStreamAlias("Voice") private Voice voice; - - public Voice getVocie() { - return voice; + + public void pushMediaId(String mediaId) { + this.voice = new Voice(mediaId); } - public void pushMediaId(String mediaId){ - this.voice = new Voice(); - this.voice.setMediaId(mediaId); - } - - private static class Voice { - @XStreamAlias("MediaId") - private String mediaId; - - private void setMediaId(String mediaId) { - this.mediaId = mediaId; - } + + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Voice.class, "mediaId"); + return xstream.toXML(this); } + @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("[VoiceMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,mediaId=").append(getVocie().mediaId); + sb.append(" ,mediaId=").append(voice.getMediaId()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java b/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java new file mode 100644 index 00000000..cf2ab68e --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java @@ -0,0 +1,55 @@ +package com.foxinmy.weixin4j.type; + +/** + * 自定义菜单类型 + * scancode_push 到 location_selec + * 仅支持微信iPhone5.4.1以上版本,和Android5 .4以上版本的微信用户 旧版本微信用户点击后将没有回应 + * 开发者也不能正常接收到事件推送。 + * + * @className ButtonType + * @author jy + * @date 2014年9月30日 + * @since JDK 1.7 + * @see 按钮类型 + */ +public enum ButtonType { + /** + * 点击推事件 用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event + * 的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互; + */ + click, + /** + * 跳转URL 用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的网页URL,可与网页授权获取用户基本信息接口结合,获得用户基本信息。 + */ + view, + /** + * 扫码推事件 用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后显示扫描结果(如果是URL,将进入URL),且会将扫码的结果传给开发者, + * 开发者可以下发消息。 + */ + scancode_push, + /** + * 扫码推事件且弹出“消息接收中”提示框用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后,将扫码的结果传给开发者,同时收起扫一扫工具, + * 然后弹出“消息接收中”提示框,随后可能会收到开发者下发的消息。 + */ + scancode_waitmsg, + /** + * 弹出系统拍照发图用户点击按钮后,微信客户端将调起系统相机,完成拍照操作后,会将拍摄的相片发送给开发者,并推送事件给开发者,同时收起系统相机, + * 随后可能会收到开发者下发的消息。 + */ + pic_sysphoto, + /** + * 弹出拍照或者相册发图用户点击按钮后,微信客户端将弹出选择器供用户选择“拍照”或者“从手机相册选择”。用户选择后即走其他两种流程。 + */ + pic_photo_or_albu, + /** + * 弹出微信相册发图器用户点击按钮后,微信客户端将调起微信相册,完成选择操作后,将选择的相片发送给开发者的服务器,并推送事件给开发者,同时收起相册, + * 随后可能会收到开发者下发的消息。 + */ + pic_weixin, + /** + * 弹出地理位置选择器用户点击按钮后,微信客户端将调起地理位置选择工具,完成选择操作后,将选择的地理位置发送给开发者的服务器,同时收起位置选择工具, + * 随后可能会收到开发者下发的消息。 + */ + location_select; +} diff --git a/src/main/java/com/foxinmy/weixin4j/type/EventType.java b/src/main/java/com/foxinmy/weixin4j/type/EventType.java index a8e864b8..bc85ce90 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/EventType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/EventType.java @@ -3,21 +3,36 @@ package com.foxinmy.weixin4j.type; import com.foxinmy.weixin4j.msg.event.EventMessage; import com.foxinmy.weixin4j.msg.event.LocationEventMessage; import com.foxinmy.weixin4j.msg.event.MassEventMessage; -import com.foxinmy.weixin4j.msg.event.MenuEventMessage; import com.foxinmy.weixin4j.msg.event.ScanEventMessage; import com.foxinmy.weixin4j.msg.event.ScribeEventMessage; +import com.foxinmy.weixin4j.msg.event.TemplatesendjobfinishMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuLocationEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuPhotoEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuScanEventMessage; /** - * * 事件类型 - * @author jy.hu - * + * + * @className EventType + * @author jy + * @date 2014年9月30日 + * @since JDK 1.7 + * @see */ public enum EventType { - subscribe(ScribeEventMessage.class), unsubscribe(ScribeEventMessage.class), - scan(ScanEventMessage.class),click(MenuEventMessage.class),view(MenuEventMessage.class), - location(LocationEventMessage.class),MASSSENDJOBFINISH(MassEventMessage.class); - + subscribe(ScribeEventMessage.class), unsubscribe(ScribeEventMessage.class), scan( + ScanEventMessage.class), scancode_push(MenuScanEventMessage.class), view( + MenuEventMessage.class), scancode_waitmsg( + MenuScanEventMessage.class), pic_sysphoto( + MenuPhotoEventMessage.class), pic_photo_or_album( + MenuPhotoEventMessage.class), pic_weixin( + MenuPhotoEventMessage.class), location_select( + MenuLocationEventMessage.class), click(MenuEventMessage.class), location( + LocationEventMessage.class), massendjobfinish( + MassEventMessage.class), templatesendjobfinish( + TemplatesendjobfinishMessage.class); + private Class extends EventMessage> eventClass; EventType(Class extends EventMessage> eventClass) { diff --git a/src/main/java/com/foxinmy/weixin4j/type/MediaType.java b/src/main/java/com/foxinmy/weixin4j/type/MediaType.java index 1f567181..322ba3ce 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/MediaType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/MediaType.java @@ -6,13 +6,20 @@ package com.foxinmy.weixin4j.type; * 语音(voice):256K,播放长度不超过60s,支持AMR\MP3格式 * 视频(video):1MB,支持MP4格式 * 缩略图(thumb):64KB,支持JPG格式 - * 媒体文件在后台保存时间为3天,即3天后media_id失效 + * + * 媒体文件在后台保存时间为3天,即3天后media_id失效 + * + * * @author jy.hu * @date 2014年4月2日 * @since JDK 1.7 */ public enum MediaType { - image("image/jpeg",".jpg"), voice("binary/octet-stream","amr"), vedio("binary/octet-stream","mp4"), thumb("image/jpeg","jpg"); + image("image/jpeg", "jpg"), voice("binary/octet-stream", "amr"), vedio( + "binary/octet-stream", "mp4"), thumb("image/jpeg", "jpg"), text( + "application/json", ""), music("binary/octet-stream", "mp3"), news( + "application/json", ""), mpnews("application/json", ""), mpvideo( + "binary/octet-stream", ""); MediaType(String contentType, String formatType) { this.contentType = contentType; @@ -26,6 +33,7 @@ public enum MediaType { } private String formatType; + public String getFormatType() { return formatType; } diff --git a/src/main/java/com/foxinmy/weixin4j/type/MessageType.java b/src/main/java/com/foxinmy/weixin4j/type/MessageType.java index 21a7b6dc..a883d993 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/MessageType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/MessageType.java @@ -10,6 +10,7 @@ import com.foxinmy.weixin4j.msg.in.VideoMessage; import com.foxinmy.weixin4j.msg.in.VoiceMessage; import com.foxinmy.weixin4j.msg.out.ArticleMessage; import com.foxinmy.weixin4j.msg.out.MusicMessage; +import com.foxinmy.weixin4j.msg.out.TransferMessage; /** * @@ -20,9 +21,13 @@ import com.foxinmy.weixin4j.msg.out.MusicMessage; */ public enum MessageType { // 接收到的消息类型 - text(TextMessage.class), image(ImageMessage.class), voice(VoiceMessage.class), video(VideoMessage.class), location(LocationMessage.class), link(LinkMessage.class), event(EventMessage.class), + text(TextMessage.class), image(ImageMessage.class), voice( + VoiceMessage.class), video(VideoMessage.class), location( + LocationMessage.class), link(LinkMessage.class), event( + EventMessage.class), // 发送的消息类型 - music(MusicMessage.class), news(ArticleMessage.class); + music(MusicMessage.class), news(ArticleMessage.class), transfer_customer_service( + TransferMessage.class); private Class extends BaseMessage> messageClass; MessageType(Class extends BaseMessage> messageClass) { diff --git a/src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java b/src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java similarity index 91% rename from src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java rename to src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java index f428c33b..b419bd1c 100644 --- a/src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java +++ b/src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java @@ -8,8 +8,8 @@ import java.util.regex.Pattern; import com.foxinmy.weixin4j.WeixinProxy; -public class WeixinConfig { - public WeixinConfig() { +public class ConfigUtil { + public ConfigUtil() { } private static Properties props = new Properties(); @@ -38,7 +38,6 @@ public class WeixinConfig { m.appendTail(sb); return sb.toString(); } - public static void main(String[] args) { System.out.println(getValue("api_token_uri")); } diff --git a/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java b/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java new file mode 100644 index 00000000..60eae107 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java @@ -0,0 +1,67 @@ +package com.foxinmy.weixin4j.util; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.Writer; +import java.nio.charset.Charset; + +/** + * IOUtil + * + * @className IOUtil + * @author jy.hu + * @date 2014年9月22日 + * @since JDK 1.7 + * @see org.apache.commons.io.IOUtils + */ +public class IOUtil { + + private static final int EOF = -1; + private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; + + public static byte[] toByteArray(Reader input) throws IOException { + return toByteArray(input, Charset.defaultCharset()); + } + + public static byte[] toByteArray(Reader input, Charset encoding) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + copy(input, output, encoding); + return output.toByteArray(); + } + + public static void copy(Reader input, OutputStream output, Charset encoding) throws IOException { + OutputStreamWriter out = new OutputStreamWriter(output, encoding); + copyLarge(input, out, new char[DEFAULT_BUFFER_SIZE]); + out.flush(); + } + + public static byte[] toByteArray(InputStream input) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + copyLarge(input, output, new byte[DEFAULT_BUFFER_SIZE]); + return output.toByteArray(); + } + + private static long copyLarge(InputStream input, OutputStream output, byte[] buffer) throws IOException { + long count = 0; + int n = 0; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } + + private static long copyLarge(Reader input, Writer output, char[] buffer) throws IOException { + long count = 0; + int n = 0; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java b/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java new file mode 100644 index 00000000..82a23ef3 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java @@ -0,0 +1,135 @@ +package com.foxinmy.weixin4j.util; + +import java.io.InputStream; +import java.util.Arrays; + +import org.apache.commons.codec.digest.DigestUtils; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.DocumentHelper; +import org.dom4j.io.SAXReader; +import org.jsoup.helper.StringUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.type.EventType; +import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; + +public class MessageUtil { + + private final static Logger log = LoggerFactory.getLogger(MessageUtil.class); + + /** + * 验证微信签名 + * + * @param echostr + * 随机字符串 + * @param timestamp + * 时间戳 + * @param nonce + * 随机数 + * @param signature + * 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数 + * @return 开发者通过检验signature对请求进行相关校验。若确认此次GET请求来自微信服务器 + * 请原样返回echostr参数内容,则接入生效 成为开发者成功,否则接入失败 + * @see 接入指南 + */ + public static String signature(String echostr, String timestamp, String nonce, String signature) { + String app_token = ConfigUtil.getValue("app_token"); + if (StringUtil.isBlank(app_token)) { + log.error("signature fail : token is null!"); + return null; + } + if (StringUtil.isBlank(echostr) || StringUtil.isBlank(timestamp) || StringUtil.isBlank(nonce)) { + log.error("signature fail : invalid parameter!"); + return null; + } + String _signature = null; + try { + String[] a = { app_token, timestamp, nonce }; + Arrays.sort(a); + StringBuilder sb = new StringBuilder(3); + for (String str : a) { + sb.append(str); + } + _signature = DigestUtils.sha1Hex(sb.toString()); + } catch (Exception e) { + log.error("signature error", e); + } + if (signature.equals(_signature)) { + return echostr; + } else { + log.error("signature fail : invalid signature!"); + return null; + } + } + + /** + * xml消息转换为消息对象 + * + * 微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次 + * + * + * @param xml + * 消息字符串 + * @return 消息对象 + * @throws DocumentException + * @see 验证消息的合法性 + * @see 普通消息 + * @see 事件触发 + * @see com.foxinmy.weixin4j.type.MessageType + * @see com.feican.weixin.msg.BaeMessage + * @see com.foxinmy.weixin4j.msg.TextMessage + * @see com.foxinmy.weixin4j.msg.in.ImageMessage + * @see com.foxinmy.weixin4j.msg.in.VoiceMessage + * @see com.foxinmy.weixin4j.msg.in.VideoMessage + * @see com.foxinmy.weixin4j.msg.in.LocationMessage + * @see com.foxinmy.weixin4j.msg.in.LinkMessage + * @see com.foxinmy.weixin4j.msg.event.ScribeEventMessage + * @see com.foxinmy.weixin4j.msg.event.ScanEventMessage + * @see com.foxinmy.weixin4j.msg.event.LocationEventMessage + * @see com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage + */ + public static BaseMessage xml2msg(String xml) throws DocumentException { + if (StringUtil.isBlank(xml)) + return null; + Document doc = DocumentHelper.parseText(xml); + String type = doc.selectSingleNode("/xml/MsgType").getStringValue(); + if (StringUtil.isBlank(type)) { + return null; + } + XStream xstream = new XStream(); + MessageType messageType = MessageType.valueOf(type.toLowerCase()); + Class extends BaseMessage> messageClass = messageType.getMessageClass(); + if (messageType == MessageType.event) { + type = doc.selectSingleNode("/xml/Event").getStringValue(); + messageClass = EventType.valueOf(type.toLowerCase()).getEventClass(); + } + xstream.alias("xml", messageClass); + xstream.ignoreUnknownElements(); + xstream.autodetectAnnotations(true); + xstream.processAnnotations(messageClass); + return xstream.fromXML(doc.asXML(), messageClass); + } + + /** + * xml消息转换为消息对象 + * + * @param inputStream + * 带消息字符串的输入流 + * @return 消息对象 + * @throws DocumentException + * @see {@link com.foxinmy.weixin4j.WeixinProxy#xml2msg(String)} + */ + public static BaseMessage xml2msg(InputStream inputStream) throws DocumentException { + SAXReader reader = new SAXReader(); + Document doc = reader.read(inputStream); + return xml2msg(doc.asXML()); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java b/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java deleted file mode 100644 index 19fd87e4..00000000 --- a/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.foxinmy.weixin4j.util; - -public class WeixinUtil { - - public static boolean isBlank(String str) { - return str == null || str.isEmpty(); - } -} diff --git a/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java b/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java index 5c0186c6..4a811a6c 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java @@ -9,7 +9,7 @@ import org.junit.Test; import com.foxinmy.weixin4j.WeixinProxy; import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.model.Button; -import com.foxinmy.weixin4j.model.Button.BtnType; +import com.foxinmy.weixin4j.type.ButtonType; /** * 自定义菜单测试 @@ -31,7 +31,7 @@ public class ButtonTest { List btnList = new ArrayList(); Button b = new Button("test"); - b.setType(BtnType.click); + b.setType(ButtonType.click); b.setKey("123"); btnList.add(b); diff --git a/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java b/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java index 8b78305e..bb6bec88 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java @@ -50,7 +50,7 @@ public class GroupTest { @Test public void getid() { try { - System.out.println(weixinProxy.findGroupByOpenId("owGBft_vbBbOaQOmpEUE4xDLeRSU")); + System.out.println(weixinProxy.getGroupByOpenId("owGBft_vbBbOaQOmpEUE4xDLeRSU")); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); diff --git a/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java b/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java new file mode 100644 index 00000000..6d34a733 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java @@ -0,0 +1,22 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Test; + +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.http.HttpRequest; + +public class HttpTest { + private static HttpRequest request; + static { + request = new HttpRequest(); + } + + @Test + public void test(){ + try { + System.out.println(request.get("http://www.baidu.com")); + } catch (WeixinException e) { + e.printStackTrace(); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java b/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java index f907fa3d..d54e649b 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java @@ -31,7 +31,7 @@ public class MediaTest { File file = new File("D:\\test.jpg"); try { System.out.println(weixinProxy.uploadMedia(file, MediaType.image)); - //usAxLEJxFXAjXVlLu_BSw0GvS2YEEoGeelRBybNZBGvMsdxiIcD1F9yBWYd9jVZx + //vvU_AUtovWyfAxQ8J1DsCoNMtK6U_bUmTpe6lpINUOVRLvt_7rtO4zxzBpPgkmay } catch (WeixinException e) { System.out.println(e.getErrorMsg()); } @@ -40,7 +40,7 @@ public class MediaTest { @Test public void download() { try { - System.out.println(weixinProxy.downloadMedia("usAxLEJxFXAjXVlLu_BSw0GvS2YEEoGeelRBybNZBGvMsdxiIcD1F9yBWYd9jVZx", MediaType.image)); + System.out.println(weixinProxy.downloadMedia("vvU_AUtovWyfAxQ8J1DsCoNMtK6U_bUmTpe6lpINUOVRLvt_7rtO4zxzBpPgkmay", MediaType.image)); } catch (WeixinException e) { System.out.println(e.getErrorMsg()); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java new file mode 100644 index 00000000..2cd36584 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java @@ -0,0 +1,194 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Test; + +import com.foxinmy.weixin4j.util.MessageUtil; + +/** + * 接收事件消息格式测试 + * + * @author jy.hu + * @date 2014年3月24日 + * @since JDK 1.7 + */ +public class MessageEventInTest { + + private StringBuilder xmlSb = new StringBuilder(); + + /***************** event message *********************/ + @Test + public void scribe() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void scan() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void scan_scribe() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void location1() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("23.137466"); + xmlSb.append("113.352425"); + xmlSb.append("119.385040"); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_click() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_link() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_scan() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_photo() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("1"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_location() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java index 39269754..fdd40042 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java @@ -1,134 +1,19 @@ package com.foxinmy.weixin4j.test; -import org.junit.Before; import org.junit.Test; -import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.util.MessageUtil; /** - * 接收消息格式测试 + * 接受一般消息格式测试 + * * @author jy.hu * @date 2014年3月24日 * @since JDK 1.7 */ public class MessageInTest { + private StringBuilder xmlSb = new StringBuilder(); - private WeixinProxy weixinProxy; - - @Before - public void init(){ - weixinProxy = new WeixinProxy(); - } - - /***************** event message *********************/ - @Test - public void scribe() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void scan() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - @Test - public void scan_scribe() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void location1() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("23.137466"); - xmlSb.append("113.352425"); - xmlSb.append("119.385040"); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void menu_click() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void menu_link() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } /***************** common message *********************/ @@ -144,7 +29,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -163,7 +48,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -182,7 +67,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -202,7 +87,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -221,7 +106,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -242,7 +127,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -262,7 +147,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java new file mode 100644 index 00000000..8f6a130f --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java @@ -0,0 +1,114 @@ +package com.foxinmy.weixin4j.test; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.model.MpArticle; +import com.foxinmy.weixin4j.type.MediaType; + +/** + * 群发消息 + * + * @className MpNewsTest + * @author jy + * @date 2014年4月27日 + * @since JDK 1.7 + * @see + */ +public class MessageMassTest { + private WeixinProxy weixinProxy; + + @Before + public void init() { + this.weixinProxy = new WeixinProxy(); + } + + @Test + public void uploadArticle() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.uploadArticle(articles); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void uploadVideo() { + try { + weixinProxy.uploadVideo("mediaId", "title", "desc"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massByGroup() { + try { + weixinProxy.massByGroup("123", MediaType.image, "groupId"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massByOpenIds() { + try { + weixinProxy.massByOpenIds("123", MediaType.image, "openIds"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massArticleByGroup() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.massArticleByGroup(articles, "0"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massArticleByOpenIds() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.massArticleByOpenIds(articles, + "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void deleteMass() { + try { + weixinProxy.deleteMassNews("34182"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java index f3be10bb..59aed8de 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java @@ -7,6 +7,7 @@ import org.junit.Test; import com.foxinmy.weixin4j.WeixinProxy; import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.msg.model.Music; import com.foxinmy.weixin4j.msg.notify.ArticleNotify; import com.foxinmy.weixin4j.msg.notify.BaseNotify; import com.foxinmy.weixin4j.msg.notify.ImageNotify; @@ -41,27 +42,29 @@ public class MessageNotifyTest { @Test public void image() { - ImageNotify notify = new ImageNotify("123", "to"); + ImageNotify notify = new ImageNotify("to"); + notify.pushMediaId("123"); System.out.println(notify.toJson()); } @Test public void voice() { - VoiceNotify notify = new VoiceNotify("123", "to"); + VoiceNotify notify = new VoiceNotify("to"); + notify.pushMediaId("123"); System.out.println(notify.toJson()); } @Test public void video() { VideoNotify notify = new VideoNotify("to"); - notify.pushVideo("123", "title", "desc"); + notify.pushVideo("123","m123"); System.out.println(notify.toJson()); } @Test public void music() { MusicNotify notify = new MusicNotify("to"); - notify.pushMusic("title", "desc", "url", "hqUrl", "mediaId"); + notify.pushMusic("url", "hqUrl", "mediaId"); System.out.println(notify.toJson()); } @@ -74,16 +77,27 @@ public class MessageNotifyTest { } @Test - public void send() { - BaseNotify t = new TextNotify("哈哈哈哈", "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + public void send1() { + BaseNotify notify = new TextNotify("哈哈哈哈", "owGBft_vbBbOaQOmpEUE4xDLeRSU"); try { - weixinProxy.sendNotify(t); + weixinProxy.sendNotify(notify); String mediaId = weixinProxy.uploadMedia(new File("D:\\test.jpg"), MediaType.image); - t = new ImageNotify(mediaId, "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + ImageNotify t = new ImageNotify("owGBft_vbBbOaQOmpEUE4xDLeRSU"); + t.pushMediaId(mediaId); weixinProxy.sendNotify(t); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); } } + + @Test + public void send2() { + try { + weixinProxy.sendNotify("to",new Music("thumbMediaId")); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java index 00021aa0..ddb309d4 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java @@ -1,7 +1,9 @@ package com.foxinmy.weixin4j.test; +import org.junit.Before; import org.junit.Test; +import com.foxinmy.weixin4j.msg.BaseMessage; import com.foxinmy.weixin4j.msg.TextMessage; import com.foxinmy.weixin4j.msg.out.ArticleMessage; import com.foxinmy.weixin4j.msg.out.ImageMessage; @@ -17,56 +19,52 @@ import com.foxinmy.weixin4j.msg.out.VoiceMessage; * @since JDK 1.7 */ public class MessageOutTest { + private BaseMessage inMessage; + + @Before + public void init() { + this.inMessage = new TextMessage(); + this.inMessage.setFromUserName("fromusername"); + this.inMessage.setToUserName("tousername"); + } + @Test public void text() { - TextMessage message = new TextMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.setContent("text message"); + TextMessage message = new TextMessage("text", inMessage); System.out.println(message.toXml()); } @Test public void image() { - ImageMessage message = new ImageMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + ImageMessage message = new ImageMessage(inMessage); message.pushMediaId("mediaId"); System.out.println(message.toXml()); } @Test public void voice() { - VoiceMessage message = new VoiceMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + VoiceMessage message = new VoiceMessage(inMessage); message.pushMediaId("mediaId"); System.out.println(message.toXml()); } - + @Test public void video() { - VideoMessage message = new VideoMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.pushVideo("mediaId", "title", "title"); + VideoMessage message = new VideoMessage(inMessage); + message.pushVideo("mediaId"); System.out.println(message.toXml()); } - + @Test public void music() { - MusicMessage message = new MusicMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.pushMusic("title", "desc", "url", "hqurl", "mediaId"); + MusicMessage message = new MusicMessage(inMessage); + message.pushMusic("mediaId"); System.out.println(message.toXml()); } - + @Test public void article() { - ArticleMessage message = new ArticleMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + ArticleMessage message = new ArticleMessage(inMessage); message.pushArticle("title1", "desc1", "picUrl1", "url1"); message.pushArticle("title2", "desc2", "picUrl2", "url2"); System.out.println(message.toXml()); diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java new file mode 100644 index 00000000..b8165a91 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java @@ -0,0 +1,30 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Before; +import org.junit.Test; + +import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.msg.out.TemplateMessage; + +public class MessageTemplTest { + private WeixinProxy weixinProxy; + + @Before + public void init() { + this.weixinProxy = new WeixinProxy(); + } + + @Test + public void test() { + TemplateMessage tplMessage = new TemplateMessage("touser", + "template_id", "url"); + tplMessage.pushData("name", "fox"); + System.out.print(tplMessage.toJson()); + try { + System.out.print(weixinProxy.sendTplMessage(tplMessage)); + } catch (WeixinException e) { + System.out.println(e.getErrorMsg()); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java b/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java deleted file mode 100644 index 5fa1ec67..00000000 --- a/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.foxinmy.weixin4j.test; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; - -import com.foxinmy.weixin4j.WeixinProxy; -import com.foxinmy.weixin4j.exception.WeixinException; -import com.foxinmy.weixin4j.model.MpArticle; -import com.foxinmy.weixin4j.type.MediaType; - -/** - * 群发消息 - * - * @className MpNewsTest - * @author jy - * @date 2014年4月27日 - * @since JDK 1.7 - * @see - */ -public class MpNewsTest { - private WeixinProxy weixinProxy; - - @Before - public void init() { - this.weixinProxy = new WeixinProxy(); - } - - @Test - public void massByGroup(){ - List articles = new ArrayList(); - try { - String thumbMediaId = weixinProxy.uploadMedia(new File("/tmp/test.jpg"), MediaType.image); - articles.add(new MpArticle(thumbMediaId, "title", "content")); - weixinProxy.massNewsByGroup(articles, "0"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } - - @Test - public void massByOpenIds(){ - List articles = new ArrayList(); - try { - String thumbMediaId = weixinProxy.uploadMedia(new File("/tmp/test.jpg"), MediaType.image); - articles.add(new MpArticle(thumbMediaId, "title", "content")); - weixinProxy.massNewsByOpenIds(articles, "owGBft_vbBbOaQOmpEUE4xDLeRSU"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } - - @Test - public void deleteMass(){ - try { - weixinProxy.deleteMassNews("34182"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } -} diff --git a/src/test/java/com/foxinmy/weixin4j/test/QRTest.java b/src/test/java/com/foxinmy/weixin4j/test/QRTest.java index 11934fa9..f18d1aa7 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/QRTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/QRTest.java @@ -25,10 +25,10 @@ public class QRTest { @Test public void temp_qr() { - QRParameter qr = new QRParameter(1200, QRType.QR_SCENE, 1); + QRParameter qr = new QRParameter(1200, QRType.TEMPORARY, 2); try { System.out.println(qr.toJson()); - weixinProxy.getQR(qr); + System.out.println(weixinProxy.getQR(qr)); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); @@ -37,10 +37,10 @@ public class QRTest { @Test public void forever_qr() { - QRParameter qr = new QRParameter(QRType.QR_LIMIT_SCENE, 1); + QRParameter qr = new QRParameter(QRType.PERMANENCE, 1); try { System.out.println(qr.toJson()); - weixinProxy.getQR(qr); + System.out.println(weixinProxy.getQR(qr)); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java b/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java index 37d549d7..a2f8a266 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java @@ -3,7 +3,8 @@ package com.foxinmy.weixin4j.test; import org.junit.Before; import org.junit.Test; -import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.api.token.FileTokenApi; +import com.foxinmy.weixin4j.api.token.TokenApi; import com.foxinmy.weixin4j.exception.WeixinException; /** @@ -14,17 +15,17 @@ import com.foxinmy.weixin4j.exception.WeixinException; * @since JDK 1.7 */ public class TokenTest { - private WeixinProxy weixinProxy; + private TokenApi tokenApi; @Before public void init() { - weixinProxy = new WeixinProxy(); + tokenApi = new FileTokenApi(); } @Test public void getToken() { try { - System.out.println(weixinProxy.getToken()); + System.out.println(tokenApi.getToken()); } catch (WeixinException e) { e.printStackTrace(); }
(); } this.articles.add(new Article(title, desc, picUrl, url)); - count ++; + count++; } - @XStreamAlias("item") - private static class Article { - @XStreamAlias("Title") - private String title; // 图文消息标题 - @XStreamAlias("Description") - private String desc; // 图文消息描述 - @XStreamAlias("PicUrl") - private String picUrl; // 图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200 - @XStreamAlias("Url") - private String url; // 点击图文消息跳转链接 - - public Article(String title, String desc, String picUrl, String url) { - this.title = title; - this.desc = desc; - this.picUrl = picUrl; - this.url = url; + public void pushFirstArticle(String title, String desc, String picUrl, + String url) { + if (this.articles == null) { + this.articles = new LinkedList(); } + this.articles.addFirst(new Article(title, desc, picUrl, url)); + } - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Article ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,picUrl=").append(picUrl); - sb.append(" ,url=").append(url).append(")"); - return sb.toString(); + public void pushLastArticle(String title, String desc, String picUrl, + String url) { + if (this.articles == null) { + this.articles = new LinkedList(); } + this.articles.addLast(new Article(title, desc, picUrl, url)); + } + + public Article removeLastArticle() { + if (this.articles != null) { + return this.articles.removeLast(); + } + return null; + } + + 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() { + 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 diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java index 2da50a01..fb58ecb8 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java @@ -1,38 +1,50 @@ 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 回复图片消息 + * @see 回复图片消息 + * @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() { - super(MessageType.image); + public ImageMessage(BaseMessage inMessage) { + super(MessageType.image, inMessage); super.getMsgType().setMessageClass(ImageMessage.class); } + 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(); - this.image.mediaId = mediaId; + this.image = new Image(mediaId); } - private static class Image { - @XStreamAlias("MediaId") - private String mediaId; + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Image.class, "mediaId"); + return xstream.toXML(this); } @Override @@ -41,7 +53,7 @@ public class ImageMessage extends BaseMessage { sb.append("[ImageMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,mediaId=").append(this.image.mediaId); + sb.append(" ,mediaId=").append(this.image.getMediaId()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java index c790b9ac..419f32d6 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java @@ -1,74 +1,61 @@ 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 回复音乐消息 + * @see 回复音乐消息 + * @see com.foxinmy.weixin4j.msg.model.Music * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class MusicMessage extends BaseMessage { private static final long serialVersionUID = 4384403772658796395L; - public MusicMessage() { - super(MessageType.music); + public MusicMessage(BaseMessage inMessage) { + super(MessageType.music, inMessage); } @XStreamAlias("Music") private Music music; - public Music getMusic() { - return this.music; + public void pushMusic(String mediaId) { + this.music = new Music(mediaId); } - public void pushMusic(String title, String desc, String url, String hqUrl, String mediaId) { - this.music = new Music(); - this.music.thumbMediaId = mediaId; - this.music.desc = desc; - this.music.hqMusicUrl = hqUrl; - this.music.MusicURL = url; - this.music.title = title; + public void setMusic(Music music) { + this.music = music; } - private static class Music { - @XStreamAlias("Title") - private String title; // 音乐标题 - @XStreamAlias("Description") - private String desc; // 音乐描述 - @XStreamAlias("MusicURL") - private String MusicURL; // 音乐链接 - @XStreamAlias("HQMusicUrl") - private String hqMusicUrl; // 高质量音乐链接,WIFI环境优先使用该链接播放音乐 - @XStreamAlias("ThumbMediaId") - private String thumbMediaId; // 缩略图的媒体id,通过上传多媒体文件,得到的id - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Music ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,musicURL=").append(MusicURL); - sb.append(" ,hqMusicUrl=").append(hqMusicUrl); - sb.append(" ,thumbMediaId=").append(thumbMediaId).append(")"); - return sb.toString(); - } + @Override + public String 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(getMusic().toString()); + sb.append(" ,music=").append(music.toString()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java new file mode 100644 index 00000000..3721504b --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java @@ -0,0 +1,117 @@ +package com.foxinmy.weixin4j.msg.out; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +import com.alibaba.fastjson.JSON; + +/** + * 模板消息 + * + * @className TemplateMessage + * @author jy + * @date 2014年9月29日 + * @since JDK 1.7 + * @see + */ +public class TemplateMessage implements Serializable { + + private static final long serialVersionUID = 7950608393821661436L; + + private String touser; + private String template_id; + private String url; + private String topcolor = "#FF0000"; + private Map data; + + public void pushData(String key, String value) { + this.data.put(key, new Item(value)); + } + + public TemplateMessage(String touser, String template_id, String url) { + this.touser = touser; + this.template_id = template_id; + this.url = url; + this.data = new HashMap(); + } + + private static class Item implements Serializable { + private static final long serialVersionUID = 1L; + private String value; + private String color; + + public Item(String value) { + this(value, "#173177"); + } + + public Item(String value, String color) { + this.value = value; + this.color = color; + } + + public String getValue() { + return value; + } + + public String getColor() { + return color; + } + + @Override + public String toString() { + return "$ [value=" + getValue() + ", color=" + getColor() + "]"; + } + } + + public String getTouser() { + return touser; + } + + public void setTouser(String touser) { + this.touser = touser; + } + + public String getTemplate_id() { + return template_id; + } + + public void setTemplate_id(String template_id) { + this.template_id = template_id; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getTopcolor() { + return topcolor; + } + + public void setTopcolor(String topcolor) { + this.topcolor = topcolor; + } + + public Map getData() { + return data; + } + + public void setData(Map data) { + this.data = data; + } + + @Override + public String toString() { + return "TemplateMessage [touser=" + touser + ", template_id=" + + template_id + ", url=" + url + ", topcolor=" + topcolor + + ", data=" + data + "]"; + } + + public String toJson() { + return JSON.toJSONString(this); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java new file mode 100644 index 00000000..b89621aa --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java @@ -0,0 +1,25 @@ +package com.foxinmy.weixin4j.msg.out; + +import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.type.MessageType; + +/** + * 转移消息到多客服端消息 + * + * @className TransferMessage + * @author jy.hu + * @date 2014年6月28日 + * @since JDK 1.7 + * @see 多客服转移消息 + * @see com.foxinmy.weixin4j.msg.BaseMessage + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + */ +public class TransferMessage extends BaseMessage { + + private static final long serialVersionUID = -5479496746108594940L; + + public TransferMessage(BaseMessage inMessage) { + super(MessageType.transfer_customer_service,inMessage); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java index d16c5a12..d6cdfc91 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java @@ -1,58 +1,52 @@ package com.foxinmy.weixin4j.msg.out; import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.msg.model.Video; import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 回复视频消息 + * * @className VideoMessage * @author jy.hu * @date 2014年4月6日 * @since JDK 1.7 - * @see 回复视频消息 + * @see 回复视频消息 + * @see com.foxinmy.weixin4j.msg.model.Video * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class VideoMessage extends BaseMessage { private static final long serialVersionUID = -1013075358679078381L; - public VideoMessage() { - super(MessageType.video); + public VideoMessage(BaseMessage inMessage) { + super(MessageType.video, inMessage); super.getMsgType().setMessageClass(VideoMessage.class); } @XStreamAlias("Video") private Video video; - public Video getVideo() { - return this.video; + public void pushVideo(String mediaId) { + this.video = new Video(mediaId); } - public void pushVideo(String mediaId, String title, String desc) { - this.video = new Video(); - this.video.desc = desc; - this.video.mediaId = mediaId; - this.video.title = title; + public void setVideo(Video video) { + this.video = video; } - private static class Video { - @XStreamAlias("MediaId") - private String mediaId; - @XStreamAlias("Title") - private String title; - @XStreamAlias("Description") - private String desc; - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Video mediaId=").append(mediaId); - sb.append(" ,title=").append(title); - sb.append(" ,desc=").append(desc).append(")"); - return super.toString(); - } + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Video.class, "mediaId"); + xstream.aliasField("Title", Video.class, "title"); + xstream.aliasField("Description", Video.class, "desc"); + xstream.omitField(Video.class, "thumbMediaId"); + return xstream.toXML(this); } @Override @@ -61,7 +55,7 @@ public class VideoMessage extends BaseMessage { sb.append("[VideoMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,video=").append(getVideo().toString()); + sb.append(" ,video=").append(video.toString()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java index 93052907..dcac1046 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java @@ -1,53 +1,60 @@ package com.foxinmy.weixin4j.msg.out; import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.msg.model.Voice; import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 语音消息 + * * @className VoiceMessage * @author jy.hu * @date 2014年3月23日 * @since JDK 1.7 - * @see 回复语音消息 + * @see 回复语音消息 + * @see com.foxinmy.weixin4j.msg.model.Voice * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class VoiceMessage extends BaseMessage { private static final long serialVersionUID = -7944926238652243793L; - public VoiceMessage() { - super(MessageType.voice); + public VoiceMessage(BaseMessage inMessage) { + super(MessageType.voice, inMessage); super.getMsgType().setMessageClass(VoiceMessage.class); } + + public VoiceMessage(String mediaId, BaseMessage inMessage) { + super(MessageType.voice, inMessage); + super.getMsgType().setMessageClass(VoiceMessage.class); + this.pushMediaId(mediaId); + } + @XStreamAlias("Voice") private Voice voice; - - public Voice getVocie() { - return voice; + + public void pushMediaId(String mediaId) { + this.voice = new Voice(mediaId); } - public void pushMediaId(String mediaId){ - this.voice = new Voice(); - this.voice.setMediaId(mediaId); - } - - private static class Voice { - @XStreamAlias("MediaId") - private String mediaId; - - private void setMediaId(String mediaId) { - this.mediaId = mediaId; - } + + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Voice.class, "mediaId"); + return xstream.toXML(this); } + @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("[VoiceMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,mediaId=").append(getVocie().mediaId); + sb.append(" ,mediaId=").append(voice.getMediaId()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java b/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java new file mode 100644 index 00000000..cf2ab68e --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java @@ -0,0 +1,55 @@ +package com.foxinmy.weixin4j.type; + +/** + * 自定义菜单类型 + * scancode_push 到 location_selec + * 仅支持微信iPhone5.4.1以上版本,和Android5 .4以上版本的微信用户 旧版本微信用户点击后将没有回应 + * 开发者也不能正常接收到事件推送。 + * + * @className ButtonType + * @author jy + * @date 2014年9月30日 + * @since JDK 1.7 + * @see 按钮类型 + */ +public enum ButtonType { + /** + * 点击推事件 用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event + * 的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互; + */ + click, + /** + * 跳转URL 用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的网页URL,可与网页授权获取用户基本信息接口结合,获得用户基本信息。 + */ + view, + /** + * 扫码推事件 用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后显示扫描结果(如果是URL,将进入URL),且会将扫码的结果传给开发者, + * 开发者可以下发消息。 + */ + scancode_push, + /** + * 扫码推事件且弹出“消息接收中”提示框用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后,将扫码的结果传给开发者,同时收起扫一扫工具, + * 然后弹出“消息接收中”提示框,随后可能会收到开发者下发的消息。 + */ + scancode_waitmsg, + /** + * 弹出系统拍照发图用户点击按钮后,微信客户端将调起系统相机,完成拍照操作后,会将拍摄的相片发送给开发者,并推送事件给开发者,同时收起系统相机, + * 随后可能会收到开发者下发的消息。 + */ + pic_sysphoto, + /** + * 弹出拍照或者相册发图用户点击按钮后,微信客户端将弹出选择器供用户选择“拍照”或者“从手机相册选择”。用户选择后即走其他两种流程。 + */ + pic_photo_or_albu, + /** + * 弹出微信相册发图器用户点击按钮后,微信客户端将调起微信相册,完成选择操作后,将选择的相片发送给开发者的服务器,并推送事件给开发者,同时收起相册, + * 随后可能会收到开发者下发的消息。 + */ + pic_weixin, + /** + * 弹出地理位置选择器用户点击按钮后,微信客户端将调起地理位置选择工具,完成选择操作后,将选择的地理位置发送给开发者的服务器,同时收起位置选择工具, + * 随后可能会收到开发者下发的消息。 + */ + location_select; +} diff --git a/src/main/java/com/foxinmy/weixin4j/type/EventType.java b/src/main/java/com/foxinmy/weixin4j/type/EventType.java index a8e864b8..bc85ce90 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/EventType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/EventType.java @@ -3,21 +3,36 @@ package com.foxinmy.weixin4j.type; import com.foxinmy.weixin4j.msg.event.EventMessage; import com.foxinmy.weixin4j.msg.event.LocationEventMessage; import com.foxinmy.weixin4j.msg.event.MassEventMessage; -import com.foxinmy.weixin4j.msg.event.MenuEventMessage; import com.foxinmy.weixin4j.msg.event.ScanEventMessage; import com.foxinmy.weixin4j.msg.event.ScribeEventMessage; +import com.foxinmy.weixin4j.msg.event.TemplatesendjobfinishMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuLocationEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuPhotoEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuScanEventMessage; /** - * * 事件类型 - * @author jy.hu - * + * + * @className EventType + * @author jy + * @date 2014年9月30日 + * @since JDK 1.7 + * @see */ public enum EventType { - subscribe(ScribeEventMessage.class), unsubscribe(ScribeEventMessage.class), - scan(ScanEventMessage.class),click(MenuEventMessage.class),view(MenuEventMessage.class), - location(LocationEventMessage.class),MASSSENDJOBFINISH(MassEventMessage.class); - + subscribe(ScribeEventMessage.class), unsubscribe(ScribeEventMessage.class), scan( + ScanEventMessage.class), scancode_push(MenuScanEventMessage.class), view( + MenuEventMessage.class), scancode_waitmsg( + MenuScanEventMessage.class), pic_sysphoto( + MenuPhotoEventMessage.class), pic_photo_or_album( + MenuPhotoEventMessage.class), pic_weixin( + MenuPhotoEventMessage.class), location_select( + MenuLocationEventMessage.class), click(MenuEventMessage.class), location( + LocationEventMessage.class), massendjobfinish( + MassEventMessage.class), templatesendjobfinish( + TemplatesendjobfinishMessage.class); + private Class extends EventMessage> eventClass; EventType(Class extends EventMessage> eventClass) { diff --git a/src/main/java/com/foxinmy/weixin4j/type/MediaType.java b/src/main/java/com/foxinmy/weixin4j/type/MediaType.java index 1f567181..322ba3ce 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/MediaType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/MediaType.java @@ -6,13 +6,20 @@ package com.foxinmy.weixin4j.type; * 语音(voice):256K,播放长度不超过60s,支持AMR\MP3格式 * 视频(video):1MB,支持MP4格式 * 缩略图(thumb):64KB,支持JPG格式 - * 媒体文件在后台保存时间为3天,即3天后media_id失效 + * + * 媒体文件在后台保存时间为3天,即3天后media_id失效 + * + * * @author jy.hu * @date 2014年4月2日 * @since JDK 1.7 */ public enum MediaType { - image("image/jpeg",".jpg"), voice("binary/octet-stream","amr"), vedio("binary/octet-stream","mp4"), thumb("image/jpeg","jpg"); + image("image/jpeg", "jpg"), voice("binary/octet-stream", "amr"), vedio( + "binary/octet-stream", "mp4"), thumb("image/jpeg", "jpg"), text( + "application/json", ""), music("binary/octet-stream", "mp3"), news( + "application/json", ""), mpnews("application/json", ""), mpvideo( + "binary/octet-stream", ""); MediaType(String contentType, String formatType) { this.contentType = contentType; @@ -26,6 +33,7 @@ public enum MediaType { } private String formatType; + public String getFormatType() { return formatType; } diff --git a/src/main/java/com/foxinmy/weixin4j/type/MessageType.java b/src/main/java/com/foxinmy/weixin4j/type/MessageType.java index 21a7b6dc..a883d993 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/MessageType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/MessageType.java @@ -10,6 +10,7 @@ import com.foxinmy.weixin4j.msg.in.VideoMessage; import com.foxinmy.weixin4j.msg.in.VoiceMessage; import com.foxinmy.weixin4j.msg.out.ArticleMessage; import com.foxinmy.weixin4j.msg.out.MusicMessage; +import com.foxinmy.weixin4j.msg.out.TransferMessage; /** * @@ -20,9 +21,13 @@ import com.foxinmy.weixin4j.msg.out.MusicMessage; */ public enum MessageType { // 接收到的消息类型 - text(TextMessage.class), image(ImageMessage.class), voice(VoiceMessage.class), video(VideoMessage.class), location(LocationMessage.class), link(LinkMessage.class), event(EventMessage.class), + text(TextMessage.class), image(ImageMessage.class), voice( + VoiceMessage.class), video(VideoMessage.class), location( + LocationMessage.class), link(LinkMessage.class), event( + EventMessage.class), // 发送的消息类型 - music(MusicMessage.class), news(ArticleMessage.class); + music(MusicMessage.class), news(ArticleMessage.class), transfer_customer_service( + TransferMessage.class); private Class extends BaseMessage> messageClass; MessageType(Class extends BaseMessage> messageClass) { diff --git a/src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java b/src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java similarity index 91% rename from src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java rename to src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java index f428c33b..b419bd1c 100644 --- a/src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java +++ b/src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java @@ -8,8 +8,8 @@ import java.util.regex.Pattern; import com.foxinmy.weixin4j.WeixinProxy; -public class WeixinConfig { - public WeixinConfig() { +public class ConfigUtil { + public ConfigUtil() { } private static Properties props = new Properties(); @@ -38,7 +38,6 @@ public class WeixinConfig { m.appendTail(sb); return sb.toString(); } - public static void main(String[] args) { System.out.println(getValue("api_token_uri")); } diff --git a/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java b/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java new file mode 100644 index 00000000..60eae107 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java @@ -0,0 +1,67 @@ +package com.foxinmy.weixin4j.util; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.Writer; +import java.nio.charset.Charset; + +/** + * IOUtil + * + * @className IOUtil + * @author jy.hu + * @date 2014年9月22日 + * @since JDK 1.7 + * @see org.apache.commons.io.IOUtils + */ +public class IOUtil { + + private static final int EOF = -1; + private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; + + public static byte[] toByteArray(Reader input) throws IOException { + return toByteArray(input, Charset.defaultCharset()); + } + + public static byte[] toByteArray(Reader input, Charset encoding) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + copy(input, output, encoding); + return output.toByteArray(); + } + + public static void copy(Reader input, OutputStream output, Charset encoding) throws IOException { + OutputStreamWriter out = new OutputStreamWriter(output, encoding); + copyLarge(input, out, new char[DEFAULT_BUFFER_SIZE]); + out.flush(); + } + + public static byte[] toByteArray(InputStream input) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + copyLarge(input, output, new byte[DEFAULT_BUFFER_SIZE]); + return output.toByteArray(); + } + + private static long copyLarge(InputStream input, OutputStream output, byte[] buffer) throws IOException { + long count = 0; + int n = 0; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } + + private static long copyLarge(Reader input, Writer output, char[] buffer) throws IOException { + long count = 0; + int n = 0; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java b/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java new file mode 100644 index 00000000..82a23ef3 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java @@ -0,0 +1,135 @@ +package com.foxinmy.weixin4j.util; + +import java.io.InputStream; +import java.util.Arrays; + +import org.apache.commons.codec.digest.DigestUtils; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.DocumentHelper; +import org.dom4j.io.SAXReader; +import org.jsoup.helper.StringUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.type.EventType; +import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; + +public class MessageUtil { + + private final static Logger log = LoggerFactory.getLogger(MessageUtil.class); + + /** + * 验证微信签名 + * + * @param echostr + * 随机字符串 + * @param timestamp + * 时间戳 + * @param nonce + * 随机数 + * @param signature + * 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数 + * @return 开发者通过检验signature对请求进行相关校验。若确认此次GET请求来自微信服务器 + * 请原样返回echostr参数内容,则接入生效 成为开发者成功,否则接入失败 + * @see 接入指南 + */ + public static String signature(String echostr, String timestamp, String nonce, String signature) { + String app_token = ConfigUtil.getValue("app_token"); + if (StringUtil.isBlank(app_token)) { + log.error("signature fail : token is null!"); + return null; + } + if (StringUtil.isBlank(echostr) || StringUtil.isBlank(timestamp) || StringUtil.isBlank(nonce)) { + log.error("signature fail : invalid parameter!"); + return null; + } + String _signature = null; + try { + String[] a = { app_token, timestamp, nonce }; + Arrays.sort(a); + StringBuilder sb = new StringBuilder(3); + for (String str : a) { + sb.append(str); + } + _signature = DigestUtils.sha1Hex(sb.toString()); + } catch (Exception e) { + log.error("signature error", e); + } + if (signature.equals(_signature)) { + return echostr; + } else { + log.error("signature fail : invalid signature!"); + return null; + } + } + + /** + * xml消息转换为消息对象 + * + * 微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次 + * + * + * @param xml + * 消息字符串 + * @return 消息对象 + * @throws DocumentException + * @see 验证消息的合法性 + * @see 普通消息 + * @see 事件触发 + * @see com.foxinmy.weixin4j.type.MessageType + * @see com.feican.weixin.msg.BaeMessage + * @see com.foxinmy.weixin4j.msg.TextMessage + * @see com.foxinmy.weixin4j.msg.in.ImageMessage + * @see com.foxinmy.weixin4j.msg.in.VoiceMessage + * @see com.foxinmy.weixin4j.msg.in.VideoMessage + * @see com.foxinmy.weixin4j.msg.in.LocationMessage + * @see com.foxinmy.weixin4j.msg.in.LinkMessage + * @see com.foxinmy.weixin4j.msg.event.ScribeEventMessage + * @see com.foxinmy.weixin4j.msg.event.ScanEventMessage + * @see com.foxinmy.weixin4j.msg.event.LocationEventMessage + * @see com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage + */ + public static BaseMessage xml2msg(String xml) throws DocumentException { + if (StringUtil.isBlank(xml)) + return null; + Document doc = DocumentHelper.parseText(xml); + String type = doc.selectSingleNode("/xml/MsgType").getStringValue(); + if (StringUtil.isBlank(type)) { + return null; + } + XStream xstream = new XStream(); + MessageType messageType = MessageType.valueOf(type.toLowerCase()); + Class extends BaseMessage> messageClass = messageType.getMessageClass(); + if (messageType == MessageType.event) { + type = doc.selectSingleNode("/xml/Event").getStringValue(); + messageClass = EventType.valueOf(type.toLowerCase()).getEventClass(); + } + xstream.alias("xml", messageClass); + xstream.ignoreUnknownElements(); + xstream.autodetectAnnotations(true); + xstream.processAnnotations(messageClass); + return xstream.fromXML(doc.asXML(), messageClass); + } + + /** + * xml消息转换为消息对象 + * + * @param inputStream + * 带消息字符串的输入流 + * @return 消息对象 + * @throws DocumentException + * @see {@link com.foxinmy.weixin4j.WeixinProxy#xml2msg(String)} + */ + public static BaseMessage xml2msg(InputStream inputStream) throws DocumentException { + SAXReader reader = new SAXReader(); + Document doc = reader.read(inputStream); + return xml2msg(doc.asXML()); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java b/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java deleted file mode 100644 index 19fd87e4..00000000 --- a/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.foxinmy.weixin4j.util; - -public class WeixinUtil { - - public static boolean isBlank(String str) { - return str == null || str.isEmpty(); - } -} diff --git a/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java b/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java index 5c0186c6..4a811a6c 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java @@ -9,7 +9,7 @@ import org.junit.Test; import com.foxinmy.weixin4j.WeixinProxy; import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.model.Button; -import com.foxinmy.weixin4j.model.Button.BtnType; +import com.foxinmy.weixin4j.type.ButtonType; /** * 自定义菜单测试 @@ -31,7 +31,7 @@ public class ButtonTest { List btnList = new ArrayList(); Button b = new Button("test"); - b.setType(BtnType.click); + b.setType(ButtonType.click); b.setKey("123"); btnList.add(b); diff --git a/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java b/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java index 8b78305e..bb6bec88 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java @@ -50,7 +50,7 @@ public class GroupTest { @Test public void getid() { try { - System.out.println(weixinProxy.findGroupByOpenId("owGBft_vbBbOaQOmpEUE4xDLeRSU")); + System.out.println(weixinProxy.getGroupByOpenId("owGBft_vbBbOaQOmpEUE4xDLeRSU")); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); diff --git a/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java b/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java new file mode 100644 index 00000000..6d34a733 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java @@ -0,0 +1,22 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Test; + +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.http.HttpRequest; + +public class HttpTest { + private static HttpRequest request; + static { + request = new HttpRequest(); + } + + @Test + public void test(){ + try { + System.out.println(request.get("http://www.baidu.com")); + } catch (WeixinException e) { + e.printStackTrace(); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java b/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java index f907fa3d..d54e649b 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java @@ -31,7 +31,7 @@ public class MediaTest { File file = new File("D:\\test.jpg"); try { System.out.println(weixinProxy.uploadMedia(file, MediaType.image)); - //usAxLEJxFXAjXVlLu_BSw0GvS2YEEoGeelRBybNZBGvMsdxiIcD1F9yBWYd9jVZx + //vvU_AUtovWyfAxQ8J1DsCoNMtK6U_bUmTpe6lpINUOVRLvt_7rtO4zxzBpPgkmay } catch (WeixinException e) { System.out.println(e.getErrorMsg()); } @@ -40,7 +40,7 @@ public class MediaTest { @Test public void download() { try { - System.out.println(weixinProxy.downloadMedia("usAxLEJxFXAjXVlLu_BSw0GvS2YEEoGeelRBybNZBGvMsdxiIcD1F9yBWYd9jVZx", MediaType.image)); + System.out.println(weixinProxy.downloadMedia("vvU_AUtovWyfAxQ8J1DsCoNMtK6U_bUmTpe6lpINUOVRLvt_7rtO4zxzBpPgkmay", MediaType.image)); } catch (WeixinException e) { System.out.println(e.getErrorMsg()); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java new file mode 100644 index 00000000..2cd36584 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java @@ -0,0 +1,194 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Test; + +import com.foxinmy.weixin4j.util.MessageUtil; + +/** + * 接收事件消息格式测试 + * + * @author jy.hu + * @date 2014年3月24日 + * @since JDK 1.7 + */ +public class MessageEventInTest { + + private StringBuilder xmlSb = new StringBuilder(); + + /***************** event message *********************/ + @Test + public void scribe() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void scan() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void scan_scribe() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void location1() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("23.137466"); + xmlSb.append("113.352425"); + xmlSb.append("119.385040"); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_click() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_link() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_scan() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_photo() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("1"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_location() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java index 39269754..fdd40042 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java @@ -1,134 +1,19 @@ package com.foxinmy.weixin4j.test; -import org.junit.Before; import org.junit.Test; -import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.util.MessageUtil; /** - * 接收消息格式测试 + * 接受一般消息格式测试 + * * @author jy.hu * @date 2014年3月24日 * @since JDK 1.7 */ public class MessageInTest { + private StringBuilder xmlSb = new StringBuilder(); - private WeixinProxy weixinProxy; - - @Before - public void init(){ - weixinProxy = new WeixinProxy(); - } - - /***************** event message *********************/ - @Test - public void scribe() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void scan() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - @Test - public void scan_scribe() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void location1() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("23.137466"); - xmlSb.append("113.352425"); - xmlSb.append("119.385040"); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void menu_click() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void menu_link() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } /***************** common message *********************/ @@ -144,7 +29,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -163,7 +48,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -182,7 +67,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -202,7 +87,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -221,7 +106,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -242,7 +127,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -262,7 +147,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java new file mode 100644 index 00000000..8f6a130f --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java @@ -0,0 +1,114 @@ +package com.foxinmy.weixin4j.test; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.model.MpArticle; +import com.foxinmy.weixin4j.type.MediaType; + +/** + * 群发消息 + * + * @className MpNewsTest + * @author jy + * @date 2014年4月27日 + * @since JDK 1.7 + * @see + */ +public class MessageMassTest { + private WeixinProxy weixinProxy; + + @Before + public void init() { + this.weixinProxy = new WeixinProxy(); + } + + @Test + public void uploadArticle() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.uploadArticle(articles); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void uploadVideo() { + try { + weixinProxy.uploadVideo("mediaId", "title", "desc"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massByGroup() { + try { + weixinProxy.massByGroup("123", MediaType.image, "groupId"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massByOpenIds() { + try { + weixinProxy.massByOpenIds("123", MediaType.image, "openIds"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massArticleByGroup() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.massArticleByGroup(articles, "0"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massArticleByOpenIds() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.massArticleByOpenIds(articles, + "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void deleteMass() { + try { + weixinProxy.deleteMassNews("34182"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java index f3be10bb..59aed8de 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java @@ -7,6 +7,7 @@ import org.junit.Test; import com.foxinmy.weixin4j.WeixinProxy; import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.msg.model.Music; import com.foxinmy.weixin4j.msg.notify.ArticleNotify; import com.foxinmy.weixin4j.msg.notify.BaseNotify; import com.foxinmy.weixin4j.msg.notify.ImageNotify; @@ -41,27 +42,29 @@ public class MessageNotifyTest { @Test public void image() { - ImageNotify notify = new ImageNotify("123", "to"); + ImageNotify notify = new ImageNotify("to"); + notify.pushMediaId("123"); System.out.println(notify.toJson()); } @Test public void voice() { - VoiceNotify notify = new VoiceNotify("123", "to"); + VoiceNotify notify = new VoiceNotify("to"); + notify.pushMediaId("123"); System.out.println(notify.toJson()); } @Test public void video() { VideoNotify notify = new VideoNotify("to"); - notify.pushVideo("123", "title", "desc"); + notify.pushVideo("123","m123"); System.out.println(notify.toJson()); } @Test public void music() { MusicNotify notify = new MusicNotify("to"); - notify.pushMusic("title", "desc", "url", "hqUrl", "mediaId"); + notify.pushMusic("url", "hqUrl", "mediaId"); System.out.println(notify.toJson()); } @@ -74,16 +77,27 @@ public class MessageNotifyTest { } @Test - public void send() { - BaseNotify t = new TextNotify("哈哈哈哈", "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + public void send1() { + BaseNotify notify = new TextNotify("哈哈哈哈", "owGBft_vbBbOaQOmpEUE4xDLeRSU"); try { - weixinProxy.sendNotify(t); + weixinProxy.sendNotify(notify); String mediaId = weixinProxy.uploadMedia(new File("D:\\test.jpg"), MediaType.image); - t = new ImageNotify(mediaId, "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + ImageNotify t = new ImageNotify("owGBft_vbBbOaQOmpEUE4xDLeRSU"); + t.pushMediaId(mediaId); weixinProxy.sendNotify(t); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); } } + + @Test + public void send2() { + try { + weixinProxy.sendNotify("to",new Music("thumbMediaId")); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java index 00021aa0..ddb309d4 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java @@ -1,7 +1,9 @@ package com.foxinmy.weixin4j.test; +import org.junit.Before; import org.junit.Test; +import com.foxinmy.weixin4j.msg.BaseMessage; import com.foxinmy.weixin4j.msg.TextMessage; import com.foxinmy.weixin4j.msg.out.ArticleMessage; import com.foxinmy.weixin4j.msg.out.ImageMessage; @@ -17,56 +19,52 @@ import com.foxinmy.weixin4j.msg.out.VoiceMessage; * @since JDK 1.7 */ public class MessageOutTest { + private BaseMessage inMessage; + + @Before + public void init() { + this.inMessage = new TextMessage(); + this.inMessage.setFromUserName("fromusername"); + this.inMessage.setToUserName("tousername"); + } + @Test public void text() { - TextMessage message = new TextMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.setContent("text message"); + TextMessage message = new TextMessage("text", inMessage); System.out.println(message.toXml()); } @Test public void image() { - ImageMessage message = new ImageMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + ImageMessage message = new ImageMessage(inMessage); message.pushMediaId("mediaId"); System.out.println(message.toXml()); } @Test public void voice() { - VoiceMessage message = new VoiceMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + VoiceMessage message = new VoiceMessage(inMessage); message.pushMediaId("mediaId"); System.out.println(message.toXml()); } - + @Test public void video() { - VideoMessage message = new VideoMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.pushVideo("mediaId", "title", "title"); + VideoMessage message = new VideoMessage(inMessage); + message.pushVideo("mediaId"); System.out.println(message.toXml()); } - + @Test public void music() { - MusicMessage message = new MusicMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.pushMusic("title", "desc", "url", "hqurl", "mediaId"); + MusicMessage message = new MusicMessage(inMessage); + message.pushMusic("mediaId"); System.out.println(message.toXml()); } - + @Test public void article() { - ArticleMessage message = new ArticleMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + ArticleMessage message = new ArticleMessage(inMessage); message.pushArticle("title1", "desc1", "picUrl1", "url1"); message.pushArticle("title2", "desc2", "picUrl2", "url2"); System.out.println(message.toXml()); diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java new file mode 100644 index 00000000..b8165a91 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java @@ -0,0 +1,30 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Before; +import org.junit.Test; + +import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.msg.out.TemplateMessage; + +public class MessageTemplTest { + private WeixinProxy weixinProxy; + + @Before + public void init() { + this.weixinProxy = new WeixinProxy(); + } + + @Test + public void test() { + TemplateMessage tplMessage = new TemplateMessage("touser", + "template_id", "url"); + tplMessage.pushData("name", "fox"); + System.out.print(tplMessage.toJson()); + try { + System.out.print(weixinProxy.sendTplMessage(tplMessage)); + } catch (WeixinException e) { + System.out.println(e.getErrorMsg()); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java b/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java deleted file mode 100644 index 5fa1ec67..00000000 --- a/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.foxinmy.weixin4j.test; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; - -import com.foxinmy.weixin4j.WeixinProxy; -import com.foxinmy.weixin4j.exception.WeixinException; -import com.foxinmy.weixin4j.model.MpArticle; -import com.foxinmy.weixin4j.type.MediaType; - -/** - * 群发消息 - * - * @className MpNewsTest - * @author jy - * @date 2014年4月27日 - * @since JDK 1.7 - * @see - */ -public class MpNewsTest { - private WeixinProxy weixinProxy; - - @Before - public void init() { - this.weixinProxy = new WeixinProxy(); - } - - @Test - public void massByGroup(){ - List articles = new ArrayList(); - try { - String thumbMediaId = weixinProxy.uploadMedia(new File("/tmp/test.jpg"), MediaType.image); - articles.add(new MpArticle(thumbMediaId, "title", "content")); - weixinProxy.massNewsByGroup(articles, "0"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } - - @Test - public void massByOpenIds(){ - List articles = new ArrayList(); - try { - String thumbMediaId = weixinProxy.uploadMedia(new File("/tmp/test.jpg"), MediaType.image); - articles.add(new MpArticle(thumbMediaId, "title", "content")); - weixinProxy.massNewsByOpenIds(articles, "owGBft_vbBbOaQOmpEUE4xDLeRSU"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } - - @Test - public void deleteMass(){ - try { - weixinProxy.deleteMassNews("34182"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } -} diff --git a/src/test/java/com/foxinmy/weixin4j/test/QRTest.java b/src/test/java/com/foxinmy/weixin4j/test/QRTest.java index 11934fa9..f18d1aa7 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/QRTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/QRTest.java @@ -25,10 +25,10 @@ public class QRTest { @Test public void temp_qr() { - QRParameter qr = new QRParameter(1200, QRType.QR_SCENE, 1); + QRParameter qr = new QRParameter(1200, QRType.TEMPORARY, 2); try { System.out.println(qr.toJson()); - weixinProxy.getQR(qr); + System.out.println(weixinProxy.getQR(qr)); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); @@ -37,10 +37,10 @@ public class QRTest { @Test public void forever_qr() { - QRParameter qr = new QRParameter(QRType.QR_LIMIT_SCENE, 1); + QRParameter qr = new QRParameter(QRType.PERMANENCE, 1); try { System.out.println(qr.toJson()); - weixinProxy.getQR(qr); + System.out.println(weixinProxy.getQR(qr)); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java b/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java index 37d549d7..a2f8a266 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java @@ -3,7 +3,8 @@ package com.foxinmy.weixin4j.test; import org.junit.Before; import org.junit.Test; -import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.api.token.FileTokenApi; +import com.foxinmy.weixin4j.api.token.TokenApi; import com.foxinmy.weixin4j.exception.WeixinException; /** @@ -14,17 +15,17 @@ import com.foxinmy.weixin4j.exception.WeixinException; * @since JDK 1.7 */ public class TokenTest { - private WeixinProxy weixinProxy; + private TokenApi tokenApi; @Before public void init() { - weixinProxy = new WeixinProxy(); + tokenApi = new FileTokenApi(); } @Test public void getToken() { try { - System.out.println(weixinProxy.getToken()); + System.out.println(tokenApi.getToken()); } catch (WeixinException e) { e.printStackTrace(); }
(); } + this.articles.addFirst(new Article(title, desc, picUrl, url)); + } - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Article ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,picUrl=").append(picUrl); - sb.append(" ,url=").append(url).append(")"); - return sb.toString(); + public void pushLastArticle(String title, String desc, String picUrl, + String url) { + if (this.articles == null) { + this.articles = new LinkedList(); } + this.articles.addLast(new Article(title, desc, picUrl, url)); + } + + public Article removeLastArticle() { + if (this.articles != null) { + return this.articles.removeLast(); + } + return null; + } + + 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() { + 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 diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java index 2da50a01..fb58ecb8 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java @@ -1,38 +1,50 @@ 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 回复图片消息 + * @see 回复图片消息 + * @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() { - super(MessageType.image); + public ImageMessage(BaseMessage inMessage) { + super(MessageType.image, inMessage); super.getMsgType().setMessageClass(ImageMessage.class); } + 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(); - this.image.mediaId = mediaId; + this.image = new Image(mediaId); } - private static class Image { - @XStreamAlias("MediaId") - private String mediaId; + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Image.class, "mediaId"); + return xstream.toXML(this); } @Override @@ -41,7 +53,7 @@ public class ImageMessage extends BaseMessage { sb.append("[ImageMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,mediaId=").append(this.image.mediaId); + sb.append(" ,mediaId=").append(this.image.getMediaId()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java index c790b9ac..419f32d6 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java @@ -1,74 +1,61 @@ 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 回复音乐消息 + * @see 回复音乐消息 + * @see com.foxinmy.weixin4j.msg.model.Music * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class MusicMessage extends BaseMessage { private static final long serialVersionUID = 4384403772658796395L; - public MusicMessage() { - super(MessageType.music); + public MusicMessage(BaseMessage inMessage) { + super(MessageType.music, inMessage); } @XStreamAlias("Music") private Music music; - public Music getMusic() { - return this.music; + public void pushMusic(String mediaId) { + this.music = new Music(mediaId); } - public void pushMusic(String title, String desc, String url, String hqUrl, String mediaId) { - this.music = new Music(); - this.music.thumbMediaId = mediaId; - this.music.desc = desc; - this.music.hqMusicUrl = hqUrl; - this.music.MusicURL = url; - this.music.title = title; + public void setMusic(Music music) { + this.music = music; } - private static class Music { - @XStreamAlias("Title") - private String title; // 音乐标题 - @XStreamAlias("Description") - private String desc; // 音乐描述 - @XStreamAlias("MusicURL") - private String MusicURL; // 音乐链接 - @XStreamAlias("HQMusicUrl") - private String hqMusicUrl; // 高质量音乐链接,WIFI环境优先使用该链接播放音乐 - @XStreamAlias("ThumbMediaId") - private String thumbMediaId; // 缩略图的媒体id,通过上传多媒体文件,得到的id - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Music ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,musicURL=").append(MusicURL); - sb.append(" ,hqMusicUrl=").append(hqMusicUrl); - sb.append(" ,thumbMediaId=").append(thumbMediaId).append(")"); - return sb.toString(); - } + @Override + public String 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(getMusic().toString()); + sb.append(" ,music=").append(music.toString()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java new file mode 100644 index 00000000..3721504b --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java @@ -0,0 +1,117 @@ +package com.foxinmy.weixin4j.msg.out; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +import com.alibaba.fastjson.JSON; + +/** + * 模板消息 + * + * @className TemplateMessage + * @author jy + * @date 2014年9月29日 + * @since JDK 1.7 + * @see + */ +public class TemplateMessage implements Serializable { + + private static final long serialVersionUID = 7950608393821661436L; + + private String touser; + private String template_id; + private String url; + private String topcolor = "#FF0000"; + private Map data; + + public void pushData(String key, String value) { + this.data.put(key, new Item(value)); + } + + public TemplateMessage(String touser, String template_id, String url) { + this.touser = touser; + this.template_id = template_id; + this.url = url; + this.data = new HashMap(); + } + + private static class Item implements Serializable { + private static final long serialVersionUID = 1L; + private String value; + private String color; + + public Item(String value) { + this(value, "#173177"); + } + + public Item(String value, String color) { + this.value = value; + this.color = color; + } + + public String getValue() { + return value; + } + + public String getColor() { + return color; + } + + @Override + public String toString() { + return "$ [value=" + getValue() + ", color=" + getColor() + "]"; + } + } + + public String getTouser() { + return touser; + } + + public void setTouser(String touser) { + this.touser = touser; + } + + public String getTemplate_id() { + return template_id; + } + + public void setTemplate_id(String template_id) { + this.template_id = template_id; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getTopcolor() { + return topcolor; + } + + public void setTopcolor(String topcolor) { + this.topcolor = topcolor; + } + + public Map getData() { + return data; + } + + public void setData(Map data) { + this.data = data; + } + + @Override + public String toString() { + return "TemplateMessage [touser=" + touser + ", template_id=" + + template_id + ", url=" + url + ", topcolor=" + topcolor + + ", data=" + data + "]"; + } + + public String toJson() { + return JSON.toJSONString(this); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java new file mode 100644 index 00000000..b89621aa --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java @@ -0,0 +1,25 @@ +package com.foxinmy.weixin4j.msg.out; + +import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.type.MessageType; + +/** + * 转移消息到多客服端消息 + * + * @className TransferMessage + * @author jy.hu + * @date 2014年6月28日 + * @since JDK 1.7 + * @see 多客服转移消息 + * @see com.foxinmy.weixin4j.msg.BaseMessage + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + */ +public class TransferMessage extends BaseMessage { + + private static final long serialVersionUID = -5479496746108594940L; + + public TransferMessage(BaseMessage inMessage) { + super(MessageType.transfer_customer_service,inMessage); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java index d16c5a12..d6cdfc91 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java @@ -1,58 +1,52 @@ package com.foxinmy.weixin4j.msg.out; import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.msg.model.Video; import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 回复视频消息 + * * @className VideoMessage * @author jy.hu * @date 2014年4月6日 * @since JDK 1.7 - * @see 回复视频消息 + * @see 回复视频消息 + * @see com.foxinmy.weixin4j.msg.model.Video * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class VideoMessage extends BaseMessage { private static final long serialVersionUID = -1013075358679078381L; - public VideoMessage() { - super(MessageType.video); + public VideoMessage(BaseMessage inMessage) { + super(MessageType.video, inMessage); super.getMsgType().setMessageClass(VideoMessage.class); } @XStreamAlias("Video") private Video video; - public Video getVideo() { - return this.video; + public void pushVideo(String mediaId) { + this.video = new Video(mediaId); } - public void pushVideo(String mediaId, String title, String desc) { - this.video = new Video(); - this.video.desc = desc; - this.video.mediaId = mediaId; - this.video.title = title; + public void setVideo(Video video) { + this.video = video; } - private static class Video { - @XStreamAlias("MediaId") - private String mediaId; - @XStreamAlias("Title") - private String title; - @XStreamAlias("Description") - private String desc; - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Video mediaId=").append(mediaId); - sb.append(" ,title=").append(title); - sb.append(" ,desc=").append(desc).append(")"); - return super.toString(); - } + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Video.class, "mediaId"); + xstream.aliasField("Title", Video.class, "title"); + xstream.aliasField("Description", Video.class, "desc"); + xstream.omitField(Video.class, "thumbMediaId"); + return xstream.toXML(this); } @Override @@ -61,7 +55,7 @@ public class VideoMessage extends BaseMessage { sb.append("[VideoMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,video=").append(getVideo().toString()); + sb.append(" ,video=").append(video.toString()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java index 93052907..dcac1046 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java @@ -1,53 +1,60 @@ package com.foxinmy.weixin4j.msg.out; import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.msg.model.Voice; import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 语音消息 + * * @className VoiceMessage * @author jy.hu * @date 2014年3月23日 * @since JDK 1.7 - * @see 回复语音消息 + * @see 回复语音消息 + * @see com.foxinmy.weixin4j.msg.model.Voice * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class VoiceMessage extends BaseMessage { private static final long serialVersionUID = -7944926238652243793L; - public VoiceMessage() { - super(MessageType.voice); + public VoiceMessage(BaseMessage inMessage) { + super(MessageType.voice, inMessage); super.getMsgType().setMessageClass(VoiceMessage.class); } + + public VoiceMessage(String mediaId, BaseMessage inMessage) { + super(MessageType.voice, inMessage); + super.getMsgType().setMessageClass(VoiceMessage.class); + this.pushMediaId(mediaId); + } + @XStreamAlias("Voice") private Voice voice; - - public Voice getVocie() { - return voice; + + public void pushMediaId(String mediaId) { + this.voice = new Voice(mediaId); } - public void pushMediaId(String mediaId){ - this.voice = new Voice(); - this.voice.setMediaId(mediaId); - } - - private static class Voice { - @XStreamAlias("MediaId") - private String mediaId; - - private void setMediaId(String mediaId) { - this.mediaId = mediaId; - } + + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Voice.class, "mediaId"); + return xstream.toXML(this); } + @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("[VoiceMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,mediaId=").append(getVocie().mediaId); + sb.append(" ,mediaId=").append(voice.getMediaId()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java b/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java new file mode 100644 index 00000000..cf2ab68e --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java @@ -0,0 +1,55 @@ +package com.foxinmy.weixin4j.type; + +/** + * 自定义菜单类型 + * scancode_push 到 location_selec + * 仅支持微信iPhone5.4.1以上版本,和Android5 .4以上版本的微信用户 旧版本微信用户点击后将没有回应 + * 开发者也不能正常接收到事件推送。 + * + * @className ButtonType + * @author jy + * @date 2014年9月30日 + * @since JDK 1.7 + * @see 按钮类型 + */ +public enum ButtonType { + /** + * 点击推事件 用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event + * 的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互; + */ + click, + /** + * 跳转URL 用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的网页URL,可与网页授权获取用户基本信息接口结合,获得用户基本信息。 + */ + view, + /** + * 扫码推事件 用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后显示扫描结果(如果是URL,将进入URL),且会将扫码的结果传给开发者, + * 开发者可以下发消息。 + */ + scancode_push, + /** + * 扫码推事件且弹出“消息接收中”提示框用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后,将扫码的结果传给开发者,同时收起扫一扫工具, + * 然后弹出“消息接收中”提示框,随后可能会收到开发者下发的消息。 + */ + scancode_waitmsg, + /** + * 弹出系统拍照发图用户点击按钮后,微信客户端将调起系统相机,完成拍照操作后,会将拍摄的相片发送给开发者,并推送事件给开发者,同时收起系统相机, + * 随后可能会收到开发者下发的消息。 + */ + pic_sysphoto, + /** + * 弹出拍照或者相册发图用户点击按钮后,微信客户端将弹出选择器供用户选择“拍照”或者“从手机相册选择”。用户选择后即走其他两种流程。 + */ + pic_photo_or_albu, + /** + * 弹出微信相册发图器用户点击按钮后,微信客户端将调起微信相册,完成选择操作后,将选择的相片发送给开发者的服务器,并推送事件给开发者,同时收起相册, + * 随后可能会收到开发者下发的消息。 + */ + pic_weixin, + /** + * 弹出地理位置选择器用户点击按钮后,微信客户端将调起地理位置选择工具,完成选择操作后,将选择的地理位置发送给开发者的服务器,同时收起位置选择工具, + * 随后可能会收到开发者下发的消息。 + */ + location_select; +} diff --git a/src/main/java/com/foxinmy/weixin4j/type/EventType.java b/src/main/java/com/foxinmy/weixin4j/type/EventType.java index a8e864b8..bc85ce90 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/EventType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/EventType.java @@ -3,21 +3,36 @@ package com.foxinmy.weixin4j.type; import com.foxinmy.weixin4j.msg.event.EventMessage; import com.foxinmy.weixin4j.msg.event.LocationEventMessage; import com.foxinmy.weixin4j.msg.event.MassEventMessage; -import com.foxinmy.weixin4j.msg.event.MenuEventMessage; import com.foxinmy.weixin4j.msg.event.ScanEventMessage; import com.foxinmy.weixin4j.msg.event.ScribeEventMessage; +import com.foxinmy.weixin4j.msg.event.TemplatesendjobfinishMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuLocationEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuPhotoEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuScanEventMessage; /** - * * 事件类型 - * @author jy.hu - * + * + * @className EventType + * @author jy + * @date 2014年9月30日 + * @since JDK 1.7 + * @see */ public enum EventType { - subscribe(ScribeEventMessage.class), unsubscribe(ScribeEventMessage.class), - scan(ScanEventMessage.class),click(MenuEventMessage.class),view(MenuEventMessage.class), - location(LocationEventMessage.class),MASSSENDJOBFINISH(MassEventMessage.class); - + subscribe(ScribeEventMessage.class), unsubscribe(ScribeEventMessage.class), scan( + ScanEventMessage.class), scancode_push(MenuScanEventMessage.class), view( + MenuEventMessage.class), scancode_waitmsg( + MenuScanEventMessage.class), pic_sysphoto( + MenuPhotoEventMessage.class), pic_photo_or_album( + MenuPhotoEventMessage.class), pic_weixin( + MenuPhotoEventMessage.class), location_select( + MenuLocationEventMessage.class), click(MenuEventMessage.class), location( + LocationEventMessage.class), massendjobfinish( + MassEventMessage.class), templatesendjobfinish( + TemplatesendjobfinishMessage.class); + private Class extends EventMessage> eventClass; EventType(Class extends EventMessage> eventClass) { diff --git a/src/main/java/com/foxinmy/weixin4j/type/MediaType.java b/src/main/java/com/foxinmy/weixin4j/type/MediaType.java index 1f567181..322ba3ce 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/MediaType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/MediaType.java @@ -6,13 +6,20 @@ package com.foxinmy.weixin4j.type; * 语音(voice):256K,播放长度不超过60s,支持AMR\MP3格式 * 视频(video):1MB,支持MP4格式 * 缩略图(thumb):64KB,支持JPG格式 - * 媒体文件在后台保存时间为3天,即3天后media_id失效 + * + * 媒体文件在后台保存时间为3天,即3天后media_id失效 + * + * * @author jy.hu * @date 2014年4月2日 * @since JDK 1.7 */ public enum MediaType { - image("image/jpeg",".jpg"), voice("binary/octet-stream","amr"), vedio("binary/octet-stream","mp4"), thumb("image/jpeg","jpg"); + image("image/jpeg", "jpg"), voice("binary/octet-stream", "amr"), vedio( + "binary/octet-stream", "mp4"), thumb("image/jpeg", "jpg"), text( + "application/json", ""), music("binary/octet-stream", "mp3"), news( + "application/json", ""), mpnews("application/json", ""), mpvideo( + "binary/octet-stream", ""); MediaType(String contentType, String formatType) { this.contentType = contentType; @@ -26,6 +33,7 @@ public enum MediaType { } private String formatType; + public String getFormatType() { return formatType; } diff --git a/src/main/java/com/foxinmy/weixin4j/type/MessageType.java b/src/main/java/com/foxinmy/weixin4j/type/MessageType.java index 21a7b6dc..a883d993 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/MessageType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/MessageType.java @@ -10,6 +10,7 @@ import com.foxinmy.weixin4j.msg.in.VideoMessage; import com.foxinmy.weixin4j.msg.in.VoiceMessage; import com.foxinmy.weixin4j.msg.out.ArticleMessage; import com.foxinmy.weixin4j.msg.out.MusicMessage; +import com.foxinmy.weixin4j.msg.out.TransferMessage; /** * @@ -20,9 +21,13 @@ import com.foxinmy.weixin4j.msg.out.MusicMessage; */ public enum MessageType { // 接收到的消息类型 - text(TextMessage.class), image(ImageMessage.class), voice(VoiceMessage.class), video(VideoMessage.class), location(LocationMessage.class), link(LinkMessage.class), event(EventMessage.class), + text(TextMessage.class), image(ImageMessage.class), voice( + VoiceMessage.class), video(VideoMessage.class), location( + LocationMessage.class), link(LinkMessage.class), event( + EventMessage.class), // 发送的消息类型 - music(MusicMessage.class), news(ArticleMessage.class); + music(MusicMessage.class), news(ArticleMessage.class), transfer_customer_service( + TransferMessage.class); private Class extends BaseMessage> messageClass; MessageType(Class extends BaseMessage> messageClass) { diff --git a/src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java b/src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java similarity index 91% rename from src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java rename to src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java index f428c33b..b419bd1c 100644 --- a/src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java +++ b/src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java @@ -8,8 +8,8 @@ import java.util.regex.Pattern; import com.foxinmy.weixin4j.WeixinProxy; -public class WeixinConfig { - public WeixinConfig() { +public class ConfigUtil { + public ConfigUtil() { } private static Properties props = new Properties(); @@ -38,7 +38,6 @@ public class WeixinConfig { m.appendTail(sb); return sb.toString(); } - public static void main(String[] args) { System.out.println(getValue("api_token_uri")); } diff --git a/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java b/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java new file mode 100644 index 00000000..60eae107 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java @@ -0,0 +1,67 @@ +package com.foxinmy.weixin4j.util; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.Writer; +import java.nio.charset.Charset; + +/** + * IOUtil + * + * @className IOUtil + * @author jy.hu + * @date 2014年9月22日 + * @since JDK 1.7 + * @see org.apache.commons.io.IOUtils + */ +public class IOUtil { + + private static final int EOF = -1; + private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; + + public static byte[] toByteArray(Reader input) throws IOException { + return toByteArray(input, Charset.defaultCharset()); + } + + public static byte[] toByteArray(Reader input, Charset encoding) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + copy(input, output, encoding); + return output.toByteArray(); + } + + public static void copy(Reader input, OutputStream output, Charset encoding) throws IOException { + OutputStreamWriter out = new OutputStreamWriter(output, encoding); + copyLarge(input, out, new char[DEFAULT_BUFFER_SIZE]); + out.flush(); + } + + public static byte[] toByteArray(InputStream input) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + copyLarge(input, output, new byte[DEFAULT_BUFFER_SIZE]); + return output.toByteArray(); + } + + private static long copyLarge(InputStream input, OutputStream output, byte[] buffer) throws IOException { + long count = 0; + int n = 0; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } + + private static long copyLarge(Reader input, Writer output, char[] buffer) throws IOException { + long count = 0; + int n = 0; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java b/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java new file mode 100644 index 00000000..82a23ef3 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java @@ -0,0 +1,135 @@ +package com.foxinmy.weixin4j.util; + +import java.io.InputStream; +import java.util.Arrays; + +import org.apache.commons.codec.digest.DigestUtils; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.DocumentHelper; +import org.dom4j.io.SAXReader; +import org.jsoup.helper.StringUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.type.EventType; +import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; + +public class MessageUtil { + + private final static Logger log = LoggerFactory.getLogger(MessageUtil.class); + + /** + * 验证微信签名 + * + * @param echostr + * 随机字符串 + * @param timestamp + * 时间戳 + * @param nonce + * 随机数 + * @param signature + * 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数 + * @return 开发者通过检验signature对请求进行相关校验。若确认此次GET请求来自微信服务器 + * 请原样返回echostr参数内容,则接入生效 成为开发者成功,否则接入失败 + * @see 接入指南 + */ + public static String signature(String echostr, String timestamp, String nonce, String signature) { + String app_token = ConfigUtil.getValue("app_token"); + if (StringUtil.isBlank(app_token)) { + log.error("signature fail : token is null!"); + return null; + } + if (StringUtil.isBlank(echostr) || StringUtil.isBlank(timestamp) || StringUtil.isBlank(nonce)) { + log.error("signature fail : invalid parameter!"); + return null; + } + String _signature = null; + try { + String[] a = { app_token, timestamp, nonce }; + Arrays.sort(a); + StringBuilder sb = new StringBuilder(3); + for (String str : a) { + sb.append(str); + } + _signature = DigestUtils.sha1Hex(sb.toString()); + } catch (Exception e) { + log.error("signature error", e); + } + if (signature.equals(_signature)) { + return echostr; + } else { + log.error("signature fail : invalid signature!"); + return null; + } + } + + /** + * xml消息转换为消息对象 + * + * 微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次 + * + * + * @param xml + * 消息字符串 + * @return 消息对象 + * @throws DocumentException + * @see 验证消息的合法性 + * @see 普通消息 + * @see 事件触发 + * @see com.foxinmy.weixin4j.type.MessageType + * @see com.feican.weixin.msg.BaeMessage + * @see com.foxinmy.weixin4j.msg.TextMessage + * @see com.foxinmy.weixin4j.msg.in.ImageMessage + * @see com.foxinmy.weixin4j.msg.in.VoiceMessage + * @see com.foxinmy.weixin4j.msg.in.VideoMessage + * @see com.foxinmy.weixin4j.msg.in.LocationMessage + * @see com.foxinmy.weixin4j.msg.in.LinkMessage + * @see com.foxinmy.weixin4j.msg.event.ScribeEventMessage + * @see com.foxinmy.weixin4j.msg.event.ScanEventMessage + * @see com.foxinmy.weixin4j.msg.event.LocationEventMessage + * @see com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage + */ + public static BaseMessage xml2msg(String xml) throws DocumentException { + if (StringUtil.isBlank(xml)) + return null; + Document doc = DocumentHelper.parseText(xml); + String type = doc.selectSingleNode("/xml/MsgType").getStringValue(); + if (StringUtil.isBlank(type)) { + return null; + } + XStream xstream = new XStream(); + MessageType messageType = MessageType.valueOf(type.toLowerCase()); + Class extends BaseMessage> messageClass = messageType.getMessageClass(); + if (messageType == MessageType.event) { + type = doc.selectSingleNode("/xml/Event").getStringValue(); + messageClass = EventType.valueOf(type.toLowerCase()).getEventClass(); + } + xstream.alias("xml", messageClass); + xstream.ignoreUnknownElements(); + xstream.autodetectAnnotations(true); + xstream.processAnnotations(messageClass); + return xstream.fromXML(doc.asXML(), messageClass); + } + + /** + * xml消息转换为消息对象 + * + * @param inputStream + * 带消息字符串的输入流 + * @return 消息对象 + * @throws DocumentException + * @see {@link com.foxinmy.weixin4j.WeixinProxy#xml2msg(String)} + */ + public static BaseMessage xml2msg(InputStream inputStream) throws DocumentException { + SAXReader reader = new SAXReader(); + Document doc = reader.read(inputStream); + return xml2msg(doc.asXML()); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java b/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java deleted file mode 100644 index 19fd87e4..00000000 --- a/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.foxinmy.weixin4j.util; - -public class WeixinUtil { - - public static boolean isBlank(String str) { - return str == null || str.isEmpty(); - } -} diff --git a/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java b/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java index 5c0186c6..4a811a6c 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java @@ -9,7 +9,7 @@ import org.junit.Test; import com.foxinmy.weixin4j.WeixinProxy; import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.model.Button; -import com.foxinmy.weixin4j.model.Button.BtnType; +import com.foxinmy.weixin4j.type.ButtonType; /** * 自定义菜单测试 @@ -31,7 +31,7 @@ public class ButtonTest { List btnList = new ArrayList(); Button b = new Button("test"); - b.setType(BtnType.click); + b.setType(ButtonType.click); b.setKey("123"); btnList.add(b); diff --git a/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java b/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java index 8b78305e..bb6bec88 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java @@ -50,7 +50,7 @@ public class GroupTest { @Test public void getid() { try { - System.out.println(weixinProxy.findGroupByOpenId("owGBft_vbBbOaQOmpEUE4xDLeRSU")); + System.out.println(weixinProxy.getGroupByOpenId("owGBft_vbBbOaQOmpEUE4xDLeRSU")); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); diff --git a/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java b/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java new file mode 100644 index 00000000..6d34a733 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java @@ -0,0 +1,22 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Test; + +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.http.HttpRequest; + +public class HttpTest { + private static HttpRequest request; + static { + request = new HttpRequest(); + } + + @Test + public void test(){ + try { + System.out.println(request.get("http://www.baidu.com")); + } catch (WeixinException e) { + e.printStackTrace(); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java b/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java index f907fa3d..d54e649b 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java @@ -31,7 +31,7 @@ public class MediaTest { File file = new File("D:\\test.jpg"); try { System.out.println(weixinProxy.uploadMedia(file, MediaType.image)); - //usAxLEJxFXAjXVlLu_BSw0GvS2YEEoGeelRBybNZBGvMsdxiIcD1F9yBWYd9jVZx + //vvU_AUtovWyfAxQ8J1DsCoNMtK6U_bUmTpe6lpINUOVRLvt_7rtO4zxzBpPgkmay } catch (WeixinException e) { System.out.println(e.getErrorMsg()); } @@ -40,7 +40,7 @@ public class MediaTest { @Test public void download() { try { - System.out.println(weixinProxy.downloadMedia("usAxLEJxFXAjXVlLu_BSw0GvS2YEEoGeelRBybNZBGvMsdxiIcD1F9yBWYd9jVZx", MediaType.image)); + System.out.println(weixinProxy.downloadMedia("vvU_AUtovWyfAxQ8J1DsCoNMtK6U_bUmTpe6lpINUOVRLvt_7rtO4zxzBpPgkmay", MediaType.image)); } catch (WeixinException e) { System.out.println(e.getErrorMsg()); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java new file mode 100644 index 00000000..2cd36584 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java @@ -0,0 +1,194 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Test; + +import com.foxinmy.weixin4j.util.MessageUtil; + +/** + * 接收事件消息格式测试 + * + * @author jy.hu + * @date 2014年3月24日 + * @since JDK 1.7 + */ +public class MessageEventInTest { + + private StringBuilder xmlSb = new StringBuilder(); + + /***************** event message *********************/ + @Test + public void scribe() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void scan() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void scan_scribe() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void location1() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("23.137466"); + xmlSb.append("113.352425"); + xmlSb.append("119.385040"); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_click() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_link() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_scan() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_photo() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("1"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_location() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java index 39269754..fdd40042 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java @@ -1,134 +1,19 @@ package com.foxinmy.weixin4j.test; -import org.junit.Before; import org.junit.Test; -import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.util.MessageUtil; /** - * 接收消息格式测试 + * 接受一般消息格式测试 + * * @author jy.hu * @date 2014年3月24日 * @since JDK 1.7 */ public class MessageInTest { + private StringBuilder xmlSb = new StringBuilder(); - private WeixinProxy weixinProxy; - - @Before - public void init(){ - weixinProxy = new WeixinProxy(); - } - - /***************** event message *********************/ - @Test - public void scribe() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void scan() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - @Test - public void scan_scribe() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void location1() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("23.137466"); - xmlSb.append("113.352425"); - xmlSb.append("119.385040"); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void menu_click() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void menu_link() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } /***************** common message *********************/ @@ -144,7 +29,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -163,7 +48,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -182,7 +67,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -202,7 +87,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -221,7 +106,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -242,7 +127,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -262,7 +147,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java new file mode 100644 index 00000000..8f6a130f --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java @@ -0,0 +1,114 @@ +package com.foxinmy.weixin4j.test; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.model.MpArticle; +import com.foxinmy.weixin4j.type.MediaType; + +/** + * 群发消息 + * + * @className MpNewsTest + * @author jy + * @date 2014年4月27日 + * @since JDK 1.7 + * @see + */ +public class MessageMassTest { + private WeixinProxy weixinProxy; + + @Before + public void init() { + this.weixinProxy = new WeixinProxy(); + } + + @Test + public void uploadArticle() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.uploadArticle(articles); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void uploadVideo() { + try { + weixinProxy.uploadVideo("mediaId", "title", "desc"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massByGroup() { + try { + weixinProxy.massByGroup("123", MediaType.image, "groupId"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massByOpenIds() { + try { + weixinProxy.massByOpenIds("123", MediaType.image, "openIds"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massArticleByGroup() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.massArticleByGroup(articles, "0"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massArticleByOpenIds() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.massArticleByOpenIds(articles, + "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void deleteMass() { + try { + weixinProxy.deleteMassNews("34182"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java index f3be10bb..59aed8de 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java @@ -7,6 +7,7 @@ import org.junit.Test; import com.foxinmy.weixin4j.WeixinProxy; import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.msg.model.Music; import com.foxinmy.weixin4j.msg.notify.ArticleNotify; import com.foxinmy.weixin4j.msg.notify.BaseNotify; import com.foxinmy.weixin4j.msg.notify.ImageNotify; @@ -41,27 +42,29 @@ public class MessageNotifyTest { @Test public void image() { - ImageNotify notify = new ImageNotify("123", "to"); + ImageNotify notify = new ImageNotify("to"); + notify.pushMediaId("123"); System.out.println(notify.toJson()); } @Test public void voice() { - VoiceNotify notify = new VoiceNotify("123", "to"); + VoiceNotify notify = new VoiceNotify("to"); + notify.pushMediaId("123"); System.out.println(notify.toJson()); } @Test public void video() { VideoNotify notify = new VideoNotify("to"); - notify.pushVideo("123", "title", "desc"); + notify.pushVideo("123","m123"); System.out.println(notify.toJson()); } @Test public void music() { MusicNotify notify = new MusicNotify("to"); - notify.pushMusic("title", "desc", "url", "hqUrl", "mediaId"); + notify.pushMusic("url", "hqUrl", "mediaId"); System.out.println(notify.toJson()); } @@ -74,16 +77,27 @@ public class MessageNotifyTest { } @Test - public void send() { - BaseNotify t = new TextNotify("哈哈哈哈", "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + public void send1() { + BaseNotify notify = new TextNotify("哈哈哈哈", "owGBft_vbBbOaQOmpEUE4xDLeRSU"); try { - weixinProxy.sendNotify(t); + weixinProxy.sendNotify(notify); String mediaId = weixinProxy.uploadMedia(new File("D:\\test.jpg"), MediaType.image); - t = new ImageNotify(mediaId, "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + ImageNotify t = new ImageNotify("owGBft_vbBbOaQOmpEUE4xDLeRSU"); + t.pushMediaId(mediaId); weixinProxy.sendNotify(t); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); } } + + @Test + public void send2() { + try { + weixinProxy.sendNotify("to",new Music("thumbMediaId")); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java index 00021aa0..ddb309d4 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java @@ -1,7 +1,9 @@ package com.foxinmy.weixin4j.test; +import org.junit.Before; import org.junit.Test; +import com.foxinmy.weixin4j.msg.BaseMessage; import com.foxinmy.weixin4j.msg.TextMessage; import com.foxinmy.weixin4j.msg.out.ArticleMessage; import com.foxinmy.weixin4j.msg.out.ImageMessage; @@ -17,56 +19,52 @@ import com.foxinmy.weixin4j.msg.out.VoiceMessage; * @since JDK 1.7 */ public class MessageOutTest { + private BaseMessage inMessage; + + @Before + public void init() { + this.inMessage = new TextMessage(); + this.inMessage.setFromUserName("fromusername"); + this.inMessage.setToUserName("tousername"); + } + @Test public void text() { - TextMessage message = new TextMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.setContent("text message"); + TextMessage message = new TextMessage("text", inMessage); System.out.println(message.toXml()); } @Test public void image() { - ImageMessage message = new ImageMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + ImageMessage message = new ImageMessage(inMessage); message.pushMediaId("mediaId"); System.out.println(message.toXml()); } @Test public void voice() { - VoiceMessage message = new VoiceMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + VoiceMessage message = new VoiceMessage(inMessage); message.pushMediaId("mediaId"); System.out.println(message.toXml()); } - + @Test public void video() { - VideoMessage message = new VideoMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.pushVideo("mediaId", "title", "title"); + VideoMessage message = new VideoMessage(inMessage); + message.pushVideo("mediaId"); System.out.println(message.toXml()); } - + @Test public void music() { - MusicMessage message = new MusicMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.pushMusic("title", "desc", "url", "hqurl", "mediaId"); + MusicMessage message = new MusicMessage(inMessage); + message.pushMusic("mediaId"); System.out.println(message.toXml()); } - + @Test public void article() { - ArticleMessage message = new ArticleMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + ArticleMessage message = new ArticleMessage(inMessage); message.pushArticle("title1", "desc1", "picUrl1", "url1"); message.pushArticle("title2", "desc2", "picUrl2", "url2"); System.out.println(message.toXml()); diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java new file mode 100644 index 00000000..b8165a91 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java @@ -0,0 +1,30 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Before; +import org.junit.Test; + +import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.msg.out.TemplateMessage; + +public class MessageTemplTest { + private WeixinProxy weixinProxy; + + @Before + public void init() { + this.weixinProxy = new WeixinProxy(); + } + + @Test + public void test() { + TemplateMessage tplMessage = new TemplateMessage("touser", + "template_id", "url"); + tplMessage.pushData("name", "fox"); + System.out.print(tplMessage.toJson()); + try { + System.out.print(weixinProxy.sendTplMessage(tplMessage)); + } catch (WeixinException e) { + System.out.println(e.getErrorMsg()); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java b/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java deleted file mode 100644 index 5fa1ec67..00000000 --- a/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.foxinmy.weixin4j.test; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; - -import com.foxinmy.weixin4j.WeixinProxy; -import com.foxinmy.weixin4j.exception.WeixinException; -import com.foxinmy.weixin4j.model.MpArticle; -import com.foxinmy.weixin4j.type.MediaType; - -/** - * 群发消息 - * - * @className MpNewsTest - * @author jy - * @date 2014年4月27日 - * @since JDK 1.7 - * @see - */ -public class MpNewsTest { - private WeixinProxy weixinProxy; - - @Before - public void init() { - this.weixinProxy = new WeixinProxy(); - } - - @Test - public void massByGroup(){ - List articles = new ArrayList(); - try { - String thumbMediaId = weixinProxy.uploadMedia(new File("/tmp/test.jpg"), MediaType.image); - articles.add(new MpArticle(thumbMediaId, "title", "content")); - weixinProxy.massNewsByGroup(articles, "0"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } - - @Test - public void massByOpenIds(){ - List articles = new ArrayList(); - try { - String thumbMediaId = weixinProxy.uploadMedia(new File("/tmp/test.jpg"), MediaType.image); - articles.add(new MpArticle(thumbMediaId, "title", "content")); - weixinProxy.massNewsByOpenIds(articles, "owGBft_vbBbOaQOmpEUE4xDLeRSU"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } - - @Test - public void deleteMass(){ - try { - weixinProxy.deleteMassNews("34182"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } -} diff --git a/src/test/java/com/foxinmy/weixin4j/test/QRTest.java b/src/test/java/com/foxinmy/weixin4j/test/QRTest.java index 11934fa9..f18d1aa7 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/QRTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/QRTest.java @@ -25,10 +25,10 @@ public class QRTest { @Test public void temp_qr() { - QRParameter qr = new QRParameter(1200, QRType.QR_SCENE, 1); + QRParameter qr = new QRParameter(1200, QRType.TEMPORARY, 2); try { System.out.println(qr.toJson()); - weixinProxy.getQR(qr); + System.out.println(weixinProxy.getQR(qr)); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); @@ -37,10 +37,10 @@ public class QRTest { @Test public void forever_qr() { - QRParameter qr = new QRParameter(QRType.QR_LIMIT_SCENE, 1); + QRParameter qr = new QRParameter(QRType.PERMANENCE, 1); try { System.out.println(qr.toJson()); - weixinProxy.getQR(qr); + System.out.println(weixinProxy.getQR(qr)); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java b/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java index 37d549d7..a2f8a266 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java @@ -3,7 +3,8 @@ package com.foxinmy.weixin4j.test; import org.junit.Before; import org.junit.Test; -import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.api.token.FileTokenApi; +import com.foxinmy.weixin4j.api.token.TokenApi; import com.foxinmy.weixin4j.exception.WeixinException; /** @@ -14,17 +15,17 @@ import com.foxinmy.weixin4j.exception.WeixinException; * @since JDK 1.7 */ public class TokenTest { - private WeixinProxy weixinProxy; + private TokenApi tokenApi; @Before public void init() { - weixinProxy = new WeixinProxy(); + tokenApi = new FileTokenApi(); } @Test public void getToken() { try { - System.out.println(weixinProxy.getToken()); + System.out.println(tokenApi.getToken()); } catch (WeixinException e) { e.printStackTrace(); }
(); } + this.articles.addLast(new Article(title, desc, picUrl, url)); + } + + public Article removeLastArticle() { + if (this.articles != null) { + return this.articles.removeLast(); + } + return null; + } + + 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() { + 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 diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java index 2da50a01..fb58ecb8 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/ImageMessage.java @@ -1,38 +1,50 @@ 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 回复图片消息 + * @see 回复图片消息 + * @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() { - super(MessageType.image); + public ImageMessage(BaseMessage inMessage) { + super(MessageType.image, inMessage); super.getMsgType().setMessageClass(ImageMessage.class); } + 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(); - this.image.mediaId = mediaId; + this.image = new Image(mediaId); } - private static class Image { - @XStreamAlias("MediaId") - private String mediaId; + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Image.class, "mediaId"); + return xstream.toXML(this); } @Override @@ -41,7 +53,7 @@ public class ImageMessage extends BaseMessage { sb.append("[ImageMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,mediaId=").append(this.image.mediaId); + sb.append(" ,mediaId=").append(this.image.getMediaId()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java index c790b9ac..419f32d6 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/MusicMessage.java @@ -1,74 +1,61 @@ 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 回复音乐消息 + * @see 回复音乐消息 + * @see com.foxinmy.weixin4j.msg.model.Music * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class MusicMessage extends BaseMessage { private static final long serialVersionUID = 4384403772658796395L; - public MusicMessage() { - super(MessageType.music); + public MusicMessage(BaseMessage inMessage) { + super(MessageType.music, inMessage); } @XStreamAlias("Music") private Music music; - public Music getMusic() { - return this.music; + public void pushMusic(String mediaId) { + this.music = new Music(mediaId); } - public void pushMusic(String title, String desc, String url, String hqUrl, String mediaId) { - this.music = new Music(); - this.music.thumbMediaId = mediaId; - this.music.desc = desc; - this.music.hqMusicUrl = hqUrl; - this.music.MusicURL = url; - this.music.title = title; + public void setMusic(Music music) { + this.music = music; } - private static class Music { - @XStreamAlias("Title") - private String title; // 音乐标题 - @XStreamAlias("Description") - private String desc; // 音乐描述 - @XStreamAlias("MusicURL") - private String MusicURL; // 音乐链接 - @XStreamAlias("HQMusicUrl") - private String hqMusicUrl; // 高质量音乐链接,WIFI环境优先使用该链接播放音乐 - @XStreamAlias("ThumbMediaId") - private String thumbMediaId; // 缩略图的媒体id,通过上传多媒体文件,得到的id - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Music ,title=").append(title); - sb.append(" ,description=").append(desc); - sb.append(" ,musicURL=").append(MusicURL); - sb.append(" ,hqMusicUrl=").append(hqMusicUrl); - sb.append(" ,thumbMediaId=").append(thumbMediaId).append(")"); - return sb.toString(); - } + @Override + public String 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(getMusic().toString()); + sb.append(" ,music=").append(music.toString()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java new file mode 100644 index 00000000..3721504b --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/TemplateMessage.java @@ -0,0 +1,117 @@ +package com.foxinmy.weixin4j.msg.out; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +import com.alibaba.fastjson.JSON; + +/** + * 模板消息 + * + * @className TemplateMessage + * @author jy + * @date 2014年9月29日 + * @since JDK 1.7 + * @see + */ +public class TemplateMessage implements Serializable { + + private static final long serialVersionUID = 7950608393821661436L; + + private String touser; + private String template_id; + private String url; + private String topcolor = "#FF0000"; + private Map data; + + public void pushData(String key, String value) { + this.data.put(key, new Item(value)); + } + + public TemplateMessage(String touser, String template_id, String url) { + this.touser = touser; + this.template_id = template_id; + this.url = url; + this.data = new HashMap(); + } + + private static class Item implements Serializable { + private static final long serialVersionUID = 1L; + private String value; + private String color; + + public Item(String value) { + this(value, "#173177"); + } + + public Item(String value, String color) { + this.value = value; + this.color = color; + } + + public String getValue() { + return value; + } + + public String getColor() { + return color; + } + + @Override + public String toString() { + return "$ [value=" + getValue() + ", color=" + getColor() + "]"; + } + } + + public String getTouser() { + return touser; + } + + public void setTouser(String touser) { + this.touser = touser; + } + + public String getTemplate_id() { + return template_id; + } + + public void setTemplate_id(String template_id) { + this.template_id = template_id; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getTopcolor() { + return topcolor; + } + + public void setTopcolor(String topcolor) { + this.topcolor = topcolor; + } + + public Map getData() { + return data; + } + + public void setData(Map data) { + this.data = data; + } + + @Override + public String toString() { + return "TemplateMessage [touser=" + touser + ", template_id=" + + template_id + ", url=" + url + ", topcolor=" + topcolor + + ", data=" + data + "]"; + } + + public String toJson() { + return JSON.toJSONString(this); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java new file mode 100644 index 00000000..b89621aa --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/TransferMessage.java @@ -0,0 +1,25 @@ +package com.foxinmy.weixin4j.msg.out; + +import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.type.MessageType; + +/** + * 转移消息到多客服端消息 + * + * @className TransferMessage + * @author jy.hu + * @date 2014年6月28日 + * @since JDK 1.7 + * @see 多客服转移消息 + * @see com.foxinmy.weixin4j.msg.BaseMessage + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + */ +public class TransferMessage extends BaseMessage { + + private static final long serialVersionUID = -5479496746108594940L; + + public TransferMessage(BaseMessage inMessage) { + super(MessageType.transfer_customer_service,inMessage); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java index d16c5a12..d6cdfc91 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/VideoMessage.java @@ -1,58 +1,52 @@ package com.foxinmy.weixin4j.msg.out; import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.msg.model.Video; import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 回复视频消息 + * * @className VideoMessage * @author jy.hu * @date 2014年4月6日 * @since JDK 1.7 - * @see 回复视频消息 + * @see 回复视频消息 + * @see com.foxinmy.weixin4j.msg.model.Video * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class VideoMessage extends BaseMessage { private static final long serialVersionUID = -1013075358679078381L; - public VideoMessage() { - super(MessageType.video); + public VideoMessage(BaseMessage inMessage) { + super(MessageType.video, inMessage); super.getMsgType().setMessageClass(VideoMessage.class); } @XStreamAlias("Video") private Video video; - public Video getVideo() { - return this.video; + public void pushVideo(String mediaId) { + this.video = new Video(mediaId); } - public void pushVideo(String mediaId, String title, String desc) { - this.video = new Video(); - this.video.desc = desc; - this.video.mediaId = mediaId; - this.video.title = title; + public void setVideo(Video video) { + this.video = video; } - private static class Video { - @XStreamAlias("MediaId") - private String mediaId; - @XStreamAlias("Title") - private String title; - @XStreamAlias("Description") - private String desc; - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(Video mediaId=").append(mediaId); - sb.append(" ,title=").append(title); - sb.append(" ,desc=").append(desc).append(")"); - return super.toString(); - } + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Video.class, "mediaId"); + xstream.aliasField("Title", Video.class, "title"); + xstream.aliasField("Description", Video.class, "desc"); + xstream.omitField(Video.class, "thumbMediaId"); + return xstream.toXML(this); } @Override @@ -61,7 +55,7 @@ public class VideoMessage extends BaseMessage { sb.append("[VideoMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,video=").append(getVideo().toString()); + sb.append(" ,video=").append(video.toString()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java b/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java index 93052907..dcac1046 100644 --- a/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/VoiceMessage.java @@ -1,53 +1,60 @@ package com.foxinmy.weixin4j.msg.out; import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.msg.model.Voice; import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * 语音消息 + * * @className VoiceMessage * @author jy.hu * @date 2014年3月23日 * @since JDK 1.7 - * @see 回复语音消息 + * @see 回复语音消息 + * @see com.foxinmy.weixin4j.msg.model.Voice * @see com.foxinmy.weixin4j.msg.BaseMessage - * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() + * @see com.foxinmy.weixin4j.msg.BaseMessage#toXml() */ public class VoiceMessage extends BaseMessage { private static final long serialVersionUID = -7944926238652243793L; - public VoiceMessage() { - super(MessageType.voice); + public VoiceMessage(BaseMessage inMessage) { + super(MessageType.voice, inMessage); super.getMsgType().setMessageClass(VoiceMessage.class); } + + public VoiceMessage(String mediaId, BaseMessage inMessage) { + super(MessageType.voice, inMessage); + super.getMsgType().setMessageClass(VoiceMessage.class); + this.pushMediaId(mediaId); + } + @XStreamAlias("Voice") private Voice voice; - - public Voice getVocie() { - return voice; + + public void pushMediaId(String mediaId) { + this.voice = new Voice(mediaId); } - public void pushMediaId(String mediaId){ - this.voice = new Voice(); - this.voice.setMediaId(mediaId); - } - - private static class Voice { - @XStreamAlias("MediaId") - private String mediaId; - - private void setMediaId(String mediaId) { - this.mediaId = mediaId; - } + + @Override + public String toXml() { + XStream xstream = getXStream(); + xstream.aliasField("MediaId", Voice.class, "mediaId"); + return xstream.toXML(this); } + @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("[VoiceMessage ,toUserName=").append(super.getToUserName()); sb.append(" ,fromUserName=").append(super.getFromUserName()); sb.append(" ,msgType=").append(super.getMsgType().name()); - sb.append(" ,mediaId=").append(getVocie().mediaId); + sb.append(" ,mediaId=").append(voice.getMediaId()); sb.append(" ,createTime=").append(super.getCreateTime()); sb.append(" ,msgId=").append(super.getMsgId()).append("]"); return sb.toString(); diff --git a/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java b/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java new file mode 100644 index 00000000..cf2ab68e --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/type/ButtonType.java @@ -0,0 +1,55 @@ +package com.foxinmy.weixin4j.type; + +/** + * 自定义菜单类型 + * scancode_push 到 location_selec + * 仅支持微信iPhone5.4.1以上版本,和Android5 .4以上版本的微信用户 旧版本微信用户点击后将没有回应 + * 开发者也不能正常接收到事件推送。 + * + * @className ButtonType + * @author jy + * @date 2014年9月30日 + * @since JDK 1.7 + * @see 按钮类型 + */ +public enum ButtonType { + /** + * 点击推事件 用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event + * 的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互; + */ + click, + /** + * 跳转URL 用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的网页URL,可与网页授权获取用户基本信息接口结合,获得用户基本信息。 + */ + view, + /** + * 扫码推事件 用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后显示扫描结果(如果是URL,将进入URL),且会将扫码的结果传给开发者, + * 开发者可以下发消息。 + */ + scancode_push, + /** + * 扫码推事件且弹出“消息接收中”提示框用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后,将扫码的结果传给开发者,同时收起扫一扫工具, + * 然后弹出“消息接收中”提示框,随后可能会收到开发者下发的消息。 + */ + scancode_waitmsg, + /** + * 弹出系统拍照发图用户点击按钮后,微信客户端将调起系统相机,完成拍照操作后,会将拍摄的相片发送给开发者,并推送事件给开发者,同时收起系统相机, + * 随后可能会收到开发者下发的消息。 + */ + pic_sysphoto, + /** + * 弹出拍照或者相册发图用户点击按钮后,微信客户端将弹出选择器供用户选择“拍照”或者“从手机相册选择”。用户选择后即走其他两种流程。 + */ + pic_photo_or_albu, + /** + * 弹出微信相册发图器用户点击按钮后,微信客户端将调起微信相册,完成选择操作后,将选择的相片发送给开发者的服务器,并推送事件给开发者,同时收起相册, + * 随后可能会收到开发者下发的消息。 + */ + pic_weixin, + /** + * 弹出地理位置选择器用户点击按钮后,微信客户端将调起地理位置选择工具,完成选择操作后,将选择的地理位置发送给开发者的服务器,同时收起位置选择工具, + * 随后可能会收到开发者下发的消息。 + */ + location_select; +} diff --git a/src/main/java/com/foxinmy/weixin4j/type/EventType.java b/src/main/java/com/foxinmy/weixin4j/type/EventType.java index a8e864b8..bc85ce90 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/EventType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/EventType.java @@ -3,21 +3,36 @@ package com.foxinmy.weixin4j.type; import com.foxinmy.weixin4j.msg.event.EventMessage; import com.foxinmy.weixin4j.msg.event.LocationEventMessage; import com.foxinmy.weixin4j.msg.event.MassEventMessage; -import com.foxinmy.weixin4j.msg.event.MenuEventMessage; import com.foxinmy.weixin4j.msg.event.ScanEventMessage; import com.foxinmy.weixin4j.msg.event.ScribeEventMessage; +import com.foxinmy.weixin4j.msg.event.TemplatesendjobfinishMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuLocationEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuPhotoEventMessage; +import com.foxinmy.weixin4j.msg.event.menu.MenuScanEventMessage; /** - * * 事件类型 - * @author jy.hu - * + * + * @className EventType + * @author jy + * @date 2014年9月30日 + * @since JDK 1.7 + * @see */ public enum EventType { - subscribe(ScribeEventMessage.class), unsubscribe(ScribeEventMessage.class), - scan(ScanEventMessage.class),click(MenuEventMessage.class),view(MenuEventMessage.class), - location(LocationEventMessage.class),MASSSENDJOBFINISH(MassEventMessage.class); - + subscribe(ScribeEventMessage.class), unsubscribe(ScribeEventMessage.class), scan( + ScanEventMessage.class), scancode_push(MenuScanEventMessage.class), view( + MenuEventMessage.class), scancode_waitmsg( + MenuScanEventMessage.class), pic_sysphoto( + MenuPhotoEventMessage.class), pic_photo_or_album( + MenuPhotoEventMessage.class), pic_weixin( + MenuPhotoEventMessage.class), location_select( + MenuLocationEventMessage.class), click(MenuEventMessage.class), location( + LocationEventMessage.class), massendjobfinish( + MassEventMessage.class), templatesendjobfinish( + TemplatesendjobfinishMessage.class); + private Class extends EventMessage> eventClass; EventType(Class extends EventMessage> eventClass) { diff --git a/src/main/java/com/foxinmy/weixin4j/type/MediaType.java b/src/main/java/com/foxinmy/weixin4j/type/MediaType.java index 1f567181..322ba3ce 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/MediaType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/MediaType.java @@ -6,13 +6,20 @@ package com.foxinmy.weixin4j.type; * 语音(voice):256K,播放长度不超过60s,支持AMR\MP3格式 * 视频(video):1MB,支持MP4格式 * 缩略图(thumb):64KB,支持JPG格式 - * 媒体文件在后台保存时间为3天,即3天后media_id失效 + * + * 媒体文件在后台保存时间为3天,即3天后media_id失效 + * + * * @author jy.hu * @date 2014年4月2日 * @since JDK 1.7 */ public enum MediaType { - image("image/jpeg",".jpg"), voice("binary/octet-stream","amr"), vedio("binary/octet-stream","mp4"), thumb("image/jpeg","jpg"); + image("image/jpeg", "jpg"), voice("binary/octet-stream", "amr"), vedio( + "binary/octet-stream", "mp4"), thumb("image/jpeg", "jpg"), text( + "application/json", ""), music("binary/octet-stream", "mp3"), news( + "application/json", ""), mpnews("application/json", ""), mpvideo( + "binary/octet-stream", ""); MediaType(String contentType, String formatType) { this.contentType = contentType; @@ -26,6 +33,7 @@ public enum MediaType { } private String formatType; + public String getFormatType() { return formatType; } diff --git a/src/main/java/com/foxinmy/weixin4j/type/MessageType.java b/src/main/java/com/foxinmy/weixin4j/type/MessageType.java index 21a7b6dc..a883d993 100644 --- a/src/main/java/com/foxinmy/weixin4j/type/MessageType.java +++ b/src/main/java/com/foxinmy/weixin4j/type/MessageType.java @@ -10,6 +10,7 @@ import com.foxinmy.weixin4j.msg.in.VideoMessage; import com.foxinmy.weixin4j.msg.in.VoiceMessage; import com.foxinmy.weixin4j.msg.out.ArticleMessage; import com.foxinmy.weixin4j.msg.out.MusicMessage; +import com.foxinmy.weixin4j.msg.out.TransferMessage; /** * @@ -20,9 +21,13 @@ import com.foxinmy.weixin4j.msg.out.MusicMessage; */ public enum MessageType { // 接收到的消息类型 - text(TextMessage.class), image(ImageMessage.class), voice(VoiceMessage.class), video(VideoMessage.class), location(LocationMessage.class), link(LinkMessage.class), event(EventMessage.class), + text(TextMessage.class), image(ImageMessage.class), voice( + VoiceMessage.class), video(VideoMessage.class), location( + LocationMessage.class), link(LinkMessage.class), event( + EventMessage.class), // 发送的消息类型 - music(MusicMessage.class), news(ArticleMessage.class); + music(MusicMessage.class), news(ArticleMessage.class), transfer_customer_service( + TransferMessage.class); private Class extends BaseMessage> messageClass; MessageType(Class extends BaseMessage> messageClass) { diff --git a/src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java b/src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java similarity index 91% rename from src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java rename to src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java index f428c33b..b419bd1c 100644 --- a/src/main/java/com/foxinmy/weixin4j/util/WeixinConfig.java +++ b/src/main/java/com/foxinmy/weixin4j/util/ConfigUtil.java @@ -8,8 +8,8 @@ import java.util.regex.Pattern; import com.foxinmy.weixin4j.WeixinProxy; -public class WeixinConfig { - public WeixinConfig() { +public class ConfigUtil { + public ConfigUtil() { } private static Properties props = new Properties(); @@ -38,7 +38,6 @@ public class WeixinConfig { m.appendTail(sb); return sb.toString(); } - public static void main(String[] args) { System.out.println(getValue("api_token_uri")); } diff --git a/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java b/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java new file mode 100644 index 00000000..60eae107 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java @@ -0,0 +1,67 @@ +package com.foxinmy.weixin4j.util; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.Writer; +import java.nio.charset.Charset; + +/** + * IOUtil + * + * @className IOUtil + * @author jy.hu + * @date 2014年9月22日 + * @since JDK 1.7 + * @see org.apache.commons.io.IOUtils + */ +public class IOUtil { + + private static final int EOF = -1; + private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; + + public static byte[] toByteArray(Reader input) throws IOException { + return toByteArray(input, Charset.defaultCharset()); + } + + public static byte[] toByteArray(Reader input, Charset encoding) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + copy(input, output, encoding); + return output.toByteArray(); + } + + public static void copy(Reader input, OutputStream output, Charset encoding) throws IOException { + OutputStreamWriter out = new OutputStreamWriter(output, encoding); + copyLarge(input, out, new char[DEFAULT_BUFFER_SIZE]); + out.flush(); + } + + public static byte[] toByteArray(InputStream input) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + copyLarge(input, output, new byte[DEFAULT_BUFFER_SIZE]); + return output.toByteArray(); + } + + private static long copyLarge(InputStream input, OutputStream output, byte[] buffer) throws IOException { + long count = 0; + int n = 0; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } + + private static long copyLarge(Reader input, Writer output, char[] buffer) throws IOException { + long count = 0; + int n = 0; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java b/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java new file mode 100644 index 00000000..82a23ef3 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/util/MessageUtil.java @@ -0,0 +1,135 @@ +package com.foxinmy.weixin4j.util; + +import java.io.InputStream; +import java.util.Arrays; + +import org.apache.commons.codec.digest.DigestUtils; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.DocumentHelper; +import org.dom4j.io.SAXReader; +import org.jsoup.helper.StringUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.type.EventType; +import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.xml.XStream; + +public class MessageUtil { + + private final static Logger log = LoggerFactory.getLogger(MessageUtil.class); + + /** + * 验证微信签名 + * + * @param echostr + * 随机字符串 + * @param timestamp + * 时间戳 + * @param nonce + * 随机数 + * @param signature + * 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数 + * @return 开发者通过检验signature对请求进行相关校验。若确认此次GET请求来自微信服务器 + * 请原样返回echostr参数内容,则接入生效 成为开发者成功,否则接入失败 + * @see 接入指南 + */ + public static String signature(String echostr, String timestamp, String nonce, String signature) { + String app_token = ConfigUtil.getValue("app_token"); + if (StringUtil.isBlank(app_token)) { + log.error("signature fail : token is null!"); + return null; + } + if (StringUtil.isBlank(echostr) || StringUtil.isBlank(timestamp) || StringUtil.isBlank(nonce)) { + log.error("signature fail : invalid parameter!"); + return null; + } + String _signature = null; + try { + String[] a = { app_token, timestamp, nonce }; + Arrays.sort(a); + StringBuilder sb = new StringBuilder(3); + for (String str : a) { + sb.append(str); + } + _signature = DigestUtils.sha1Hex(sb.toString()); + } catch (Exception e) { + log.error("signature error", e); + } + if (signature.equals(_signature)) { + return echostr; + } else { + log.error("signature fail : invalid signature!"); + return null; + } + } + + /** + * xml消息转换为消息对象 + * + * 微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次 + * + * + * @param xml + * 消息字符串 + * @return 消息对象 + * @throws DocumentException + * @see 验证消息的合法性 + * @see 普通消息 + * @see 事件触发 + * @see com.foxinmy.weixin4j.type.MessageType + * @see com.feican.weixin.msg.BaeMessage + * @see com.foxinmy.weixin4j.msg.TextMessage + * @see com.foxinmy.weixin4j.msg.in.ImageMessage + * @see com.foxinmy.weixin4j.msg.in.VoiceMessage + * @see com.foxinmy.weixin4j.msg.in.VideoMessage + * @see com.foxinmy.weixin4j.msg.in.LocationMessage + * @see com.foxinmy.weixin4j.msg.in.LinkMessage + * @see com.foxinmy.weixin4j.msg.event.ScribeEventMessage + * @see com.foxinmy.weixin4j.msg.event.ScanEventMessage + * @see com.foxinmy.weixin4j.msg.event.LocationEventMessage + * @see com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage + */ + public static BaseMessage xml2msg(String xml) throws DocumentException { + if (StringUtil.isBlank(xml)) + return null; + Document doc = DocumentHelper.parseText(xml); + String type = doc.selectSingleNode("/xml/MsgType").getStringValue(); + if (StringUtil.isBlank(type)) { + return null; + } + XStream xstream = new XStream(); + MessageType messageType = MessageType.valueOf(type.toLowerCase()); + Class extends BaseMessage> messageClass = messageType.getMessageClass(); + if (messageType == MessageType.event) { + type = doc.selectSingleNode("/xml/Event").getStringValue(); + messageClass = EventType.valueOf(type.toLowerCase()).getEventClass(); + } + xstream.alias("xml", messageClass); + xstream.ignoreUnknownElements(); + xstream.autodetectAnnotations(true); + xstream.processAnnotations(messageClass); + return xstream.fromXML(doc.asXML(), messageClass); + } + + /** + * xml消息转换为消息对象 + * + * @param inputStream + * 带消息字符串的输入流 + * @return 消息对象 + * @throws DocumentException + * @see {@link com.foxinmy.weixin4j.WeixinProxy#xml2msg(String)} + */ + public static BaseMessage xml2msg(InputStream inputStream) throws DocumentException { + SAXReader reader = new SAXReader(); + Document doc = reader.read(inputStream); + return xml2msg(doc.asXML()); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java b/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java deleted file mode 100644 index 19fd87e4..00000000 --- a/src/main/java/com/foxinmy/weixin4j/util/WeixinUtil.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.foxinmy.weixin4j.util; - -public class WeixinUtil { - - public static boolean isBlank(String str) { - return str == null || str.isEmpty(); - } -} diff --git a/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java b/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java index 5c0186c6..4a811a6c 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/ButtonTest.java @@ -9,7 +9,7 @@ import org.junit.Test; import com.foxinmy.weixin4j.WeixinProxy; import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.model.Button; -import com.foxinmy.weixin4j.model.Button.BtnType; +import com.foxinmy.weixin4j.type.ButtonType; /** * 自定义菜单测试 @@ -31,7 +31,7 @@ public class ButtonTest { List btnList = new ArrayList(); Button b = new Button("test"); - b.setType(BtnType.click); + b.setType(ButtonType.click); b.setKey("123"); btnList.add(b); diff --git a/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java b/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java index 8b78305e..bb6bec88 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/GroupTest.java @@ -50,7 +50,7 @@ public class GroupTest { @Test public void getid() { try { - System.out.println(weixinProxy.findGroupByOpenId("owGBft_vbBbOaQOmpEUE4xDLeRSU")); + System.out.println(weixinProxy.getGroupByOpenId("owGBft_vbBbOaQOmpEUE4xDLeRSU")); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); diff --git a/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java b/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java new file mode 100644 index 00000000..6d34a733 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/HttpTest.java @@ -0,0 +1,22 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Test; + +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.http.HttpRequest; + +public class HttpTest { + private static HttpRequest request; + static { + request = new HttpRequest(); + } + + @Test + public void test(){ + try { + System.out.println(request.get("http://www.baidu.com")); + } catch (WeixinException e) { + e.printStackTrace(); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java b/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java index f907fa3d..d54e649b 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MediaTest.java @@ -31,7 +31,7 @@ public class MediaTest { File file = new File("D:\\test.jpg"); try { System.out.println(weixinProxy.uploadMedia(file, MediaType.image)); - //usAxLEJxFXAjXVlLu_BSw0GvS2YEEoGeelRBybNZBGvMsdxiIcD1F9yBWYd9jVZx + //vvU_AUtovWyfAxQ8J1DsCoNMtK6U_bUmTpe6lpINUOVRLvt_7rtO4zxzBpPgkmay } catch (WeixinException e) { System.out.println(e.getErrorMsg()); } @@ -40,7 +40,7 @@ public class MediaTest { @Test public void download() { try { - System.out.println(weixinProxy.downloadMedia("usAxLEJxFXAjXVlLu_BSw0GvS2YEEoGeelRBybNZBGvMsdxiIcD1F9yBWYd9jVZx", MediaType.image)); + System.out.println(weixinProxy.downloadMedia("vvU_AUtovWyfAxQ8J1DsCoNMtK6U_bUmTpe6lpINUOVRLvt_7rtO4zxzBpPgkmay", MediaType.image)); } catch (WeixinException e) { System.out.println(e.getErrorMsg()); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java new file mode 100644 index 00000000..2cd36584 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageEventInTest.java @@ -0,0 +1,194 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Test; + +import com.foxinmy.weixin4j.util.MessageUtil; + +/** + * 接收事件消息格式测试 + * + * @author jy.hu + * @date 2014年3月24日 + * @since JDK 1.7 + */ +public class MessageEventInTest { + + private StringBuilder xmlSb = new StringBuilder(); + + /***************** event message *********************/ + @Test + public void scribe() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void scan() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void scan_scribe() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void location1() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("23.137466"); + xmlSb.append("113.352425"); + xmlSb.append("119.385040"); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_click() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_link() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_scan() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_photo() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("1"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void menu_location() { + try { + xmlSb.delete(0, xmlSb.length()); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append("123456789"); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + xmlSb.append(""); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java index 39269754..fdd40042 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageInTest.java @@ -1,134 +1,19 @@ package com.foxinmy.weixin4j.test; -import org.junit.Before; import org.junit.Test; -import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.util.MessageUtil; /** - * 接收消息格式测试 + * 接受一般消息格式测试 + * * @author jy.hu * @date 2014年3月24日 * @since JDK 1.7 */ public class MessageInTest { + private StringBuilder xmlSb = new StringBuilder(); - private WeixinProxy weixinProxy; - - @Before - public void init(){ - weixinProxy = new WeixinProxy(); - } - - /***************** event message *********************/ - @Test - public void scribe() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void scan() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - @Test - public void scan_scribe() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void location1() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("23.137466"); - xmlSb.append("113.352425"); - xmlSb.append("119.385040"); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void menu_click() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void menu_link() { - try { - xmlSb.delete(0, xmlSb.length()); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append("123456789"); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); - } catch (Exception e) { - e.printStackTrace(); - } - } /***************** common message *********************/ @@ -144,7 +29,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -163,7 +48,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -182,7 +67,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -202,7 +87,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -221,7 +106,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -242,7 +127,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -262,7 +147,7 @@ public class MessageInTest { xmlSb.append(""); xmlSb.append("1234567890123456"); xmlSb.append(""); - System.out.println(weixinProxy.xml2msg(xmlSb.toString())); + System.out.println(MessageUtil.xml2msg(xmlSb.toString())); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java new file mode 100644 index 00000000..8f6a130f --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageMassTest.java @@ -0,0 +1,114 @@ +package com.foxinmy.weixin4j.test; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.model.MpArticle; +import com.foxinmy.weixin4j.type.MediaType; + +/** + * 群发消息 + * + * @className MpNewsTest + * @author jy + * @date 2014年4月27日 + * @since JDK 1.7 + * @see + */ +public class MessageMassTest { + private WeixinProxy weixinProxy; + + @Before + public void init() { + this.weixinProxy = new WeixinProxy(); + } + + @Test + public void uploadArticle() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.uploadArticle(articles); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void uploadVideo() { + try { + weixinProxy.uploadVideo("mediaId", "title", "desc"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massByGroup() { + try { + weixinProxy.massByGroup("123", MediaType.image, "groupId"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massByOpenIds() { + try { + weixinProxy.massByOpenIds("123", MediaType.image, "openIds"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massArticleByGroup() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.massArticleByGroup(articles, "0"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void massArticleByOpenIds() { + List articles = new ArrayList(); + try { + String thumbMediaId = weixinProxy.uploadMedia(new File( + "/tmp/test.jpg"), MediaType.image); + articles.add(new MpArticle(thumbMediaId, "title", "content")); + weixinProxy.massArticleByOpenIds(articles, + "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } + + @Test + public void deleteMass() { + try { + weixinProxy.deleteMassNews("34182"); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java index f3be10bb..59aed8de 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageNotifyTest.java @@ -7,6 +7,7 @@ import org.junit.Test; import com.foxinmy.weixin4j.WeixinProxy; import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.msg.model.Music; import com.foxinmy.weixin4j.msg.notify.ArticleNotify; import com.foxinmy.weixin4j.msg.notify.BaseNotify; import com.foxinmy.weixin4j.msg.notify.ImageNotify; @@ -41,27 +42,29 @@ public class MessageNotifyTest { @Test public void image() { - ImageNotify notify = new ImageNotify("123", "to"); + ImageNotify notify = new ImageNotify("to"); + notify.pushMediaId("123"); System.out.println(notify.toJson()); } @Test public void voice() { - VoiceNotify notify = new VoiceNotify("123", "to"); + VoiceNotify notify = new VoiceNotify("to"); + notify.pushMediaId("123"); System.out.println(notify.toJson()); } @Test public void video() { VideoNotify notify = new VideoNotify("to"); - notify.pushVideo("123", "title", "desc"); + notify.pushVideo("123","m123"); System.out.println(notify.toJson()); } @Test public void music() { MusicNotify notify = new MusicNotify("to"); - notify.pushMusic("title", "desc", "url", "hqUrl", "mediaId"); + notify.pushMusic("url", "hqUrl", "mediaId"); System.out.println(notify.toJson()); } @@ -74,16 +77,27 @@ public class MessageNotifyTest { } @Test - public void send() { - BaseNotify t = new TextNotify("哈哈哈哈", "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + public void send1() { + BaseNotify notify = new TextNotify("哈哈哈哈", "owGBft_vbBbOaQOmpEUE4xDLeRSU"); try { - weixinProxy.sendNotify(t); + weixinProxy.sendNotify(notify); String mediaId = weixinProxy.uploadMedia(new File("D:\\test.jpg"), MediaType.image); - t = new ImageNotify(mediaId, "owGBft_vbBbOaQOmpEUE4xDLeRSU"); + ImageNotify t = new ImageNotify("owGBft_vbBbOaQOmpEUE4xDLeRSU"); + t.pushMediaId(mediaId); weixinProxy.sendNotify(t); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); } } + + @Test + public void send2() { + try { + weixinProxy.sendNotify("to",new Music("thumbMediaId")); + } catch (WeixinException e) { + System.out.println(e.getErrorCode()); + System.out.println(e.getErrorMsg()); + } + } } diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java index 00021aa0..ddb309d4 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageOutTest.java @@ -1,7 +1,9 @@ package com.foxinmy.weixin4j.test; +import org.junit.Before; import org.junit.Test; +import com.foxinmy.weixin4j.msg.BaseMessage; import com.foxinmy.weixin4j.msg.TextMessage; import com.foxinmy.weixin4j.msg.out.ArticleMessage; import com.foxinmy.weixin4j.msg.out.ImageMessage; @@ -17,56 +19,52 @@ import com.foxinmy.weixin4j.msg.out.VoiceMessage; * @since JDK 1.7 */ public class MessageOutTest { + private BaseMessage inMessage; + + @Before + public void init() { + this.inMessage = new TextMessage(); + this.inMessage.setFromUserName("fromusername"); + this.inMessage.setToUserName("tousername"); + } + @Test public void text() { - TextMessage message = new TextMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.setContent("text message"); + TextMessage message = new TextMessage("text", inMessage); System.out.println(message.toXml()); } @Test public void image() { - ImageMessage message = new ImageMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + ImageMessage message = new ImageMessage(inMessage); message.pushMediaId("mediaId"); System.out.println(message.toXml()); } @Test public void voice() { - VoiceMessage message = new VoiceMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + VoiceMessage message = new VoiceMessage(inMessage); message.pushMediaId("mediaId"); System.out.println(message.toXml()); } - + @Test public void video() { - VideoMessage message = new VideoMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.pushVideo("mediaId", "title", "title"); + VideoMessage message = new VideoMessage(inMessage); + message.pushVideo("mediaId"); System.out.println(message.toXml()); } - + @Test public void music() { - MusicMessage message = new MusicMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); - message.pushMusic("title", "desc", "url", "hqurl", "mediaId"); + MusicMessage message = new MusicMessage(inMessage); + message.pushMusic("mediaId"); System.out.println(message.toXml()); } - + @Test public void article() { - ArticleMessage message = new ArticleMessage(); - message.setFromUserName("fromUser"); - message.setToUserName("toUser"); + ArticleMessage message = new ArticleMessage(inMessage); message.pushArticle("title1", "desc1", "picUrl1", "url1"); message.pushArticle("title2", "desc2", "picUrl2", "url2"); System.out.println(message.toXml()); diff --git a/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java b/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java new file mode 100644 index 00000000..b8165a91 --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/MessageTemplTest.java @@ -0,0 +1,30 @@ +package com.foxinmy.weixin4j.test; + +import org.junit.Before; +import org.junit.Test; + +import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.msg.out.TemplateMessage; + +public class MessageTemplTest { + private WeixinProxy weixinProxy; + + @Before + public void init() { + this.weixinProxy = new WeixinProxy(); + } + + @Test + public void test() { + TemplateMessage tplMessage = new TemplateMessage("touser", + "template_id", "url"); + tplMessage.pushData("name", "fox"); + System.out.print(tplMessage.toJson()); + try { + System.out.print(weixinProxy.sendTplMessage(tplMessage)); + } catch (WeixinException e) { + System.out.println(e.getErrorMsg()); + } + } +} diff --git a/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java b/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java deleted file mode 100644 index 5fa1ec67..00000000 --- a/src/test/java/com/foxinmy/weixin4j/test/MpNewsTest.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.foxinmy.weixin4j.test; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; - -import com.foxinmy.weixin4j.WeixinProxy; -import com.foxinmy.weixin4j.exception.WeixinException; -import com.foxinmy.weixin4j.model.MpArticle; -import com.foxinmy.weixin4j.type.MediaType; - -/** - * 群发消息 - * - * @className MpNewsTest - * @author jy - * @date 2014年4月27日 - * @since JDK 1.7 - * @see - */ -public class MpNewsTest { - private WeixinProxy weixinProxy; - - @Before - public void init() { - this.weixinProxy = new WeixinProxy(); - } - - @Test - public void massByGroup(){ - List articles = new ArrayList(); - try { - String thumbMediaId = weixinProxy.uploadMedia(new File("/tmp/test.jpg"), MediaType.image); - articles.add(new MpArticle(thumbMediaId, "title", "content")); - weixinProxy.massNewsByGroup(articles, "0"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } - - @Test - public void massByOpenIds(){ - List articles = new ArrayList(); - try { - String thumbMediaId = weixinProxy.uploadMedia(new File("/tmp/test.jpg"), MediaType.image); - articles.add(new MpArticle(thumbMediaId, "title", "content")); - weixinProxy.massNewsByOpenIds(articles, "owGBft_vbBbOaQOmpEUE4xDLeRSU"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } - - @Test - public void deleteMass(){ - try { - weixinProxy.deleteMassNews("34182"); - } catch (WeixinException e) { - System.out.println(e.getErrorCode()); - System.out.println(e.getErrorMsg()); - } - } -} diff --git a/src/test/java/com/foxinmy/weixin4j/test/QRTest.java b/src/test/java/com/foxinmy/weixin4j/test/QRTest.java index 11934fa9..f18d1aa7 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/QRTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/QRTest.java @@ -25,10 +25,10 @@ public class QRTest { @Test public void temp_qr() { - QRParameter qr = new QRParameter(1200, QRType.QR_SCENE, 1); + QRParameter qr = new QRParameter(1200, QRType.TEMPORARY, 2); try { System.out.println(qr.toJson()); - weixinProxy.getQR(qr); + System.out.println(weixinProxy.getQR(qr)); } catch (WeixinException e) { System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); @@ -37,10 +37,10 @@ public class QRTest { @Test public void forever_qr() { - QRParameter qr = new QRParameter(QRType.QR_LIMIT_SCENE, 1); + QRParameter qr = new QRParameter(QRType.PERMANENCE, 1); try { System.out.println(qr.toJson()); - weixinProxy.getQR(qr); + System.out.println(weixinProxy.getQR(qr)); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java b/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java index 37d549d7..a2f8a266 100644 --- a/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java +++ b/src/test/java/com/foxinmy/weixin4j/test/TokenTest.java @@ -3,7 +3,8 @@ package com.foxinmy.weixin4j.test; import org.junit.Before; import org.junit.Test; -import com.foxinmy.weixin4j.WeixinProxy; +import com.foxinmy.weixin4j.api.token.FileTokenApi; +import com.foxinmy.weixin4j.api.token.TokenApi; import com.foxinmy.weixin4j.exception.WeixinException; /** @@ -14,17 +15,17 @@ import com.foxinmy.weixin4j.exception.WeixinException; * @since JDK 1.7 */ public class TokenTest { - private WeixinProxy weixinProxy; + private TokenApi tokenApi; @Before public void init() { - weixinProxy = new WeixinProxy(); + tokenApi = new FileTokenApi(); } @Test public void getToken() { try { - System.out.println(weixinProxy.getToken()); + System.out.println(tokenApi.getToken()); } catch (WeixinException e) { e.printStackTrace(); }