🆕 #2309 【企业微信】新增微信客服-接待人员管理、会话分配与消息收发、基础信息获取等相关接口

This commit is contained in:
Boris 2022-01-29 22:58:00 +08:00 committed by Binary Wang
parent 37fe7d21ef
commit 438d5833f9
22 changed files with 1096 additions and 0 deletions

View File

@ -1,6 +1,10 @@
package me.chanjar.weixin.cp.api;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import lombok.NonNull;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.bean.WxCpBaseResp;
import me.chanjar.weixin.cp.bean.external.*;
@ -921,5 +925,35 @@ public interface WxCpExternalContactService {
*/
WxCpProductAlbumResult getProductAlbum(String productId) throws WxErrorException;
/**
* <pre>
* 上传附件资源
* https://open.work.weixin.qq.com/api/doc/90001/90143/95178
* </pre>
* @param mediaType
* @param fileType
* @param attachmentType
* @param inputStream
* @return
* @throws WxErrorException
* @throws IOException
*/
WxMediaUploadResult uploadAttachment(String mediaType, String fileType, Integer attachmentType,
InputStream inputStream) throws WxErrorException, IOException;
/**
* <pre>
* 上传附件资源
* https://open.work.weixin.qq.com/api/doc/90001/90143/95178
* </pre>
* @param mediaType
* @param attachmentType
* @param file
* @return
* @throws WxErrorException
*/
WxMediaUploadResult uploadAttachment(String mediaType, Integer attachmentType, File file)
throws WxErrorException;
}

View File

