From 81afb394844784ed581a4c31aa025c23713dd746 Mon Sep 17 00:00:00 2001 From: "jy.hu" Date: Sun, 16 Nov 2014 13:23:23 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=A4=9A=E5=AE=A2=E6=9C=8D?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 9 +- pom.xml | 2 +- weixin4j-mp/README.md | 8 +- weixin4j-mp/weixin4j-mp-api/README.md | 8 +- .../com/foxinmy/weixin4j/mp/WeixinProxy.java | 37 +++++-- .../foxinmy/weixin4j/mp/api/CustomApi.java | 98 +++++++++++++++++++ .../foxinmy/weixin4j/mp/api/NotifyApi.java | 41 +------- .../foxinmy/weixin4j/mp/api/weixin.properties | 4 + .../weixin4j/mp/model/CustomRecord.java | 33 ++----- .../foxinmy/weixin4j/mp/model/KfAccount.java | 96 ++++++++++++++++++ .../mp/response/TransferResponse.java | 48 ++++++++- .../mp/type/CustomRecordOperCode.java | 30 ++++++ .../weixin4j/mp/type/KfOnlineStatus.java | 29 ++++++ .../foxinmy/weixin4j/mp/util/EntityUtil.java | 29 ++++++ .../weixin4j/mp/test/msg/CustomTest.java | 57 +++++++++++ .../weixin4j/mp/test/msg/NotifyMsgTest.java | 4 +- weixin4j-mp/weixin4j-mp-server/README.md | 4 +- 17 files changed, 452 insertions(+), 85 deletions(-) create mode 100644 weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/CustomApi.java create mode 100644 weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/model/KfAccount.java create mode 100644 weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/type/CustomRecordOperCode.java create mode 100644 weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/type/KfOnlineStatus.java create mode 100644 weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/util/EntityUtil.java create mode 100644 weixin4j-mp/weixin4j-mp-api/src/test/java/com/foxinmy/weixin4j/mp/test/msg/CustomTest.java diff --git a/README.md b/README.md index 7361b5a9..6a9878b3 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ weixin4j + **weixin4j-mp**: 新增V2版本`退款申请`、`退款查询`、`对账单下载`三个接口 - + **weixin-mp**: 新增一个简单的`语义理解`接口 + + **weixin4j-mp**: 新增一个简单的`语义理解`接口 * 2014-11-11 @@ -74,17 +74,16 @@ weixin4j + **weixin4j-mp**: 新增被动消息的`加密`以及回复消息的`解密` +* 2014-11-16 + + + **weixin4j-mp**: 新增`多客服`接口 接下来 ------ -* 公众号智能接口 - * 被扫支付 * 企业号API封装 -* 公众号多客服 - * 微信小店 * 微信卡券 \ No newline at end of file diff --git a/pom.xml b/pom.xml index c662868c..33d8ad45 100644 --- a/pom.xml +++ b/pom.xml @@ -44,7 +44,7 @@ 1.4.7 4.2.5 1.9 - 1.1.9 + 1.2.1 1.7.3 1.1.6 2.6.0 diff --git a/weixin4j-mp/README.md b/weixin4j-mp/README.md index 7c25e0b9..98b4112a 100644 --- a/weixin4j-mp/README.md +++ b/weixin4j-mp/README.md @@ -46,7 +46,7 @@ weixin4j-mp * 2014-11-03 - + `weixin-mp`分离为`weixin-mp-api`和`weixin-mp-server`两个工程 + + `weixin-mp`分离为`weixin4j-mp-api`和`weixin4j-mp-server`两个工程 + **weixin4j-mp**: 新增`支付`模块 @@ -70,4 +70,8 @@ weixin4j-mp + **weixin4j-mp-server**: 解决`server工程`打包不能运行问题(`ClassUtil`无法获取jar包里面的类) - + **weixin4j-mp-server**: 新增被动消息的`加密`以及回复消息的`解密` \ No newline at end of file + + **weixin4j-mp-server**: 新增被动消息的`加密`以及回复消息的`解密` + +* 2014-11-16 + + + **weixin4j-mp-api**: 新增`多客服`接口 \ No newline at end of file diff --git a/weixin4j-mp/weixin4j-mp-api/README.md b/weixin4j-mp/weixin4j-mp-api/README.md index 07698944..bc117502 100644 --- a/weixin4j-mp/weixin4j-mp-api/README.md +++ b/weixin4j-mp/weixin4j-mp-api/README.md @@ -11,6 +11,8 @@ weixin4j-mp-api * NotifyApi `客服消息API` +* CustomApi `多客服API`* + * MassApi `群发消息API` * UserApi `用户管理API` @@ -108,4 +110,8 @@ weixin.properties说明 * 2014-11-15 - + 新增获取`微信服务器IP地址接口` \ No newline at end of file + + 新增获取`微信服务器IP地址接口` + +* 2014-11-16 + + + 新增`多客服`接口 \ No newline at end of file diff --git a/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/WeixinProxy.java b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/WeixinProxy.java index 3dabbdf2..66d1cb54 100644 --- a/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/WeixinProxy.java +++ b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/WeixinProxy.java @@ -11,6 +11,7 @@ import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.http.JsonResult; import com.foxinmy.weixin4j.http.XmlResult; import com.foxinmy.weixin4j.model.WeixinAccount; +import com.foxinmy.weixin4j.mp.api.CustomApi; import com.foxinmy.weixin4j.mp.api.GroupApi; import com.foxinmy.weixin4j.mp.api.HelperApi; import com.foxinmy.weixin4j.mp.api.MassApi; @@ -25,6 +26,7 @@ import com.foxinmy.weixin4j.mp.model.Button; import com.foxinmy.weixin4j.mp.model.CustomRecord; import com.foxinmy.weixin4j.mp.model.Following; import com.foxinmy.weixin4j.mp.model.Group; +import com.foxinmy.weixin4j.mp.model.KfAccount; import com.foxinmy.weixin4j.mp.model.MpArticle; import com.foxinmy.weixin4j.mp.model.OauthToken; import com.foxinmy.weixin4j.mp.model.QRParameter; @@ -57,6 +59,7 @@ public class WeixinProxy { private final MediaApi mediaApi; private final NotifyApi notifyApi; + private final CustomApi customApi; private final MassApi massApi; private final UserApi userApi; private final GroupApi groupApi; @@ -101,6 +104,7 @@ public class WeixinProxy { public WeixinProxy(TokenHolder tokenHolder) { this.mediaApi = new MediaApi(tokenHolder); this.notifyApi = new NotifyApi(tokenHolder); + this.customApi = new CustomApi(tokenHolder); this.massApi = new MassApi(tokenHolder); this.userApi = new UserApi(tokenHolder); this.groupApi = new GroupApi(tokenHolder); @@ -236,13 +240,13 @@ public class WeixinProxy { * @param baseMsg * 消息类型 * @return 发送结果 - * @throws WeixinException * @see com.foxinmy.weixin4j.mp.msg.model.Text * @see com.foxinmy.weixin4j.mp.msg.model.Image * @see com.foxinmy.weixin4j.mp.msg.model.Music * @see com.foxinmy.weixin4j.mp.msg.model.Video * @see com.foxinmy.weixin4j.mp.msg.model.Voice * @see com.foxinmy.weixin4j.mp.api.NotifyApi + * @throws WeixinException */ public JsonResult sendNotify(String touser, BaseMsg baseMsg) throws WeixinException { @@ -253,7 +257,7 @@ public class WeixinProxy { * 客服聊天记录 * * @param openId - * 用户标识 可为空 + * 用户标识 为空时则查询全部记录 * @param starttime * 查询开始时间 * @param endtime @@ -262,18 +266,37 @@ public class WeixinProxy { * 每页大小 每页最多拉取1000条 * @param pageindex * 查询第几页 从1开始 - * @throws WeixinException * @see com.foxinmy.weixin4j.mp.model.CustomRecord - * @see com.foxinmy.weixin4j.mp.api.NotifyApi + * @see com.foxinmy.weixin4j.mp.api.CustomApi + * @see 查询客服聊天记录 * @see 查询客服聊天记录 + * @throws WeixinException */ - public List getCustomRecord(String openId, long starttime, - long endtime, int pagesize, int pageindex) throws WeixinException { - return notifyApi.getCustomRecord(openId, starttime, endtime, pagesize, + public List getCustomRecord(String openId, Date starttime, + Date endtime, int pagesize, int pageindex) throws WeixinException { + return customApi.getCustomRecord(openId, starttime, endtime, pagesize, pageindex); } + /** + * 获取公众号中所设置的客服基本信息,包括客服工号、客服昵称、客服登录账号 + * + * @param isOnline + * 是否在线 为ture时可以可以获取客服在线状态(手机在线、PC客户端在线、手机和PC客户端全都在线)、客服自动接入最大值、 + * 客服当前接待客户数 + * @return 多客服信息列表 + * @see com.foxinmy.weixin4j.mp.model.KfAccount + * @see com.foxinmy.weixin4j.mp.api.CustomApi + * @see 获取客服基本信息 + * @see 获取在线客服接待信息 + * @throws WeixinException + */ + public List getKfAccountList(boolean isOnline) + throws WeixinException { + return customApi.getKfAccountList(isOnline); + } + /** * 上传图文消息,一个图文消息支持1到10条图文 * diff --git a/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/CustomApi.java b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/CustomApi.java new file mode 100644 index 00000000..32e2441e --- /dev/null +++ b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/CustomApi.java @@ -0,0 +1,98 @@ +package com.foxinmy.weixin4j.mp.api; + +import java.util.Date; +import java.util.List; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.http.Response; +import com.foxinmy.weixin4j.model.Token; +import com.foxinmy.weixin4j.mp.model.CustomRecord; +import com.foxinmy.weixin4j.mp.model.KfAccount; +import com.foxinmy.weixin4j.token.TokenHolder; + +/** + * 多客服API + * + * @className CustomApi + * @author jy + * @date 2014年11月16日 + * @since JDK 1.7 + * @see 多客服说明 + */ +public class CustomApi extends BaseApi { + + private final TokenHolder tokenHolder; + + public CustomApi(TokenHolder tokenHolder) { + this.tokenHolder = tokenHolder; + } + + /** + * 客服聊天记录 + * + * @param openId + * 用户标识 可为空 + * @param starttime + * 查询开始时间 + * @param endtime + * 查询结束时间 每次查询不能跨日查询 + * @param pagesize + * 每页大小 每页最多拉取1000条 + * @param pageindex + * 查询第几页 从1开始 + * @throws WeixinException + * @see com.foxinmy.weixin4j.mp.model.CustomRecord + * @see 查询客服聊天记录 + * @see 查询客服聊天记录 + */ + public List getCustomRecord(String openId, Date starttime, + Date endtime, int pagesize, int pageindex) throws WeixinException { + JSONObject obj = new JSONObject(); + obj.put("openId", openId == null ? "" : openId); + obj.put("starttime", starttime.getTime() / 1000); + obj.put("endtime", endtime.getTime() / 1000); + obj.put("pagesize", pagesize > 1000 ? 1000 : pagesize); + obj.put("pageindex", pageindex); + String custom_record_uri = getRequestUri("custom_record_uri"); + Token token = tokenHolder.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); + } + + /** + * 获取公众号中所设置的客服基本信息,包括客服工号、客服昵称、客服登录账号 + * + * @param isOnline + * 是否在线 为ture时可以可以获取客服在线状态(手机在线、PC客户端在线、手机和PC客户端全都在线)、客服自动接入最大值、 + * 客服当前接待客户数 + * @return 多客服信息列表 + * @see com.foxinmy.weixin4j.mp.model.KfAccount + * @see 获取客服基本信息 + * @see 获取在线客服接待信息 + * @throws WeixinException + */ + public List getKfAccountList(boolean isOnline) + throws WeixinException { + Token token = tokenHolder.getToken(); + String text = ""; + if (isOnline) { + String getonlinekflist_uri = getRequestUri("getonlinekflist_uri"); + Response response = request.post(String.format(getonlinekflist_uri, + token.getAccessToken())); + text = response.getAsJson().getString("kf_online_list"); + } else { + String getkflist_uri = getRequestUri("getkflist_uri"); + Response response = request.post(String.format(getkflist_uri, + token.getAccessToken())); + text = response.getAsJson().getString("kf_list"); + } + return JSON.parseArray(text, KfAccount.class); + } +} \ No newline at end of file diff --git a/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/NotifyApi.java b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/NotifyApi.java index bc06850c..1a2dfd51 100644 --- a/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/NotifyApi.java +++ b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/NotifyApi.java @@ -2,13 +2,10 @@ package com.foxinmy.weixin4j.mp.api; import java.util.List; -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.http.JsonResult; import com.foxinmy.weixin4j.http.Response; import com.foxinmy.weixin4j.model.Token; -import com.foxinmy.weixin4j.mp.model.CustomRecord; import com.foxinmy.weixin4j.mp.msg.model.Article; import com.foxinmy.weixin4j.mp.msg.model.BaseMsg; import com.foxinmy.weixin4j.mp.msg.notify.ArticleNotify; @@ -16,7 +13,7 @@ import com.foxinmy.weixin4j.mp.msg.notify.BaseNotify; import com.foxinmy.weixin4j.token.TokenHolder; /** - * 客服相关API + * 客服消息API * * @className NotifyApi * @author jy.hu @@ -126,40 +123,4 @@ public class NotifyApi extends BaseApi { return sendNotify(jsonPara.toString()); } - - /** - * 客服聊天记录 - * - * @param openId - * 用户标识 可为空 - * @param starttime - * 查询开始时间 - * @param endtime - * 查询结束时间 每次查询不能跨日查询 - * @param pagesize - * 每页大小 每页最多拉取1000条 - * @param pageindex - * 查询第几页 从1开始 - * @throws WeixinException - * @see com.foxinmy.weixin4j.mp.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 = getRequestUri("custom_record_uri"); - Token token = tokenHolder.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/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/weixin.properties b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/weixin.properties index 8879ad91..75382e59 100644 --- a/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/weixin.properties +++ b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/weixin.properties @@ -63,6 +63,10 @@ mass_openid_uri={api_cgi_url}/message/mass/send?access_token=%s mass_delete_uri={api_cgi_url}/message/mass/delete?access_token=%s # \u5ba2\u670d\u804a\u5929\u8bb0\u5f55 custom_record_uri={api_cgi_url}/customservice/getrecord?access_token=%s +# \u5ba2\u670d\u57fa\u672c\u4fe1\u606f +getkflist_uri={api_cgi_url}/customservice/getkflist?access_token=%s +# \u5728\u7ebf\u5ba2\u670d\u57fa\u672c\u4fe1\u606f +getonlinekflist_uri={api_cgi_url}/customservice/getonlinekflist?access_token=%s # \u957f\u94fe\u63a5\u8f6c\u77ed\u94fe\u63a5 shorturl_uri={api_cgi_url}/shorturl?access_token=%s p_shorturl_uri={mch_base_url}/tools/shorturl diff --git a/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/model/CustomRecord.java b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/model/CustomRecord.java index 6eef8b33..c943ab1e 100644 --- a/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/model/CustomRecord.java +++ b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/model/CustomRecord.java @@ -3,6 +3,9 @@ package com.foxinmy.weixin4j.mp.model; import java.io.Serializable; import java.util.Date; +import com.foxinmy.weixin4j.mp.type.CustomRecordOperCode; +import com.foxinmy.weixin4j.mp.util.EntityUtil; + /** * 客服聊天记录 * @@ -18,7 +21,7 @@ public class CustomRecord implements Serializable { private static final long serialVersionUID = -4024147769411601325L; private String worker;// 客服账号 private String openid;// 用户的标识 - private Opercode opercode;// 操作ID(会话状态) + private CustomRecordOperCode opercode;// 操作ID(会话状态) private Date time;// 操作时间 private String text;// 聊天记录 @@ -38,20 +41,20 @@ public class CustomRecord implements Serializable { this.openid = openid; } - public Opercode getOpercode() { + public CustomRecordOperCode getOpercode() { return opercode; } - public void setOpercode(Opercode opercode) { - this.opercode = opercode; + public void setOpercode(int opercode) { + this.opercode = EntityUtil.getCustomRecordOperCode(opercode); } public Date getTime() { return time; } - public void setTime(Date time) { - this.time = time; + public void setTime(long time) { + this.time = new Date(time * 1000); } public String getText() { @@ -62,24 +65,6 @@ public class CustomRecord implements Serializable { this.text = text; } - public enum Opercode { - MISS(1000, "创建未接入会话"), ONLINE(1001, "接入会话"), CALL(1002, "主动发起会话"), CLOSE( - 1004, "关闭会话"), RASE(1005, "抢接会话"), RECEIVE1(2001, "公众号收到消息"), SEND( - 2002, "客服发送消息"), RECEIVE2(2003, "客服收到消息"); - private int code; - private String desc; - Opercode(int code, String desc) { - this.code = code; - this.desc = desc; - } - public int getCode() { - return code; - } - public String getDesc() { - return desc; - } - } - @Override public String toString() { StringBuilder sb = new StringBuilder(); diff --git a/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/model/KfAccount.java b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/model/KfAccount.java new file mode 100644 index 00000000..01a7e504 --- /dev/null +++ b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/model/KfAccount.java @@ -0,0 +1,96 @@ +package com.foxinmy.weixin4j.mp.model; + +import java.io.Serializable; + +import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.mp.type.KfOnlineStatus; + +/** + * 多客服账号信息 + * + * @className KfAccount + * @author jy + * @date 2014年11月16日 + * @since JDK 1.7 + * @see 多客服账号信息 + */ +public class KfAccount implements Serializable { + + private static final long serialVersionUID = -4565570894727129245L; + + @JSONField(name = "kf_account") + // 客服账号@微信别名 微信别名如有修改,旧账号返回旧的微信别名,新增的账号返回新的微信别名 + private String account; + @JSONField(name = "kf_nick") + private String nickName;// 客服昵称 + @JSONField(name = "kf_id") + private String id;// 客服工号 + + // 以下字段是调用在线客服状态返回的字段 + private KfOnlineStatus status; // 客服在线状态 1:pc在线,2:手机在线 若pc和手机同时在线则为 1+2=3 + @JSONField(name = "auto_accept") + private int autoAccept;// 客服设置的最大自动接入数 + @JSONField(name = "accepted_case") + private int acceptedCase;// 客服当前正在接待的会话数 + + public String getAccount() { + return account; + } + + public void setAccount(String account) { + this.account = account; + } + + public String getNickName() { + return nickName; + } + + public void setNickName(String nickName) { + this.nickName = nickName; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public KfOnlineStatus getStatus() { + return status; + } + + public void setStatus(int status) { + if (status == 1) { + this.status = KfOnlineStatus.PC; + } else if (status == 2) { + this.status = KfOnlineStatus.MOBILE; + } else { + this.status = KfOnlineStatus.BOTH; + } + } + + public int getAutoAccept() { + return autoAccept; + } + + public void setAutoAccept(int autoAccept) { + this.autoAccept = autoAccept; + } + + public int getAcceptedCase() { + return acceptedCase; + } + + public void setAcceptedCase(int acceptedCase) { + this.acceptedCase = acceptedCase; + } + + @Override + public String toString() { + return "KfAccount [account=" + account + ", nickName=" + nickName + + ", id=" + id + ", status=" + status + ", autoAccept=" + + autoAccept + ", acceptedCase=" + acceptedCase + "]"; + } +} diff --git a/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/response/TransferResponse.java b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/response/TransferResponse.java index a6230201..108fa65e 100644 --- a/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/response/TransferResponse.java +++ b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/response/TransferResponse.java @@ -13,6 +13,7 @@ import com.thoughtworks.xstream.annotations.XStreamAlias; * @since JDK 1.7 * @see 多客服转移消息 + * @see 将消息转发到多客服 * @see com.foxinmy.weixin4j.mp.response.BaseResponse * @see com.foxinmy.weixin4j.mp.response.BaseResponse#toXml() */ @@ -24,4 +25,49 @@ public class TransferResponse extends BaseResponse { public TransferResponse(BaseMessage inMessage) { super(ResponseType.transfer_customer_service, inMessage); } -} + + /** + * 需如果指定的客服没有接入能力(不在线、没有开启自动接入或者自动接入已满) 该用户会一直等待指定客服有接入能力后才会被接入 而不会被其他客服接待 + * + * @param inMessage + * @param kfAccount + * 转移客服的账号 + */ + public TransferResponse(BaseMessage inMessage, String kfAccount) { + super(ResponseType.transfer_customer_service, inMessage); + this.transInfo = new TransInfo(kfAccount); + } + + @XStreamAlias("TransInfo") + private TransInfo transInfo; + + public String getTransAccount() { + if (transInfo != null) { + return transInfo.getKfAccount(); + } + return null; + } + + public void setTransAccount(String kfAccount) { + this.transInfo = new TransInfo(kfAccount); + } + + private static class TransInfo { + // 指定会话接入的客服账号 + @XStreamAlias("KfAccount") + private String kfAccount; + + public TransInfo(String kfAccount) { + this.kfAccount = kfAccount; + } + + public String getKfAccount() { + return kfAccount; + } + + @Override + public String toString() { + return "TransInfo [kfAccount=" + kfAccount + "]"; + } + } +} \ No newline at end of file diff --git a/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/type/CustomRecordOperCode.java b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/type/CustomRecordOperCode.java new file mode 100644 index 00000000..09de5e7c --- /dev/null +++ b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/type/CustomRecordOperCode.java @@ -0,0 +1,30 @@ +package com.foxinmy.weixin4j.mp.type; + +/** + * 客服消息记录中的回话状态 + * @className CustomRecordOperCode + * @author jy + * @date 2014年11月16日 + * @since JDK 1.7 + * @see + */ +public enum CustomRecordOperCode { + MISS(1000, "创建未接入会话"), ONLINE(1001, "接入会话"), CALL(1002, "主动发起会话"), CLOSE( + 1004, "关闭会话"), RASE(1005, "抢接会话"), RECEIVE1(2001, "公众号收到消息"), SEND( + 2002, "客服发送消息"), RECEIVE2(2003, "客服收到消息"); + private int code; + private String desc; + + CustomRecordOperCode(int code, String desc) { + this.code = code; + this.desc = desc; + } + + public int getCode() { + return code; + } + + public String getDesc() { + return desc; + } +} diff --git a/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/type/KfOnlineStatus.java b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/type/KfOnlineStatus.java new file mode 100644 index 00000000..a10475c7 --- /dev/null +++ b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/type/KfOnlineStatus.java @@ -0,0 +1,29 @@ +package com.foxinmy.weixin4j.mp.type; + +/** + * 多客服在线状态 + * + * @className KfOnlineStatus + * @author jy + * @date 2014年11月16日 + * @since JDK 1.7 + * @see + */ +public enum KfOnlineStatus { + PC(1, "PC在线"), MOBILE(2, "手机在线"), BOTH(3, "PC跟手机同时在线"); + private int code; + private String desc; + + KfOnlineStatus(int code, String desc) { + this.code = code; + this.desc = desc; + } + + public int getCode() { + return code; + } + + public String getDesc() { + return desc; + } +} diff --git a/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/util/EntityUtil.java b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/util/EntityUtil.java new file mode 100644 index 00000000..1b1a5718 --- /dev/null +++ b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/util/EntityUtil.java @@ -0,0 +1,29 @@ +package com.foxinmy.weixin4j.mp.util; + +import java.util.HashMap; +import java.util.Map; + +import com.foxinmy.weixin4j.mp.type.CustomRecordOperCode; + +/** + * 实体帮助类 + * + * @className EntityUtil + * @author jy + * @date 2014年11月16日 + * @since JDK 1.7 + * @see + */ +public class EntityUtil { + private static Map customRecordOperCodeMap; + static { + customRecordOperCodeMap = new HashMap(); + for (CustomRecordOperCode operCode : CustomRecordOperCode.values()) { + customRecordOperCodeMap.put(operCode.getCode(), operCode); + } + } + + public static CustomRecordOperCode getCustomRecordOperCode(int code) { + return customRecordOperCodeMap.get(code); + } +} diff --git a/weixin4j-mp/weixin4j-mp-api/src/test/java/com/foxinmy/weixin4j/mp/test/msg/CustomTest.java b/weixin4j-mp/weixin4j-mp-api/src/test/java/com/foxinmy/weixin4j/mp/test/msg/CustomTest.java new file mode 100644 index 00000000..48c964af --- /dev/null +++ b/weixin4j-mp/weixin4j-mp-api/src/test/java/com/foxinmy/weixin4j/mp/test/msg/CustomTest.java @@ -0,0 +1,57 @@ +package com.foxinmy.weixin4j.mp.test.msg; + +import java.util.Calendar; +import java.util.Date; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.mp.api.CustomApi; +import com.foxinmy.weixin4j.mp.model.CustomRecord; +import com.foxinmy.weixin4j.mp.model.KfAccount; +import com.foxinmy.weixin4j.mp.test.TokenTest; + +/** + * 客服消息测试 + * + * @className MessageNotifyTest + * @author jy.hu + * @date 2014年4月10日 + * @since JDK 1.7 + * @see + */ +public class CustomTest extends TokenTest { + + private CustomApi customApi; + + @Before + public void init() { + customApi = new CustomApi(tokenHolder); + } + + @Test + public void customRecord() throws WeixinException { + String openId = ""; + Calendar calendar = Calendar.getInstance(); + calendar.set(Calendar.HOUR_OF_DAY, 9); + calendar.add(Calendar.DAY_OF_MONTH, -2); + Date starttime = calendar.getTime(); + calendar.set(Calendar.HOUR_OF_DAY, 21); + Date endtime = calendar.getTime(); + int pagesize = 10; + int pageindex = 1; + List recordList = customApi.getCustomRecord(openId, + starttime, endtime, pagesize, pageindex); + System.out.println(recordList); + } + + @Test + public void kfList() throws WeixinException { + List kfList = customApi.getKfAccountList(false); + System.out.println(kfList); + kfList = customApi.getKfAccountList(true); + System.out.println(kfList); + } +} diff --git a/weixin4j-mp/weixin4j-mp-api/src/test/java/com/foxinmy/weixin4j/mp/test/msg/NotifyMsgTest.java b/weixin4j-mp/weixin4j-mp-api/src/test/java/com/foxinmy/weixin4j/mp/test/msg/NotifyMsgTest.java index 67b1067b..28f08909 100644 --- a/weixin4j-mp/weixin4j-mp-api/src/test/java/com/foxinmy/weixin4j/mp/test/msg/NotifyMsgTest.java +++ b/weixin4j-mp/weixin4j-mp-api/src/test/java/com/foxinmy/weixin4j/mp/test/msg/NotifyMsgTest.java @@ -93,8 +93,8 @@ public class NotifyMsgTest extends TokenTest { @Test public void send2() throws WeixinException, IOException { - String mediaId = mediaApi.uploadMedia(new File( - "/tmp/test.jpg"), MediaType.image); + String mediaId = mediaApi.uploadMedia(new File("/tmp/test.jpg"), + MediaType.image); ImageNotify imageNotify = new ImageNotify( "owGBft_vbBbOaQOmpEUE4xDLeRSU"); imageNotify.pushMediaId(mediaId); diff --git a/weixin4j-mp/weixin4j-mp-server/README.md b/weixin4j-mp/weixin4j-mp-server/README.md index 35124778..1cedb071 100644 --- a/weixin4j-mp/weixin4j-mp-server/README.md +++ b/weixin4j-mp/weixin4j-mp-server/README.md @@ -28,7 +28,7 @@ weixin4j-mp-server > account={"appId":"appId","appSecret":"appSecret", > "token":"开放者的token 非必须","openId":"公众号的openid 非必须", -> "encodingAesKey":"公众号设置了加密方式且为「安全模式」需要填入", +> "encodingAesKey":"公众号设置了加密方式且为「安全模式」时需要填入", > "mchId":"V3.x版本下的微信商户号", > "partnerId":"财付通的商户号","partnerKey":"财付通商户权限密钥Key", > "version":"针对微信支付的版本号(目前可能为2,3),如果不填则按照mchId非空与否来做判断", @@ -49,7 +49,7 @@ weixin4j-mp-server ------- * 2014-11-03 - + 得到`weixin-mp-server`工程 + + 得到`weixin4j-mp-server`工程 * 2014-11-15