Co-authored-by: 袁启勋 <xun.yuan@infoship.cn>dev1
| @@ -1,8 +1,10 @@ | |||
| package me.chanjar.weixin.cp.api; | |||
| import me.chanjar.weixin.common.error.WxErrorException; | |||
| import me.chanjar.weixin.cp.bean.WxCpUserExternalContactInfo; | |||
| import me.chanjar.weixin.cp.bean.*; | |||
| import java.util.Calendar; | |||
| import java.util.Date; | |||
| import java.util.List; | |||
| /** | |||
| @@ -85,4 +87,79 @@ public interface WxCpExternalContactService { | |||
| */ | |||
| List<String> listFollowUser() throws WxErrorException; | |||
| /** | |||
| * 企业和第三方可通过此接口,获取所有离职成员的客户列表,并可进一步调用离职成员的外部联系人再分配接口将这些客户重新分配给其他企业成员。 | |||
| * @param page | |||
| * @param pageSize | |||
| * @return | |||
| * @throws WxErrorException | |||
| */ | |||
| WxCpUserExternalUnassignList listUnassignedList(Integer page, Integer pageSize) throws WxErrorException; | |||
| /** | |||
| * 企业可通过此接口,将已离职成员的外部联系人分配给另一个成员接替联系。 | |||
| * @param externalUserid | |||
| * @param handOverUserid | |||
| * @param takeOverUserid | |||
| * @return | |||
| * @throws WxErrorException | |||
| */ | |||
| WxCpBaseResp transferExternalContact(String externalUserid,String handOverUserid,String takeOverUserid)throws WxErrorException; | |||
| /** <pre> | |||
| * 该接口用于获取配置过客户群管理的客户群列表。 | |||
| * 企业需要使用“客户联系”secret或配置到“可调用应用”列表中的自建应用secret所获取的accesstoken来调用(accesstoken如何获取?)。 | |||
| * 暂不支持第三方调用。 | |||
| * 微信文档:https://work.weixin.qq.com/api/doc/90000/90135/92119 | |||
| * </pre> | |||
| */ | |||
| WxCpUserExternalGroupChatList listGroupChat(Integer pageIndex,Integer pageSize,int status,String[] userIds,String[] partyIds) throws WxErrorException; | |||
| /** | |||
| * <pre> | |||
| * 通过客户群ID,获取详情。包括群名、群成员列表、群成员入群时间、入群方式。(客户群是由具有客户群使用权限的成员创建的外部群) | |||
| * 企业需要使用“客户联系”secret或配置到“可调用应用”列表中的自建应用secret所获取的accesstoken来调用(accesstoken如何获取?)。 | |||
| * 暂不支持第三方调用。 | |||
| * 微信文档:https://work.weixin.qq.com/api/doc/90000/90135/92122 | |||
| * </pre> | |||
| * | |||
| * @param chatId | |||
| * @return | |||
| * @throws WxErrorException | |||
| */ | |||
| WxCpUserExternalGroupChatInfo getGroupChat(String chatId) throws WxErrorException; | |||
| /** | |||
| * <pre> | |||
| * 企业可通过此接口获取成员联系客户的数据,包括发起申请数、新增客户数、聊天数、发送消息数和删除/拉黑成员的客户数等指标。 | |||
| * 企业需要使用“客户联系”secret或配置到“可调用应用”列表中的自建应用secret所获取的accesstoken来调用(accesstoken如何获取?)。 | |||
| * 第三方应用需拥有“企业客户”权限。 | |||
| * 第三方/自建应用调用时传入的userid和partyid要在应用的可见范围内; | |||
| * </pre> | |||
| * @param startTime | |||
| * @param endTime | |||
| * @param userIds | |||
| * @param partyIds | |||
| * @return | |||
| * @throws WxErrorException | |||
| */ | |||
| WxCpUserExternalUserBehaviorStatistic getUserBehaviorStatistic(Date startTime, Date endTime, String[] userIds, String[] partyIds) throws WxErrorException; | |||
| /** | |||
| * <pre> | |||
| * 获取指定日期全天的统计数据。注意,企业微信仅存储60天的数据。 | |||
| * 企业需要使用“客户联系”secret或配置到“可调用应用”列表中的自建应用secret所获取的accesstoken来调用(accesstoken如何获取?)。 | |||
| * 暂不支持第三方调用。 | |||
| * </pre> | |||
| * @param startTime | |||
| * @param orderBy | |||
| * @param orderAsc | |||
| * @param pageIndex | |||
| * @param pageSize | |||
| * @param userIds | |||
| * @param partyIds | |||
| * @return | |||
| * @throws WxErrorException | |||
| */ | |||
| WxCpUserExternalGroupChatStatistic getGroupChatStatistic(Date startTime,Integer orderBy,Integer orderAsc,Integer pageIndex,Integer pageSize, String[] userIds, String[] partyIds) throws WxErrorException; | |||
| } | |||
| @@ -1,12 +1,14 @@ | |||
| package me.chanjar.weixin.cp.api.impl; | |||
| import com.google.gson.Gson; | |||
| import com.google.gson.JsonObject; | |||
| import me.chanjar.weixin.common.error.WxErrorException; | |||
| import me.chanjar.weixin.cp.api.WxCpExternalContactService; | |||
| import me.chanjar.weixin.cp.api.WxCpService; | |||
| import me.chanjar.weixin.cp.bean.WxCpUserExternalContactInfo; | |||
| import me.chanjar.weixin.cp.bean.WxCpUserExternalContactList; | |||
| import me.chanjar.weixin.cp.bean.WxCpUserWithExternalPermission; | |||
| import me.chanjar.weixin.cp.bean.*; | |||
| import org.apache.commons.lang3.ArrayUtils; | |||
| import java.util.Date; | |||
| import java.util.List; | |||
| import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.ExternalContact.*; | |||
| @@ -45,4 +47,96 @@ public class WxCpExternalContactServiceImpl implements WxCpExternalContactServic | |||
| String responseContent = this.mainService.get(url, null); | |||
| return WxCpUserWithExternalPermission.fromJson(responseContent).getFollowUser(); | |||
| } | |||
| @Override | |||
| public WxCpUserExternalUnassignList listUnassignedList(Integer pageIndex, Integer pageSize) throws WxErrorException { | |||
| JsonObject json = new JsonObject(); | |||
| json.addProperty("page_id",pageIndex == null ? 0 : pageIndex); | |||
| json.addProperty("page_size",pageSize == null ? 100 : pageSize); | |||
| final String url = this.mainService.getWxCpConfigStorage().getApiUrl(LIST_UNASSIGNED_CONTACT); | |||
| final String result = this.mainService.post(url, json.toString()); | |||
| return WxCpUserExternalUnassignList.fromJson(result); | |||
| } | |||
| @Override | |||
| public WxCpBaseResp transferExternalContact(String externalUserid, String handOverUserid, String takeOverUserid) throws WxErrorException { | |||
| JsonObject json = new JsonObject(); | |||
| json.addProperty("external_userid", externalUserid); | |||
| json.addProperty("handover_userid", handOverUserid); | |||
| json.addProperty("takeover_userid", takeOverUserid); | |||
| final String url = this.mainService.getWxCpConfigStorage().getApiUrl(TRANSFER_UNASSIGNED_CONTACT); | |||
| final String result = this.mainService.post(url, json.toString()); | |||
| return WxCpBaseResp.fromJson(result); | |||
| } | |||
| @Override | |||
| public WxCpUserExternalGroupChatList listGroupChat(Integer pageIndex, Integer pageSize, int status, String[] userIds, String[] partyIds) throws WxErrorException { | |||
| JsonObject json = new JsonObject(); | |||
| json.addProperty("offset",pageIndex == null ? 0 : pageIndex); | |||
| json.addProperty("limit",pageSize == null ? 100 : pageSize); | |||
| json.addProperty("status_filter",status); | |||
| if(ArrayUtils.isNotEmpty(userIds) || ArrayUtils.isNotEmpty(partyIds)){ | |||
| JsonObject ownerFilter = new JsonObject(); | |||
| if(ArrayUtils.isNotEmpty(userIds)){ | |||
| json.add("userid", new Gson().toJsonTree(userIds).getAsJsonArray()); | |||
| } | |||
| if(ArrayUtils.isNotEmpty(partyIds)){ | |||
| json.add("partyid", new Gson().toJsonTree(partyIds).getAsJsonArray()); | |||
| } | |||
| json.add("owner_filter",ownerFilter); | |||
| } | |||
| final String url = this.mainService.getWxCpConfigStorage().getApiUrl(GROUP_CHAT_LIST); | |||
| final String result = this.mainService.post(url, json.toString()); | |||
| return WxCpUserExternalGroupChatList.fromJson(result); | |||
| } | |||
| @Override | |||
| public WxCpUserExternalGroupChatInfo getGroupChat(String chatId) throws WxErrorException { | |||
| JsonObject json = new JsonObject(); | |||
| json.addProperty("chat_id", chatId); | |||
| final String url = this.mainService.getWxCpConfigStorage().getApiUrl(GROUP_CHAT_INFO); | |||
| final String result = this.mainService.post(url, json.toString()); | |||
| return WxCpUserExternalGroupChatInfo.fromJson(result); | |||
| } | |||
| @Override | |||
| public WxCpUserExternalUserBehaviorStatistic getUserBehaviorStatistic(Date startTime, Date endTime, String[] userIds, String[] partyIds) throws WxErrorException { | |||
| JsonObject json = new JsonObject(); | |||
| json.addProperty("start_time", startTime.getTime()/1000); | |||
| json.addProperty("end_time", endTime.getTime()/1000); | |||
| if(ArrayUtils.isNotEmpty(userIds) || ArrayUtils.isNotEmpty(partyIds)){ | |||
| if(ArrayUtils.isNotEmpty(userIds)){ | |||
| json.add("userid", new Gson().toJsonTree(userIds).getAsJsonArray()); | |||
| } | |||
| if(ArrayUtils.isNotEmpty(partyIds)){ | |||
| json.add("partyid", new Gson().toJsonTree(partyIds).getAsJsonArray()); | |||
| } | |||
| } | |||
| final String url = this.mainService.getWxCpConfigStorage().getApiUrl(LIST_USER_BEHAVIOR_DATA); | |||
| final String result = this.mainService.post(url, json.toString()); | |||
| return WxCpUserExternalUserBehaviorStatistic.fromJson(result); | |||
| } | |||
| @Override | |||
| public WxCpUserExternalGroupChatStatistic getGroupChatStatistic(Date startTime, Integer orderBy, Integer orderAsc, Integer pageIndex, Integer pageSize, String[] userIds, String[] partyIds) throws WxErrorException { | |||
| JsonObject json = new JsonObject(); | |||
| json.addProperty("day_begin_time", startTime.getTime()/1000); | |||
| json.addProperty("order_by", orderBy == null ? 1 : orderBy); | |||
| json.addProperty("order_asc",orderAsc == null ? 0 : orderAsc); | |||
| json.addProperty("offset",pageIndex == null ? 0 : pageIndex); | |||
| json.addProperty("limit",pageSize == null ? 500 : pageSize); | |||
| if(ArrayUtils.isNotEmpty(userIds) || ArrayUtils.isNotEmpty(partyIds)){ | |||
| JsonObject ownerFilter = new JsonObject(); | |||
| if(ArrayUtils.isNotEmpty(userIds)){ | |||
| json.add("userid_list", new Gson().toJsonTree(userIds).getAsJsonArray()); | |||
| } | |||
| if(ArrayUtils.isNotEmpty(partyIds)){ | |||
| json.add("userid_list", new Gson().toJsonTree(partyIds).getAsJsonArray()); | |||
| } | |||
| json.add("owner_filter",ownerFilter); | |||
| } | |||
| final String url = this.mainService.getWxCpConfigStorage().getApiUrl(LIST_GROUP_CHAT_DATA); | |||
| final String result = this.mainService.post(url, json.toString()); | |||
| return WxCpUserExternalGroupChatStatistic.fromJson(result); | |||
| } | |||
| } | |||
| @@ -0,0 +1,28 @@ | |||
| package me.chanjar.weixin.cp.bean; | |||
| import com.google.gson.annotations.SerializedName; | |||
| import lombok.Getter; | |||
| import lombok.Setter; | |||
| import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; | |||
| /** | |||
| * @author yqx | |||
| * @date 2020/3/16 | |||
| */ | |||
| @Getter | |||
| @Setter | |||
| public class WxCpBaseResp { | |||
| @SerializedName("errcode") | |||
| protected Long errcode; | |||
| @SerializedName("errmsg") | |||
| protected String errmsg; | |||
| public boolean success() { | |||
| return getErrcode() == 0; | |||
| } | |||
| public static WxCpBaseResp fromJson(String json) { | |||
| return WxCpGsonBuilder.create().fromJson(json, WxCpBaseResp.class); | |||
| } | |||
| } | |||
| @@ -1,42 +1,44 @@ | |||
| package me.chanjar.weixin.cp.bean; | |||
| import java.io.Serializable; | |||
| import com.google.gson.annotations.SerializedName; | |||
| import lombok.Data; | |||
| import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; | |||
| /** | |||
| * 微信部门. | |||
| * | |||
| * @author Daniel Qian | |||
| */ | |||
| @Data | |||
| public class WxCpTpCorp implements Serializable { | |||
| private static final long serialVersionUID = -5028321625140879571L; | |||
| @SerializedName("corpid") | |||
| private String corpId; | |||
| @SerializedName("corp_name") | |||
| private String corpName; | |||
| @SerializedName("corp_full_name") | |||
| private String corpFullName; | |||
| @SerializedName("corp_type") | |||
| private String corpType; | |||
| @SerializedName("corp_square_logo_url") | |||
| private String corpSquareLogoUrl; | |||
| @SerializedName("corp_user_max") | |||
| private String corpUserMax; | |||
| @SerializedName("permanent_code") | |||
| private String permanentCode; | |||
| public static WxCpTpCorp fromJson(String json) { | |||
| return WxCpGsonBuilder.create().fromJson(json, WxCpTpCorp.class); | |||
| } | |||
| public String toJson() { | |||
| return WxCpGsonBuilder.create().toJson(this); | |||
| } | |||
| } | |||
| package me.chanjar.weixin.cp.bean; | |||
| import java.io.Serializable; | |||
| import com.google.gson.annotations.SerializedName; | |||
| import lombok.Data; | |||
| import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; | |||
| /** | |||
| * 微信部门. | |||
| * | |||
| * @author Daniel Qian | |||
| */ | |||
| @Data | |||
| public class WxCpTpCorp implements Serializable { | |||
| private static final long serialVersionUID = -5028321625140879571L; | |||
| @SerializedName("corpid") | |||
| private String corpId; | |||
| @SerializedName("corp_name") | |||
| private String corpName; | |||
| @SerializedName("corp_full_name") | |||
| private String corpFullName; | |||
| @SerializedName("corp_type") | |||
| private String corpType; | |||
| @SerializedName("corp_square_logo_url") | |||
| private String corpSquareLogoUrl; | |||
| @SerializedName("corp_user_max") | |||
| private String corpUserMax; | |||
| @SerializedName("permanent_code") | |||
| private String permanentCode; | |||
| @SerializedName("auth_info") | |||
| private String authInfo; | |||
| public static WxCpTpCorp fromJson(String json) { | |||
| return WxCpGsonBuilder.create().fromJson(json, WxCpTpCorp.class); | |||
| } | |||
| public String toJson() { | |||
| return WxCpGsonBuilder.create().toJson(this); | |||
| } | |||
| } | |||
| @@ -1,68 +1,72 @@ | |||
| package me.chanjar.weixin.cp.bean; | |||
| import java.io.Serializable; | |||
| import java.util.Map; | |||
| import com.thoughtworks.xstream.annotations.XStreamAlias; | |||
| import com.thoughtworks.xstream.annotations.XStreamConverter; | |||
| import lombok.Data; | |||
| import lombok.extern.slf4j.Slf4j; | |||
| import me.chanjar.weixin.common.util.XmlUtils; | |||
| import me.chanjar.weixin.common.util.crypto.WxCryptUtil; | |||
| import me.chanjar.weixin.common.util.xml.XStreamCDataConverter; | |||
| import me.chanjar.weixin.cp.bean.outxmlbuilder.ImageBuilder; | |||
| import me.chanjar.weixin.cp.bean.outxmlbuilder.NewsBuilder; | |||
| import me.chanjar.weixin.cp.bean.outxmlbuilder.TextBuilder; | |||
| import me.chanjar.weixin.cp.bean.outxmlbuilder.VideoBuilder; | |||
| import me.chanjar.weixin.cp.bean.outxmlbuilder.VoiceBuilder; | |||
| import me.chanjar.weixin.cp.config.WxCpConfigStorage; | |||
| import me.chanjar.weixin.cp.config.WxCpTpConfigStorage; | |||
| import me.chanjar.weixin.cp.util.crypto.WxCpCryptUtil; | |||
| import me.chanjar.weixin.cp.util.xml.XStreamTransformer; | |||
| /** | |||
| * 回调推送的message | |||
| * https://work.weixin.qq.com/api/doc#90001/90143/90612 | |||
| * | |||
| * @author zhenjun cai | |||
| */ | |||
| @XStreamAlias("xml") | |||
| @Slf4j | |||
| @Data | |||
| public class WxCpTpXmlMessage implements Serializable { | |||
| private static final long serialVersionUID = 6031833682211475786L; | |||
| /** | |||
| * 使用dom4j解析的存放所有xml属性和值的map. | |||
| */ | |||
| private Map<String, Object> allFieldsMap; | |||
| @XStreamAlias("SuiteId") | |||
| @XStreamConverter(value = XStreamCDataConverter.class) | |||
| protected String suiteId; | |||
| @XStreamAlias("InfoType") | |||
| @XStreamConverter(value = XStreamCDataConverter.class) | |||
| protected String infoType; | |||
| @XStreamAlias("TimeStamp") | |||
| @XStreamConverter(value = XStreamCDataConverter.class) | |||
| protected String timeStamp; | |||
| @XStreamAlias("SuiteTicket") | |||
| @XStreamConverter(value = XStreamCDataConverter.class) | |||
| protected String suiteTicket; | |||
| @XStreamAlias("AuthCode") | |||
| @XStreamConverter(value = XStreamCDataConverter.class) | |||
| protected String authCode; | |||
| public static WxCpTpXmlMessage fromXml(String xml) { | |||
| //修改微信变态的消息内容格式,方便解析 | |||
| //xml = xml.replace("</PicList><PicList>", ""); | |||
| final WxCpTpXmlMessage xmlPackage = XStreamTransformer.fromXml(WxCpTpXmlMessage.class, xml); | |||
| xmlPackage.setAllFieldsMap(XmlUtils.xml2Map(xml)); | |||
| return xmlPackage; | |||
| } | |||
| } | |||
| package me.chanjar.weixin.cp.bean; | |||
| import java.io.Serializable; | |||
| import java.util.Map; | |||
| import com.thoughtworks.xstream.annotations.XStreamAlias; | |||
| import com.thoughtworks.xstream.annotations.XStreamConverter; | |||
| import lombok.Data; | |||
| import lombok.extern.slf4j.Slf4j; | |||
| import me.chanjar.weixin.common.util.XmlUtils; | |||
| import me.chanjar.weixin.common.util.crypto.WxCryptUtil; | |||
| import me.chanjar.weixin.common.util.xml.XStreamCDataConverter; | |||
| import me.chanjar.weixin.cp.bean.outxmlbuilder.ImageBuilder; | |||
| import me.chanjar.weixin.cp.bean.outxmlbuilder.NewsBuilder; | |||
| import me.chanjar.weixin.cp.bean.outxmlbuilder.TextBuilder; | |||
| import me.chanjar.weixin.cp.bean.outxmlbuilder.VideoBuilder; | |||
| import me.chanjar.weixin.cp.bean.outxmlbuilder.VoiceBuilder; | |||
| import me.chanjar.weixin.cp.config.WxCpConfigStorage; | |||
| import me.chanjar.weixin.cp.config.WxCpTpConfigStorage; | |||
| import me.chanjar.weixin.cp.util.crypto.WxCpCryptUtil; | |||
| import me.chanjar.weixin.cp.util.xml.XStreamTransformer; | |||
| /** | |||
| * 回调推送的message | |||
| * https://work.weixin.qq.com/api/doc#90001/90143/90612 | |||
| * | |||
| * @author zhenjun cai | |||
| */ | |||
| @XStreamAlias("xml") | |||
| @Slf4j | |||
| @Data | |||
| public class WxCpTpXmlMessage implements Serializable { | |||
| private static final long serialVersionUID = 6031833682211475786L; | |||
| /** | |||
| * 使用dom4j解析的存放所有xml属性和值的map. | |||
| */ | |||
| private Map<String, Object> allFieldsMap; | |||
| @XStreamAlias("SuiteId") | |||
| @XStreamConverter(value = XStreamCDataConverter.class) | |||
| protected String suiteId; | |||
| @XStreamAlias("InfoType") | |||
| @XStreamConverter(value = XStreamCDataConverter.class) | |||
| protected String infoType; | |||
| @XStreamAlias("TimeStamp") | |||
| @XStreamConverter(value = XStreamCDataConverter.class) | |||
| protected String timeStamp; | |||
| @XStreamAlias("SuiteTicket") | |||
| @XStreamConverter(value = XStreamCDataConverter.class) | |||
| protected String suiteTicket; | |||
| @XStreamAlias("AuthCode") | |||
| @XStreamConverter(value = XStreamCDataConverter.class) | |||
| protected String authCode; | |||
| @XStreamAlias("AuthCorpId") | |||
| @XStreamConverter(value = XStreamCDataConverter.class) | |||
| protected String authCorpId; | |||
| public static WxCpTpXmlMessage fromXml(String xml) { | |||
| //修改微信变态的消息内容格式,方便解析 | |||
| //xml = xml.replace("</PicList><PicList>", ""); | |||
| final WxCpTpXmlMessage xmlPackage = XStreamTransformer.fromXml(WxCpTpXmlMessage.class, xml); | |||
| xmlPackage.setAllFieldsMap(XmlUtils.xml2Map(xml)); | |||
| return xmlPackage; | |||
| } | |||
| } | |||
| @@ -0,0 +1,75 @@ | |||
| package me.chanjar.weixin.cp.bean; | |||
| import com.google.gson.annotations.SerializedName; | |||
| import lombok.Getter; | |||
| import lombok.Setter; | |||
| import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; | |||
| import java.util.List; | |||
| /** | |||
| * @author yqx | |||
| * @date 2020/3/116 | |||
| */ | |||
| @Getter | |||
| @Setter | |||
| public class WxCpUserExternalGroupChatInfo extends WxCpBaseResp{ | |||
| @SerializedName("group_chat") | |||
| private GroupChat groupChat; | |||
| @Getter | |||
| @Setter | |||
| public static class GroupChat { | |||
| @SerializedName("chat_id") | |||
| private String chatId; | |||
| @SerializedName("name") | |||
| private String name; | |||
| @SerializedName("owner") | |||
| private String owner; | |||
| @SerializedName("create_time") | |||
| private Long createTime; | |||
| @SerializedName("notice") | |||
| private String notice; | |||
| @SerializedName("member_list") | |||
| private List<GroupMember> memberList; | |||
| } | |||
| @Getter | |||
| @Setter | |||
| public static class GroupMember { | |||
| @SerializedName("userid") | |||
| private String userId; | |||
| /** | |||
| * 成员类型。 | |||
| * 1 - 企业成员 | |||
| * 2 - 外部联系人 | |||
| */ | |||
| @SerializedName("type") | |||
| private int type; | |||
| @SerializedName("join_time") | |||
| private Long joinTime; | |||
| /** | |||
| * 入群方式。 | |||
| * 1 - 由成员邀请入群(直接邀请入群) | |||
| * 2 - 由成员邀请入群(通过邀请链接入群) | |||
| * 3 - 通过扫描群二维码入群 | |||
| */ | |||
| @SerializedName("join_scene") | |||
| private int joinScene; | |||
| } | |||
| public static WxCpUserExternalGroupChatInfo fromJson(String json) { | |||
| return WxCpGsonBuilder.create().fromJson(json, WxCpUserExternalGroupChatInfo.class); | |||
| } | |||
| } | |||
| @@ -0,0 +1,46 @@ | |||
| package me.chanjar.weixin.cp.bean; | |||
| import com.google.gson.annotations.SerializedName; | |||
| import lombok.Getter; | |||
| import lombok.Setter; | |||
| import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; | |||
| import java.util.List; | |||
| /** | |||
| * @author yqx | |||
| * @date 2020/3/116 | |||
| */ | |||
| @Getter | |||
| @Setter | |||
| public class WxCpUserExternalGroupChatList extends WxCpBaseResp { | |||
| @SerializedName("group_chat_list") | |||
| private List<ChatStatus> groupChatList; | |||
| @Getter | |||
| @Setter | |||
| public static class ChatStatus { | |||
| /** | |||
| * 客户群ID | |||
| */ | |||
| @SerializedName("chat_id") | |||
| private String chatId; | |||
| /** | |||
| * 客户群状态 | |||
| * 0 - 正常 | |||
| * 1 - 跟进人离职 | |||
| * 2 - 离职继承中 | |||
| * 3 - 离职继承完成 | |||
| */ | |||
| @SerializedName("status") | |||
| private int status; | |||
| } | |||
| public static WxCpUserExternalGroupChatList fromJson(String json) { | |||
| return WxCpGsonBuilder.create().fromJson(json, WxCpUserExternalGroupChatList.class); | |||
| } | |||
| } | |||
| @@ -0,0 +1,90 @@ | |||
| package me.chanjar.weixin.cp.bean; | |||
| import com.google.gson.annotations.SerializedName; | |||
| import lombok.Getter; | |||
| import lombok.Setter; | |||
| import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; | |||
| import java.util.List; | |||
| /** | |||
| * 联系客户群统计数据 | |||
| * | |||
| * @author yqx | |||
| * @date 2020/3/16 | |||
| */ | |||
| @Getter | |||
| @Setter | |||
| public class WxCpUserExternalGroupChatStatistic extends WxCpBaseResp{ | |||
| @SerializedName("total") | |||
| int total; | |||
| @SerializedName("next_offset") | |||
| int nextOffset; | |||
| @SerializedName("items") | |||
| List<StatisticItem> itemList; | |||
| @Getter | |||
| @Setter | |||
| public static class StatisticItem { | |||
| @SerializedName("owner") | |||
| String owner; | |||
| @SerializedName("data") | |||
| ItemData itemData; | |||
| } | |||
| @Getter | |||
| @Setter | |||
| public static class ItemData { | |||
| /** | |||
| * 新增客户群数量 | |||
| */ | |||
| @SerializedName("new_chat_cnt") | |||
| int newChatCnt; | |||
| /** | |||
| * 截至当天客户群总数量 | |||
| */ | |||
| @SerializedName("chat_total") | |||
| int chatTotal; | |||
| /** | |||
| * 截至当天有发过消息的客户群数量 | |||
| */ | |||
| @SerializedName("chat_has_msg") | |||
| int chatHasMsg; | |||
| /** | |||
| * 客户群新增群人数。 | |||
| */ | |||
| @SerializedName("new_member_cnt") | |||
| int newMemberCnt; | |||
| /** | |||
| * 截至当天客户群总人数 | |||
| */ | |||
| @SerializedName("member_total") | |||
| int memberTotal; | |||
| /** | |||
| * 截至当天有发过消息的群成员数 | |||
| */ | |||
| @SerializedName("member_has_msg") | |||
| int memberHasMsg; | |||
| /** | |||
| * 截至当天客户群消息总数 | |||
| */ | |||
| @SerializedName("msg_total") | |||
| int msgTotal; | |||
| } | |||
| public static WxCpUserExternalGroupChatStatistic fromJson(String json) { | |||
| return WxCpGsonBuilder.create().fromJson(json, WxCpUserExternalGroupChatStatistic.class); | |||
| } | |||
| } | |||
| @@ -0,0 +1,52 @@ | |||
| package me.chanjar.weixin.cp.bean; | |||
| import com.google.gson.annotations.Expose; | |||
| import com.google.gson.annotations.SerializedName; | |||
| import lombok.Getter; | |||
| import lombok.Setter; | |||
| import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; | |||
| import java.util.List; | |||
| /** | |||
| * 离职员工外部联系人列表 | |||
| * @author yqx | |||
| * @date 2020/3/15 | |||
| */ | |||
| @Getter | |||
| @Setter | |||
| public class WxCpUserExternalUnassignList extends WxCpBaseResp{ | |||
| @SerializedName("info") | |||
| private List<UnassignInfo> unassignInfos; | |||
| @SerializedName("is_last") | |||
| private boolean isLast; | |||
| @Getter | |||
| @Setter | |||
| public static class UnassignInfo { | |||
| /** | |||
| * 离职成员userid | |||
| */ | |||
| @SerializedName("handover_userid") | |||
| private String handoverUserid; | |||
| /** | |||
| * 外部联系人userid | |||
| */ | |||
| @SerializedName("external_userid") | |||
| private String externalUserid; | |||
| /** | |||
| * 成员离职时间 | |||
| */ | |||
| @SerializedName("dimission_time") | |||
| private Long dimissionTime; | |||
| } | |||
| public static WxCpUserExternalUnassignList fromJson(String json) { | |||
| return WxCpGsonBuilder.create().fromJson(json, WxCpUserExternalUnassignList.class); | |||
| } | |||
| } | |||
| @@ -0,0 +1,78 @@ | |||
| package me.chanjar.weixin.cp.bean; | |||
| import com.google.gson.annotations.SerializedName; | |||
| import lombok.Getter; | |||
| import lombok.Setter; | |||
| import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; | |||
| import java.util.List; | |||
| /** | |||
| * 联系客户统计数据 | |||
| * @author yqx | |||
| * @date 2020/3/16 | |||
| */ | |||
| @Getter | |||
| @Setter | |||
| public class WxCpUserExternalUserBehaviorStatistic extends WxCpBaseResp { | |||
| @SerializedName("behavior_data") | |||
| private List<Behavior> behaviorList; | |||
| @Getter | |||
| @Setter | |||
| public static class Behavior { | |||
| /** | |||
| * 数据日期,为当日0点的时间戳 | |||
| */ | |||
| @SerializedName("stat_time") | |||
| private Long statTime; | |||
| /** | |||
| * 聊天总数, 成员有主动发送过消息的聊天数,包括单聊和群聊。 | |||
| */ | |||
| @SerializedName("chat_cnt") | |||
| private int chatCnt; | |||
| /** | |||
| * 发送消息数,成员在单聊和群聊中发送的消息总数。 | |||
| */ | |||
| @SerializedName("message_cnt") | |||
| private int messageCnt; | |||
| /** | |||
| * 已回复聊天占比,客户主动发起聊天后,成员在一个自然日内有回复过消息的聊天数/客户主动发起的聊天数比例,不包括群聊,仅在确有回复时返回。 | |||
| */ | |||
| @SerializedName("reply_percentage") | |||
| private double replyPercentage; | |||
| /** | |||
| * 平均首次回复时长,单位为分钟,即客户主动发起聊天后,成员在一个自然日内首次回复的时长间隔为首次回复时长,所有聊天的首次回复总时长/已回复的聊天总数即为平均首次回复时长,不包括群聊,仅在确有回复时返回。 | |||
| */ | |||
| @SerializedName("avg_reply_time") | |||
| private int avgReplyTime; | |||
| /** | |||
| * 删除/拉黑成员的客户数,即将成员删除或加入黑名单的客户数。 | |||
| */ | |||
| @SerializedName("negative_fee_back_cnt") | |||
| private int negativeFeeBackCnt; | |||
| /** | |||
| * 发起申请数,成员通过「搜索手机号」、「扫一扫」、「从微信好友中添加」、「从群聊中添加」、「添加共享、分配给我的客户」、「添加单向、双向删除好友关系的好友」、「从新的联系人推荐中添加」等渠道主动向客户发起的好友申请数量。 | |||
| */ | |||
| @SerializedName("new_apply_cnt") | |||
| private int newApplyCnt; | |||
| /** | |||
| * 新增客户数,成员新添加的客户数量。 | |||
| */ | |||
| @SerializedName("new_contact_cnt") | |||
| private int newContactCnt; | |||
| } | |||
| public static WxCpUserExternalUserBehaviorStatistic fromJson(String json) { | |||
| return WxCpGsonBuilder.create().fromJson(json, WxCpUserExternalUserBehaviorStatistic.class); | |||
| } | |||
| } | |||
| @@ -118,5 +118,11 @@ public final class WxCpApiPathConsts { | |||
| public static final String GET_FOLLOW_USER_LIST = "/cgi-bin/externalcontact/get_follow_user_list"; | |||
| public static final String GET_CONTACT_DETAIL = "/cgi-bin/externalcontact/get?external_userid="; | |||
| public static final String LIST_EXTERNAL_CONTACT = "/cgi-bin/externalcontact/list?userid="; | |||
| public static final String LIST_UNASSIGNED_CONTACT = "/cgi-bin/externalcontact/get_unassigned_list"; | |||
| public static final String TRANSFER_UNASSIGNED_CONTACT = "/cgi-bin/externalcontact/transfer"; | |||
| public static final String GROUP_CHAT_LIST = "/cgi-bin/externalcontact/groupchat/list"; | |||
| public static final String GROUP_CHAT_INFO = "/cgi-bin/externalcontact/groupchat/get"; | |||
| public static final String LIST_USER_BEHAVIOR_DATA = "/cgi-bin/externalcontact/get_user_behavior_data"; | |||
| public static final String LIST_GROUP_CHAT_DATA = "/cgi-bin/externalcontact/groupchat/statistic"; | |||
| } | |||
| } | |||