浏览代码

#730 公众号模块增加客服输入状态接口

master
Binary Wang 6 年前
父节点
当前提交
314871cea6
共有 3 个文件被更改,包括 106 次插入29 次删除
  1. +58
    -9
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java
  2. +27
    -12
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java
  3. +21
    -8
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java

+ 58
- 9
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java 查看文件

@@ -1,16 +1,21 @@
package me.chanjar.weixin.mp.api; package me.chanjar.weixin.mp.api;


import java.io.File;
import java.util.Date;

import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage; import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage;
import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfAccountRequest; import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfAccountRequest;
import me.chanjar.weixin.mp.bean.kefu.result.*;

import java.io.File;
import java.util.Date;
import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfList;
import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfMsgList;
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;


/** /**
* <pre> * <pre>
* 客服接口
* 客服接口.
* 注意:命名采用kefu拼音的原因是:其英文CustomerService如果再加上Service后缀显得有点啰嗦,如果不加又显得表意不完整。 * 注意:命名采用kefu拼音的原因是:其英文CustomerService如果再加上Service后缀显得有点啰嗦,如果不加又显得表意不完整。
* </pre> * </pre>
* *
@@ -30,7 +35,8 @@ public interface WxMpKefuService {
String KFSESSION_GET_SESSION = "https://api.weixin.qq.com/customservice/kfsession/getsession?openid=%s"; String KFSESSION_GET_SESSION = "https://api.weixin.qq.com/customservice/kfsession/getsession?openid=%s";
String KFSESSION_GET_SESSION_LIST = "https://api.weixin.qq.com/customservice/kfsession/getsessionlist?kf_account=%s"; String KFSESSION_GET_SESSION_LIST = "https://api.weixin.qq.com/customservice/kfsession/getsessionlist?kf_account=%s";
String KFSESSION_GET_WAIT_CASE = "https://api.weixin.qq.com/customservice/kfsession/getwaitcase"; String KFSESSION_GET_WAIT_CASE = "https://api.weixin.qq.com/customservice/kfsession/getwaitcase";
String MSGRECORD_GET_MSG_LIST = "https://api.weixin.qq.com/customservice/msgrecord/getmsglist";
String MSG_RECORD_LIST = "https://api.weixin.qq.com/customservice/msgrecord/getmsglist";
String CUSTOM_TYPING = "https://api.weixin.qq.com/cgi-bin/message/custom/typing";


/** /**
* <pre> * <pre>
@@ -38,6 +44,8 @@ public interface WxMpKefuService {
* 详情请见: <a href="http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140547&token=&lang=zh_CN">发送客服消息</a> * 详情请见: <a href="http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140547&token=&lang=zh_CN">发送客服消息</a>
* 接口url格式:https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN * 接口url格式:https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN
* </pre> * </pre>
*
* @throws WxErrorException 异常
*/ */
boolean sendKefuMessage(WxMpKefuMessage message) throws WxErrorException; boolean sendKefuMessage(WxMpKefuMessage message) throws WxErrorException;