@ -1,5 +1,6 @@
package me.chanjar.weixin.cp.api;
import java.util.List;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.bean.WxCpBaseResp;
import me.chanjar.weixin.cp.bean.kf.WxCpKfAccountAdd;
@ -9,6 +10,14 @@ import me.chanjar.weixin.cp.bean.kf.WxCpKfAccountLink;
import me.chanjar.weixin.cp.bean.kf.WxCpKfAccountLinkResp;
import me.chanjar.weixin.cp.bean.kf.WxCpKfAccountListResp;
import me.chanjar.weixin.cp.bean.kf.WxCpKfAccountUpd;
import me.chanjar.weixin.cp.bean.kf.WxCpKfCustomerBatchGetResp;
import me.chanjar.weixin.cp.bean.kf.WxCpKfMsgListResp;
import me.chanjar.weixin.cp.bean.kf.WxCpKfMsgSendRequest;
import me.chanjar.weixin.cp.bean.kf.WxCpKfMsgSendResp;
import me.chanjar.weixin.cp.bean.kf.WxCpKfServiceStateResp;
import me.chanjar.weixin.cp.bean.kf.WxCpKfServiceStateTransResp;
import me.chanjar.weixin.cp.bean.kf.WxCpKfServicerListResp;
import me.chanjar.weixin.cp.bean.kf.WxCpKfServicerOpResp;
/**
* 微信客服接口
@ -67,4 +76,116 @@ public interface WxCpKfService {
*/
WxCpKfAccountLinkResp getAccountLink(WxCpKfAccountLink link) throws WxErrorException;
/**
* 接待人员管理
* 添加指定客服帐号的接待人员每个客服帐号目前最多可添加500个接待人员
* @param openKfid 客服帐号ID
* @param userIdList 接待人员userid列表第三方应用填密文userid即open_userid
* 可填充个数1 ~ 100超过100个需分批调用
* @return 添加客服账号结果
* @throws WxErrorException 异常
*/
WxCpKfServicerOpResp addServicer(String openKfid, List<String> userIdList) throws WxErrorException;
/**
* 接待人员管理
* 从客服帐号删除接待人员
* @param openKfid 客服帐号ID
* @param userIdList 接待人员userid列表第三方应用填密文userid即open_userid
* 可填充个数1 ~ 100超过100个需分批调用
* @return 删除客服账号结果
* @throws WxErrorException 异常
*/
WxCpKfServicerOpResp delServicer(String openKfid, List<String> userIdList) throws WxErrorException;
/**
* 接待人员管理
* 获取某个客服帐号的接待人员列表
* @param openKfid 客服帐号ID
* @return 接待人员列表
* @throws WxErrorException 异常
*/
WxCpKfServicerListResp listServicer(String openKfid) throws WxErrorException;
/**
* 分配客服会话
* 获取会话状态
* @param openKfid 客服帐号ID
* @param externalUserId 微信客户的external_userid
* @return
* @throws WxErrorException
*/
WxCpKfServiceStateResp getServiceState(String openKfid, String externalUserId)
throws WxErrorException;
/**
* 分配客服会话
* 变更会话状态
* @param openKfid 客服帐号ID
* @param externalUserId 微信客户的external_userid
* @param serviceState 变更的目标状态状态定义和所允许的变更可参考概述中的流程图和表格
* @param servicerUserId 接待人员的userid第三方应用填密文userid即open_userid当state=3时要求必填接待人员须处于正在接待
* @return 部分状态返回回复语code
* @throws WxErrorException
*/
WxCpKfServiceStateTransResp transServiceState(String openKfid, String externalUserId,
Integer serviceState, String servicerUserId) throws WxErrorException;
/**
* 读取消息
* 微信客户发送的消息接待人员在企业微信回复的消息发送消息接口发送失败事件如被用户拒收客户点击菜单消息的回复消息
* 可以通过该接口获取具体的消息内容和事件不支持读取通过发送消息接口发送的消息
* 支持的消息类型文本图片语音视频文件位置链接名片小程序菜单事件
* @param cursor 上一次调用时返回的next_cursor第一次拉取可以不填不多于64字节
* @param token 回调事件返回的token字段10分钟内有效可不填如果不填接口有严格的频率限制不多于128字节
* @param limit 期望请求的数据量默认值和最大值都为1000
* 注意可能会出现返回条数少于limit的情况需结合返回的has_more字段判断是否继续请求
* @param voiceFormat 语音消息类型0-Amr 1-Silk默认0可通过该参数控制返回的语音格式
* @return 微信消息
* @throws WxErrorException 异常
*/
WxCpKfMsgListResp syncMsg(String cursor, String token, Integer limit, Integer voiceFormat)
throws WxErrorException;
/**
* 发送消息
* 当微信客户处于新接入待处理由智能助手接待状态下可调用该接口给用户发送消息
* 注意仅当微信客户在主动发送消息给客服后的48小时内企业可发送消息给客户最多可发送5条消息若用户继续发送消息企业可再次下发消息
* 支持发送消息类型文本图片语音视频文件图文小程序菜单消息地理位置
* @param request 发送信息
* @return 发送结果
* @throws WxErrorException 异常
*/
WxCpKfMsgSendResp sendMsg(WxCpKfMsgSendRequest request) throws WxErrorException;
/**
* 发送欢迎语等事件响应消息
* 当特定的事件回调消息包含code字段或通过接口变更到特定的会话状态会返回code字段
* 开发者可以此code为凭证调用该接口给用户发送相应事件场景下的消息如客服欢迎语客服提示语和会话结束语等
* "用户进入会话事件"以外响应消息仅支持会话处于获取该code的会话状态时发送如将会话转入待接入池时获得的code仅能在会话状态为待接入池排队中时发送
*
* 目前支持的事件场景和相关约束如下
*
* 事件场景 允许下发条数 code有效期 支持的消息类型 获取code途径
* 用户进入会话用于发送客服欢迎语 1条 20秒 文本菜单 事件回调
* 进入接待池用于发送排队提示语等 1条 48小时 文本 转接会话接口
* 从接待池接入会话用于发送非工作
* 时间的提示语或超时未回复的提示语
* 1条 48小时 文本 事件回调转接会话接口
* 结束会话用于发送结束会话提示语
* 或满意度评价等 1条 20秒 文本菜单 事件回调转接会话接口
* @param request
* @return
* @throws WxErrorException
*/
WxCpKfMsgSendResp sendMsgOnEvent(WxCpKfMsgSendRequest request) throws WxErrorException;
/**
* 获取客户基础信息
* @param externalUserIdList
* @return
* @throws WxErrorException
*/
WxCpKfCustomerBatchGetResp customerBatchGet(List<String> externalUserIdList)
throws WxErrorException;
}

View File

