diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpExternalContactService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpExternalContactService.java new file mode 100644 index 000000000..92f225869 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpExternalContactService.java @@ -0,0 +1,58 @@ +package me.chanjar.weixin.cp.api; + +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.bean.WxCpUserExternalContactInfo; + +import java.util.List; + +/** + *
+ * 外部联系人管理接口,企业微信的外部联系人的接口和通讯录接口已经拆离 + * Created by Joe Cao on 2019/6/14 + *+ * + * @author JoeCao + */ +public interface WxCpExternalContactService { + /** + * 获取外部联系人详情. + *
+ * 企业可通过此接口,根据外部联系人的userid,拉取外部联系人详情。权限说明: + * 企业需要使用外部联系人管理secret所获取的accesstoken来调用 + * 第三方应用需拥有“企业客户”权限。 + * 第三方应用调用时,返回的跟进人follow_user仅包含应用可见范围之内的成员。 + *+ * + * @param userId 外部联系人的userid + */ + WxCpUserExternalContactInfo getExternalContact(String userId) throws WxErrorException; + + /** + * 获取外部联系人列表. + *
+ * 企业可通过此接口获取指定成员添加的客户列表。 + * 客户是指配置了客户联系功能的成员所添加的外部联系人。 + * 没有配置客户联系功能的成员,所添加的外部联系人将不会作为客户返回。 + * 第三方应用需拥有“企业客户”权限。 + * 第三方应用调用时,返回的跟进人follow_user仅包含应用可见范围之内的成员。 + *+ * + * @param userId 外部联系人的userid + * @return List of External wx id + */ + List
+ * 企业需要使用外部联系人管理secret所获取的accesstoken来调用(accesstoken如何获取?); + * 第三方应用需拥有“企业客户”权限。 + * 第三方应用只能获取到可见范围内的配置了客户联系功能的成员 + *+ * + * @return List of CpUser id + */ + List
* 外部联系人详情
@@ -118,9 +113,26 @@ public class WxCpUserExternalContactInfo {
private String description;
@SerializedName("createtime")
private Long createTime;
+ private String state;
+ @SerializedName("remark_company")
+ private String remarkCompany;
+ @SerializedName("remark_mobiles")
+ private String[] remarkMobiles;
+ private Tag[] tags;
+
}
public static WxCpUserExternalContactInfo fromJson(String json) {
return WxCpGsonBuilder.create().fromJson(json, WxCpUserExternalContactInfo.class);
}
+
+ @Setter
+ @Getter
+ public static class Tag {
+ @SerializedName("group_name")
+ private String groupName;
+ @SerializedName("tag_name")
+ private String tagName;
+ private int type;
+ }
}
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUserExternalContactList.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUserExternalContactList.java
new file mode 100644
index 000000000..25e42ffc4
--- /dev/null
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUserExternalContactList.java
@@ -0,0 +1,58 @@
+package me.chanjar.weixin.cp.bean;
+
+import com.google.gson.annotations.Expose;
+import com.google.gson.annotations.SerializedName;
+import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
+
+import java.util.List;
+
+/**
+ *
+ * 外部联系人列表
+ * Created by Joe Cao on 2019/6/16.
+ * 参考文档:https://work.weixin.qq.com/api/doc#90001/90143/91570
+ *
+ *
+ * @author Joe Cao
+ */
+public class WxCpUserExternalContactList {
+ @SerializedName("errcode")
+ @Expose
+ private Long errcode;
+ @SerializedName("errmsg")
+ @Expose
+ private String errmsg;
+
+ @SerializedName("external_userid")
+ @Expose
+ private List externalUserId = null;
+
+ public Long getErrcode() {
+ return errcode;
+ }
+
+ public void setErrcode(Long errcode) {
+ this.errcode = errcode;
+ }
+
+ public String getErrmsg() {
+ return errmsg;
+ }
+
+ public void setErrmsg(String errmsg) {
+ this.errmsg = errmsg;
+ }
+
+
+ public List getExternalUserId() {
+ return externalUserId;
+ }
+
+ public void setExternalUserId(List externalUserId) {
+ this.externalUserId = externalUserId;
+ }
+
+ public static WxCpUserExternalContactList fromJson(String json) {
+ return WxCpGsonBuilder.create().fromJson(json, WxCpUserExternalContactList.class);
+ }
+}
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUserWithExternalPermission.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUserWithExternalPermission.java
new file mode 100644
index 000000000..2530c79dc
--- /dev/null
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUserWithExternalPermission.java
@@ -0,0 +1,49 @@
+package me.chanjar.weixin.cp.bean;
+
+import com.google.gson.annotations.Expose;
+import com.google.gson.annotations.SerializedName;
+import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
+
+import java.util.List;
+
+public class WxCpUserWithExternalPermission {
+ @SerializedName("errcode")
+ @Expose
+ private Long errcode;
+ @SerializedName("errmsg")
+ @Expose
+ private String errmsg;
+
+ @SerializedName("follow_user")
+ @Expose
+ private List followUser = null;
+
+ public Long getErrcode() {
+ return errcode;
+ }
+
+ public void setErrcode(Long errcode) {
+ this.errcode = errcode;
+ }
+
+ public String getErrmsg() {
+ return errmsg;
+ }
+
+ public void setErrmsg(String errmsg) {
+ this.errmsg = errmsg;
+ }
+
+ public List getFollowUser() {
+ return followUser;
+ }
+
+ public void setFollowUser(List followUser) {
+ this.followUser = followUser;
+ }
+
+
+ public static WxCpUserWithExternalPermission fromJson(String json) {
+ return WxCpGsonBuilder.create().fromJson(json, WxCpUserWithExternalPermission.class);
+ }
+}
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlMessage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlMessage.java
index 72f63b5dd..c201af5cb 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlMessage.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlMessage.java
@@ -175,6 +175,26 @@ public class WxCpXmlMessage implements Serializable {
@XStreamConverter(value = XStreamCDataConverter.class)
private String userId;
+ /**
+ * 变更信息的外部联系人的userid,注意不是企业成员的帐号.
+ */
+ @XStreamAlias("ExternalUserID")
+ @XStreamConverter(value = XStreamCDataConverter.class)
+ private String externalUserID;
+
+ /**
+ * 添加此用户的「联系我」方式配置的state参数,可用于识别添加此用户的渠道
+ */
+ @XStreamAlias("State")
+ @XStreamConverter(value = XStreamCDataConverter.class)
+ private String state;
+
+ /**
+ * 欢迎语code,可用于发送欢迎语
+ */
+ @XStreamAlias("WelcomeCode")
+ @XStreamConverter(value = XStreamCDataConverter.class)
+ private String welcomeCode;
/**
* 新的UserID,变更时推送(userid由系统生成时可更改一次).
*/
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java
index 9e1294db5..61c3459f0 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java
@@ -103,4 +103,10 @@ public final class WxCpApiPathConsts {
public static final String USER_CONVERT_TO_USERID = "/cgi-bin/user/convert_to_userid";
public static final String GET_EXTERNAL_CONTACT = "/cgi-bin/crm/get_external_contact?external_userid=";
}
+
+ public static class ExternalContact {
+ public static final String GET_EXTERNAL_CONTACT = "/cgi-bin/crm/get_external_contact?external_userid=";
+ public static final String LIST_EXTERNAL_CONTACT = "/cgi-bin/externalcontact/list?userid=";
+ public static final String GET_FOLLOW_USER_LIST = "/cgi-bin/externalcontact/get_follow_user_list";
+ }
}
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpConsts.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpConsts.java
index b3809ad0c..aa4eded45 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpConsts.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpConsts.java
@@ -89,6 +89,26 @@ public class WxCpConsts {
*/
public static final String TASKCARD_CLICK = "taskcard_click";
+ /**
+ * 企业成员添加外部联系人事件推送
+ */
+ public static final String CHANGE_EXTERNAL_CONTACT = "change_external_contact";
+
+
+ }
+
+ /**
+ * 企业外部联系人变更事件的CHANGE_TYPE
+ */
+ public static class ExternalContactChangeType {
+ /**
+ * 新增外部联系人
+ */
+ public static final String ADD_EXTERNAL_CONTACT = "add_external_contact";
+ /**
+ * 删除外部联系人
+ */
+ public static final String DEL_EXTERNAL_CONTACT = "del_external_contact";
}
/**
diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/ApiTestModule.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/ApiTestModule.java
index c87b6455a..5ef750f89 100644
--- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/ApiTestModule.java
+++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/ApiTestModule.java
@@ -52,6 +52,8 @@ public class ApiTestModule implements Module {
protected String tagId;
+ protected String externalUserId;
+
public String getUserId() {
return this.userId;
}
@@ -76,12 +78,22 @@ public class ApiTestModule implements Module {
this.tagId = tagId;
}
+ public String getExternalUserId() {
+ return externalUserId;
+ }
+
+ public void setExternalUserId(String externalUserId) {
+ this.externalUserId = externalUserId;
+ }
+
@Override
public String toString() {
return super.toString() + " > WxXmlCpConfigStorage{" +
"userId='" + this.userId + '\'' +
", departmentId='" + this.departmentId + '\'' +
", tagId='" + this.tagId + '\'' +
+ ", externalUserId='" + this.externalUserId + '\'' +
+
'}';
}
}
diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpExternalContactServiceImplTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpExternalContactServiceImplTest.java
new file mode 100644
index 000000000..d39fd6e49
--- /dev/null
+++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpExternalContactServiceImplTest.java
@@ -0,0 +1,45 @@
+package me.chanjar.weixin.cp.api.impl;
+
+import com.google.inject.Inject;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.cp.api.ApiTestModule;
+import me.chanjar.weixin.cp.api.WxCpService;
+import me.chanjar.weixin.cp.bean.WxCpUserExternalContactInfo;
+import org.testng.annotations.Guice;
+import org.testng.annotations.Test;
+
+import java.util.List;
+
+import static org.testng.Assert.assertNotNull;
+
+@Guice(modules = ApiTestModule.class)
+public class WxCpExternalContactServiceImplTest {
+ @Inject
+ private WxCpService wxCpService;
+ @Inject
+ protected ApiTestModule.WxXmlCpInMemoryConfigStorage configStorage;
+ private String userId = "someone" + System.currentTimeMillis();
+
+ @Test
+ public void testGetExternalContact() throws WxErrorException {
+ String externalUserId = this.configStorage.getExternalUserId();
+ WxCpUserExternalContactInfo result = this.wxCpService.getExternalContactService().getExternalContact(externalUserId);
+ System.out.println(result);
+ assertNotNull(result);
+ }
+
+ @Test
+ public void testListExternalContacts() throws WxErrorException {
+ String userId = this.configStorage.getUserId();
+ List ret = this.wxCpService.getExternalContactService().listExternalContacts(userId);
+ System.out.println(ret);
+ assertNotNull(ret);
+ }
+
+ @Test
+ public void testListExternalWithPermission() throws WxErrorException {
+ List ret = this.wxCpService.getExternalContactService().listFollowUser();
+ System.out.println(ret);
+ assertNotNull(ret);
+ }
+}
diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImplTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImplTest.java
index 2ec33e7ba..6b88876fb 100644
--- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImplTest.java
+++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImplTest.java
@@ -93,7 +93,7 @@ public class WxCpUserServiceImplTest {
@Test
public void testInvite() throws Exception {
WxCpInviteResult result = this.wxCpService.getUserService().invite(
- Lists.newArrayList(userId), null,null);
+ Lists.newArrayList(userId), null, null);
System.out.println(result);
}
@@ -111,10 +111,5 @@ public class WxCpUserServiceImplTest {
assertNotNull(result);
}
- @Test
- public void testGetExternalContact() throws WxErrorException {
- WxCpUserExternalContactInfo result = this.wxCpService.getUserService().getExternalContact(userId);
- System.out.println(result);
- assertNotNull(result);
- }
+
}
diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlMessageTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlMessageTest.java
index 11a2dbe46..ad9a04b61 100644
--- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlMessageTest.java
+++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlMessageTest.java
@@ -1,6 +1,7 @@
package me.chanjar.weixin.cp.bean;
import me.chanjar.weixin.common.api.WxConsts;
+import me.chanjar.weixin.cp.constant.WxCpConsts;
import org.testng.annotations.Test;
import static me.chanjar.weixin.cp.constant.WxCpConsts.EventType.TASKCARD_CLICK;
@@ -106,7 +107,7 @@ public class WxCpXmlMessageTest {
"2 " +
"" +
"";
- WxCpXmlMessage wxMessage = WxCpXmlMessage.fromXml(xml.replace("",""));
+ WxCpXmlMessage wxMessage = WxCpXmlMessage.fromXml(xml.replace(" ", ""));
assertEquals(wxMessage.getToUserName(), "wx45a0972125658be9");
assertEquals(wxMessage.getFromUserName(), "xiaohe");
assertEquals(wxMessage.getCreateTime(), new Long(1502012364L));
@@ -173,4 +174,52 @@ public class WxCpXmlMessageTest {
assertEquals(wxMessage.getEventKey(), "key111");
assertEquals(wxMessage.getTaskId(), "taskid111");
}
+
+ public void testAddExternalUserEvent() {
+ String xml = "" +
+ " " +
+ " " +
+ "1403610513 " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " ";
+ WxCpXmlMessage wxMessage = WxCpXmlMessage.fromXml(xml);
+ assertEquals(wxMessage.getToUserName(), "toUser");
+ assertEquals(wxMessage.getFromUserName(), "sys");
+ assertEquals(wxMessage.getCreateTime(), Long.valueOf(1403610513L));
+ assertEquals(wxMessage.getMsgType(), WxConsts.XmlMsgType.EVENT);
+ assertEquals(wxMessage.getEvent(), WxCpConsts.EventType.CHANGE_EXTERNAL_CONTACT);
+ assertEquals(wxMessage.getChangeType(), WxCpConsts.ExternalContactChangeType.ADD_EXTERNAL_CONTACT);
+ assertEquals(wxMessage.getExternalUserID(), "woAJ2GCAAAXtWyujaWJHDDGi0mACH71w");
+ assertEquals(wxMessage.getState(), "teststate");
+ assertEquals(wxMessage.getWelcomeCode(), "WELCOMECODE");
+
+ }
+
+ public void testDelExternalUserEvent() {
+ String xml = "" +
+ " " +
+ " " +
+ "1403610513 " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " ";
+ WxCpXmlMessage wxMessage = WxCpXmlMessage.fromXml(xml);
+ assertEquals(wxMessage.getToUserName(), "toUser");
+ assertEquals(wxMessage.getFromUserName(), "sys");
+ assertEquals(wxMessage.getCreateTime(), Long.valueOf(1403610513L));
+ assertEquals(wxMessage.getMsgType(), WxConsts.XmlMsgType.EVENT);
+ assertEquals(wxMessage.getEvent(), WxCpConsts.EventType.CHANGE_EXTERNAL_CONTACT);
+ assertEquals(wxMessage.getChangeType(), WxCpConsts.ExternalContactChangeType.DEL_EXTERNAL_CONTACT);
+ assertEquals(wxMessage.getUserId(), "zhangsan");
+ assertEquals(wxMessage.getExternalUserID(), "woAJ2GCAAAXtWyujaWJHDDGi0mACH71w");
+ }
}