From 23c7960a83902a4a89a5d49bff11e006babd969e Mon Sep 17 00:00:00 2001 From: jinyu Date: Sun, 9 Aug 2015 09:25:22 +0800 Subject: [PATCH] =?UTF-8?q?weixin4j-qy:=E4=BC=9A=E8=AF=9DAPI=E6=9A=B4?= =?UTF-8?q?=E9=9C=B2=E5=88=B0WeixinProxy=E7=B1=BB&=E9=87=8D=E5=91=BD?= =?UTF-8?q?=E5=90=8DNotifyApi#sendNotify=E4=B8=BAsendNotifyMessage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGE.md | 6 + .../src/main/resources/weixin4j.properties | 2 +- weixin4j-qy/CHANGE.md | 8 +- .../com/foxinmy/weixin4j/qy/WeixinProxy.java | 148 +++++++++++++++++- .../com/foxinmy/weixin4j/qy/api/ChatApi.java | 11 +- .../com/foxinmy/weixin4j/qy/api/MediaApi.java | 8 +- .../foxinmy/weixin4j/qy/api/NotifyApi.java | 13 +- .../weixin4j/qy/message/ChatMessage.java | 2 +- .../weixin4j/qy/test/NotifyMsgTest.java | 17 +- .../weixin4j/xml/CruxMessageHandler.java | 10 +- 10 files changed, 191 insertions(+), 34 deletions(-) diff --git a/CHANGE.md b/CHANGE.md index 7236a081..40254734 100644 --- a/CHANGE.md +++ b/CHANGE.md @@ -428,3 +428,9 @@ * 2015-08-07 + 主要去掉了实体类中的字段上@JSONFiled上的deserialize=false属性和不合理的format方法 + +* 2015-08-09 + + + **weixin4j-qy**: 会话API暴露到WeixinProxy类 + + + **weixin4j-qy**: 重命名NotifyApi#sendNotify为sendNotifyMessage diff --git a/weixin4j-mp/src/main/resources/weixin4j.properties b/weixin4j-mp/src/main/resources/weixin4j.properties index 987677c5..798fb2b3 100644 --- a/weixin4j-mp/src/main/resources/weixin4j.properties +++ b/weixin4j-mp/src/main/resources/weixin4j.properties @@ -1,6 +1,6 @@ # \u6d4b\u8bd5\u4e4b\u7528 \u6b63\u5f0f\u73af\u5883\u4e0bcopy\u4e00\u4efd\u5230classpath # \u516c\u4f17\u53f7\u4fe1\u606f -account={"id":"wxd5d03da81b799b9a","secret":"c787a9fcec16fd712b77679c1fc8084f",\ +account={"id":"wx4ab8f8de58159a57","secret":"1d4eb0f4bf556aaed539f30ed05ca795",\ "mchId":"V3.x\u7248\u672c\u4e0b\u7684\u5fae\u4fe1\u5546\u6237\u53f7 \u670d\u52a1\u53f7\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165",\ "partnerId":"V2\u7248\u672c\u4e0b\u7684\u8d22\u4ed8\u901a\u7684\u5546\u6237\u53f7 \u670d\u52a1\u53f7\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165",\ "partnerKey":"V2\u7248\u672c\u4e0b\u7684\u8d22\u4ed8\u901a\u5546\u6237\u6743\u9650\u5bc6\u94a5Key \u670d\u52a1\u53f7\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165",\ diff --git a/weixin4j-qy/CHANGE.md b/weixin4j-qy/CHANGE.md index cabb4fc9..a55ccfa9 100644 --- a/weixin4j-qy/CHANGE.md +++ b/weixin4j-qy/CHANGE.md @@ -86,4 +86,10 @@ * 2015-08-01 - + 新增聊天服务接口[ChatApi](./src/main/java/com/foxinmy/weixin4j/qy/api/ChatApi.java) \ No newline at end of file + + 新增会话服务接口[ChatApi](./src/main/java/com/foxinmy/weixin4j/qy/api/ChatApi.java) + +* 2015-08-09 + + + 会话API暴露到WeixinProxy类 + + + 重命名NotifyApi#sendNotify为sendNotifyMessage \ No newline at end of file diff --git a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/WeixinProxy.java b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/WeixinProxy.java index c9faf0da..b71759fd 100644 --- a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/WeixinProxy.java +++ b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/WeixinProxy.java @@ -15,6 +15,7 @@ import com.foxinmy.weixin4j.model.MediaRecord; import com.foxinmy.weixin4j.model.MediaUploadResult; import com.foxinmy.weixin4j.qy.api.AgentApi; import com.foxinmy.weixin4j.qy.api.BatchApi; +import com.foxinmy.weixin4j.qy.api.ChatApi; import com.foxinmy.weixin4j.qy.api.HelperApi; import com.foxinmy.weixin4j.qy.api.MediaApi; import com.foxinmy.weixin4j.qy.api.MenuApi; @@ -23,17 +24,21 @@ import com.foxinmy.weixin4j.qy.api.PartyApi; import com.foxinmy.weixin4j.qy.api.QyApi; import com.foxinmy.weixin4j.qy.api.TagApi; import com.foxinmy.weixin4j.qy.api.UserApi; +import com.foxinmy.weixin4j.qy.message.ChatMessage; import com.foxinmy.weixin4j.qy.message.NotifyMessage; import com.foxinmy.weixin4j.qy.model.AgentInfo; import com.foxinmy.weixin4j.qy.model.AgentOverview; import com.foxinmy.weixin4j.qy.model.AgentSetter; import com.foxinmy.weixin4j.qy.model.BatchResult; import com.foxinmy.weixin4j.qy.model.Callback; +import com.foxinmy.weixin4j.qy.model.ChatInfo; +import com.foxinmy.weixin4j.qy.model.ChatMute; import com.foxinmy.weixin4j.qy.model.IdParameter; import com.foxinmy.weixin4j.qy.model.Party; import com.foxinmy.weixin4j.qy.model.Tag; import com.foxinmy.weixin4j.qy.model.User; import com.foxinmy.weixin4j.qy.token.WeixinTokenCreator; +import com.foxinmy.weixin4j.qy.type.ChatType; import com.foxinmy.weixin4j.qy.type.InviteType; import com.foxinmy.weixin4j.qy.type.UserStatus; import com.foxinmy.weixin4j.token.TokenHolder; @@ -61,6 +66,7 @@ public class WeixinProxy { private final HelperApi helperApi; private final AgentApi agentApi; private final BatchApi batchApi; + private final ChatApi chatApi; private final TokenHolder tokenHolder; @@ -118,6 +124,7 @@ public class WeixinProxy { this.notifyApi = new NotifyApi(tokenHolder); this.menuApi = new MenuApi(tokenHolder); this.mediaApi = new MediaApi(tokenHolder); + this.chatApi = new ChatApi(tokenHolder); } public TokenHolder getTokenHolder() { @@ -125,14 +132,14 @@ public class WeixinProxy { } /** - * 发送消息(需要管理员对应用有使用权限,对收件人touser、toparty、totag有查看权限,否则本次调用失败) + * 发送客服消息(需要管理员对应用有使用权限,对收件人touser、toparty、totag有查看权限,否则本次调用失败) *

