From c040ba3929415f3de1609792af8119101f747451 Mon Sep 17 00:00:00 2001 From: BinaryWang Date: Mon, 18 Jul 2016 12:10:12 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=9F=A5=E7=9C=8B=E5=AE=A2?= =?UTF-8?q?=E6=9C=8D=E8=81=8A=E5=A4=A9=E8=AE=B0=E5=BD=95=E7=9A=84=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=20#5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- weixin-java-mp/pom.xml | 6 ++ .../weixin/mp/api/WxMpKefuService.java | 26 ++++-- .../mp/api/impl/WxMpKefuServiceImpl.java | 56 +++++++----- .../mp/bean/kefu/result/WxMpKfMsgList.java | 55 ++++++++++++ .../mp/bean/kefu/result/WxMpKfMsgRecord.java | 87 +++++++++++++++++++ .../mp/api/impl/WxMpKefuServiceImplTest.java | 22 +++-- 6 files changed, 220 insertions(+), 32 deletions(-) create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfMsgList.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfMsgRecord.java diff --git a/weixin-java-mp/pom.xml b/weixin-java-mp/pom.xml index 47daf679..a338ff5c 100644 --- a/weixin-java-mp/pom.xml +++ b/weixin-java-mp/pom.xml @@ -47,6 +47,12 @@ org.eclipse.jetty jetty-servlet test + + + joda-time + joda-time + 2.9.4 + test diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java index fc927bc4..38eaa8a0 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java @@ -1,14 +1,11 @@ package me.chanjar.weixin.mp.api; import java.io.File; +import java.util.Date; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfAccountRequest; -import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfList; -import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfOnlineList; -import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionGetResult; -import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionList; -import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionWaitCaseList; +import me.chanjar.weixin.mp.bean.kefu.result.*; /** * 客服接口 , @@ -135,4 +132,23 @@ public interface WxMpKefuService { * */ WxMpKfSessionWaitCaseList kfSessionGetWaitCase() throws WxErrorException; + + //*******************获取聊天记录的接口***********************// + /** + *
+   * 获取聊天记录
+   * 此接口返回的聊天记录中,对于图片、语音、视频,分别展示成文本格式的[image]、[voice]、[video]
+   * 详情请见:获取聊天记录
+   * 接口url格式: https://api.weixin.qq.com/customservice/msgrecord/getmsglist?access_token=ACCESS_TOKEN
+   * 
+ * + * @param startTime 起始时间 + * @param endTime 结束时间 + * @param msgId 消息id顺序从小到大,从1开始 + * @param number 每次获取条数,最多10000条 + * @return 聊天记录对象 + * @throws WxErrorException + */ + WxMpKfMsgList kfMsgList(Date startTime, Date endTime, Integer msgId, Integer number) throws WxErrorException; + } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java index c78c873d..d3857700 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java @@ -1,7 +1,10 @@ package me.chanjar.weixin.mp.api.impl; import java.io.File; +import java.util.Date; +import com.google.gson.JsonObject; +import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; @@ -10,11 +13,7 @@ import me.chanjar.weixin.mp.api.WxMpKefuService; import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfAccountRequest; import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfSessionRequest; -import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfList; -import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfOnlineList; -import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionGetResult; -import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionList; -import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionWaitCaseList; +import me.chanjar.weixin.mp.bean.kefu.result.*; /** * @@ -22,6 +21,7 @@ import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionWaitCaseList; * */ public class WxMpKefuServiceImpl implements WxMpKefuService { + public static final String API_URL_PREFIX = "https://api.weixin.qq.com/customservice"; private WxMpService wxMpService; public WxMpKefuServiceImpl(WxMpService wxMpService) { @@ -30,7 +30,7 @@ public class WxMpKefuServiceImpl implements WxMpKefuService { @Override public WxMpKfList kfList() throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/customservice/getkflist"; + String url = API_URL_PREFIX + "/getkflist"; String responseContent = this.wxMpService .execute(new SimpleGetRequestExecutor(), url, null); return WxMpKfList.fromJson(responseContent); @@ -38,7 +38,7 @@ public class WxMpKefuServiceImpl implements WxMpKefuService { @Override public WxMpKfOnlineList kfOnlineList() throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/customservice/getonlinekflist"; + String url = API_URL_PREFIX + "/getonlinekflist"; String responseContent = this.wxMpService .execute(new SimpleGetRequestExecutor(), url, null); return WxMpKfOnlineList.fromJson(responseContent); @@ -47,7 +47,7 @@ public class WxMpKefuServiceImpl implements WxMpKefuService { @Override public boolean kfAccountAdd(WxMpKfAccountRequest request) throws WxErrorException { - String url = "https://api.weixin.qq.com/customservice/kfaccount/add"; + String url = API_URL_PREFIX + "/kfaccount/add"; this.wxMpService.execute(new SimplePostRequestExecutor(), url, request.toJson()); return true; @@ -56,7 +56,7 @@ public class WxMpKefuServiceImpl implements WxMpKefuService { @Override public boolean kfAccountUpdate(WxMpKfAccountRequest request) throws WxErrorException { - String url = "https://api.weixin.qq.com/customservice/kfaccount/update"; + String url = API_URL_PREFIX + "/kfaccount/update"; this.wxMpService.execute(new SimplePostRequestExecutor(), url, request.toJson()); return true; @@ -64,7 +64,7 @@ public class WxMpKefuServiceImpl implements WxMpKefuService { @Override public boolean kfAccountInviteWorker(WxMpKfAccountRequest request) throws WxErrorException { - String url = "https://api.weixin.qq.com/customservice/kfaccount/inviteworker"; + String url = API_URL_PREFIX + "/kfaccount/inviteworker"; this.wxMpService.execute(new SimplePostRequestExecutor(), url, request.toJson()); return true; @@ -73,16 +73,14 @@ public class WxMpKefuServiceImpl implements WxMpKefuService { @Override public boolean kfAccountUploadHeadImg(String kfAccount, File imgFile) throws WxErrorException { - String url = "https://api.weixin.qq.com/customservice/kfaccount/uploadheadimg?kf_account=" - + kfAccount; + String url = API_URL_PREFIX + "/kfaccount/uploadheadimg?kf_account=" + kfAccount; this.wxMpService.execute(new MediaUploadRequestExecutor(), url, imgFile); return true; } @Override public boolean kfAccountDel(String kfAccount) throws WxErrorException { - String url = "https://api.weixin.qq.com/customservice/kfaccount/del?kf_account=" - + kfAccount; + String url = API_URL_PREFIX + "/kfaccount/del?kf_account=" + kfAccount; this.wxMpService.execute(new SimpleGetRequestExecutor(), url, null); return true; } @@ -91,7 +89,7 @@ public class WxMpKefuServiceImpl implements WxMpKefuService { public boolean kfSessionCreate(String openid, String kfAccount) throws WxErrorException { WxMpKfSessionRequest request = new WxMpKfSessionRequest(kfAccount, openid); - String url = "https://api.weixin.qq.com/customservice/kfsession/create"; + String url = API_URL_PREFIX + "/kfsession/create"; this.wxMpService.execute(new SimplePostRequestExecutor(), url, request.toJson()); return true; @@ -101,7 +99,7 @@ public class WxMpKefuServiceImpl implements WxMpKefuService { public boolean kfSessionClose(String openid, String kfAccount) throws WxErrorException { WxMpKfSessionRequest request = new WxMpKfSessionRequest(kfAccount, openid); - String url = "https://api.weixin.qq.com/customservice/kfsession/close"; + String url = API_URL_PREFIX + "/kfsession/close"; this.wxMpService.execute(new SimplePostRequestExecutor(), url, request.toJson()); return true; @@ -110,8 +108,7 @@ public class WxMpKefuServiceImpl implements WxMpKefuService { @Override public WxMpKfSessionGetResult kfSessionGet(String openid) throws WxErrorException { - String url = "https://api.weixin.qq.com/customservice/kfsession/getsession?openid=" - + openid; + String url = API_URL_PREFIX + "/kfsession/getsession?openid=" + openid; String responseContent = this.wxMpService .execute(new SimpleGetRequestExecutor(), url, null); return WxMpKfSessionGetResult.fromJson(responseContent); @@ -120,8 +117,7 @@ public class WxMpKefuServiceImpl implements WxMpKefuService { @Override public WxMpKfSessionList kfSessionList(String kfAccount) throws WxErrorException { - String url = "https://api.weixin.qq.com/customservice/kfsession/getsessionlist?kf_account=" - + kfAccount; + String url = API_URL_PREFIX + "/kfsession/getsessionlist?kf_account=" + kfAccount; String responseContent = this.wxMpService .execute(new SimpleGetRequestExecutor(), url, null); return WxMpKfSessionList.fromJson(responseContent); @@ -130,10 +126,28 @@ public class WxMpKefuServiceImpl implements WxMpKefuService { @Override public WxMpKfSessionWaitCaseList kfSessionGetWaitCase() throws WxErrorException { - String url = "https://api.weixin.qq.com/customservice/kfsession/getwaitcase"; + String url = API_URL_PREFIX + "/kfsession/getwaitcase"; String responseContent = this.wxMpService .execute(new SimpleGetRequestExecutor(), url, null); return WxMpKfSessionWaitCaseList.fromJson(responseContent); } + @Override + public WxMpKfMsgList kfMsgList(Date startTime, Date endTime, Integer msgId, Integer number) throws WxErrorException { + if(startTime.after(endTime)){ + throw new WxErrorException(WxError.newBuilder().setErrorMsg("起始时间不能晚于结束时间!").build()); + } + + String url = API_URL_PREFIX + "/msgrecord/getmsglist"; + + JsonObject param = new JsonObject(); + param.addProperty("starttime", startTime.getTime() / 1000); //starttime 起始时间,unix时间戳 + param.addProperty("endtime", endTime.getTime() / 1000); //endtime 结束时间,unix时间戳,每次查询时段不能超过24小时 + param.addProperty("msgid", msgId); //msgid 消息id顺序从小到大,从1开始 + param.addProperty("number", number); //number 每次获取条数,最多10000条 + + String responseContent = this.wxMpService.execute(new SimplePostRequestExecutor(), url, param.toString()); + return WxMpKfMsgList.fromJson(responseContent); + } + } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfMsgList.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfMsgList.java new file mode 100644 index 00000000..5078a2e5 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfMsgList.java @@ -0,0 +1,55 @@ +package me.chanjar.weixin.mp.bean.kefu.result; + +import com.google.gson.annotations.SerializedName; +import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import java.util.List; + +/** + * Created by Binary Wang on 2016/7/15. + */ +public class WxMpKfMsgList { + @SerializedName("recordlist") + private List records; + + @SerializedName("number") + private Integer number; + + @SerializedName("msgid") + private Long msgId; + + public List getRecords() { + return records; + } + + public void setRecords(List records) { + this.records = records; + } + + public Integer getNumber() { + return number; + } + + public void setNumber(Integer number) { + this.number = number; + } + + public Long getMsgId() { + return msgId; + } + + public void setMsgId(Long msgId) { + this.msgId = msgId; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE); + } + + public static WxMpKfMsgList fromJson(String responseContent) { + return WxMpGsonBuilder.INSTANCE.create().fromJson(responseContent, WxMpKfMsgList.class); + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfMsgRecord.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfMsgRecord.java new file mode 100644 index 00000000..00b7771e --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfMsgRecord.java @@ -0,0 +1,87 @@ +package me.chanjar.weixin.mp.bean.kefu.result; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.google.gson.annotations.SerializedName; +import me.chanjar.weixin.mp.util.json.WxLongTimeJsonSerializer; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * Created by Binary Wang on 2016/7/18. + */ +public class WxMpKfMsgRecord { + /** + * worker 完整客服帐号,格式为:帐号前缀@公众号微信号 + */ + @SerializedName("worker") + private String worker; + + /** + * openid 用户标识 + */ + @SerializedName("openid") + private String openid; + + /** + * opercode 操作码,2002(客服发送信息),2003(客服接收消息) + */ + @SerializedName("opercode") + private Integer operateCode; + + /** + * text 聊天记录 + */ + @SerializedName("text") + private String text; + + /** + * time 操作时间,unix时间戳 + */ + @SerializedName("time") + @JsonSerialize(using = WxLongTimeJsonSerializer.class) + private Long time; + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE); + } + public String getWorker() { + return worker; + } + + public void setWorker(String worker) { + this.worker = worker; + } + + public String getOpenid() { + return openid; + } + + public void setOpenid(String openid) { + this.openid = openid; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public Long getTime() { + return time; + } + + public void setTime(Long time) { + this.time = time; + } + + public Integer getOperateCode() { + return operateCode; + } + + public void setOperateCode(Integer operateCode) { + this.operateCode = operateCode; + } +} diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java index f02649cc..3f3e32dd 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java @@ -1,7 +1,13 @@ package me.chanjar.weixin.mp.api.impl; import java.io.File; +import java.util.Date; +import ch.qos.logback.classic.BasicConfigurator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import me.chanjar.weixin.mp.bean.kefu.result.*; +import org.joda.time.DateTime; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Guice; @@ -14,12 +20,6 @@ import me.chanjar.weixin.mp.api.ApiTestModule; import me.chanjar.weixin.mp.api.ApiTestModule.WxXmlMpInMemoryConfigStorage; import me.chanjar.weixin.mp.api.WxMpServiceImpl; import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfAccountRequest; -import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfInfo; -import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfList; -import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfOnlineList; -import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionGetResult; -import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionList; -import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionWaitCaseList; /** * 测试客服相关接口 @@ -145,4 +145,14 @@ public class WxMpKefuServiceImplTest { System.err.println(result); } + @Test + public void testKfMsgList() throws WxErrorException, JsonProcessingException { + BasicConfigurator.configureDefaultContext(); + Date startTime = DateTime.now().minusDays(1).toDate(); + Date endTime = DateTime.now().toDate(); + WxMpKfMsgList result = this.wxService.getKefuService().kfMsgList(startTime,endTime, 0, 20); + Assert.assertNotNull(result); + System.err.println(new ObjectMapper().writeValueAsString(result)); + } + }