SynDingTalkUtil.java 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591
  1. package jnpf.base.util;
  2. import com.alibaba.fastjson.JSONObject;
  3. import com.dingtalk.api.DefaultDingTalkClient;
  4. import com.dingtalk.api.DingTalkClient;
  5. import com.dingtalk.api.request.*;
  6. import com.dingtalk.api.response.*;
  7. import com.taobao.api.ApiException;
  8. import jnpf.message.model.message.DingTalkDeptModel;
  9. import jnpf.message.model.message.DingTalkUserModel;
  10. import jnpf.message.model.message.OrganizeListVO;
  11. import jnpf.permission.entity.OrganizeEntity;
  12. import jnpf.permission.model.organize.OrganizeModel;
  13. import jnpf.util.JsonUtil;
  14. import jnpf.util.StringUtil;
  15. import jnpf.util.treeutil.SumTree;
  16. import jnpf.util.treeutil.newtreeutil.TreeDotUtils;
  17. import java.util.ArrayList;
  18. import java.util.Iterator;
  19. import java.util.List;
  20. import java.util.Map;
  21. /**
  22. * 同步到企业微信的接口
  23. *
  24. * @版本: V3.1.0
  25. * @版权: 引迈信息技术有限公司(https://www.jnpfsoft.com)
  26. * @作者: JNPF开发平台组
  27. * @日期: 2021/4/30 17:11
  28. */
  29. public class SynDingTalkUtil {
  30. /**
  31. * token 接口
  32. */
  33. public static final String TOKEN = "https://oapi.dingtalk.com/gettoken";
  34. //--------------------------------------------部门--------------------------------------
  35. /**
  36. * 创建部门
  37. */
  38. public static final String CREATE_DEPARTMENT = "https://oapi.dingtalk.com/topapi/v2/department/create";
  39. /**
  40. * 更新部门
  41. */
  42. public static final String UPDATE_DEPARTMENT = "https://oapi.dingtalk.com/topapi/v2/department/update";
  43. /**
  44. * 删除部门
  45. */
  46. public static final String DELETE_DEPARTMENT = "https://oapi.dingtalk.com/topapi/v2/department/delete";
  47. /**
  48. * 获取部门列表
  49. */
  50. public static final String GET_DEPARTMENT_LIST = "https://oapi.dingtalk.com/topapi/v2/department/listsub";
  51. /**
  52. * 获取单个部门信息
  53. */
  54. public static final String GET_DEPARTMENT_INFO = "https://oapi.dingtalk.com/topapi/v2/department/get";
  55. //-------------------------------------------用户-----------------------------------------------------
  56. /**
  57. * 创建用户
  58. */
  59. public static final String CREATE_USER = "https://oapi.dingtalk.com/topapi/v2/user/create";
  60. /**
  61. * 更新用户
  62. */
  63. public static final String UPDATE_USER = "https://oapi.dingtalk.com/topapi/v2/user/update";
  64. /**
  65. * 删除用户
  66. */
  67. public static final String DELETE_USER = "https://oapi.dingtalk.com/topapi/v2/user/delete";
  68. /**
  69. * 获取用户列表(返回精简的员工信息列表)
  70. */
  71. public static final String GET_USER_LIST = "https://oapi.dingtalk.com/topapi/user/listsimple";
  72. /**
  73. * 获取用户列表(返回详细的员工信息列表)
  74. */
  75. public static final String GET_USER_DETAIL_LIST = "https://oapi.dingtalk.com/topapi/v2/user/list";
  76. /**
  77. * 获取单个成员信息
  78. */
  79. public static final String GET_SINGLE_USER = "https://oapi.dingtalk.com/topapi/v2/user/get";
  80. /**
  81. * 获取接口访问凭证
  82. */
  83. public static JSONObject getAccessToken(String corpId, String corpSecret) {
  84. JSONObject retMsg = new JSONObject();
  85. retMsg.put("code", true);
  86. try {
  87. DingTalkClient client = new DefaultDingTalkClient(TOKEN);
  88. OapiGettokenRequest req = new OapiGettokenRequest();
  89. req.setAppkey(corpId);
  90. req.setAppsecret(corpSecret);
  91. req.setHttpMethod("GET");
  92. OapiGettokenResponse rsp = client.execute(req);
  93. retMsg.put("access_token", rsp.getAccessToken());
  94. if (!rsp.isSuccess()) {
  95. retMsg.put("code", false);
  96. retMsg.put("access_token", "");
  97. }
  98. } catch (ApiException e) {
  99. retMsg.put("code", false);
  100. retMsg.put("access_token", "");
  101. }
  102. return retMsg;
  103. }
  104. //------------------------------------接口:部门管理的增删改查-------------------------------------
  105. /**
  106. * 创建钉钉部门接口
  107. *
  108. * @param deptModel
  109. * @param accessToken
  110. * @return
  111. */
  112. public static JSONObject createDepartment(DingTalkDeptModel deptModel, String accessToken) {
  113. JSONObject retMsg = new JSONObject();
  114. boolean codeFlag = true;
  115. String errorMsg = "";
  116. String deptId = "0";
  117. try {
  118. DingTalkClient client = new DefaultDingTalkClient(CREATE_DEPARTMENT);
  119. OapiV2DepartmentCreateRequest req = new OapiV2DepartmentCreateRequest();
  120. req.setParentId(deptModel.getParentId());
  121. req.setName(deptModel.getName());
  122. req.setOrder(deptModel.getOrder());
  123. req.setCreateDeptGroup(deptModel.getCreateDeptGroup());
  124. req.setSourceIdentifier(deptModel.getSourceIdentifier());
  125. OapiV2DepartmentCreateResponse rsp = client.execute(req, accessToken);
  126. if (rsp.isSuccess()) {
  127. codeFlag = true;
  128. JSONObject bodyObject = JSONObject.parseObject(rsp.getBody());
  129. bodyObject = JSONObject.parseObject(bodyObject.getString("result"));
  130. deptId = bodyObject.getLong("dept_id").toString();
  131. } else {
  132. codeFlag = false;
  133. errorMsg = rsp.getErrmsg();
  134. }
  135. } catch (ApiException e) {
  136. codeFlag = false;
  137. errorMsg = e.toString();
  138. }
  139. retMsg.put("code", codeFlag);
  140. retMsg.put("error", errorMsg);
  141. retMsg.put("retDeptId", deptId);
  142. return retMsg;
  143. }
  144. /**
  145. * 更新钉钉部门接口
  146. *
  147. * @param deptModel
  148. * @param accessToken
  149. * @return
  150. */
  151. public static JSONObject updateDepartment(DingTalkDeptModel deptModel, String accessToken) {
  152. JSONObject retMsg = new JSONObject();
  153. boolean codeFlag = true;
  154. String errorMsg = "";
  155. try {
  156. DingTalkClient client = new DefaultDingTalkClient(UPDATE_DEPARTMENT);
  157. OapiV2DepartmentUpdateRequest req = new OapiV2DepartmentUpdateRequest();
  158. req.setDeptId(deptModel.getDeptId());
  159. req.setParentId(deptModel.getParentId());
  160. req.setOrder(deptModel.getOrder());
  161. req.setName(deptModel.getName());
  162. // 设置部门主管,先建部门、再建设用户、再更新部门主管
  163. if (StringUtil.isNotEmpty(deptModel.getDeptManagerUseridList())) {
  164. req.setDeptManagerUseridList(deptModel.getDeptManagerUseridList());
  165. }
  166. OapiV2DepartmentUpdateResponse rsp = client.execute(req, accessToken);
  167. if (!rsp.isSuccess()) {
  168. codeFlag = false;
  169. errorMsg = rsp.getErrmsg();
  170. }
  171. } catch (ApiException e) {
  172. codeFlag = false;
  173. errorMsg = e.toString();
  174. }
  175. retMsg.put("code", codeFlag);
  176. retMsg.put("error", errorMsg);
  177. return retMsg;
  178. }
  179. /**
  180. * 删除钉钉部门接口
  181. *
  182. * @param id
  183. * @param accessToken
  184. * @return
  185. */
  186. public static JSONObject deleteDepartment(Long id, String accessToken) {
  187. JSONObject retMsg = new JSONObject();
  188. boolean codeFlag = true;
  189. String errorMsg = "";
  190. try {
  191. DingTalkClient client = new DefaultDingTalkClient(DELETE_DEPARTMENT);
  192. OapiV2DepartmentDeleteRequest req = new OapiV2DepartmentDeleteRequest();
  193. req.setDeptId(id);
  194. OapiV2DepartmentDeleteResponse rsp = client.execute(req, accessToken);
  195. if (!rsp.isSuccess()) {
  196. codeFlag = false;
  197. errorMsg = rsp.getErrmsg();
  198. }
  199. } catch (ApiException e) {
  200. codeFlag = false;
  201. errorMsg = e.toString();
  202. }
  203. retMsg.put("code", codeFlag);
  204. retMsg.put("error", errorMsg);
  205. return retMsg;
  206. }
  207. /**
  208. * 获取钉钉部门列表信息接口(一次只能获取下一级部门,不能多级查询)
  209. *
  210. * @param id
  211. * @param accessToken
  212. * @return
  213. */
  214. public static JSONObject getDepartmentList(Long id, String accessToken) {
  215. JSONObject retMsg = new JSONObject();
  216. boolean codeFlag = true;
  217. String errorMsg = "";
  218. List<OapiV2DepartmentListsubResponse.DeptBaseResponse> departmentAllList = new ArrayList<>();
  219. retMsg = getDepartmentListSub(id, accessToken, departmentAllList);
  220. if (!retMsg.getBoolean("code")) {
  221. codeFlag = false;
  222. errorMsg = "获取钉钉所有部门列表失败";
  223. }
  224. retMsg.put("code", codeFlag);
  225. retMsg.put("error", errorMsg);
  226. retMsg.put("department", departmentAllList);
  227. return retMsg;
  228. }
  229. /**
  230. * 递归获取部门信息列表
  231. *
  232. * @param id
  233. * @param accessToken
  234. * @param departmentAllList
  235. * @return
  236. */
  237. public static JSONObject getDepartmentListSub(Long id, String accessToken, List<OapiV2DepartmentListsubResponse.DeptBaseResponse> departmentAllList) {
  238. JSONObject retMsg = new JSONObject();
  239. boolean codeFlag = true;
  240. String errorMsg = "";
  241. List<OapiV2DepartmentListsubResponse.DeptBaseResponse> departmentList = new ArrayList<>();
  242. try {
  243. DingTalkClient client = new DefaultDingTalkClient(GET_DEPARTMENT_LIST);
  244. OapiV2DepartmentListsubRequest req = new OapiV2DepartmentListsubRequest();
  245. req.setDeptId(id);
  246. OapiV2DepartmentListsubResponse rsp = client.execute(req, accessToken);
  247. if (!rsp.isSuccess()) {
  248. retMsg.put("code", false);
  249. retMsg.put("error", rsp.getErrmsg());
  250. return retMsg;
  251. } else {
  252. departmentList = rsp.getResult();
  253. if (departmentList.size() > 0) {
  254. for (OapiV2DepartmentListsubResponse.DeptBaseResponse deptEntity : departmentList) {
  255. departmentAllList.add(deptEntity);
  256. retMsg = getDepartmentListSub(deptEntity.getDeptId(), accessToken, departmentAllList);
  257. if (!retMsg.getBoolean("code")) {
  258. codeFlag = false;
  259. errorMsg = rsp.getErrmsg();
  260. break;
  261. }
  262. }
  263. }
  264. }
  265. } catch (ApiException e) {
  266. codeFlag = false;
  267. errorMsg = e.toString();
  268. }
  269. retMsg.put("code", codeFlag);
  270. retMsg.put("error", errorMsg);
  271. return retMsg;
  272. }
  273. /**
  274. * 获取指定的钉钉部门信息接口
  275. *
  276. * @param deptId
  277. * @param accessToken
  278. * @return
  279. */
  280. public static JSONObject getDepartmentInfo(Long deptId, String accessToken) {
  281. JSONObject retMsg = new JSONObject();
  282. boolean codeFlag = true;
  283. String errorMsg = "";
  284. OapiV2DepartmentGetResponse.DeptGetResponse departmentInfo = new OapiV2DepartmentGetResponse.DeptGetResponse();
  285. try {
  286. DingTalkClient client = new DefaultDingTalkClient(GET_DEPARTMENT_INFO);
  287. OapiV2DepartmentGetRequest req = new OapiV2DepartmentGetRequest();
  288. req.setDeptId(deptId);
  289. OapiV2DepartmentGetResponse rsp = client.execute(req, accessToken);
  290. if (!rsp.isSuccess()) {
  291. codeFlag = false;
  292. errorMsg = rsp.getErrmsg();
  293. } else {
  294. departmentInfo = rsp.getResult();
  295. }
  296. } catch (ApiException e) {
  297. codeFlag = false;
  298. errorMsg = e.toString();
  299. }
  300. retMsg.put("code", codeFlag);
  301. retMsg.put("error", errorMsg);
  302. retMsg.put("departmentInfo", departmentInfo);
  303. return retMsg;
  304. }
  305. //------------------------------------接口:用户管理的增删改查-------------------------------------
  306. /**
  307. * 创建钉钉用户信息接口
  308. *
  309. * @param userModel
  310. * @param accessToken
  311. * @return
  312. */
  313. public static JSONObject createUser(DingTalkUserModel userModel, String accessToken) {
  314. JSONObject retMsg = new JSONObject();
  315. boolean codeFlag = true;
  316. String errorMsg = "";
  317. try {
  318. DingTalkClient client = new DefaultDingTalkClient(CREATE_USER);
  319. OapiV2UserCreateRequest req = new OapiV2UserCreateRequest();
  320. req.setUserid(userModel.getUserid());
  321. req.setName(userModel.getName());
  322. req.setMobile(userModel.getMobile());
  323. req.setTelephone(userModel.getTelephone());
  324. req.setJobNumber(userModel.getJobNumber());
  325. req.setTitle(userModel.getTitle());
  326. req.setEmail(userModel.getEmail());
  327. req.setWorkPlace(userModel.getWorkPlace());
  328. req.setDeptIdList(userModel.getDeptIdList());
  329. req.setHiredDate(userModel.getHiredDate());
  330. // 以下属性未设置
  331. // hide_mobile org_email extension senior_mode login_email
  332. // exclusive_account exclusive_account_type login_id init_password
  333. OapiV2UserCreateResponse rsp = client.execute(req, accessToken);
  334. if (!rsp.isSuccess()) {
  335. codeFlag = false;
  336. errorMsg = rsp.getErrmsg();
  337. }
  338. } catch (ApiException e) {
  339. codeFlag = false;
  340. errorMsg = e.toString();
  341. }
  342. retMsg.put("code", codeFlag);
  343. retMsg.put("error", errorMsg);
  344. return retMsg;
  345. }
  346. /**
  347. * 更新钉钉用户信息接口
  348. *
  349. * @param userModel
  350. * @param accessToken
  351. * @return
  352. */
  353. public static JSONObject updateUser(DingTalkUserModel userModel, String accessToken) {
  354. JSONObject retMsg = new JSONObject();
  355. boolean codeFlag = true;
  356. String errorMsg = "";
  357. try {
  358. DingTalkClient client = new DefaultDingTalkClient(UPDATE_USER);
  359. OapiV2UserUpdateRequest req = new OapiV2UserUpdateRequest();
  360. req.setUserid(userModel.getUserid());
  361. req.setName(userModel.getName());
  362. req.setMobile(userModel.getMobile());
  363. req.setTelephone(userModel.getTelephone());
  364. req.setJobNumber(userModel.getJobNumber());
  365. req.setTitle(userModel.getTitle());
  366. req.setEmail(userModel.getEmail());
  367. req.setWorkPlace(userModel.getWorkPlace());
  368. req.setDeptIdList(userModel.getDeptIdList());
  369. req.setHiredDate(userModel.getHiredDate());
  370. // 以下属性未设置
  371. // hide_mobile org_email extension senior_mode login_email
  372. // exclusive_account exclusive_account_type login_id init_password
  373. OapiV2UserUpdateResponse rsp = client.execute(req, accessToken);
  374. if (!rsp.isSuccess()) {
  375. codeFlag = false;
  376. errorMsg = rsp.getErrmsg();
  377. }
  378. } catch (ApiException e) {
  379. codeFlag = false;
  380. errorMsg = e.toString();
  381. }
  382. retMsg.put("code", codeFlag);
  383. retMsg.put("error", errorMsg);
  384. return retMsg;
  385. }
  386. /**
  387. * 删除钉钉用户信息接口
  388. *
  389. * @param userId
  390. * @param accessToken
  391. * @return
  392. */
  393. public static JSONObject deleteUser(String userId, String accessToken) {
  394. JSONObject retMsg = new JSONObject();
  395. boolean codeFlag = true;
  396. String errorMsg = "";
  397. try {
  398. DingTalkClient client = new DefaultDingTalkClient(DELETE_USER);
  399. OapiV2UserDeleteRequest req = new OapiV2UserDeleteRequest();
  400. req.setUserid(userId);
  401. OapiV2UserDeleteResponse rsp = client.execute(req, accessToken);
  402. if (!rsp.isSuccess()) {
  403. codeFlag = false;
  404. errorMsg = rsp.getErrmsg();
  405. }
  406. } catch (ApiException e) {
  407. codeFlag = false;
  408. errorMsg = e.toString();
  409. }
  410. retMsg.put("code", codeFlag);
  411. retMsg.put("error", errorMsg);
  412. return retMsg;
  413. }
  414. public static JSONObject getUserDingList(List<String> departmentList, String accessToken) {
  415. JSONObject retMsg = new JSONObject();
  416. boolean codeFlag = true;
  417. String errorMsg = "";
  418. List<OapiV2UserListResponse.ListUserResponse> userAllList = new ArrayList<>();
  419. // 钉钉限制每页记录数:不超过100
  420. // retMsg = getUserListSub(1L,0L,100L,accessToken,userAllList);
  421. // if(!retMsg.getBoolean("code")){
  422. // codeFlag = false;
  423. // errorMsg = "获取钉钉所有用户列表失败";
  424. // }
  425. if (!departmentList.isEmpty()) {
  426. for (String deptId : departmentList) {
  427. retMsg = getUserListSub(Long.parseLong(deptId), 0L, 100L, accessToken, userAllList);
  428. if (!retMsg.getBoolean("code")) {
  429. codeFlag = false;
  430. errorMsg = "获取钉钉所有用户列表失败";
  431. break;
  432. }
  433. }
  434. }
  435. retMsg.put("code", codeFlag);
  436. retMsg.put("error", errorMsg);
  437. retMsg.put("userlist", userAllList);
  438. return retMsg;
  439. }
  440. public static JSONObject getUserList(List<DingTalkDeptModel> departmentList, String accessToken) {
  441. JSONObject retMsg = new JSONObject();
  442. boolean codeFlag = true;
  443. String errorMsg = "";
  444. List<OapiV2UserListResponse.ListUserResponse> userAllList = new ArrayList<>();
  445. // 钉钉限制每页记录数:不超过100
  446. retMsg = getUserListSub(1L, 0L, 100L, accessToken, userAllList);
  447. if (!retMsg.getBoolean("code")) {
  448. codeFlag = false;
  449. errorMsg = "获取钉钉所有用户列表失败";
  450. }
  451. if (departmentList.size() > 0 && retMsg.getBoolean("code")) {
  452. for (DingTalkDeptModel deptEntity : departmentList) {
  453. retMsg = getUserListSub(deptEntity.getDeptId(), 0L, 100L, accessToken, userAllList);
  454. if (!retMsg.getBoolean("code")) {
  455. codeFlag = false;
  456. errorMsg = "获取钉钉所有用户列表失败";
  457. break;
  458. }
  459. }
  460. }
  461. retMsg.put("code", codeFlag);
  462. retMsg.put("error", errorMsg);
  463. retMsg.put("userlist", userAllList);
  464. return retMsg;
  465. }
  466. public static JSONObject getUserListSub(Long deptId, Long cursor, Long size, String accessToken,
  467. List<OapiV2UserListResponse.ListUserResponse> userAllList) {
  468. JSONObject retMsg = new JSONObject();
  469. List<OapiV2UserListResponse.ListUserResponse> userList = new ArrayList<>();
  470. OapiV2UserListResponse.PageResult pageResult = new OapiV2UserListResponse.PageResult();
  471. try {
  472. DingTalkClient client = new DefaultDingTalkClient(GET_USER_DETAIL_LIST);
  473. OapiV2UserListRequest req = new OapiV2UserListRequest();
  474. req.setDeptId(deptId);
  475. req.setCursor(cursor);
  476. req.setSize(size);
  477. OapiV2UserListResponse rsp = client.execute(req, accessToken);
  478. if (rsp.isSuccess()) {
  479. pageResult = rsp.getResult();
  480. userList = pageResult.getList();
  481. for (OapiV2UserListResponse.ListUserResponse userEntity : userList) {
  482. userAllList.add(userEntity);
  483. }
  484. if (pageResult.getHasMore()) {
  485. retMsg = getUserListSub(deptId, pageResult.getNextCursor(), size, accessToken, userAllList);
  486. if (!retMsg.getBoolean("code")) {
  487. retMsg.put("code", false);
  488. retMsg.put("error", rsp.getErrmsg());
  489. return retMsg;
  490. }
  491. }
  492. }
  493. } catch (ApiException e) {
  494. retMsg.put("code", false);
  495. retMsg.put("error", e.toString());
  496. return retMsg;
  497. }
  498. retMsg.put("code", true);
  499. retMsg.put("error", "");
  500. return retMsg;
  501. }
  502. /**
  503. * 按目录树结构数据转化为列表
  504. *
  505. * @param selectorVO
  506. * @param organizeList
  507. * @param listByOrder
  508. */
  509. public static <T> void getOrganizeTreeToList(OrganizeListVO selectorVO, Map<String, T> organizeList, List<T> listByOrder) {
  510. if (selectorVO.isHasChildren()) {
  511. List<OrganizeListVO> voChildren = selectorVO.getChildren();
  512. Iterator<OrganizeListVO> iterator = voChildren.iterator();
  513. while (iterator.hasNext()) {
  514. OrganizeListVO organizeSelectorVO = iterator.next();
  515. T entity = organizeList.get(organizeSelectorVO.getId());
  516. listByOrder.add(entity);
  517. if (organizeSelectorVO.isHasChildren()) {
  518. getOrganizeTreeToList(organizeSelectorVO, organizeList, listByOrder);
  519. }
  520. }
  521. }
  522. }
  523. }