* 1) 发送人员列表存在错误的userid:执行发送,开发者需注意返回结果说明
* 2)发送人员不在通讯录权限范围内:不执行发送任务,返回首个出错的userid
* 3)发送人员不在应用可见范围内:不执行发送任务,返回首个出错的userid
*

* - * @param notify + * @param message * 客服消息对象 * @return * 如果对应用或收件人、部门、标签任何一个无权限,则本次发送失败;如果收件人、部门或标签不存在,发送仍然执行,但返回无效的部分
@@ -153,8 +160,9 @@ public class WeixinProxy { * @see com.foxinmy.weixin4j.tuple.MpNews * @see com.foxinmy.weixin4j.qy.message.NotifyMessage */ - public JSONObject sendNotify(NotifyMessage notify) throws WeixinException { - return notifyApi.sendNotify(notify); + public JSONObject sendNotifyMessage(NotifyMessage message) + throws WeixinException { + return notifyApi.sendNotifyMessage(message); } /** @@ -1040,6 +1048,136 @@ public class WeixinProxy { public String openid2userid(String openid) throws WeixinException { return userApi.openid2userid(openid); } - + + /** + * 创建会话 如果会话id为空,程序会自动生成一个唯一ID + * + * @param chatInfo + * 会话信息 + * @return 会话ID + * @see com.foxinmy.weixin4j.qy.api.ChatApi + * @see com.foxinmy.weixin4j.qy.model.ChatInfo + * @see 创建会话 + * @throws WeixinException + */ + public String createChat(ChatInfo chatInfo) throws WeixinException { + return chatApi.createChat(chatInfo); + } + + /** + * 获取会话 + * + * @param chatId + * 会话ID + * @return 会话信息 + * @see com.foxinmy.weixin4j.qy.api.ChatApi + * @see com.foxinmy.weixin4j.qy.model.ChatInfo + * @see 获取会话 + * @throws WeixinException + */ + public ChatInfo getChat(String chatId) throws WeixinException { + return chatApi.getChat(chatId); + } + + /** + * 更新会话 + * + * @param chatInfo + * 会话信息 至少保持会话ID不能为空 + * @param operator + * 操作人userid + * @param addUsers + * 会话新增成员列表 + * @param deleteUsers + * 会话退出成员列表 + * @return 处理结果 + * @see com.foxinmy.weixin4j.qy.api.ChatApi + * @see com.foxinmy.weixin4j.qy.model.ChatInfo + * @see 修改会话信息 + * @throws WeixinException + */ + public JsonResult updateChat(ChatInfo chatInfo, String operator, + List addUsers, List deleteUsers) + throws WeixinException { + return chatApi.updateChat(chatInfo, operator, addUsers, deleteUsers); + } + + /** + * 退出会话 + * + * @param chatId + * 会话ID + * @param operator + * 操作人userid + * @return 处理结果 + * @see com.foxinmy.weixin4j.qy.api.ChatApi + * @see 退出会话 + * @throws WeixinException + */ + public JsonResult quitChat(String chatId, String operator) + throws WeixinException { + return chatApi.quitChat(chatId, operator); + } + + /** + * 清除会话未读状态 + * + * @param targetId + * 会话值,为userid|chatid,分别表示:成员id|会话id + * @param owner + * 会话所有者的userid + * @param chatType + * 会话类型:single|group,分别表示:群聊|单聊 + * @return 处理结果 + * @see com.foxinmy.weixin4j.qy.api.ChatApi + * @see 清除会话未读状态 + * @throws WeixinException + */ + public JsonResult clearChatNotify(String targetId, String owner, + ChatType chatType) throws WeixinException { + return chatApi.clearChatNotify(targetId, owner, chatType); + } + + /** + * 设置成员接收到的消息是否提醒。主要场景是用于对接企业im的在线状态,如成员处于在线状态时,可以设置该成员的消息免打扰。当成员离线时,关闭免打扰状态 + * ,对微信端进行提醒。 + * + * @param chatMutes + * 提醒参数 + * @see com.foxinmy.weixin4j.qy.api.ChatApi + * @see com.foxinmy.weixin4j.qy.model.ChatMute + * @see 设置成员新消息免打扰 + * @return 列表中不存在的成员,剩余合法成员会继续执行。 + * @throws WeixinException + */ + public List setChatMute(List chatMutes) + throws WeixinException { + return chatApi.setChatMute(chatMutes); + } + + /** + * 发送会话消息 + * + * @param message + * 消息对象 + * @return 处理结果 + * @see com.foxinmy.weixin4j.qy.api.ChatApi + * @see com.foxinmy.weixin4j.qy.message.ChatMessage + * @see 发送消息 + * @throws WeixinException + */ + public JsonResult sendChatMessage(ChatMessage message) + throws WeixinException { + return chatApi.sendChatMessage(message); + } + public final static String VERSION = "1.5.2"; } diff --git a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/ChatApi.java b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/ChatApi.java index 5c6bc99c..27f330c0 100644 --- a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/ChatApi.java +++ b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/ChatApi.java @@ -140,7 +140,7 @@ public class ChatApi extends QyApi { /** * 清除会话未读状态 * - * @param v + * @param targetId * 会话值,为userid|chatid,分别表示:成员id|会话id * @param owner * 会话所有者的userid @@ -151,7 +151,7 @@ public class ChatApi extends QyApi { * href="http://qydev.weixin.qq.com/wiki/index.php?title=%E4%BC%81%E4%B8%9A%E5%8F%B7%E6%B6%88%E6%81%AF%E6%8E%A5%E5%8F%A3%E8%AF%B4%E6%98%8E#.E6.B8.85.E9.99.A4.E4.BC.9A.E8.AF.9D.E6.9C.AA.E8.AF.BB.E7.8A.B6.E6.80.81">清除会话未读状态 * @throws WeixinException */ - public JsonResult clearNotify(String targetId, String owner, + public JsonResult clearChatNotify(String targetId, String owner, ChatType chatType) throws WeixinException { JSONObject chat = new JSONObject(); chat.put("type", chatType.name()); @@ -171,13 +171,15 @@ public class ChatApi extends QyApi { * ,对微信端进行提醒。 * * @param chatMutes + * 提醒参数 + * @see com.foxinmy.weixin4j.qy.model.ChatMute * @see 设置成员新消息免打扰 * @return 列表中不存在的成员,剩余合法成员会继续执行。 * @throws WeixinException */ - public List setMute(List chatMutes) + public List setChatMute(List chatMutes) throws WeixinException { JSONObject mute = new JSONObject(); mute.put("user_mute_list", chatMutes); @@ -201,7 +203,8 @@ public class ChatApi extends QyApi { * href="http://qydev.weixin.qq.com/wiki/index.php?title=%E4%BC%81%E4%B8%9A%E5%8F%B7%E6%B6%88%E6%81%AF%E6%8E%A5%E5%8F%A3%E8%AF%B4%E6%98%8E#.E5.8F.91.E6.B6.88.E6.81.AF">发送消息 * @throws WeixinException */ - public JsonResult sendMessage(ChatMessage message) throws WeixinException { + public JsonResult sendChatMessage(ChatMessage message) + throws WeixinException { ChatTuple tuple = message.getChatTuple(); String msgtype = tuple.getMessageType(); JSONObject msg = new JSONObject(); diff --git a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/MediaApi.java b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/MediaApi.java index 02127ff2..40e2769a 100644 --- a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/MediaApi.java +++ b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/MediaApi.java @@ -9,6 +9,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.StringWriter; import java.util.ArrayList; +import java.util.Collection; import java.util.Date; import java.util.LinkedHashMap; import java.util.List; @@ -523,9 +524,10 @@ public class MediaApi extends QyApi { public boolean apply(Object object, String name, Object value) { if (column.containsKey(name)) { - if (name.equalsIgnoreCase("department")) { - column.put(name, StringUtil.join( - (JSONArray) JSON.toJSON(value), ';')); + if (value instanceof Collection) { + column.put(name, + StringUtil.join(((Collection) value) + .iterator(), ';')); } else { column.put(name, value); } diff --git a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/NotifyApi.java b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/NotifyApi.java index 57eee51f..2f4005d4 100644 --- a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/NotifyApi.java +++ b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/NotifyApi.java @@ -12,7 +12,7 @@ import com.foxinmy.weixin4j.token.TokenHolder; import com.foxinmy.weixin4j.tuple.NotifyTuple; /** - * 发送消息API + * 客服消息API * * @className NotifyApi * @author jy.hu @@ -46,7 +46,7 @@ public class NotifyApi extends QyApi { * 3)发送人员不在应用可见范围内:不执行发送任务,返回首个出错的userid
*

* - * @param notify + * @param message * 客服消息对象 * @return 如果无权限,则本次发送失败;如果收件人不存在或未关注,发送仍然执行。两种情况下均返回无效的部分
{ "errcode": * 0, "errmsg": "ok", "invaliduser": "UserID1", @@ -65,11 +65,12 @@ public class NotifyApi extends QyApi { * @see com.foxinmy.weixin4j.tuple.MpNews * @see com.foxinmy.weixin4j.qy.message.NotifyMessage */ - public JSONObject sendNotify(NotifyMessage notify) throws WeixinException { - NotifyTuple tuple = notify.getTuple(); - Map target = notify.getTarget().getParameter(); + public JSONObject sendNotifyMessage(NotifyMessage message) + throws WeixinException { + NotifyTuple tuple = message.getTuple(); + Map target = message.getTarget().getParameter(); String msgtype = tuple.getMessageType(); - JSONObject obj = (JSONObject) JSON.toJSON(notify); + JSONObject obj = (JSONObject) JSON.toJSON(message); obj.put("msgtype", msgtype); obj.put(msgtype, tuple); if (target == null || target.isEmpty()) { diff --git a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/message/ChatMessage.java b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/message/ChatMessage.java index fa55256c..3baaa930 100644 --- a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/message/ChatMessage.java +++ b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/message/ChatMessage.java @@ -8,7 +8,7 @@ import com.foxinmy.weixin4j.qy.type.ChatType; import com.foxinmy.weixin4j.tuple.ChatTuple; /** - * 聊天消息对象 + * 会话消息对象 * * @className ChatMessage * @author jy diff --git a/weixin4j-qy/src/test/java/com/foxinmy/weixin4j/qy/test/NotifyMsgTest.java b/weixin4j-qy/src/test/java/com/foxinmy/weixin4j/qy/test/NotifyMsgTest.java index cc85f11d..9ae51b17 100644 --- a/weixin4j-qy/src/test/java/com/foxinmy/weixin4j/qy/test/NotifyMsgTest.java +++ b/weixin4j-qy/src/test/java/com/foxinmy/weixin4j/qy/test/NotifyMsgTest.java @@ -38,33 +38,33 @@ public class NotifyMsgTest extends TokenTest { @Test public void text() throws WeixinException { NotifyMessage notify = new NotifyMessage(0, new Text("content")); - System.out.println(notifyApi.sendNotify(notify)); + System.out.println(notifyApi.sendNotifyMessage(notify)); } @Test public void image() throws WeixinException { NotifyMessage notify = new NotifyMessage(0, new Image("123")); - System.out.println(notifyApi.sendNotify(notify)); + System.out.println(notifyApi.sendNotifyMessage(notify)); } @Test public void voice() throws WeixinException { NotifyMessage notify = new NotifyMessage(0, new Voice("123")); - System.out.println(notifyApi.sendNotify(notify)); + System.out.println(notifyApi.sendNotifyMessage(notify)); } @Test public void video() throws WeixinException { NotifyMessage notify = new NotifyMessage(0, new Video("mediaId", "title", "desc")); - System.out.println(notifyApi.sendNotify(notify)); + System.out.println(notifyApi.sendNotifyMessage(notify)); } @Test public void file() throws WeixinException { File file = new File("file"); NotifyMessage notify = new NotifyMessage(0, file); - System.out.println(notifyApi.sendNotify(notify)); + System.out.println(notifyApi.sendNotifyMessage(notify)); } @Test @@ -73,7 +73,7 @@ public class NotifyMsgTest extends TokenTest { NotifyMessage notify = new NotifyMessage(0, news); news.addArticle("title1", "desc1", "picUrl1", "url1"); news.addArticle("title2", "desc2", "picUrl2", "url2"); - System.out.println(notifyApi.sendNotify(notify)); + System.out.println(notifyApi.sendNotifyMessage(notify)); } @Test @@ -82,13 +82,14 @@ public class NotifyMsgTest extends TokenTest { NotifyMessage notify = new NotifyMessage(0, news); news.addArticle("thumbMediaId1", "title1", "content1"); news.addArticle("thumbMediaId2", "title1", "content2"); - System.out.println(notifyApi.sendNotify(notify)); + System.out.println(notifyApi.sendNotifyMessage(notify)); } @Test public void send1() throws WeixinException { Text text = new Text("this is a text"); - JSONObject result = notifyApi.sendNotify(new NotifyMessage(1, text)); + JSONObject result = notifyApi.sendNotifyMessage(new NotifyMessage(1, + text)); Assert.assertEquals(0, result.getIntValue("errcode")); } } diff --git a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/xml/CruxMessageHandler.java b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/xml/CruxMessageHandler.java index 5a9eb5c6..8d5aea73 100644 --- a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/xml/CruxMessageHandler.java +++ b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/xml/CruxMessageHandler.java @@ -30,7 +30,7 @@ public class CruxMessageHandler extends DefaultHandler { private String toUserName; private String msgType; private String eventType; - private boolean agentId; + private boolean hasAgent; private Set nodeNames; private String content; @@ -41,7 +41,7 @@ public class CruxMessageHandler extends DefaultHandler { toUserName = null; msgType = null; eventType = null; - agentId = false; + hasAgent = false; nodeNames = new HashSet(); } @@ -57,8 +57,8 @@ public class CruxMessageHandler extends DefaultHandler { msgType = content.toLowerCase(); } else if (localName.equalsIgnoreCase("event")) { eventType = content.toLowerCase(); - } else if (localName.equalsIgnoreCase("agentId")) { - agentId = true; + } else if (localName.startsWith("agent")) { + hasAgent = true; } } @@ -69,7 +69,7 @@ public class CruxMessageHandler extends DefaultHandler { } public AccountType getAccountType() { - if (agentId) { + if (hasAgent) { return AccountType.QY; } if (StringUtil.isBlank(msgType) && StringUtil.isBlank(eventType)) {