Jelajahi Sumber

:new: #2013【企业微信】第三方应用开发增加标签管理的相关接口

Zhangq 4 tahun lalu
induk
melakukan
2869a086c0

+ 28 - 0
weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpTpTag.java

@@ -0,0 +1,28 @@
+package me.chanjar.weixin.cp.bean;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
+
+import java.io.Serializable;
+
+/**
+ *
+ * @author zhangq <zhangq002@gmail.com>
+ * @since 2021-02-14 16:15 16:15
+ */
+@Data
+public class WxCpTpTag implements Serializable {
+
+  private static final long serialVersionUID = 581740383760234134L;
+
+  @SerializedName("tagid")
+  private String tagId;
+
+  @SerializedName("tagname")
+  private String tagName;
+
+  public static WxCpTpTag deserialize(String json) {
+    return WxCpGsonBuilder.create().fromJson(json, WxCpTpTag.class);
+  }
+}

+ 16 - 0
weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpTpTagAddOrRemoveUsersResult.java

@@ -0,0 +1,16 @@
+package me.chanjar.weixin.cp.bean;
+
+import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
+
+/**
+ * 企业微信第三方开发-增加标签成员成员api响应体
+ * @author zhangq <zhangq002@gmail.com>
+ * @since 2021/2/14 16:44
+ */
+public class WxCpTpTagAddOrRemoveUsersResult extends WxCpTagAddOrRemoveUsersResult {
+  private static final long serialVersionUID = 3490401800490702052L;
+
+  public static WxCpTpTagAddOrRemoveUsersResult deserialize(String json) {
+    return WxCpGsonBuilder.create().fromJson(json, WxCpTpTagAddOrRemoveUsersResult.class);
+  }
+}

+ 17 - 0
weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpTpTagGetResult.java

@@ -0,0 +1,17 @@
+package me.chanjar.weixin.cp.bean;
+
+import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
+
+/**
+ * 获取标签成员接口响应体
+ * @author zhangq <zhangq002@gmail.com>
+ * @since 2021/2/14 16:28
+ */
+public class WxCpTpTagGetResult extends WxCpTagGetResult {
+  private static final long serialVersionUID = 9051748686315562400L;
+
+  public static WxCpTpTagGetResult deserialize(String json) {
+    return WxCpGsonBuilder.create().fromJson(json, WxCpTpTagGetResult.class);
+  }
+
+}

+ 28 - 0
weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpService.java

@@ -491,4 +491,32 @@ public interface WxCpTpService {
    */
   WxJsapiSignature createSuiteJsApiTicketSignature(String url, String authCorpId) throws WxErrorException;
 
+  /**
+   * 使套件accessToken缓存失效
+   */
+  void expireSuiteAccessToken();
+
+  /**
+   * 使机构accessToken缓存失效
+   * @param authCorpId 机构id
+   */
+  void expireAccessToken(String authCorpId);
+
+  /**
+   * 使机构jsapiticket缓存失效
+   * @param authCorpId 机构id
+   */
+  void expireAuthCorpJsApiTicket(String authCorpId);
+
+  /**
+   * 使应用jsapiticket失效
+   * @param authCorpId 机构id
+   */
+  void expireAuthSuiteJsApiTicket(String authCorpId);
+
+  /**
+   * 使供应商accessToken失效
+   */
+  void expireProviderToken();
+
 }

+ 90 - 0
weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpTagService.java