@@ -49,6 +57,8 @@ public interface WxMpKefuService {
* 详情请见:<a href="http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044813&token=&lang=zh_CN">客服管理</a> * 详情请见:<a href="http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044813&token=&lang=zh_CN">客服管理</a>
* 接口url格式:https://api.weixin.qq.com/cgi-bin/customservice/getkflist?access_token=ACCESS_TOKEN * 接口url格式:https://api.weixin.qq.com/cgi-bin/customservice/getkflist?access_token=ACCESS_TOKEN
* </pre> * </pre>
*
* @throws WxErrorException 异常
*/ */
WxMpKfList kfList() throws WxErrorException; WxMpKfList kfList() throws WxErrorException;


@@ -58,6 +68,8 @@ public interface WxMpKefuService {
* 详情请见:<a href="http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044813&token=&lang=zh_CN">客服管理</a> * 详情请见:<a href="http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044813&token=&lang=zh_CN">客服管理</a>
* 接口url格式:https://api.weixin.qq.com/cgi-bin/customservice/getonlinekflist?access_token=ACCESS_TOKEN * 接口url格式:https://api.weixin.qq.com/cgi-bin/customservice/getonlinekflist?access_token=ACCESS_TOKEN
* </pre> * </pre>
*
* @throws WxErrorException 异常
*/ */
WxMpKfOnlineList kfOnlineList() throws WxErrorException; WxMpKfOnlineList kfOnlineList() throws WxErrorException;


@@ -67,6 +79,8 @@ public interface WxMpKefuService {
* 详情请见:<a href="http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044813&token=&lang=zh_CN">客服管理</a> * 详情请见:<a href="http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044813&token=&lang=zh_CN">客服管理</a>
* 接口url格式:https://api.weixin.qq.com/customservice/kfaccount/add?access_token=ACCESS_TOKEN * 接口url格式:https://api.weixin.qq.com/customservice/kfaccount/add?access_token=ACCESS_TOKEN
* </pre> * </pre>
*
* @throws WxErrorException 异常
*/ */
boolean kfAccountAdd(WxMpKfAccountRequest request) throws WxErrorException; boolean kfAccountAdd(WxMpKfAccountRequest request) throws WxErrorException;


@@ -85,6 +99,8 @@ public interface WxMpKefuService {
* 详情请见:<a href="http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044813&token=&lang=zh_CN">客服管理</a> * 详情请见:<a href="http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044813&token=&lang=zh_CN">客服管理</a>
* 接口url格式:https://api.weixin.qq.com/customservice/kfaccount/inviteworker?access_token=ACCESS_TOKEN * 接口url格式:https://api.weixin.qq.com/customservice/kfaccount/inviteworker?access_token=ACCESS_TOKEN
* </pre> * </pre>
*
* @throws WxErrorException 异常
*/ */
boolean kfAccountInviteWorker(WxMpKfAccountRequest request) throws WxErrorException; boolean kfAccountInviteWorker(WxMpKfAccountRequest request) throws WxErrorException;


@@ -94,8 +110,10 @@ public interface WxMpKefuService {
* 详情请见:<a href="http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044813&token=&lang=zh_CN">客服管理</a> * 详情请见:<a href="http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044813&token=&lang=zh_CN">客服管理</a>
* 接口url格式:https://api.weixin.qq.com/customservice/kfaccount/uploadheadimg?access_token=ACCESS_TOKEN&kf_account=KFACCOUNT * 接口url格式:https://api.weixin.qq.com/customservice/kfaccount/uploadheadimg?access_token=ACCESS_TOKEN&kf_account=KFACCOUNT
* </pre> * </pre>
*
* @throws WxErrorException 异常
*/ */
boolean kfAccountUploadHeadImg(String kfAccount, File imgFile) throws WxErrorException;
boolean kfAccountUploadHeadImg(String kfAccount, File imgFile) throws WxErrorException;


/** /**
* <pre> * <pre>
@@ -103,6 +121,8 @@ public interface WxMpKefuService {
* 详情请见:<a href="http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044813&token=&lang=zh_CN">客服管理</a> * 详情请见:<a href="http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044813&token=&lang=zh_CN">客服管理</a>
* 接口url格式:https://api.weixin.qq.com/customservice/kfaccount/del?access_token=ACCESS_TOKEN&kf_account=KFACCOUNT * 接口url格式:https://api.weixin.qq.com/customservice/kfaccount/del?access_token=ACCESS_TOKEN&kf_account=KFACCOUNT
* </pre> * </pre>
*
* @throws WxErrorException 异常
*/ */
boolean kfAccountDel(String kfAccount) throws WxErrorException; boolean kfAccountDel(String kfAccount) throws WxErrorException;


@@ -115,6 +135,8 @@ public interface WxMpKefuService {
* 详情请见:<a href="http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044820&token=&lang=zh_CN">客服会话控制接口</a> * 详情请见:<a href="http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044820&token=&lang=zh_CN">客服会话控制接口</a>
* 接口url格式: https://api.weixin.qq.com/customservice/kfsession/create?access_token=ACCESS_TOKEN * 接口url格式: https://api.weixin.qq.com/customservice/kfsession/create?access_token=ACCESS_TOKEN
* </pre> * </pre>
*
* @throws WxErrorException 异常
*/ */
boolean kfSessionCreate(String openid, String kfAccount) throws WxErrorException; boolean kfSessionCreate(String openid, String kfAccount) throws WxErrorException;


@@ -125,6 +147,8 @@ public interface WxMpKefuService {
* 详情请见:<a href="http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044820&token=&lang=zh_CN">客服会话控制接口</a> * 详情请见:<a href="http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044820&token=&lang=zh_CN">客服会话控制接口</a>
* 接口url格式: https://api.weixin.qq.com/customservice/kfsession/close?access_token=ACCESS_TOKEN * 接口url格式: https://api.weixin.qq.com/customservice/kfsession/close?access_token=ACCESS_TOKEN
* </pre> * </pre>
*
* @throws WxErrorException 异常
*/ */
boolean kfSessionClose(String openid, String kfAccount) throws WxErrorException; boolean kfSessionClose(String openid, String kfAccount) throws WxErrorException;


@@ -135,6 +159,8 @@ public interface WxMpKefuService {
* 详情请见:<a href="http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044820&token=&lang=zh_CN">客服会话控制接口</a> * 详情请见:<a href="http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044820&token=&lang=zh_CN">客服会话控制接口</a>
* 接口url格式: https://api.weixin.qq.com/customservice/kfsession/getsession?access_token=ACCESS_TOKEN&openid=OPENID * 接口url格式: https://api.weixin.qq.com/customservice/kfsession/getsession?access_token=ACCESS_TOKEN&openid=OPENID
* </pre> * </pre>
*
* @throws WxErrorException 异常
*/ */
WxMpKfSessionGetResult kfSessionGet(String openid) throws WxErrorException; WxMpKfSessionGetResult kfSessionGet(String openid) throws WxErrorException;


@@ -145,6 +171,8 @@ public interface WxMpKefuService {
* 详情请见:<a href="http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044820&token=&lang=zh_CN">客服会话控制</a> * 详情请见:<a href="http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044820&token=&lang=zh_CN">客服会话控制</a>
* 接口url格式: https://api.weixin.qq.com/customservice/kfsession/getsessionlist?access_token=ACCESS_TOKEN&kf_account=KFACCOUNT * 接口url格式: https://api.weixin.qq.com/customservice/kfsession/getsessionlist?access_token=ACCESS_TOKEN&kf_account=KFACCOUNT
* </pre> * </pre>
*
* @throws WxErrorException 异常
*/ */
WxMpKfSessionList kfSessionList(String kfAccount) throws WxErrorException; WxMpKfSessionList kfSessionList(String kfAccount) throws WxErrorException;


@@ -155,6 +183,8 @@ public interface WxMpKefuService {
* 详情请见:<a href="http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044820&token=&lang=zh_CN">客服会话控制</a> * 详情请见:<a href="http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044820&token=&lang=zh_CN">客服会话控制</a>
* 接口url格式: https://api.weixin.qq.com/customservice/kfsession/getwaitcase?access_token=ACCESS_TOKEN * 接口url格式: https://api.weixin.qq.com/customservice/kfsession/getwaitcase?access_token=ACCESS_TOKEN
* </pre> * </pre>
*
* @throws WxErrorException 异常
*/ */
WxMpKfSessionWaitCaseList kfSessionGetWaitCase() throws WxErrorException; WxMpKfSessionWaitCaseList kfSessionGetWaitCase() throws WxErrorException;


@@ -173,7 +203,7 @@ public interface WxMpKefuService {
* @param msgId 消息id顺序从小到大,从1开始 * @param msgId 消息id顺序从小到大,从1开始
* @param number 每次获取条数,最多10000条 * @param number 每次获取条数,最多10000条
* @return 聊天记录对象 * @return 聊天记录对象
* @throws WxErrorException
* @throws WxErrorException 异常
*/ */
WxMpKfMsgList kfMsgList(Date startTime, Date endTime, Long msgId, Integer number) throws WxErrorException; WxMpKfMsgList kfMsgList(Date startTime, Date endTime, Long msgId, Integer number) throws WxErrorException;


@@ -188,8 +218,27 @@ public interface WxMpKefuService {
* @param startTime 起始时间 * @param startTime 起始时间
* @param endTime 结束时间 * @param endTime 结束时间
* @return 聊天记录对象 * @return 聊天记录对象
* @throws WxErrorException
* @throws WxErrorException 异常
*/ */
WxMpKfMsgList kfMsgList(Date startTime, Date endTime) throws WxErrorException; WxMpKfMsgList kfMsgList(Date startTime, Date endTime) throws WxErrorException;


/**
* <pre>
* 客服输入状态
* 开发者可通过调用“客服输入状态”接口,返回客服当前输入状态给用户。
* 此接口需要客服消息接口权限。
* 如果不满足发送客服消息的触发条件,则无法下发输入状态。
* 下发输入状态,需要客服之前30秒内跟用户有过消息交互。
* 在输入状态中(持续15s),不可重复下发输入态。
* 在输入状态中,如果向用户下发消息,会同时取消输入状态。
*
* 详情请见:<a href="https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140547">客服输入状态</a>
* 接口url格式:https://api.weixin.qq.com/cgi-bin/message/custom/typing?access_token=ACCESS_TOKEN
* </pre>
*
* @param openid 用户id
* @param command "Typing":对用户下发“正在输入"状态 "CancelTyping":取消对用户的”正在输入"状态
* @throws WxErrorException 异常
*/
boolean sendKfTypingState(String openid, String command) throws WxErrorException;
} }

+ 27
- 12
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java 查看文件

@@ -1,8 +1,14 @@
package me.chanjar.weixin.mp.api.impl; package me.chanjar.weixin.mp.api.impl;


import java.io.File;
import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor;
import me.chanjar.weixin.mp.api.WxMpKefuService; import me.chanjar.weixin.mp.api.WxMpKefuService;
@@ -10,12 +16,12 @@ import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage; import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage;
import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfAccountRequest; 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.request.WxMpKfSessionRequest;
import me.chanjar.weixin.mp.bean.kefu.result.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.Date;
import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfList;
import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfMsgList;
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;


/** /**
* @author Binary Wang * @author Binary Wang
@@ -120,12 +126,12 @@ public class WxMpKefuServiceImpl implements WxMpKefuService {
} }


JsonObject param = new JsonObject(); 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条
param.addProperty("starttime", startTime.getTime() / 1000);
param.addProperty("endtime", endTime.getTime() / 1000);
param.addProperty("msgid", msgId);
param.addProperty("number", number);


String responseContent = this.wxMpService.post(MSGRECORD_GET_MSG_LIST, param.toString());
String responseContent = this.wxMpService.post(MSG_RECORD_LIST, param.toString());


return WxMpKfMsgList.fromJson(responseContent); return WxMpKfMsgList.fromJson(responseContent);
} }
@@ -149,4 +155,13 @@ public class WxMpKefuServiceImpl implements WxMpKefuService {
return result; return result;
} }


@Override
public boolean sendKfTypingState(String openid, String command) throws WxErrorException {
JsonObject params = new JsonObject();
params.addProperty("touser", openid);
params.addProperty("command", command);
String responseContent = this.wxMpService.post(CUSTOM_TYPING, params.toString());
return responseContent != null;
}

} }

+ 21
- 8
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java 查看文件

@@ -1,5 +1,11 @@
package me.chanjar.weixin.mp.api.impl; package me.chanjar.weixin.mp.api.impl;


import java.io.File;
import java.util.Date;

import org.joda.time.DateTime;
import org.testng.annotations.*;

import com.google.inject.Inject; import com.google.inject.Inject;
import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.error.WxErrorException;
@@ -8,12 +14,13 @@ import me.chanjar.weixin.mp.api.test.ApiTestModule;
import me.chanjar.weixin.mp.api.test.TestConfigStorage; import me.chanjar.weixin.mp.api.test.TestConfigStorage;
import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage; import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage;
import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfAccountRequest; import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfAccountRequest;
import me.chanjar.weixin.mp.bean.kefu.result.*;
import org.joda.time.DateTime;
import org.testng.annotations.*;

import java.io.File;
import java.util.Date;
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.WxMpKfMsgList;
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 static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;


@@ -134,8 +141,7 @@ public class WxMpKefuServiceImplTest {
} }


@Test(dataProvider = "getKfAccountAndOpenid") @Test(dataProvider = "getKfAccountAndOpenid")
public void testKfSessionClose(String kfAccount, String openid)
throws WxErrorException {
public void testKfSessionClose(String kfAccount, String openid) throws WxErrorException {
boolean result = this.wxService.getKefuService().kfSessionClose(openid, kfAccount); boolean result = this.wxService.getKefuService().kfSessionClose(openid, kfAccount);
assertThat(result).isTrue(); assertThat(result).isTrue();
} }
@@ -178,4 +184,11 @@ public class WxMpKefuServiceImplTest {
assertThat(result).isNotNull(); assertThat(result).isNotNull();
System.err.println(result); System.err.println(result);
} }

@Test
public void testSendKfTypingState() throws WxErrorException {
TestConfigStorage configStorage = (TestConfigStorage) this.wxService.getWxMpConfigStorage();
boolean result = this.wxService.getKefuService().sendKfTypingState(configStorage.getOpenid(), "Typing");
assertThat(result).isTrue();
}
} }

正在加载...
取消
保存