🆕 #2150 【企业微信】补充完善部分客户联系接口,以及服务商模式外部联系人openid转换接口

This commit is contained in:
pg 2021-06-22 10:57:32 +08:00 committed by GitHub
parent 566e5f31c7
commit 3963c6d471
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 486 additions and 1 deletions

View File

@ -6,6 +6,7 @@ import me.chanjar.weixin.cp.bean.WxCpBaseResp;
import me.chanjar.weixin.cp.bean.external.*;
import me.chanjar.weixin.cp.bean.external.contact.WxCpExternalContactBatchInfo;
import me.chanjar.weixin.cp.bean.external.contact.WxCpExternalContactInfo;
import org.jetbrains.annotations.NotNull;
import java.util.Date;
import java.util.List;
@ -134,6 +135,14 @@ public interface WxCpExternalContactService {
*/
WxCpExternalContactInfo getContactDetail(String userId) throws WxErrorException;
/**
* 企业和服务商可通过此接口将微信外部联系人的userid转为微信openid用于调用支付相关接口暂不支持企业微信外部联系人ExternalUserid为wo开头的userid转openid
* @param externalUserid 微信外部联系人的userid
* @return 该企业的外部联系人openid
* @throws WxErrorException .
*/
String convertToOpenid(String externalUserid) throws WxErrorException;
/**
* 批量获取客户详情.
* <pre>
@ -225,9 +234,85 @@ public interface WxCpExternalContactService {
* @param takeOverUserid the take over userid
* @return wx cp base resp
* @throws WxErrorException the wx error exception
* @deprecated 此后续将不再更新维护,建议使用 {@link #transferCustomer(WxCpUserTransferCustomerReq)}
*/
@Deprecated
WxCpBaseResp transferExternalContact(String externalUserid, String handOverUserid, String takeOverUserid) throws WxErrorException;
/**
* 企业可通过此接口转接在职成员的客户给其他成员
* <per>
* external_userid必须是handover_userid的客户即配置了客户联系功能的成员所添加的联系人
* 在职成员的每位客户最多被分配2次客户被转接成功后将有90个自然日的服务关系保护期保护期内的客户无法再次被分配
*
* 权限说明
* * 企业需要使用客户联系secret或配置到可调用应用列表中的自建应用secret所获取的accesstoken来调用accesstoken如何获取
* 第三方应用需拥有企业客户权限->客户联系->在职继承权限
* 接替成员必须在此第三方应用或自建应用的可见范围内
* 接替成员需要配置了客户联系功能
* 接替成员需要在企业微信激活且已经过实名认证
* </per>
* @param req 转接在职成员的客户给其他成员请求实体
* @return wx cp base resp
* @throws WxErrorException the wx error exception
*/
WxCpUserTransferCustomerResp transferCustomer(WxCpUserTransferCustomerReq req) throws WxErrorException;
/**
* 企业和第三方可通过此接口查询在职成员的客户转接情况
* <per>
* 权限说明
*
* 企业需要使用客户联系secret或配置到可调用应用列表中的自建应用secret所获取的accesstoken来调用accesstoken如何获取
* 第三方应用需拥有企业客户权限->客户联系->在职继承权限
* 接替成员必须在此第三方应用或自建应用的可见范围内
* </per>
* @param handOverUserid 原添加成员的userid
* @param takeOverUserid 接替成员的userid
* @param cursor 分页查询的cursor每个分页返回的数据不会超过1000条不填或为空表示获取第一个分页
* @return 客户转接接口实体
* @throws WxErrorException the wx error exception
*/
WxCpUserTransferResultResp transferResult(@NotNull String handOverUserid, @NotNull String takeOverUserid, String cursor) throws WxErrorException;
/**
* 企业可通过此接口分配离职成员的客户给其他成员
* <per>
* handover_userid必须是已离职用户
* external_userid必须是handover_userid的客户即配置了客户联系功能的成员所添加的联系人
* 在职成员的每位客户最多被分配2次客户被转接成功后将有90个自然日的服务关系保护期保护期内的客户无法再次被分配
*
* 权限说明
*
* 企业需要使用客户联系secret或配置到可调用应用列表中的自建应用secret所获取的accesstoken来调用accesstoken如何获取
* 第三方应用需拥有企业客户权限->客户联系->离职分配权限
* 接替成员必须在此第三方应用或自建应用的可见范围内
* 接替成员需要配置了客户联系功能
* 接替成员需要在企业微信激活且已经过实名认证
* </per>
* @param req 转接在职成员的客户给其他成员请求实体
* @return wx cp base resp
* @throws WxErrorException the wx error exception
*/
WxCpUserTransferCustomerResp resignedTransferCustomer(WxCpUserTransferCustomerReq req) throws WxErrorException;
/**
* 企业和第三方可通过此接口查询离职成员的客户分配情况
* <per>
* 权限说明
*
* 企业需要使用客户联系secret或配置到可调用应用列表中的自建应用secret所获取的accesstoken来调用accesstoken如何获取
* 第三方应用需拥有企业客户权限->客户联系->在职继承权限
* 接替成员必须在此第三方应用或自建应用的可见范围内
* </per>
* @param handOverUserid 原添加成员的userid
* @param takeOverUserid 接替成员的userid
* @param cursor 分页查询的cursor每个分页返回的数据不会超过1000条不填或为空表示获取第一个分页
* @return 客户转接接口实体
* @throws WxErrorException the wx error exception
*/
WxCpUserTransferResultResp resignedTransferResult(@NotNull String handOverUserid, @NotNull String takeOverUserid, String cursor) throws WxErrorException;
/**
* <pre>
* 该接口用于获取配置过客户群管理的客户群列表
@ -260,6 +345,32 @@ public interface WxCpExternalContactService {
*/
WxCpUserExternalGroupChatInfo getGroupChat(String chatId) throws WxErrorException;
/**
*
* 企业可通过此接口将已离职成员为群主的群分配给另一个客服成员
*
* <per>
* 注意
*
* 群主离职了的客户群才可继承
* 继承给的新群主必须是配置了客户联系功能的成员
* 继承给的新群主必须有设置实名
* 继承给的新群主必须有激活企业微信
* 同一个人的群限制每天最多分配300个给新群主
*
* 权限说明:
*
* 企业需要使用客户联系secret或配置到可调用应用列表中的自建应用secret所获取的accesstoken来调用accesstoken如何获取
* 第三方应用需拥有企业客户权限->客户联系->分配离职成员的客户群权限
* 对于第三方/自建应用群主必须在应用的可见范围
* </per>
* @param chatIds 需要转群主的客户群ID列表取值范围 1 ~ 100
* @param newOwner 新群主ID
* @return 分配结果主要是分配失败的群列表
* @throws WxErrorException the wx error exception
*/
WxCpUserExternalGroupChatTransferResp transferGroupChat(String[] chatIds, String newOwner) throws WxErrorException;
/**
* <pre>
* 企业可通过此接口获取成员联系客户的数据包括发起申请数新增客户数聊天数发送消息数和删除/拉黑成员的客户数等指标
@ -397,4 +508,6 @@ public interface WxCpExternalContactService {
* @throws WxErrorException the wx error exception
*/
WxCpBaseResp markTag(String userid, String externalUserid, String[] addTag, String[] removeTag) throws WxErrorException;
}