@@ -0,0 +1,90 @@
+package me.chanjar.weixin.cp.tp.service;
+
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.cp.bean.WxCpTpTag;
+import me.chanjar.weixin.cp.bean.WxCpTpTagAddOrRemoveUsersResult;
+import me.chanjar.weixin.cp.bean.WxCpTpTagGetResult;
+
+import java.util.List;
+
+/**
+ * <pre>
+ *   企业微信第三方开发-标签相关接口
+ * </pre>
+ *
+ * @author zhangq <zhangq002@gmail.com>
+ * @since 2021-02-14 16:02
+ */
+public interface WxCpTpTagService {
+  /**
+   * 创建标签.
+   * <pre>
+   * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/tag/create?access_token=ACCESS_TOKEN
+   * 文档地址:https://work.weixin.qq.com/api/doc/90001/90143/90346
+   * </pre>
+   *
+   * @param name 标签名称,长度限制为32个字以内(汉字或英文字母),标签名不可与其他标签重名。
+   * @param id   标签id,非负整型,指定此参数时新增的标签会生成对应的标签id,不指定时则以目前最大的id自增。
+   * @return 标签id
+   * @throws WxErrorException
+   */
+  String create(String name, Integer id) throws WxErrorException;
+
+  /**
+   * 更新标签.
+   *
+   * @param tagId   标签id
+   * @param tagName 标签名
+   * @throws WxErrorException .
+   */
+  void update(String tagId, String tagName) throws WxErrorException;
+
+  /**
+   * 删除标签.
+   *
+   * @param tagId 标签id
+   * @throws WxErrorException .
+   */
+  void delete(String tagId) throws WxErrorException;
+
+  /**
+   * 获取标签成员
+   * @param tagId
+   * @return
+   * @throws WxErrorException
+   */
+  WxCpTpTagGetResult get(String tagId) throws WxErrorException;
+
+  /**
+   * 增加标签成员.
+   *
+   * @param tagId    标签id
+   * @param userIds  用户ID 列表
+   * @param partyIds 企业部门ID列表
+   * @return .
+   * @throws WxErrorException .
+   */
+  WxCpTpTagAddOrRemoveUsersResult addUsers2Tag(String tagId, List<String> userIds, List<String> partyIds)
+    throws WxErrorException;
+
+  /**
+   * 移除标签成员.
+   *
+   * @param tagId    标签id
+   * @param userIds  用户id列表
+   * @param partyIds 企业部门ID列表
+   * @return .
+   * @throws WxErrorException .
+   */
+  WxCpTpTagAddOrRemoveUsersResult removeUsersFromTag(String tagId, List<String> userIds, List<String> partyIds)
+    throws WxErrorException;
+
+  /**
+   * 获得标签列表.
+   *
+   * @return 标签列表
+   * @throws WxErrorException .
+   */
+  List<WxCpTpTag> listAll() throws WxErrorException;
+
+}

+ 25 - 0
weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/BaseWxCpTpServiceImpl.java

@@ -548,6 +548,31 @@ public abstract class BaseWxCpTpServiceImpl<H, P> implements WxCpTpService, Requ
     return doCreateWxJsapiSignature(url, authCorpId, this.getSuiteJsApiTicket(authCorpId));
   }
 
