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

This commit is contained in:
Zhangq 2021-02-26 09:31:44 +08:00 committed by GitHub
parent 367bf4ee9f
commit 2869a086c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 484 additions and 0 deletions

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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();

View File

@ -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();
}
}

View File

@ -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());
}
}

View File

@ -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>