@ -2,12 +2,19 @@ package me.chanjar.weixin.cp.api.impl;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.error.WxCpErrorMsgEnum;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.error.WxRuntimeException;
import me.chanjar.weixin.common.util.BeanUtils;
import me.chanjar.weixin.common.util.fs.FileUtils;
import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor;
import me.chanjar.weixin.common.util.json.GsonParser;
import me.chanjar.weixin.cp.api.WxCpExternalContactService;
import me.chanjar.weixin.cp.api.WxCpService;
@ -814,4 +821,19 @@ public class WxCpExternalContactServiceImpl implements WxCpExternalContactServic
return WxCpProductAlbumResult.fromJson(result);
}
@Override
public WxMediaUploadResult uploadAttachment(String mediaType, String fileType, Integer attachmentType,
InputStream inputStream) throws WxErrorException, IOException {
return uploadAttachment(mediaType, attachmentType, FileUtils.createTmpFile(inputStream,
UUID.randomUUID().toString(), fileType));
}
@Override
public WxMediaUploadResult uploadAttachment(String mediaType, Integer attachmentType, File file)
throws WxErrorException {
String params = "?media_type=" + mediaType + "&attachment_type=" + attachmentType;
final String url = this.mainService.getWxCpConfigStorage().getApiUrl(UPLOAD_ATTACHMENT + params);
return this.mainService.execute(MediaUploadRequestExecutor.create(
this.mainService.getRequestHttp()), url, file);
}
}

View File