+  @Override
+  public void expireSuiteAccessToken() {
+    this.configStorage.expireSuiteAccessToken();
+  }
+
+  @Override
+  public void expireAccessToken(String authCorpId) {
+    this.configStorage.expireAccessToken(authCorpId);
+  }
+
+  @Override
+  public void expireAuthCorpJsApiTicket(String authCorpId) {
+    this.configStorage.expireAuthCorpJsApiTicket(authCorpId);
+  }
+
+  @Override
+  public void expireAuthSuiteJsApiTicket(String authCorpId) {
+    this.configStorage.expireAuthSuiteJsApiTicket(authCorpId);
+  }
+
+  @Override
+  public void expireProviderToken() {
+    this.configStorage.expireProviderToken();
+  }
+
   private WxJsapiSignature doCreateWxJsapiSignature(String url, String authCorpId, String jsapiTicket) {
     long timestamp = System.currentTimeMillis() / 1000;
     String noncestr = RandomUtils.getRandomStr();

+ 132 - 0
weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpTagServiceImpl.java

@@ -0,0 +1,132 @@
+package me.chanjar.weixin.cp.tp.service.impl;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.reflect.TypeToken;
+import lombok.RequiredArgsConstructor;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.util.json.GsonParser;
+import me.chanjar.weixin.cp.bean.WxCpTpTag;
+import me.chanjar.weixin.cp.bean.WxCpTpTagAddOrRemoveUsersResult;
+import me.chanjar.weixin.cp.bean.WxCpTpTagGetResult;
+import me.chanjar.weixin.cp.config.WxCpTpConfigStorage;
+import me.chanjar.weixin.cp.tp.service.WxCpTpService;
+import me.chanjar.weixin.cp.tp.service.WxCpTpTagService;
+import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
+
+import java.util.List;
+
+import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Tag.*;
+
+/**
+ * <pre>
+ *   企业微信第三方开发-标签相关接口,部分照搬了WxCpTagServiceImpl
+ * </pre>
+ *
+ * @author zhangq <zhangq002@gmail.com>
+ * @since 2021-02-14 16:02
+ */
+@RequiredArgsConstructor
+public class WxCpTpTagServiceImpl implements WxCpTpTagService {
+  private final WxCpTpService mainService;
+
+  @Override
+  public String create(String name, Integer id) throws WxErrorException {
+    JsonObject o = new JsonObject();
+    o.addProperty("tagname", name);
+
+    if (id != null) {
+      o.addProperty("tagid", id);
+    }
+    return this.create(o);
+  }
+
+  private String create(JsonObject param) throws WxErrorException {
+    String url = getWxCpTpConfigStorage().getApiUrl(TAG_CREATE);
+    String responseContent = this.mainService.post(url, param.toString());
+    JsonObject jsonObject = GsonParser.parse(responseContent);
+    return jsonObject.get("tagid").getAsString();
+  }
+
+  @Override
+  public void update(String tagId, String tagName) throws WxErrorException {
+    String url = getWxCpTpConfigStorage().getApiUrl(TAG_UPDATE);
+    JsonObject o = new JsonObject();
+    o.addProperty("tagid", tagId);
+    o.addProperty("tagname", tagName);
+    this.mainService.post(url, o.toString());
+  }
+
+  @Override
+  public void delete(String tagId) throws WxErrorException {
+    String url = String.format(getWxCpTpConfigStorage().getApiUrl(TAG_DELETE), tagId);
+    this.mainService.get(url, null);
+  }
+
+  @Override
+  public List<WxCpTpTag> listAll() throws WxErrorException {
+    String url = getWxCpTpConfigStorage().getApiUrl(TAG_LIST);
+    String responseContent = this.mainService.get(url, null);
+    JsonObject tmpJson = GsonParser.parse(responseContent);
+    return WxCpGsonBuilder.create().fromJson(tmpJson.get("taglist"), new TypeToken<List<WxCpTpTag>>() {
+      // do nothing
+    }.getType());
+  }
+
+  @Override
+  public WxCpTpTagGetResult get(String tagId) throws WxErrorException {
+    if (tagId == null) {
+      throw new IllegalArgumentException("缺少tagId参数");
+    }
+
+    String url = String.format(getWxCpTpConfigStorage().getApiUrl(TAG_GET), tagId);
+    String responseContent = this.mainService.get(url, null);
+    return WxCpTpTagGetResult.deserialize(responseContent);
+  }
+
+  @Override
+  public WxCpTpTagAddOrRemoveUsersResult addUsers2Tag(String tagId, List<String> userIds, List<String> partyIds)
+    throws WxErrorException {
+    String url = getWxCpTpConfigStorage().getApiUrl(TAG_ADD_TAG_USERS);
+    JsonObject jsonObject = new JsonObject();
+    jsonObject.addProperty("tagid", tagId);
+    this.addUserIdsAndPartyIdsToJson(userIds, partyIds, jsonObject);
+
+    return WxCpTpTagAddOrRemoveUsersResult.deserialize(this.mainService.post(url, jsonObject.toString()));
+  }
+
+  @Override
+  public WxCpTpTagAddOrRemoveUsersResult removeUsersFromTag(String tagId, List<String> userIds, List<String> partyIds)
+    throws WxErrorException {
+    String url = getWxCpTpConfigStorage().getApiUrl(TAG_DEL_TAG_USERS);
+    JsonObject jsonObject = new JsonObject();
+    jsonObject.addProperty("tagid", tagId);
+    this.addUserIdsAndPartyIdsToJson(userIds, partyIds, jsonObject);
+
+    return WxCpTpTagAddOrRemoveUsersResult.deserialize(this.mainService.post(url, jsonObject.toString()));
+  }
+
+  private void addUserIdsAndPartyIdsToJson(List<String> userIds, List<String> partyIds, JsonObject jsonObject) {
+    if (userIds != null) {
+      JsonArray jsonArray = new JsonArray();
+      for (String userId : userIds) {
+        jsonArray.add(new JsonPrimitive(userId));
+      }
+      jsonObject.add("userlist", jsonArray);
+    }
+
+    if (partyIds != null) {
+      JsonArray jsonArray = new JsonArray();
+      for (String userId : partyIds) {
+        jsonArray.add(new JsonPrimitive(userId));
+      }
+      jsonObject.add("partylist", jsonArray);
+    }
+  }
+
+  @SuppressWarnings("deprecation")
+  private WxCpTpConfigStorage getWxCpTpConfigStorage() {
+    return this.mainService.getWxCpTpConfigStorage();
+  }
+}

+ 147 - 0
weixin-java-cp/src/test/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpTagServiceImplTest.java

@@ -0,0 +1,147 @@
+package me.chanjar.weixin.cp.tp.service.impl;
+
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.cp.bean.WxCpTpTag;
+import me.chanjar.weixin.cp.bean.WxCpTpTagAddOrRemoveUsersResult;
+import me.chanjar.weixin.cp.bean.WxCpTpTagGetResult;
+import me.chanjar.weixin.cp.config.WxCpTpConfigStorage;
+import me.chanjar.weixin.cp.config.impl.WxCpTpDefaultConfigImpl;
+import me.chanjar.weixin.cp.tp.service.WxCpTpTagService;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.testng.collections.CollectionUtils;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Tag.*;
+import static org.mockito.Matchers.*;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.*;
+
+/**
+ * 企业微信-第三方开发-标签管理相关测试
+ *
+ * @author zhangq
+ * @since 2021/2/15 9:14
+ */
+public class WxCpTpTagServiceImplTest {
+
+  @Mock
+  private WxCpTpServiceImpl wxCpTpService;
+
+  private WxCpTpConfigStorage configStorage;
+
+  private WxCpTpTagService wxCpTpTagService;
+
+  @BeforeClass
+  public void setUp() {
+    MockitoAnnotations.initMocks(this);
+    configStorage = new WxCpTpDefaultConfigImpl();
+    when(wxCpTpService.getWxCpTpConfigStorage()).thenReturn(configStorage);
+    wxCpTpTagService = new WxCpTpTagServiceImpl(wxCpTpService);
+  }
+
+  @Test
+  public void testCreate() throws WxErrorException {
+    String url = configStorage.getApiUrl(TAG_CREATE);
+    String tagName = "test_tag_name";
+    int tagId = 12;
+    String result = "{\"errcode\":0,\"errmsg\":\"created\",\"tagid\":12}";
+    when(wxCpTpService.post(eq(url), any(String.class))).thenReturn(result);
+
+    assertEquals(wxCpTpTagService.create(tagName, tagId), String.valueOf(tagId));
+  }
+
+  @Test
+  public void testListAll() throws WxErrorException {
+    String url = configStorage.getApiUrl(TAG_LIST);
+    String result = "{\"errcode\":0,\"errmsg\":\"ok\",\"taglist\":[{\"tagid\":1,\"tagname\":\"a\"},{\"tagid\":2,\"tagname\":\"b\"}]}";
+    when(wxCpTpService.get(eq(url), anyString())).thenReturn(result);
+
+    List<WxCpTpTag> wxCpTpTags = wxCpTpTagService.listAll();
+    assertNotNull(wxCpTpTags);
+    assertTrue(CollectionUtils.hasElements(wxCpTpTags));
+    assertEquals(wxCpTpTags.get(0).getTagId(), "1");
+    assertEquals(wxCpTpTags.get(1).getTagName(), "b");
+  }
+
+  @Test
+  public void testGet() throws WxErrorException {
+    String tagId = "anyTagId";
+    String url = String.format(configStorage.getApiUrl(TAG_GET), tagId);
+    String result = "{\"errcode\":0,\"errmsg\":\"ok\",\"tagname\":\"乒乓球协会\",\"userlist\":[{\"userid\":\"zhangsan\",\"name\":\"李四\"}],\"partylist\":[2]}";
+    when(wxCpTpService.get(eq(url), anyString())).thenReturn(result);
+
+    WxCpTpTagGetResult getResult = wxCpTpTagService.get(tagId);
+    assertEquals(getResult.getTagname(), "乒乓球协会");
+    assertEquals((int) getResult.getPartylist().get(0), 2);
+    assertEquals(getResult.getUserlist().get(0).getUserId(), "zhangsan");
+  }
+
+  @Test
+  public void testAddUsers2Tag() throws WxErrorException {
+    String tagId = "anyTagId";
+    String url = configStorage.getApiUrl(TAG_ADD_TAG_USERS);
+    // 成功时返回对象
+    String success = "{\"errcode\":0,\"errmsg\":\"ok\"}";
+    when(wxCpTpService.post(eq(url), anyString())).thenReturn(success);
+    WxCpTpTagAddOrRemoveUsersResult postResult = wxCpTpTagService
+      .addUsers2Tag(tagId, Arrays.asList("usr1", "usr2"), Arrays.asList("dept1", "dept2"));
+    assertEquals((int) postResult.getErrCode(), 0);
+    assertNull(postResult.getInvalidParty());
+    assertNull(postResult.getInvalidUsers());
+
+    // 部分失败时返回对象
+    String partFailure = "{\"errcode\":0,\"errmsg\":\"ok\",\"invalidlist\":\"usr1|usr2\",\"invalidparty\":[2,3,4]}";
+    when(wxCpTpService.post(eq(url), anyString())).thenReturn(partFailure);
+    postResult = wxCpTpTagService.addUsers2Tag(tagId, Arrays.asList("usr1", "usr2"), Arrays.asList("dept1", "dept2"));
+    assertEquals((int) postResult.getErrCode(), 0);
+    assertEquals(postResult.getInvalidUserList().size(), 2);
+    assertEquals(postResult.getInvalidUserList().get(1), "usr2");
+    assertEquals(postResult.getInvalidParty().length, 3);
+    assertEquals(postResult.getInvalidParty()[1], "3");
+
+    // 全部失败时返回对象
+    String allFailure = "{\"errcode\":40070,\"errmsg\":\"all list invalid \"}";
+    when(wxCpTpService.post(eq(url), anyString())).thenReturn(allFailure);
+    postResult = wxCpTpTagService.addUsers2Tag(tagId, Arrays.asList("usr1", "usr2"), Arrays.asList("dept1", "dept2"));
+    assertEquals((int) postResult.getErrCode(), 40070);
+    assertNull(postResult.getInvalidParty());
+    assertNull(postResult.getInvalidUsers());
+  }
+
+  @Test
+  public void testRemoveUsersFromTag() throws WxErrorException {
+    String tagId = "anyTagId";
+    String url = configStorage.getApiUrl(TAG_DEL_TAG_USERS);
+    // 成功时返回对象
+    String success = "{\"errcode\":0,\"errmsg\":\"ok\"}";
+    when(wxCpTpService.post(eq(url), anyString())).thenReturn(success);
+    WxCpTpTagAddOrRemoveUsersResult postResult = wxCpTpTagService
+      .removeUsersFromTag(tagId, Arrays.asList("usr1", "usr2"), Arrays.asList("dept1", "dept2"));
+    assertEquals((int) postResult.getErrCode(), 0);
+    assertNull(postResult.getInvalidParty());
+    assertNull(postResult.getInvalidUsers());
+
+    // 部分失败时返回对象
+    String partFailure = "{\"errcode\":0,\"errmsg\":\"ok\",\"invalidlist\":\"usr1|usr2\",\"invalidparty\":[2,3,4]}";
+    when(wxCpTpService.post(eq(url), anyString())).thenReturn(partFailure);
+    postResult = wxCpTpTagService.removeUsersFromTag(tagId, Arrays.asList("usr1", "usr2"), Arrays.asList("dept1", "dept2"));
+    assertEquals((int) postResult.getErrCode(), 0);
+    assertEquals(postResult.getInvalidUserList().size(), 2);
+    assertEquals(postResult.getInvalidUserList().get(1), "usr2");
+    assertEquals(postResult.getInvalidParty().length, 3);
+    assertEquals(postResult.getInvalidParty()[1], "3");
+
+    // 全部失败时返回对象
+    String allFailure = "{\"errcode\":40070,\"errmsg\":\"all list invalid \"}";
+    when(wxCpTpService.post(eq(url), anyString())).thenReturn(allFailure);
+    postResult = wxCpTpTagService.removeUsersFromTag(tagId, Arrays.asList("usr1", "usr2"), Arrays.asList("dept1", "dept2"));
+    assertEquals((int) postResult.getErrCode(), 40070);
+    assertNull(postResult.getInvalidParty());
+    assertNull(postResult.getInvalidUsers());
+  }
+}

+ 1 - 0
weixin-java-cp/src/test/resources/testng.xml

@@ -8,6 +8,7 @@
       <class name="me.chanjar.weixin.cp.api.WxCpMessageRouterTest"/>
       <class name="me.chanjar.weixin.cp.tp.service.impl.WxCpTpServiceImplTest"/>
       <class name="me.chanjar.weixin.cp.config.impl.WxCpTpDefaultConfigImplTest"/>
+        <class name="me.chanjar.weixin.cp.tp.service.impl.WxCpTpTagServiceImplTest"/>
     </classes>
   </test>