diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpUserService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpUserService.java index 05211d71..9f931725 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpUserService.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpUserService.java @@ -1,11 +1,12 @@ package me.chanjar.weixin.cp.api; +import java.util.List; +import java.util.Map; + import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.cp.bean.WxCpInviteResult; import me.chanjar.weixin.cp.bean.WxCpUser; - -import java.util.List; -import java.util.Map; +import me.chanjar.weixin.cp.bean.WxCpUserExternalContactInfo; /** *
@@ -18,7 +19,7 @@ import java.util.Map;
 public interface WxCpUserService {
   /**
    * 
-   *   用在二次验证的时候
+   *   用在二次验证的时候.
    *   企业在员工验证成功后,调用本方法告诉企业号平台该员工关注成功。
    * 
* @@ -28,7 +29,7 @@ public interface WxCpUserService { /** *
-   * 获取部门成员(详情)
+   * 获取部门成员(详情).
    *
    * http://qydev.weixin.qq.com/wiki/index.php?title=管理成员#.E8.8E.B7.E5.8F.96.E9.83.A8.E9.97.A8.E6.88.90.E5.91.98.28.E8.AF.A6.E6.83.85.29
    * 
@@ -41,7 +42,7 @@ public interface WxCpUserService { /** *
-   * 获取部门成员
+   * 获取部门成员.
    *
    * http://qydev.weixin.qq.com/wiki/index.php?title=管理成员#.E8.8E.B7.E5.8F.96.E9.83.A8.E9.97.A8.E6.88.90.E5.91.98
    * 
@@ -53,14 +54,14 @@ public interface WxCpUserService { List listSimpleByDepartment(Integer departId, Boolean fetchChild, Integer status) throws WxErrorException; /** - * 新建用户 + * 新建用户. * * @param user 用户对象 */ void create(WxCpUser user) throws WxErrorException; /** - * 更新用户 + * 更新用户. * * @param user 用户对象 */ @@ -68,7 +69,7 @@ public interface WxCpUserService { /** *
-   * 删除用户/批量删除成员
+   * 删除用户/批量删除成员.
    * http://qydev.weixin.qq.com/wiki/index.php?title=管理成员#.E6.89.B9.E9.87.8F.E5.88.A0.E9.99.A4.E6.88.90.E5.91.98
    * 
* @@ -77,7 +78,7 @@ public interface WxCpUserService { void delete(String... userIds) throws WxErrorException; /** - * 获取用户 + * 获取用户. * * @param userid 用户id */ @@ -85,7 +86,7 @@ public interface WxCpUserService { /** *
-   * 邀请成员
+   * 邀请成员.
    * 企业可通过接口批量邀请成员使用企业微信,邀请后将通过短信或邮件下发通知。
    * 请求方式:POST(HTTPS)
    * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/batch/invite?access_token=ACCESS_TOKEN
@@ -113,14 +114,14 @@ public interface WxCpUserService {
    * @param userId  企业内的成员id
    * @param agentId 非必填,整型,仅用于发红包。其它场景该参数不要填,如微信支付、企业转账、电子发票
    * @return map对象,可能包含以下值:
-   * - openid	企业微信成员userid对应的openid,若有传参agentid,则是针对该agentid的openid。否则是针对企业微信corpid的openid
-   * - appid	应用的appid,若请求包中不包含agentid则不返回appid。该appid在使用微信红包时会用到
+   * - openid 企业微信成员userid对应的openid,若有传参agentid,则是针对该agentid的openid。否则是针对企业微信corpid的openid
+   * - appid 应用的appid,若请求包中不包含agentid则不返回appid。该appid在使用微信红包时会用到
    */
   Map userId2Openid(String userId, Integer agentId) throws WxErrorException;
 
   /**
    * 
-   * openid转userid
+   * openid转userid.
    *
    * 该接口主要应用于使用微信支付、微信红包和企业转账之后的结果查询。
    * 开发者需要知道某个结果事件的openid对应企业微信内成员的信息时,可以通过调用该接口进行转换查询。
@@ -134,4 +135,17 @@ public interface WxCpUserService {
    * @return userid 该openid在企业微信对应的成员userid
    */
   String openid2UserId(String openid) throws WxErrorException;
+
+  /**
+   * 获取外部联系人详情.
+   * 
+   *   企业可通过此接口,根据外部联系人的userid,拉取外部联系人详情。权限说明:
+   * 企业需要使用外部联系人管理secret所获取的accesstoken来调用
+   * 第三方应用需拥有“企业客户”权限。
+   * 第三方应用调用时,返回的跟进人follow_user仅包含应用可见范围之内的成员。
+   * 
+ * + * @param userId 外部联系人的userid + */ + WxCpUserExternalContactInfo getExternalContact(String userId) throws WxErrorException; } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImpl.java index e4baff52..68224b1e 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImpl.java @@ -1,18 +1,23 @@ package me.chanjar.weixin.cp.api.impl; +import java.util.List; +import java.util.Map; + import com.google.common.collect.Maps; -import com.google.gson.*; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.JsonPrimitive; import com.google.gson.reflect.TypeToken; import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.cp.api.WxCpService; import me.chanjar.weixin.cp.api.WxCpUserService; import me.chanjar.weixin.cp.bean.WxCpInviteResult; import me.chanjar.weixin.cp.bean.WxCpUser; +import me.chanjar.weixin.cp.bean.WxCpUserExternalContactInfo; import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; -import java.util.List; -import java.util.Map; - /** *
  *  Created by BinaryWang on 2017/6/24.
@@ -178,4 +183,11 @@ public class WxCpUserServiceImpl implements WxCpUserService {
     JsonElement tmpJsonElement = new JsonParser().parse(responseContent);
     return tmpJsonElement.getAsJsonObject().get("userid").getAsString();
   }
+
+  @Override
+  public WxCpUserExternalContactInfo getExternalContact(String userId) throws WxErrorException {
+    String url = "https://qyapi.weixin.qq.com/cgi-bin/crm/get_external_contact?external_userid=" + userId;
+    String responseContent = this.mainService.get(url, null);
+    return WxCpUserExternalContactInfo.fromJson(responseContent);
+  }
 }
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUser.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUser.java
index 85dfe298..f3d5aa22 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUser.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUser.java
@@ -39,9 +39,9 @@ public class WxCpUser implements Serializable {
   /**
    * 成员对外信息.
    */
-  private List externalAttrs = new ArrayList<>();
+  private List externalAttrs = new ArrayList<>();
 
-  public void addExternalAttr(ExternalAttr externalAttr) {
+  public void addExternalAttr(ExternalAttribute externalAttr) {
     this.externalAttrs.add(externalAttr);
   }
 
@@ -68,7 +68,7 @@ public class WxCpUser implements Serializable {
   @Builder
   @NoArgsConstructor
   @AllArgsConstructor
-  public static class ExternalAttr {
+  public static class ExternalAttribute {
     /**
      * 属性类型: 0-本文 1-网页 2-小程序.
      */
@@ -99,5 +99,4 @@ public class WxCpUser implements Serializable {
      */
     private String pagePath;
   }
-
 }
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUserExternalContactInfo.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUserExternalContactInfo.java
new file mode 100644
index 00000000..466eac4a
--- /dev/null
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUserExternalContactInfo.java
@@ -0,0 +1,126 @@
+package me.chanjar.weixin.cp.bean;
+
+import java.util.List;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
+
+/**
+ * 
+ * 外部联系人详情
+ * Created by Binary Wang on 2018/9/16.
+ * 参考文档:https://work.weixin.qq.com/api/doc#13878
+ * 
+ * + * @author Binary Wang + */ +@Getter +@Setter +public class WxCpUserExternalContactInfo { + @SerializedName("external_contact") + private ExternalContact externalContact; + + @SerializedName("follow_user") + private List followedUsers; + + @Getter + @Setter + public static class ExternalContact { + @SerializedName("external_userid") + private String externalUserId; + + @SerializedName("position") + private String position; + + @SerializedName("name") + private String name; + + @SerializedName("avatar") + private String avatar; + + @SerializedName("corp_name") + private String corpName; + + @SerializedName("corp_full_name") + private String corpFullName; + + @SerializedName("type") + private Integer type; + + @SerializedName("gender") + private Integer gender; + + @SerializedName("unionid") + private String unionId; + + @SerializedName("external_profile") + private ExternalProfile externalProfile; + } + + @Setter + @Getter + public static class ExternalProfile { + @SerializedName("external_attr") + private List externalAttrs; + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class ExternalAttribute { + @Setter + @Getter + public static class Text { + private String value; + } + + @Setter + @Getter + public static class Web { + private String title; + private String url; + } + + @Setter + @Getter + public static class MiniProgram { + @SerializedName("pagepath") + private String pagePath; + private String appid; + private String title; + } + + private int type; + + private String name; + + private Text text; + + private Web web; + + @SerializedName("miniprogram") + private MiniProgram miniProgram; + } + + @Setter + @Getter + public static class FollowedUser { + @SerializedName("userid") + private String userId; + private String remark; + private String description; + @SerializedName("createtime") + private Long createTime; + } + + public static WxCpUserExternalContactInfo fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpUserExternalContactInfo.class); + } +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/WxCpUserGsonAdapter.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/WxCpUserGsonAdapter.java index f04ce29b..1dc3f687 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/WxCpUserGsonAdapter.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/json/WxCpUserGsonAdapter.java @@ -82,7 +82,7 @@ public class WxCpUserGsonAdapter implements JsonDeserializer, JsonSeri switch (type) { case 0: { user.getExternalAttrs() - .add(WxCpUser.ExternalAttr.builder() + .add(WxCpUser.ExternalAttribute.builder() .type(type) .name(name) .value(GsonHelper.getString(element.getAsJsonObject().get("text").getAsJsonObject(), "value")) @@ -93,7 +93,7 @@ public class WxCpUserGsonAdapter implements JsonDeserializer, JsonSeri case 1: { final JsonObject web = element.getAsJsonObject().get("web").getAsJsonObject(); user.getExternalAttrs() - .add(WxCpUser.ExternalAttr.builder() + .add(WxCpUser.ExternalAttribute.builder() .type(type) .name(name) .url(GsonHelper.getString(web, "url")) @@ -105,7 +105,7 @@ public class WxCpUserGsonAdapter implements JsonDeserializer, JsonSeri case 2: { final JsonObject miniprogram = element.getAsJsonObject().get("miniprogram").getAsJsonObject(); user.getExternalAttrs() - .add(WxCpUser.ExternalAttr.builder() + .add(WxCpUser.ExternalAttribute.builder() .type(type) .name(name) .appid(GsonHelper.getString(miniprogram, "appid")) @@ -196,7 +196,7 @@ public class WxCpUserGsonAdapter implements JsonDeserializer, JsonSeri if (user.getExternalAttrs().size() > 0) { JsonArray attrsJsonArray = new JsonArray(); - for (WxCpUser.ExternalAttr attr : user.getExternalAttrs()) { + for (WxCpUser.ExternalAttribute attr : user.getExternalAttrs()) { JsonObject attrJson = new JsonObject(); attrJson.addProperty("type",attr.getType()); attrJson.addProperty("name", attr.getName()); 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 9babeb3f..6b671120 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 @@ -1,22 +1,23 @@ package me.chanjar.weixin.cp.api.impl; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import org.testng.annotations.*; + import com.google.common.collect.Lists; 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.Gender; import me.chanjar.weixin.cp.bean.WxCpInviteResult; import me.chanjar.weixin.cp.bean.WxCpUser; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; -import org.testng.annotations.Guice; -import org.testng.annotations.Test; +import me.chanjar.weixin.cp.bean.WxCpUserExternalContactInfo; -import java.util.List; -import java.util.Map; - -import static org.testng.Assert.assertNotEquals; -import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.*; /** *
@@ -109,4 +110,11 @@ public class WxCpUserServiceImplTest {
     System.out.println(result);
     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/WxCpUserExternalContactInfoTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpUserExternalContactInfoTest.java
new file mode 100644
index 00000000..3c1b327c
--- /dev/null
+++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpUserExternalContactInfoTest.java
@@ -0,0 +1,129 @@
+package me.chanjar.weixin.cp.bean;
+
+import java.util.List;
+
+import org.testng.annotations.*;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * 
+ *
+ * Created by Binary Wang on 2018/9/16.
+ * 
+ * + * @author Binary Wang + */ +public class WxCpUserExternalContactInfoTest { + + @Test + public void testFromJson() { + final String json = "{\n" + + " \"errcode\": 0,\n" + + " \"errmsg\": \"ok\",\n" + + " \"external_contact\": {\n" + + " \"external_userid\": \"woAJ2GCAAAXtWyujaWJHDDGi0mACH71w\",\n" + + " \"name\": \"李四\",\n" + + " \"position\": \"Mangaer\",\n" + + " \"avatar\": \"http://p.qlogo.cn/bizmail/IcsdgagqefergqerhewSdage/0\",\n" + + " \"corp_name\": \"腾讯\",\n" + + " \"corp_full_name\": \"腾讯科技有限公司\",\n" + + " \"type\": 2,\n" + + " \"gender\": 1,\n" + + " \"unionid\": \"ozynqsulJFCZ2z1aYeS8h-nuasdfR1\",\n" + + " \"external_profile\": {\n" + + " \"external_attr\": [\n" + + " {\n" + + " \"type\": 0,\n" + + " \"name\": \"文本名称\",\n" + + " \"text\": {\n" + + " \"value\": \"文本\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"type\": 1,\n" + + " \"name\": \"网页名称\",\n" + + " \"web\": {\n" + + " \"url\": \"http://www.test.com\",\n" + + " \"title\": \"标题\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"type\": 2,\n" + + " \"name\": \"测试app\",\n" + + " \"miniprogram\": {\n" + + " \"appid\": \"wx8bd80126147df384\",\n" + + " \"pagepath\": \"/index\",\n" + + " \"title\": \"my miniprogram\"\n" + + " }\n" + + " }\n" + + " ]\n" + + " }\n" + + " },\n" + + " \"follow_user\": [\n" + + " {\n" + + " \"userid\": \"rocky\",\n" + + " \"remark\": \"李部长\",\n" + + " \"description\": \"对接采购事物\",\n" + + " \"createtime\": 1525779812\n" + + " },\n" + + " {\n" + + " \"userid\": \"tommy\",\n" + + " \"remark\": \"李总\",\n" + + " \"description\": \"采购问题咨询\",\n" + + " \"createtime\": 1525881637\n" + + " }\n" + + " ]\n" + + "}"; + + final WxCpUserExternalContactInfo contactInfo = WxCpUserExternalContactInfo.fromJson(json); + assertThat(contactInfo).isNotNull(); + assertThat(contactInfo.getExternalContact()).isNotNull(); + + assertThat(contactInfo.getExternalContact().getExternalUserId()).isEqualTo("woAJ2GCAAAXtWyujaWJHDDGi0mACH71w"); + assertThat(contactInfo.getExternalContact().getPosition()).isEqualTo("Mangaer"); + assertThat(contactInfo.getExternalContact().getAvatar()).isEqualTo("http://p.qlogo.cn/bizmail/IcsdgagqefergqerhewSdage/0"); + assertThat(contactInfo.getExternalContact().getCorpName()).isEqualTo("腾讯"); + assertThat(contactInfo.getExternalContact().getCorpFullName()).isEqualTo("腾讯科技有限公司"); + assertThat(contactInfo.getExternalContact().getType()).isEqualTo(2); + assertThat(contactInfo.getExternalContact().getGender()).isEqualTo(1); + assertThat(contactInfo.getExternalContact().getUnionId()).isEqualTo("ozynqsulJFCZ2z1aYeS8h-nuasdfR1"); + assertThat(contactInfo.getExternalContact().getName()).isEqualTo("李四"); + + assertThat(contactInfo.getExternalContact().getExternalProfile()).isNotNull(); + + final List externalAttrs = contactInfo.getExternalContact().getExternalProfile().getExternalAttrs(); + assertThat(externalAttrs).isNotEmpty(); + + final WxCpUserExternalContactInfo.ExternalAttribute externalAttr1 = externalAttrs.get(0); + assertThat(externalAttr1.getType()).isEqualTo(0); + assertThat(externalAttr1.getName()).isEqualTo("文本名称"); + assertThat(externalAttr1.getText().getValue()).isEqualTo("文本"); + + final WxCpUserExternalContactInfo.ExternalAttribute externalAttr2 = externalAttrs.get(1); + assertThat(externalAttr2.getType()).isEqualTo(1); + assertThat(externalAttr2.getName()).isEqualTo("网页名称"); + assertThat(externalAttr2.getWeb().getUrl()).isEqualTo("http://www.test.com"); + assertThat(externalAttr2.getWeb().getTitle()).isEqualTo("标题"); + + final WxCpUserExternalContactInfo.ExternalAttribute externalAttr3 = externalAttrs.get(2); + assertThat(externalAttr3.getType()).isEqualTo(2); + assertThat(externalAttr3.getName()).isEqualTo("测试app"); + assertThat(externalAttr3.getMiniProgram().getAppid()).isEqualTo("wx8bd80126147df384"); + assertThat(externalAttr3.getMiniProgram().getPagePath()).isEqualTo("/index"); + assertThat(externalAttr3.getMiniProgram().getTitle()).isEqualTo("my miniprogram"); + + + List followedUsers = contactInfo.getFollowedUsers(); + assertThat(followedUsers).isNotEmpty(); + assertThat(followedUsers.get(0).getUserId()).isEqualTo("rocky"); + assertThat(followedUsers.get(0).getRemark()).isEqualTo("李部长"); + assertThat(followedUsers.get(0).getDescription()).isEqualTo("对接采购事物"); + assertThat(followedUsers.get(0).getCreateTime()).isEqualTo(1525779812); + + assertThat(followedUsers.get(1).getUserId()).isEqualTo("tommy"); + assertThat(followedUsers.get(1).getRemark()).isEqualTo("李总"); + assertThat(followedUsers.get(1).getDescription()).isEqualTo("采购问题咨询"); + assertThat(followedUsers.get(1).getCreateTime()).isEqualTo(1525881637); + } +} diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/util/json/WxCpUserGsonAdapterTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/util/json/WxCpUserGsonAdapterTest.java index 4f2c8ea0..ec553f75 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/util/json/WxCpUserGsonAdapterTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/util/json/WxCpUserGsonAdapterTest.java @@ -78,18 +78,18 @@ public class WxCpUserGsonAdapterTest { assertThat(user).isNotNull(); assertThat(user.getExternalAttrs()).isNotEmpty(); - final WxCpUser.ExternalAttr externalAttr1 = user.getExternalAttrs().get(0); + final WxCpUser.ExternalAttribute externalAttr1 = user.getExternalAttrs().get(0); assertThat(externalAttr1.getType()).isEqualTo(0); assertThat(externalAttr1.getName()).isEqualTo("文本名称"); assertThat(externalAttr1.getValue()).isEqualTo("文本"); - final WxCpUser.ExternalAttr externalAttr2 = user.getExternalAttrs().get(1); + final WxCpUser.ExternalAttribute externalAttr2 = user.getExternalAttrs().get(1); assertThat(externalAttr2.getType()).isEqualTo(1); assertThat(externalAttr2.getName()).isEqualTo("网页名称"); assertThat(externalAttr2.getUrl()).isEqualTo("http://www.test.com"); assertThat(externalAttr2.getTitle()).isEqualTo("标题"); - final WxCpUser.ExternalAttr externalAttr3 = user.getExternalAttrs().get(2); + final WxCpUser.ExternalAttribute externalAttr3 = user.getExternalAttrs().get(2); assertThat(externalAttr3.getType()).isEqualTo(2); assertThat(externalAttr3.getName()).isEqualTo("测试app"); assertThat(externalAttr3.getAppid()).isEqualTo("wx8bd80126147df384"); @@ -100,18 +100,18 @@ public class WxCpUserGsonAdapterTest { @Test public void testSerialize() { WxCpUser user = new WxCpUser(); - user.addExternalAttr(WxCpUser.ExternalAttr.builder() + user.addExternalAttr(WxCpUser.ExternalAttribute.builder() .type(0) .name("文本名称") .value("文本") .build()); - user.addExternalAttr(WxCpUser.ExternalAttr.builder() + user.addExternalAttr(WxCpUser.ExternalAttribute.builder() .type(1) .name("网页名称") .url("http://www.test.com") .title("标题") .build()); - user.addExternalAttr(WxCpUser.ExternalAttr.builder() + user.addExternalAttr(WxCpUser.ExternalAttribute.builder() .type(2) .name("测试app") .appid("wx8bd80126147df384")