@ -1,5 +1,10 @@
package me.chanjar.weixin.cp.api.impl;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import java.util.List;
import lombok.RequiredArgsConstructor;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpKfService;
@ -12,6 +17,14 @@ import me.chanjar.weixin.cp.bean.kf.WxCpKfAccountLink;
import me.chanjar.weixin.cp.bean.kf.WxCpKfAccountLinkResp;
import me.chanjar.weixin.cp.bean.kf.WxCpKfAccountListResp;
import me.chanjar.weixin.cp.bean.kf.WxCpKfAccountUpd;
import me.chanjar.weixin.cp.bean.kf.WxCpKfCustomerBatchGetResp;
import me.chanjar.weixin.cp.bean.kf.WxCpKfMsgListResp;
import me.chanjar.weixin.cp.bean.kf.WxCpKfMsgSendRequest;
import me.chanjar.weixin.cp.bean.kf.WxCpKfMsgSendResp;
import me.chanjar.weixin.cp.bean.kf.WxCpKfServiceStateResp;
import me.chanjar.weixin.cp.bean.kf.WxCpKfServiceStateTransResp;
import me.chanjar.weixin.cp.bean.kf.WxCpKfServicerListResp;
import me.chanjar.weixin.cp.bean.kf.WxCpKfServicerOpResp;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Kf.*;
@ -25,6 +38,7 @@ import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Kf.*;
@RequiredArgsConstructor
public class WxCpKfServiceImpl implements WxCpKfService {
private final WxCpService cpService;
private static final Gson GSON = new GsonBuilder().create();
@Override
public WxCpKfAccountAddResp addAccount(WxCpKfAccountAdd add) throws WxErrorException {
@ -61,4 +75,117 @@ public class WxCpKfServiceImpl implements WxCpKfService {
return WxCpKfAccountLinkResp.fromJson(responseContent);
}
@Override
public WxCpKfServicerOpResp addServicer(String openKfid, List<String> userIdList) throws WxErrorException {
return servicerOp(openKfid, userIdList, SERVICER_ADD);
}
@Override
public WxCpKfServicerOpResp delServicer(String openKfid, List<String> userIdList) throws WxErrorException {
return servicerOp(openKfid, userIdList, SERVICER_DEL);
}
private WxCpKfServicerOpResp servicerOp(String openKfid, List<String> userIdList, String uri) throws WxErrorException {
String url = cpService.getWxCpConfigStorage().getApiUrl(uri);
JsonObject json = new JsonObject();
json.addProperty("open_kfid", openKfid);
JsonArray userIdArray = new JsonArray();
userIdList.forEach(userIdArray::add);
json.add("userid_list", userIdArray);
String responseContent = cpService.post(url, json.toString());
return WxCpKfServicerOpResp.fromJson(responseContent);
}
@Override
public WxCpKfServicerListResp listServicer(String openKfid) throws WxErrorException {
String url = cpService.getWxCpConfigStorage().getApiUrl(SERVICER_LIST + openKfid);
String responseContent = cpService.get(url, null);
return WxCpKfServicerListResp.fromJson(responseContent);
}
@Override
public WxCpKfServiceStateResp getServiceState(String openKfid, String externalUserId)
throws WxErrorException {
String url = cpService.getWxCpConfigStorage().getApiUrl(SERVICE_STATE_GET);
JsonObject json = new JsonObject();
json.addProperty("open_kfid", openKfid);
json.addProperty("external_userid", externalUserId);
String responseContent = cpService.post(url, json.toString());
return WxCpKfServiceStateResp.fromJson(responseContent);
}
@Override
public WxCpKfServiceStateTransResp transServiceState(String openKfid, String externalUserId,
Integer serviceState, String servicerUserId) throws WxErrorException {
String url = cpService.getWxCpConfigStorage().getApiUrl(SERVICE_STATE_TRANS);
JsonObject json = new JsonObject();
json.addProperty("open_kfid", openKfid);
json.addProperty("external_userid", externalUserId);
json.addProperty("service_state", serviceState);
json.addProperty("servicer_userid", servicerUserId);
String responseContent = cpService.post(url, json.toString());
return WxCpKfServiceStateTransResp.fromJson(responseContent);
}
@Override
public WxCpKfMsgListResp syncMsg(String cursor, String token, Integer limit, Integer voiceFormat)
throws WxErrorException {
String url = cpService.getWxCpConfigStorage().getApiUrl(SYNC_MSG);
JsonObject json = new JsonObject();
if (cursor!=null) {
json.addProperty("cursor", cursor);
}
if (token!=null) {
json.addProperty("token", token);
}
if (limit!=null) {
json.addProperty("limit", limit);
}
if (voiceFormat!=null) {
json.addProperty("voice_format", voiceFormat);
}
String responseContent = cpService.post(url, json);
return WxCpKfMsgListResp.fromJson(responseContent);
}
@Override
public WxCpKfMsgSendResp sendMsg(WxCpKfMsgSendRequest request) throws WxErrorException {
String url = cpService.getWxCpConfigStorage().getApiUrl(SEND_MSG);
String responseContent = cpService.post(url, GSON.toJson(request));
return WxCpKfMsgSendResp.fromJson(responseContent);
}
@Override
public WxCpKfMsgSendResp sendMsgOnEvent(WxCpKfMsgSendRequest request) throws WxErrorException {
String url = cpService.getWxCpConfigStorage().getApiUrl(SEND_MSG_ON_EVENT);
String responseContent = cpService.post(url, GSON.toJson(request));
return WxCpKfMsgSendResp.fromJson(responseContent);
}
@Override
public WxCpKfCustomerBatchGetResp customerBatchGet(List<String> externalUserIdList)
throws WxErrorException {
String url = cpService.getWxCpConfigStorage().getApiUrl(CUSTOMER_BATCH_GET);
JsonArray array = new JsonArray();
externalUserIdList.forEach(array::add);
JsonObject json = new JsonObject();
json.add("external_userid_list", array);
String responseContent = cpService.post(url, json.toString());
return WxCpKfCustomerBatchGetResp.fromJson(responseContent);
}
}

View File

@ -26,6 +26,9 @@ public class ExternalContact implements Serializable {
@SerializedName("name")
private String name;
@SerializedName("nickname")
private String nickname;
@SerializedName("avatar")
private String avatar;

View File

@ -0,0 +1,32 @@
package me.chanjar.weixin.cp.bean.kf;
import com.google.gson.annotations.SerializedName;
import java.util.List;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import me.chanjar.weixin.cp.bean.WxCpBaseResp;
import me.chanjar.weixin.cp.bean.external.contact.ExternalContact;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
/**
* @author leiin
* @date 2022/1/26 7:56 下午
*/
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@Data
public class WxCpKfCustomerBatchGetResp extends WxCpBaseResp {
private static final long serialVersionUID = -3697709507605389887L;
@SerializedName("customer_list")
private List<ExternalContact> customerList;
@SerializedName("invalid_external_userid")
private List<String> invalidExternalUserId;
public static WxCpKfCustomerBatchGetResp fromJson(String json) {
return WxCpGsonBuilder.create().fromJson(json, WxCpKfCustomerBatchGetResp.class);
}
}

View File

@ -0,0 +1,73 @@
package me.chanjar.weixin.cp.bean.kf;
import com.google.gson.annotations.SerializedName;
import java.util.List;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import me.chanjar.weixin.cp.bean.WxCpBaseResp;
import me.chanjar.weixin.cp.bean.kf.msg.WxCpKfBusinessCardMsg;
import me.chanjar.weixin.cp.bean.kf.msg.WxCpKfEventMsg;
import me.chanjar.weixin.cp.bean.kf.msg.WxCpKfLinkMsg;
import me.chanjar.weixin.cp.bean.kf.msg.WxCpKfLocationMsg;
import me.chanjar.weixin.cp.bean.kf.msg.WxCpKfMenuMsg;
import me.chanjar.weixin.cp.bean.kf.msg.WxCpKfMiniProgramMsg;
import me.chanjar.weixin.cp.bean.kf.msg.WxCpKfResourceMsg;
import me.chanjar.weixin.cp.bean.kf.msg.WxCpKfTextMsg;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
/**
* @author leiin
* @date 2022/1/26 5:24 下午
*/
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@Data
public class WxCpKfMsgListResp extends WxCpBaseResp {
private static final long serialVersionUID = -3115552079069452091L;
@SerializedName("next_cursor")
private String nextCursor;
@SerializedName("has_more")
private Integer hasMore;
@SerializedName("msg_list")
private List<WxCpKfMsgItem> msgList;
@NoArgsConstructor
@Data
public static class WxCpKfMsgItem {
@SerializedName("msgid")
private String msgId;
@SerializedName("open_kfid")
private String openKfid;
@SerializedName("external_userid")
private String externalUserId;
@SerializedName("send_time")
private Long sendTime;
private Integer origin;
@SerializedName("servicer_userid")
private String servicerUserId;
@SerializedName("msgtype")
private String msgType;
private WxCpKfTextMsg text;
private WxCpKfResourceMsg image;
private WxCpKfResourceMsg voice;
private WxCpKfResourceMsg video;
private WxCpKfResourceMsg file;
private WxCpKfLocationMsg location;
private WxCpKfLinkMsg link;
@SerializedName("business_card")
private WxCpKfBusinessCardMsg businessCard;
@SerializedName("miniprogram")
private WxCpKfMiniProgramMsg miniProgram;
@SerializedName("msgmenu")
private WxCpKfMenuMsg msgMenu;
private WxCpKfEventMsg event;
}
public static WxCpKfMsgListResp fromJson(String json) {
return WxCpGsonBuilder.create().fromJson(json, WxCpKfMsgListResp.class);
}
}

View File

@ -0,0 +1,151 @@
package me.chanjar.weixin.cp.bean.kf;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;
import me.chanjar.weixin.cp.bean.kf.msg.WxCpKfLinkMsg;
import me.chanjar.weixin.cp.bean.kf.msg.WxCpKfLocationMsg;
import me.chanjar.weixin.cp.bean.kf.msg.WxCpKfMenuMsg;
import me.chanjar.weixin.cp.bean.kf.msg.WxCpKfMiniProgramMsg;
import me.chanjar.weixin.cp.bean.kf.msg.WxCpKfResourceMsg;
import me.chanjar.weixin.cp.bean.kf.msg.WxCpKfTextMsg;
/**
* @author leiin
* @date 2022/1/26 7:00 下午
*/
@NoArgsConstructor
@Data
public class WxCpKfMsgSendRequest {
/**
* (发送欢迎语等事件响应消息) 事件响应消息对应的code通过事件回调下发仅可使用一次
*/
private String code;
/**
* <pre>
* 参数touser
* 是否必须
* 类型string
* 说明指定接收消息的客户UserID
* </pre>
*/
@SerializedName("touser")
private String toUser;
/**
* <pre>
* 参数open_kfid
* 是否必须
* 类型string
* 说明指定发送消息的客服帐号ID
* </pre>
*/
@SerializedName("open_kfid")
private String openKfid;
/**
* <pre>
* 参数msgid
* 是否必须
* 类型string
* 说明指定消息ID
* </pre>
*/
@SerializedName("msgid")
private String msgId;
/**
* <pre>
* 参数msgtype
* 是否必须
* 类型string
* 说明消息类型text,image,voice,video,file,link,miniprogram,msgmenu,location)
* </pre>
*/
@SerializedName("msgtype")
private String msgType;
/**
* <pre>
* 参数text
* 是否必须
* 类型obj
* 说明文本消息
* </pre>
*/
private WxCpKfTextMsg text;
/**
* <pre>
* 参数image
* 是否必须
* 类型obj
* 说明图片消息
* </pre>
*/
private WxCpKfResourceMsg image;
/**
* <pre>
* 参数voice
* 是否必须
* 类型obj
* 说明语音消息
* </pre>
*/
private WxCpKfResourceMsg voice;
/**
* <pre>
* 参数video
* 是否必须
* 类型obj
* 说明视频消息
* </pre>
*/
private WxCpKfResourceMsg video;
/**
* <pre>
* 参数file
* 是否必须
* 类型obj
* 说明文件消息
* </pre>
*/
private WxCpKfResourceMsg file;
/**
* <pre>
* 参数link
* 是否必须
* 类型obj
* 说明链接消息
* </pre>
*/
private WxCpKfLinkMsg link;
/**
* <pre>
* 参数miniprogram
* 是否必须
* 类型obj
* 说明小程序消息
* </pre>
*/
@SerializedName("miniprogram")
private WxCpKfMiniProgramMsg miniProgram;
/**
* <pre>
* 参数msgmenu
* 是否必须
* 类型obj
* 说明菜单消息
* </pre>
*/
@SerializedName("msgmenu")
private WxCpKfMenuMsg msgMenu;
/**
* <pre>
* 参数location
* 是否必须
* 类型obj
* 说明菜单消息
* </pre>
*/
@SerializedName("location")
private WxCpKfLocationMsg location;
}

View File

@ -0,0 +1,24 @@
package me.chanjar.weixin.cp.bean.kf;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import me.chanjar.weixin.cp.bean.WxCpBaseResp;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
/**
* @author leiin
* @date 2022/1/26 7:41 下午
*/
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@Data
public class WxCpKfMsgSendResp extends WxCpBaseResp {
@SerializedName("msgid")
private String msgId;
public static WxCpKfMsgSendResp fromJson(String json) {
return WxCpGsonBuilder.create().fromJson(json, WxCpKfMsgSendResp.class);
}
}

View File

@ -0,0 +1,28 @@
package me.chanjar.weixin.cp.bean.kf;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import me.chanjar.weixin.cp.bean.WxCpBaseResp;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
/**
* @author leiin
* @date 2022/1/26 5:00 下午
*/
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@Data
public class WxCpKfServiceStateResp extends WxCpBaseResp {
private static final long serialVersionUID = 8077134413448067090L;
@SerializedName("service_state")
private Integer serviceState;
@SerializedName("servicer_userid")
private String servicerUserId;
public static WxCpKfServiceStateResp fromJson(String json) {
return WxCpGsonBuilder.create().fromJson(json, WxCpKfServiceStateResp.class);
}
}

View File

@ -0,0 +1,27 @@
package me.chanjar.weixin.cp.bean.kf;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import me.chanjar.weixin.cp.bean.WxCpBaseResp;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
/**
* @author leiin
* @date 2022/1/26 5:03 下午
*/
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@Data
public class WxCpKfServiceStateTransResp extends WxCpBaseResp {
private static final long serialVersionUID = -7874378445629022791L;
@SerializedName("msg_code")
private String msgCode;
public static WxCpKfServiceStateTransResp fromJson(String json) {
return WxCpGsonBuilder.create().fromJson(json, WxCpKfServiceStateTransResp.class);
}
}

View File

@ -0,0 +1,35 @@
package me.chanjar.weixin.cp.bean.kf;
import com.google.gson.annotations.SerializedName;
import java.util.List;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import me.chanjar.weixin.cp.bean.WxCpBaseResp;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
/**
* @author leiin
* @date 2022/1/26 4:29 下午
*/
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@Data
public class WxCpKfServicerListResp extends WxCpBaseResp {
private static final long serialVersionUID = -5079770046571012449L;
@SerializedName("servicer_list")
private List<WxCpKfServicerStatus> servicerList;
@NoArgsConstructor
@Data
public static class WxCpKfServicerStatus {
@SerializedName("userid")
private String userId;
private Integer status;
}
public static WxCpKfServicerListResp fromJson(String json) {
return WxCpGsonBuilder.create().fromJson(json, WxCpKfServicerListResp.class);
}
}

View File

@ -0,0 +1,38 @@
package me.chanjar.weixin.cp.bean.kf;
import com.google.gson.annotations.SerializedName;
import java.util.List;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import me.chanjar.weixin.cp.bean.WxCpBaseResp;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
/**
* 添加/删除客服接待人员返回结果
* @author leiin
* @date 2022/1/26 4:11 下午
*/
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@Data
public class WxCpKfServicerOpResp extends WxCpBaseResp {
private static final long serialVersionUID = -4082459764202987034L;
@SerializedName("result_list")
private List<WxCpKfServicerResp> resultList;
@Data
@NoArgsConstructor
public static class WxCpKfServicerResp extends WxCpBaseResp {
@SerializedName("userid")
private String userId;
}
public static WxCpKfServicerOpResp fromJson(String json) {
return WxCpGsonBuilder.create().fromJson(json, WxCpKfServicerOpResp.class);
}
}

View File

@ -0,0 +1,16 @@
package me.chanjar.weixin.cp.bean.kf.msg;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author leiin
* @date 2022/1/26 5:35 下午
*/
@NoArgsConstructor
@Data
public class WxCpKfBusinessCardMsg {
@SerializedName("userid")
private String userId;
}

View File

@ -0,0 +1,40 @@
package me.chanjar.weixin.cp.bean.kf.msg;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author leiin
* @date 2022/1/26 6:44 下午
*/
@NoArgsConstructor
@Data
public class WxCpKfEventMsg {
@SerializedName("event_type")
private String eventType;
@SerializedName("open_kfid")
private String openKfid;
@SerializedName("external_userid")
private String externalUserId;
@SerializedName("servicer_userid")
private String servicerUserId;
@SerializedName("old_servicer_userid")
private String oldServicerUserId;
@SerializedName("new_servicer_userid")
private String newServicerUserId;
private String scene;
@SerializedName("scene_param")
private String sceneParam;
@SerializedName("welcome_code")
private String welcomeCode;
@SerializedName("fail_msgid")
private String failMsgId;
@SerializedName("fail_type")
private Integer failType;
private Integer status;
@SerializedName("change_type")
private Integer changeType;
@SerializedName("msg_code")
private String msgCode;
}

View File

@ -0,0 +1,53 @@
package me.chanjar.weixin.cp.bean.kf.msg;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author leiin
* @date 2022/1/26 5:33 下午
*/
@NoArgsConstructor
@Data
public class WxCpKfLinkMsg {
/**
* 参数title
* 是否必须
* 类型string
* 说明标题不超过128个字节超过会自动截断
*/
@SerializedName("title")
private String title;
/**
* 参数desc
* 是否必须
* 类型string
* 说明描述不超过512个字节超过会自动截断
*/
@SerializedName("desc")
private String desc;
/**
* 参数url
* 是否必须
* 类型string
* 说明点击后跳转的链接 最长2048字节请确保包含了协议头(http/https)
*/
@SerializedName("url")
private String url;
/**
* 参数thumb_media_id
* 是否必须
* 类型string
* 说明发送消息参数缩略图的media_id, 可以通过素材管理接口获得此处thumb_media_id即上传接口返回的media_id
*/
@SerializedName("thumb_media_id")
private String thumb_media_id;
/**
* 返回消息参数
*/
@SerializedName("pic_url")
private String picUrl;
}

View File

@ -0,0 +1,41 @@
package me.chanjar.weixin.cp.bean.kf.msg;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author leiin
* @date 2022/1/26 5:32 下午
*/
@NoArgsConstructor
@Data
public class WxCpKfLocationMsg {
/**
* 参数name
* 是否必须
* 类型string
* 说明位置名
*/
private String name;
/**
* 参数address
* 是否必须
* 类型string
* 说明地址详情说明
*/
private String address;
/**
* 参数latitude
* 是否必须
* 类型float
* 说明纬度浮点数范围为90 ~ -90
*/
private Float latitude;
/**
* 参数longitude
* 是否必须
* 类型float
* 说明经度浮点数范围为180 ~ -180
*/
private Float longitude;
}

View File

@ -0,0 +1,128 @@
package me.chanjar.weixin.cp.bean.kf.msg;
import com.google.gson.annotations.SerializedName;
import java.util.List;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
/**
* @author leiin
* @date 2022/1/26 6:33 下午
*/
@NoArgsConstructor
@Data
public class WxCpKfMenuMsg {
/**
* 参数head_content
* 是否必须
* 类型string
* 说明起始文本 不多于1024字节
*/
@SerializedName("head_content")
private String headContent;
private List<WxCpKfMenuItem> list;
/**
* 参数tail_content
* 是否必须
* 类型string
* 说明结束文本 不多于1024字节
*/
@SerializedName("tail_content")
private String tailContent;
@NoArgsConstructor
@Data
public static class WxCpKfMenuItem {
/**
* 参数type
* 是否必须
* 类型string
* 说明菜单类型click-回复菜单 view-超链接菜单 miniprogram-小程序菜单
*/
private String type;
/**
* type为click的菜单项
*/
private MenuClick click;
/**
* type为view的菜单项
*/
private MenuView view;
/**
* type为miniprogram的菜单项
*/
@SerializedName("miniprogram")
private MiniProgram miniProgram;
}
@Getter
@Setter
public static class MenuClick {
/**
* <pre>
* 是否必须
* 说明菜单ID不少于1字节 不多于128字节
* </pre>
*/
private String id;
/**
* <pre>
* 是否必须
* 说明菜单显示内容不少于1字节 不多于128字节
* </pre>
*/
private String content;
}
@Getter
@Setter
public static class MenuView {
/**
* <pre>
* 是否必须
* 说明点击后跳转的链接不少于1字节 不多于2048字节
* </pre>
*/
private String url;
/**
* <pre>
* 是否必须
* 说明菜单显示内容不少于1字节 不多于1024字节
* </pre>
*/
private String content;
}
@Getter
@Setter
public static class MiniProgram {
/**
* <pre>
* 是否必须
* 说明小程序appid
* </pre>
*/
@SerializedName("appid")
private String appId;
/**
* <pre>
* 点击后进入的小程序页面
* </pre>
*/
@SerializedName("pagepath")
private String pagePath;
/**
* <pre>
* 菜单显示内容不多于1024字节
* </pre>
*/
private String content;
}
}

View File

@ -0,0 +1,46 @@
package me.chanjar.weixin.cp.bean.kf.msg;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author leiin
* @date 2022/1/26 6:22 下午
*/
@NoArgsConstructor
@Data
public class WxCpKfMiniProgramMsg {
/**
* 参数appid
* 是否必须
* 类型string
* 说明小程序appid
*/
@SerializedName("appid")
private String appId;
/**
* 参数title
* 是否必须
* 类型string
* 说明小程序消息标题最多64个字节超过会自动截断
*/
@SerializedName("title")
private String title;
/**
* 参数thumb_media_id
* 是否必须
* 类型string
* 说明小程序消息封面的mediaid封面图建议尺寸为520*416
*/
@SerializedName("thumb_media_id")
private String thumbMediaId;
/**
* 参数pagepath
* 是否必须
* 类型string
* 说明点击消息卡片后进入的小程序页面路径注意路径要以.html为后缀否则在微信中打开会提示找不到页面
*/
@SerializedName("pagepath")
private String pagePath;
}

View File

@ -0,0 +1,16 @@
package me.chanjar.weixin.cp.bean.kf.msg;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author leiin
* @date 2022/1/26 5:31 下午
*/
@NoArgsConstructor
@Data
public class WxCpKfResourceMsg {
@SerializedName("media_id")
private String mediaId;
}

View File

@ -0,0 +1,26 @@
package me.chanjar.weixin.cp.bean.kf.msg;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author leiin
* @date 2022/1/26 5:30 下午
*/
@NoArgsConstructor
@Data
public class WxCpKfTextMsg {
/**
* <pre>
* 参数content
* 是否必须
* 类型string
* 说明消息内容最长不超过2048个字节
* </pre>
*/
private String content;
@SerializedName("menu_id")
private String menuId;
}

View File

@ -249,6 +249,8 @@ public interface WxCpApiPathConsts {
String GROUP_WELCOME_TEMPLATE_GET = "/cgi-bin/externalcontact/group_welcome_template/get";
String GROUP_WELCOME_TEMPLATE_DEL = "/cgi-bin/externalcontact/group_welcome_template/del";
String UPLOAD_ATTACHMENT = "/cgi-bin/media/upload_attachment";
}
interface Kf {
@ -258,5 +260,18 @@ public interface WxCpApiPathConsts {
String ACCOUNT_LIST = "/cgi-bin/kf/account/list";
String ADD_CONTACT_WAY = "/cgi-bin/kf/add_contact_way";
String SERVICER_ADD = "/cgi-bin/kf/servicer/add";
String SERVICER_DEL = "/cgi-bin/kf/servicer/del";
String SERVICER_LIST = "/cgi-bin/kf/servicer/list?open_kfid=";
String SERVICE_STATE_GET = "/cgi-bin/kf/service_state/get";
String SERVICE_STATE_TRANS = "/cgi-bin/kf/service_state/trans";
String SYNC_MSG = "/cgi-bin/kf/sync_msg";
String SEND_MSG = "/cgi-bin/kf/send_msg";
String SEND_MSG_ON_EVENT = "/cgi-bin/kf/send_msg_on_event";
String CUSTOMER_BATCH_GET = "/cgi-bin/kf/customer/batchget";
}
}