diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpUserService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpUserService.java index 0f2fc5dd9..1359fa66e 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpUserService.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpUserService.java @@ -53,9 +53,29 @@ public interface WxCpTpUserService { * @param departId 必填。部门id * @param fetchChild 非必填。1/0:是否递归获取子部门下面的成员 * @param status 非必填。0获取全部员工,1获取已关注成员列表,2获取禁用成员列表,4获取未关注成员列表。status可叠加 + * @param corpId 企业id * @return the list * @throws WxErrorException the wx error exception */ + List listSimpleByDepartment(Long departId, Boolean fetchChild, Integer status, String corpId) + throws WxErrorException; + + /** + *
+   * 获取部门成员.
+   *
+   * 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
+   * 
+ * + * @param departId 必填。部门id + * @param fetchChild 非必填。1/0:是否递归获取子部门下面的成员 + * @param status 非必填。0获取全部员工,1获取已关注成员列表,2获取禁用成员列表,4获取未关注成员列表。status可叠加 + * @return the list + * @throws WxErrorException the wx error exception + * @deprecated 第三方应用调用此接口需要使用 corpId 对应的 access_token,请使用 + * {@link #listSimpleByDepartment(Long, Boolean, Integer, String)} + */ + @Deprecated List listSimpleByDepartment(Long departId, Boolean fetchChild, Integer status) throws WxErrorException; /** diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpUserServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpUserServiceImpl.java index d99262746..f3d41e3ff 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpUserServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpUserServiceImpl.java @@ -97,6 +97,42 @@ public List listByDepartment(Long departId, Boolean fetchChild, Intege } @Override + public List listSimpleByDepartment(Long departId, Boolean fetchChild, Integer status, String corpId) + throws WxErrorException { + StringBuilder params = new StringBuilder(); + if (fetchChild != null) { + params.append("fetch_child=").append(fetchChild ? "1" : "0"); + } + if (status != null) { + if (params.length() > 0) { + params.append('&'); + } + params.append("status=").append(status); + } else { + if (params.length() > 0) { + params.append('&'); + } + params.append("status=0"); + } + if (params.length() > 0) { + params.append('&'); + } + params.append("access_token=") + .append(mainService.getWxCpTpConfigStorage().getAccessToken(corpId)); + + String url = mainService.getWxCpTpConfigStorage().getApiUrl(USER_SIMPLE_LIST + departId); + String responseContent = this.mainService.get(url, params.toString(), true); + JsonObject tmpJsonElement = GsonParser.parse(responseContent); + return WxCpGsonBuilder.create() + .fromJson( + tmpJsonElement.getAsJsonObject().get("userlist"), + new TypeToken>() { + }.getType() + ); + } + + @Override + @Deprecated public List listSimpleByDepartment(Long departId, Boolean fetchChild, Integer status) throws WxErrorException { String params = ""; diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpUserServiceImplTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpUserServiceImplTest.java new file mode 100644 index 000000000..1cfc7f349 --- /dev/null +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpUserServiceImplTest.java @@ -0,0 +1,85 @@ +package me.chanjar.weixin.cp.tp.service.impl; + +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.bean.WxCpUser; +import me.chanjar.weixin.cp.config.WxCpTpConfigStorage; +import me.chanjar.weixin.cp.config.impl.WxCpTpDefaultConfigImpl; +import me.chanjar.weixin.cp.tp.service.WxCpTpUserService; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import java.util.List; + +import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.User.USER_SIMPLE_LIST; +import static org.mockito.ArgumentMatchers.contains; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.testng.Assert.assertNotNull; + +/** + * 企业微信-第三方开发-用户管理相关测试. + * + * @author GitHub Copilot + */ +public class WxCpTpUserServiceImplTest { + + @Mock + private WxCpTpServiceApacheHttpClientImpl wxCpTpService; + + @Mock + private WxCpTpConfigStorage configStorage; + + private WxCpTpUserService wxCpTpUserService; + + private AutoCloseable mockitoAnnotations; + + /** + * Sets up. + */ + @BeforeClass + public void setUp() { + mockitoAnnotations = MockitoAnnotations.openMocks(this); + when(wxCpTpService.getWxCpTpConfigStorage()).thenReturn(configStorage); + WxCpTpDefaultConfigImpl defaultConfig = new WxCpTpDefaultConfigImpl(); + when(configStorage.getApiUrl(contains(USER_SIMPLE_LIST))) + .thenAnswer(invocation -> defaultConfig.getApiUrl(invocation.getArgument(0))); + wxCpTpUserService = new WxCpTpUserServiceImpl(wxCpTpService); + } + + /** + * Tear down. + * + * @throws Exception the exception + */ + @AfterClass + public void tearDown() throws Exception { + mockitoAnnotations.close(); + } + + /** + * 测试使用 corpId 的 listSimpleByDepartment 方法,验证请求使用了 access_token 而非 suite_access_token. + * + * @throws WxErrorException the wx error exception + */ + @Test + public void testListSimpleByDepartmentWithCorpId() throws WxErrorException { + Long departId = 1L; + String corpId = "test_corp_id"; + String accessToken = "test_access_token"; + String result = "{\"errcode\":0,\"errmsg\":\"ok\",\"userlist\":[{\"userid\":\"zhangsan\",\"name\":\"张三\"}]}"; + + when(configStorage.getAccessToken(corpId)).thenReturn(accessToken); + String url = new WxCpTpDefaultConfigImpl().getApiUrl(USER_SIMPLE_LIST + departId); + when(wxCpTpService.get(eq(url), contains("access_token=" + accessToken), eq(true))).thenReturn(result); + + List users = wxCpTpUserService.listSimpleByDepartment(departId, true, 0, corpId); + assertNotNull(users); + + // 验证调用时传入了 withoutSuiteAccessToken=true,确保不会附加 suite_access_token + verify(wxCpTpService).get(eq(url), contains("access_token=" + accessToken), eq(true)); + } +}