You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

4.3 KiB

dt-java SDK 部门与用户拉取 API 调研

Label: wayfinder:research Type: research Status: resolved Blocked by: (无)

Question

调研第三方库 com.github.tingyugetc520:dt-java:0.1.2(钉钉 OpenAPI 的 Java SDK,钉钉官方 dingtalk-java 的社区分支)的用法,产出票据 03 实现所需的 API 结论:

  1. 如何用 Client ID/Client Secret(企业内部应用凭证)初始化 client 并获取企业级 access token
  2. 拉取部门树列表的 API(部门 ID/名称/父部门/负责人 dept_manager_userid 字段)
  3. 按部门拉取用户详情列表的 API(姓名/手机号/unionId/userid 字段),分页方式
  4. 与现有 DingTalkAuthClient 手写 HTTP + Hutool 方式的关系:是否直接用 SDK 替换手写调用,还是仅在同步端点内使用 SDK(倾向后者,不动已验证的登录链路)
  5. Maven 仓库可用性(中央仓库是否有 0.1.2 版本)与传递依赖冲突风险

产出:一页结论(含关键类名、调用示例、API 端点对照),供票据 03 直接照抄实现。

Answer

调研完成(源码已克隆到 tmp/DtJava/ 可直接查阅)。结论如下:

1. 可用性与形态

  • Maven Central 确认存在 com.github.tingyugetc520:dt-java:0.1.2(2021-03-08 发布)。封装的是旧版 oapi.dingtalk.com 接口(非新版 api.dingtalk.com),5 年未更新但旧版接口仍在服务。

2. 初始化(凭证)

DtDefaultConfigImpl config = new DtDefaultConfigImpl();
config.setCorpId("xxx");      // ⚠️ yml 目前没有,需新增配置
config.setAgentId(123L);       // ⚠️ yml 目前没有,需新增配置
config.setAppKey(clientId);    // = 现有 crm.auth.dingtalk.client-id
config.setAppSecret(clientSecret); // = 现有 client-secret

DtServiceImpl dtService = new DtServiceImpl();
dtService.setDtConfigStorage(config);
// SDK 自管企业 token(旧版 gettoken 接口,内部自动刷新)

包名根:com.github.tingyugetc520.ali.dingtalk.*(注意不是 com.github.....dtjava)。

3. 部门树:DtDepartmentService

List<DtDepart> depts = dtService.getDepartmentService().list(null, true); // 递归全量

DtDepart 字段仅 id / name / parentId / order——没有 dept_manager_userid

4. 部门负责人:从用户侧反查(关键修正)

部门负责人不在 DtDepart,而在 DtUser.isLeaderInDeparts: Map<deptId, Boolean>(获取部门用户详情接口返回)。同步逻辑应为:拉用户时聚合 isLeaderInDeparts,反写对应部门的负责人字段。

5. 用户:DtUserService

// 部门用户详情(offset/size 分页,循环拉到不足一页为止)
List<DtUser> users = dtService.getUserService().listByDepartment(deptId, offset, size, null);
// 单个详情
DtUser u = dtService.getUserService().getById(userId);

DtUser 关键字段:userId / unionId / name / mobile / position / jobNumber / email / avatar / departIds(多部门) / active / isAdmin / isLeaderInDeparts / hiredDate——同步到 auth_user(account=userId,username=name,mobile,部门挂载 departIds,在职状态可看 active)完全够用。

6. 与现有 DingTalkAuthClient 的关系

SDK 用旧版 oapi + 自管 token;现有登录链路用新版 api.dingtalk.com + 手写 HTTP。两套并存无冲突,同步端点单独用 SDK,不动已验证的登录链路(维持倾向结论)。

7. 传递依赖风险(需在票据 03 处理)

pom 传递依赖较旧:okhttp 4.5.0、httpclient、guava 29.0-jre、gson 2.8.0、xstream 1.4.15(有已知 CVE,仅事件回调 XML 反序列化用到,同步链路不触碰)、commons-io 2.5、commons-lang3 3.10。与 Spring Boot 3 BOM 管理的版本存在降级竞争(Maven 最近优先,Boot BOM 在父 POM 通常胜出)。建议:引入时对 xstream、guava、gson 做 exclusions 或显式锁定 Boot 版本,验证 mvn dependency:tree 无降级后再用。

给票据 03 的落地清单

  1. yml crm.auth.dingtalk 新增 corp-idagent-id 两项(用户提供值)
  2. crm-auth pom 引 dt-java(带 exclusions)
  3. 同步:list(null,true) 拉部门树 → sys_dept(parentId 挂树);逐部门 listByDepartment 分页拉用户 → auth_user;聚合 isLeaderInDeparts 反写部门负责人
  4. 部门循环注意钉钉限流(建议每请求间隔 ~100ms,或并发 2~3 线程 + 限流)