View File

@ -7,6 +7,8 @@ import lombok.RequiredArgsConstructor;
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.json.GsonParser;
import me.chanjar.weixin.cp.api.WxCpExternalContactService;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.WxCpBaseResp;
@ -15,6 +17,7 @@ import me.chanjar.weixin.cp.bean.external.contact.WxCpExternalContactBatchInfo;
import me.chanjar.weixin.cp.bean.external.contact.WxCpExternalContactInfo;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.Date;
@ -106,6 +109,16 @@ public class WxCpExternalContactServiceImpl implements WxCpExternalContactServic
return WxCpExternalContactInfo.fromJson(responseContent);
}
@Override
public String convertToOpenid(@NotNull String externalUserId) throws WxErrorException {
JsonObject json = new JsonObject();
json.addProperty("external_userid", externalUserId);
final String url = this.mainService.getWxCpConfigStorage().getApiUrl(CONVERT_TO_OPENID);
String responseContent = this.mainService.post(url, json.toString());
JsonObject tmpJson = GsonParser.parse(responseContent);
return tmpJson.get("openid").getAsString();
}
@Override
public WxCpExternalContactBatchInfo getContactDetailBatch(String userId,
String cursor,
@ -176,6 +189,44 @@ public class WxCpExternalContactServiceImpl implements WxCpExternalContactServic
return WxCpBaseResp.fromJson(result);
}
@Override
public WxCpUserTransferCustomerResp transferCustomer(WxCpUserTransferCustomerReq req) throws WxErrorException {
BeanUtils.checkRequiredFields(req);
final String url = this.mainService.getWxCpConfigStorage().getApiUrl(TRANSFER_CUSTOMER);
final String result = this.mainService.post(url, req.toJson());
return WxCpUserTransferCustomerResp.fromJson(result);
}
@Override
public WxCpUserTransferResultResp transferResult(@NotNull String handOverUserid, @NotNull String takeOverUserid, String cursor) throws WxErrorException {
JsonObject json = new JsonObject();
json.addProperty("cursor", cursor);
json.addProperty("handover_userid", handOverUserid);
json.addProperty("takeover_userid", takeOverUserid);
final String url = this.mainService.getWxCpConfigStorage().getApiUrl(TRANSFER_RESULT);
final String result = this.mainService.post(url, json.toString());
return WxCpUserTransferResultResp.fromJson(result);
}
@Override
public WxCpUserTransferCustomerResp resignedTransferCustomer(WxCpUserTransferCustomerReq req) throws WxErrorException {
BeanUtils.checkRequiredFields(req);
final String url = this.mainService.getWxCpConfigStorage().getApiUrl(RESIGNED_TRANSFER_CUSTOMER);
final String result = this.mainService.post(url, req.toJson());
return WxCpUserTransferCustomerResp.fromJson(result);
}
@Override
public WxCpUserTransferResultResp resignedTransferResult(@NotNull String handOverUserid, @NotNull String takeOverUserid, String cursor) throws WxErrorException {
JsonObject json = new JsonObject();
json.addProperty("cursor", cursor);
json.addProperty("handover_userid", handOverUserid);
json.addProperty("takeover_userid", takeOverUserid);
final String url = this.mainService.getWxCpConfigStorage().getApiUrl(RESIGNED_TRANSFER_RESULT);
final String result = this.mainService.post(url, json.toString());
return WxCpUserTransferResultResp.fromJson(result);
}
@Override
public WxCpUserExternalGroupChatList listGroupChat(Integer pageIndex, Integer pageSize, int status, String[] userIds, String[] partyIds) throws WxErrorException {
JsonObject json = new JsonObject();
@ -206,6 +257,18 @@ public class WxCpExternalContactServiceImpl implements WxCpExternalContactServic
return WxCpUserExternalGroupChatInfo.fromJson(result);
}
@Override
public WxCpUserExternalGroupChatTransferResp transferGroupChat(String[] chatIds, String newOwner) throws WxErrorException {
JsonObject json = new JsonObject();
if (ArrayUtils.isNotEmpty(chatIds)) {
json.add("chat_id_list", new Gson().toJsonTree(chatIds).getAsJsonArray());
}
json.addProperty("new_owner", newOwner);
final String url = this.mainService.getWxCpConfigStorage().getApiUrl(GROUP_CHAT_TRANSFER);
final String result = this.mainService.post(url, json.toString());
return WxCpUserExternalGroupChatTransferResp.fromJson(result);
}
@Override
public WxCpUserExternalUserBehaviorStatistic getUserBehaviorStatistic(Date startTime, Date endTime, String[] userIds, String[] partyIds) throws WxErrorException {
JsonObject json = new JsonObject();

View File

@ -0,0 +1,51 @@
package me.chanjar.weixin.cp.bean.external;
import com.google.gson.annotations.SerializedName;
import lombok.Getter;
import lombok.Setter;
import me.chanjar.weixin.cp.bean.WxCpBaseResp;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
import java.util.List;
/**
* 分配离职成员的客户群结果
* @author pg
* @date 2021年6月21日
*/
@Getter
@Setter
public class WxCpUserExternalGroupChatTransferResp extends WxCpBaseResp {
private static final long serialVersionUID = -943124579487821819L;
/**
* 没有成功继承的群列表
*/
@SerializedName("failed_chat_list")
private List<GroupChatFailedTransfer> failedChatList;
public static WxCpUserExternalGroupChatTransferResp fromJson(String json) {
return WxCpGsonBuilder.create().fromJson(json, WxCpUserExternalGroupChatTransferResp.class);
}
public String toJson() {
return WxCpGsonBuilder.create().toJson(this);
}
@Getter
@Setter
public static class GroupChatFailedTransfer extends WxCpBaseResp {
private static final long serialVersionUID = -5836775099634587239L;
/**
* 没能成功继承的群ID
*/
private String chatId;
public static WxCpUserExternalGroupChatTransferResp.GroupChatFailedTransfer fromJson(String json) {
return WxCpGsonBuilder.create().fromJson(json, WxCpUserExternalGroupChatTransferResp.GroupChatFailedTransfer.class);
}
public String toJson() {
return WxCpGsonBuilder.create().toJson(this);
}
}
}

View File

@ -0,0 +1,49 @@
package me.chanjar.weixin.cp.bean.external;
import com.google.gson.annotations.SerializedName;
import lombok.Getter;
import lombok.Setter;
import me.chanjar.weixin.common.annotation.Required;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
import java.io.Serializable;
import java.util.List;
/**
* 转接在职成员的客户给其他成员请求对象
*
* @author pg
* @date 2021年6月21日
*/
@Getter
@Setter
public class WxCpUserTransferCustomerReq implements Serializable {
private static final long serialVersionUID = -309819538677411801L;
/**
* 原跟进成员的userid
*/
@SerializedName("handover_userid")
@Required
private String handOverUserid;
/**
* 接替成员的userid
*/
@SerializedName("takeover_userid")
@Required
private String takeOverUserid;
/**
* 客户的external_userid列表每次最多分配100个客户
*/
@SerializedName("external_userid")
@Required
private List<String> externalUserid;
/**
* 转移成功后发给客户的消息最多200个字符不填则使用默认文案
*/
@SerializedName("transfer_success_msg")
private String transferMsg;
public String toJson() {
return WxCpGsonBuilder.create().toJson(this);
}
}

View File

@ -0,0 +1,60 @@
package me.chanjar.weixin.cp.bean.external;
import com.google.gson.annotations.SerializedName;
import lombok.Getter;
import lombok.Setter;
import me.chanjar.weixin.cp.bean.WxCpBaseResp;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
import java.io.Serializable;
import java.util.List;
/**
* 转接在职成员的客户给其他成员返回对象
*
* @author pg
* @date 2021年6月21日
*/
@Getter
@Setter
public class WxCpUserTransferCustomerResp extends WxCpBaseResp {
private static final long serialVersionUID = -8030598756503590089L;
/**
* 客户转移结果列表
*/
private List<TransferCustomer> customer;
public static WxCpUserTransferCustomerResp fromJson(String json) {
return WxCpGsonBuilder.create().fromJson(json, WxCpUserTransferCustomerResp.class);
}
public String toJson() {
return WxCpGsonBuilder.create().toJson(this);
}
/**
* 转接客户结果实体
*/
@Getter
@Setter
public static class TransferCustomer implements Serializable {
private static final long serialVersionUID = 8720554208727083338L;
/**
* 客户的external_userid
*/
@SerializedName("external_userid")
private String externalUserid;
/**
* 对此客户进行分配的结果, 0表示成功发起接替,待24小时后自动接替,并不代表最终接替成功
*/
private Integer errcode;
public static WxCpUserTransferCustomerResp.TransferCustomer fromJson(String json) {
return WxCpGsonBuilder.create().fromJson(json, WxCpUserTransferCustomerResp.TransferCustomer.class);
}
public String toJson() {
return WxCpGsonBuilder.create().toJson(this);
}
}
}

View File

@ -0,0 +1,92 @@
package me.chanjar.weixin.cp.bean.external;
import com.google.gson.annotations.SerializedName;
import lombok.Getter;
import lombok.Setter;
import me.chanjar.weixin.cp.bean.WxCpBaseResp;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
import java.io.Serializable;
/**
* 在职成员的客户转接情况
* @author pg
* @date 2021年6月21日
*/
@Getter
@Setter
public class WxCpUserTransferResultResp extends WxCpBaseResp {
private static final long serialVersionUID = 6897979567174991786L;
@SerializedName("next_cursor")
private String nextCursor;
public static WxCpUserTransferResultResp fromJson(String json) {
return WxCpGsonBuilder.create().fromJson(json, WxCpUserTransferResultResp.class);
}
public String toJson() {
return WxCpGsonBuilder.create().toJson(this);
}
/**
* 客户转接结果实体
*/
@Getter
@Setter
public static class TransferResult implements Serializable {
private static final long serialVersionUID = 2847784363733118393L;
/**
* 客户的external_userid
*/
@SerializedName("external_userid")
private String externalUserid;
/**
* 接替状态 1-接替完毕 2-等待接替 3-客户拒绝 4-接替成员客户达到上限 5-无接替记录
*/
private STATUS status;
/**
* 接替客户的时间如果是等待接替状态则为未来的自动接替时间
*/
@SerializedName("takeover_time")
private Long takeOverTime;
public static WxCpUserTransferResultResp.TransferResult fromJson(String json) {
return WxCpGsonBuilder.create().fromJson(json, WxCpUserTransferResultResp.TransferResult.class);
}
public String toJson() {
return WxCpGsonBuilder.create().toJson(this);
}
}
public enum STATUS {
/**
* 接替完毕
*/
@SerializedName("1")
COMPLETE,
/**
* 等待接替
*/
@SerializedName("2")
WAITING,
/**
* 客户拒绝
*/
@SerializedName("3")
REFUSED,
/**
* 接替成员客户达到上限
*/
@SerializedName("4")
LIMIT,
/**
* 无接替记录
*/
@SerializedName("5")
NORECORD
}
}

View File

@ -175,13 +175,20 @@ public interface WxCpApiPathConsts {
String CLOSE_TEMP_CHAT = "/cgi-bin/externalcontact/close_temp_chat";
String GET_FOLLOW_USER_LIST = "/cgi-bin/externalcontact/get_follow_user_list";
String GET_CONTACT_DETAIL = "/cgi-bin/externalcontact/get?external_userid=";
String CONVERT_TO_OPENID = "/cgi-bin/externalcontact/convert_to_openid";
String GET_CONTACT_DETAIL_BATCH = "/cgi-bin/externalcontact/batch/get_by_user?";
String UPDATE_REMARK = "/cgi-bin/externalcontact/remark";
String LIST_EXTERNAL_CONTACT = "/cgi-bin/externalcontact/list?userid=";
String LIST_UNASSIGNED_CONTACT = "/cgi-bin/externalcontact/get_unassigned_list";
@Deprecated
String TRANSFER_UNASSIGNED_CONTACT = "/cgi-bin/externalcontact/transfer";
String TRANSFER_CUSTOMER = "/cgi-bin/externalcontact/transfer_customer";
String TRANSFER_RESULT = "/cgi-bin/externalcontact/transfer_result";
String RESIGNED_TRANSFER_CUSTOMER = "/cgi-bin/externalcontact/resigned/transfer_customer";
String RESIGNED_TRANSFER_RESULT = "/cgi-bin/externalcontact/resigned/transfer_result";
String GROUP_CHAT_LIST = "/cgi-bin/externalcontact/groupchat/list";
String GROUP_CHAT_INFO = "/cgi-bin/externalcontact/groupchat/get";
String GROUP_CHAT_TRANSFER = "/cgi-bin/externalcontact/groupchat/transfer";
String LIST_USER_BEHAVIOR_DATA = "/cgi-bin/externalcontact/get_user_behavior_data";
String LIST_GROUP_CHAT_DATA = "/cgi-bin/externalcontact/groupchat/statistic";
String ADD_MSG_TEMPLATE = "/cgi-bin/externalcontact/add_msg_template";

View File

@ -16,6 +16,7 @@ import org.testng.annotations.Guice;
import org.testng.annotations.Test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
@ -196,13 +197,62 @@ public class WxCpExternalContactServiceImplTest {
}
@Test
public void testListGroupChat() {
public void testTransferCustomer() throws WxErrorException {
WxCpUserTransferCustomerReq req = new WxCpUserTransferCustomerReq();
req.setExternalUserid(Collections.emptyList());
req.setHandOverUserid("123");
req.setTakeOverUserid("234");
WxCpBaseResp result = this.wxCpService.getExternalContactService().transferCustomer(req);
System.out.println(result);
assertNotNull(result);
}
@Test
public void testTrnsferResult() throws WxErrorException {
WxCpUserTransferResultResp result = this.wxCpService.getExternalContactService().transferResult("123", "234", "");
System.out.println(result);
assertNotNull(result);
}
@Test
public void testresignedTransferCustomer() throws WxErrorException {
WxCpUserTransferCustomerReq req = new WxCpUserTransferCustomerReq();
req.setExternalUserid(Collections.emptyList());
req.setHandOverUserid("123");
req.setTakeOverUserid("234");
WxCpBaseResp result = this.wxCpService.getExternalContactService().resignedTransferCustomer(req);
System.out.println(result);
assertNotNull(result);
}
@Test
public void testresignedTrnsferResult() throws WxErrorException {
WxCpUserTransferResultResp result = this.wxCpService.getExternalContactService().resignedTransferResult("123", "234", "");
System.out.println(result);
assertNotNull(result);
}
@Test
public void testListGroupChat() throws WxErrorException {
WxCpUserExternalGroupChatList result = this.wxCpService.getExternalContactService().listGroupChat(0, 100 ,0,new String[1],new String[1]);
System.out.println(result);
assertNotNull(result);
}
@Test
public void testGetGroupChat() {
}
@Test
public void testTransferGroupChat() throws WxErrorException {
String[] str = {"wri1_QEAAATfnZl_VJ4hlQda0e4Mgf1A"};
WxCpUserExternalGroupChatTransferResp result = this.wxCpService.getExternalContactService().transferGroupChat(str, "123");
System.out.println(result);
assertNotNull(result);
}
@Test
public void testGetUserBehaviorStatistic() {
}