DingTool.java 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. package cn.com.lzt.common.util.dingding;
  2. import java.util.*;
  3. import cn.hutool.core.date.DateUtil;
  4. import com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenRequest;
  5. import com.aliyun.tea.TeaException;
  6. import com.aliyun.teaopenapi.models.Config;
  7. import com.dingtalk.api.DefaultDingTalkClient;
  8. import com.dingtalk.api.DingTalkClient;
  9. import com.dingtalk.api.request.OapiAttendanceGetcolumnvalRequest;
  10. import com.dingtalk.api.request.OapiGetJsapiTicketRequest;
  11. import com.dingtalk.api.request.OapiV2UserGetbymobileRequest;
  12. import com.dingtalk.api.response.OapiAttendanceGetcolumnvalResponse;
  13. import com.dingtalk.api.response.OapiGetJsapiTicketResponse;
  14. import com.dingtalk.api.response.OapiV2UserGetbymobileResponse;
  15. import org.apache.http.util.TextUtils;
  16. import org.jeecgframework.core.constant.Globals;
  17. import org.jeecgframework.core.util.ResourceUtil;
  18. import com.alibaba.fastjson.JSON;
  19. import com.alibaba.fastjson.JSONArray;
  20. import com.alibaba.fastjson.JSONObject;
  21. import com.dingtalk.open.client.ServiceFactory;
  22. import com.dingtalk.open.client.api.model.corp.CorpUserDetail;
  23. import com.dingtalk.open.client.api.model.corp.CorpUserDetailList;
  24. import com.dingtalk.open.client.api.model.corp.Department;
  25. import com.dingtalk.open.client.api.service.corp.CorpDepartmentService;
  26. import com.dingtalk.open.client.api.service.corp.CorpUserService;
  27. import com.dingtalk.open.client.common.SdkInitException;
  28. import com.dingtalk.open.client.common.ServiceException;
  29. import com.dingtalk.open.client.common.ServiceNotExistException;
  30. import cn.com.lzt.common.util.Constants;
  31. import cn.com.lzt.common.util.dingding.entity.KaoqinEntity;
  32. public class DingTool {
  33. private String accessToken;
  34. private String jsTicket;
  35. public DingTool() {
  36. // ResourceBundle bundle = java.util.ResourceBundle.getBundle("config");
  37. // corpId = bundle.getString("corpId");
  38. // corpSecret= bundle.getString("corpSecret");
  39. // 获取accessTokenID
  40. try
  41. {
  42. /*ServiceFactory serviceFactory = ServiceFactory.getInstance();
  43. CorpConnectionService corpConnectionService = serviceFactory.getOpenService(CorpConnectionService.class);
  44. accessToken = corpConnectionService.getCorpToken(Constants.CORP_ID, Constants.CORP_SECRET);
  45. if(accessToken.length() > 0) {
  46. JsapiService jsapiService = serviceFactory.getOpenService(JsapiService.class);
  47. JsapiTicket JsapiTicket = jsapiService.getJsapiTicket(accessToken, "jsapi");
  48. jsTicket = JsapiTicket.getTicket();
  49. }*/
  50. // 新版获取accessToken方法, sdk方式
  51. Config config = new Config();
  52. config.protocol = "https";
  53. config.regionId = "central";
  54. com.aliyun.dingtalkoauth2_1_0.Client client = new com.aliyun.dingtalkoauth2_1_0.Client(config);
  55. GetAccessTokenRequest getAccessTokenRequest = new GetAccessTokenRequest()
  56. .setAppKey(Constants.APP_KEY)
  57. .setAppSecret(Constants.APP_SECRET);
  58. accessToken = client.getAccessToken(getAccessTokenRequest).getBody().getAccessToken();
  59. // 获取jsapi_ticket
  60. DingTalkClient talkClient = new DefaultDingTalkClient("https://oapi.dingtalk.com/get_jsapi_ticket");
  61. OapiGetJsapiTicketRequest req = new OapiGetJsapiTicketRequest();
  62. req.setHttpMethod("GET");
  63. OapiGetJsapiTicketResponse rsp = talkClient.execute(req, accessToken);
  64. jsTicket = rsp.getBody();
  65. } catch (SdkInitException e) {
  66. e.printStackTrace();
  67. } catch (ServiceException e) {
  68. e.printStackTrace();
  69. } catch (ServiceNotExistException e) {
  70. e.printStackTrace();
  71. } catch (TeaException err) {
  72. if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
  73. // err 中含有 code 和 message 属性,可帮助定位问题
  74. }
  75. } catch (Exception _err) {
  76. TeaException err = new TeaException(_err.getMessage(), _err);
  77. if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
  78. // err 中含有 code 和 message 属性,可帮助定位问题
  79. }
  80. }
  81. }
  82. private boolean isServerOnline() {
  83. return ResourceUtil.getConfigByName(Globals.SERVER_TYPE).equals(Globals.SERVER_TYPE_LINE);
  84. }
  85. /**
  86. * 创建部门
  87. *
  88. * @param name 部门名称
  89. * @param parentId 父部门ID
  90. * @param order 顺序
  91. * @param createDeptGroup 是否创建一个关联此部门的企业群 (默认false)
  92. * @return 部门ID(创建失败,返回"")
  93. */
  94. public String createDepartment(String name, String parentId, String order, boolean createDeptGroup){
  95. String returnStr = "";
  96. if(name.indexOf("-") > -1) {
  97. name = name.replaceAll("-", "_");
  98. }
  99. if(!isServerOnline()) {
  100. return returnStr;
  101. }
  102. try{
  103. CorpDepartmentService corpDepartmentService = ServiceFactory.getInstance().getOpenService(CorpDepartmentService.class);
  104. returnStr = corpDepartmentService.deptCreate(accessToken, name, parentId, order, createDeptGroup);
  105. } catch (Exception e) {
  106. e.printStackTrace();
  107. }
  108. return returnStr;
  109. }
  110. /**
  111. * 查询部门详情
  112. *
  113. * @param deptId 部门ID
  114. *
  115. */
  116. public Department getDepartment(String deptId) {
  117. String url = "https://oapi.dingtalk.com/department/get?access_token=" + accessToken + "&id=" + deptId ;
  118. JSONObject reponseJson = null;
  119. Department department = new Department();
  120. try {
  121. reponseJson = HttpHelper.httpGet(url);
  122. if(null != reponseJson) {
  123. department = reponseJson.toJavaObject(Department.class);
  124. }
  125. System.out.print(reponseJson);
  126. } catch (Exception e) {
  127. e.printStackTrace();
  128. }
  129. return department;
  130. }
  131. /**
  132. * 查询子部门信息
  133. *
  134. * @param parentDeptId 父部门ID
  135. * @return deptList 子部门信息List
  136. */
  137. public List<Department> listDepartments(String parentDeptId) {
  138. List<Department> deptList = new ArrayList<Department>();
  139. try {
  140. CorpDepartmentService corpDepartmentService = ServiceFactory.getInstance().getOpenService(CorpDepartmentService.class);
  141. deptList = corpDepartmentService.getDeptList(accessToken, parentDeptId);
  142. } catch (Exception e) {
  143. e.printStackTrace();
  144. }
  145. return deptList;
  146. }
  147. /**
  148. * 更新部门信息
  149. *
  150. * @param id 部门Id
  151. * @param name 部门名
  152. * @param parentId 父部门Id
  153. * @param order 顺序
  154. * @param createDeptGroup 是否创建一个关联此部门的企业群 (默认false)
  155. * @param autoAddUser 如果有新人加入部门是否会自动加入部门群 (默认true)
  156. * @param deptManagerUseridList 部门的主管列表,取值为由主管的userid组成的字符串,不同的userid使用’| 符号进行分割 (不需要 "")
  157. * @param deptHiding 是否隐藏部门, true表示隐藏, false表示显示 (默认false)
  158. * @param deptPerimits 可以查看指定隐藏部门的其他部门列表,如果部门隐藏,则此值生效,取值为其他的部门id组成的的字符串,使用 | 符号进行分割(不需要 "")
  159. * @param userPerimits 可以查看指定隐藏部门的其他人员列表,如果部门隐藏,则此值生效,取值为其他的人员userid组成的的字符串,使用| 符号进行分割(不需要 "")
  160. * @param outerDept 是否本部门的员工仅可见员工自己, 为true时,本部门员工默认只能看到员工自己 (默认false)
  161. * @param outerPermitDepts 本部门的员工仅可见员工自己为true时,可以配置额外可见部门,值为部门id组成的的字符串,使用|符号进行分割(不需要 "")
  162. * @param outerPermitUsers 本部门的员工仅可见员工自己为true时,可以配置额外可见人员,值为userid组成的的字符串,使用|符号进行分割(不需要 "")
  163. * @param orgDeptOwner 企业群群主(不需要 "")
  164. *
  165. * @return returnFlg 更新成败flg
  166. *
  167. *
  168. */
  169. public boolean updateDepartment(long id, String name,
  170. String parentId, String order, boolean createDeptGroup,
  171. boolean autoAddUser, String deptManagerUseridList, boolean deptHiding, String deptPerimits,
  172. String userPerimits, boolean outerDept, String outerPermitDepts,
  173. String outerPermitUsers, String orgDeptOwner) {
  174. boolean returnFlg = true;
  175. if(name.indexOf("-") > -1) {
  176. name = name.replaceAll("-", "_");
  177. }
  178. if(!isServerOnline()) {
  179. return false;
  180. }
  181. try {
  182. CorpDepartmentService corpDepartmentService = ServiceFactory.getInstance().getOpenService(CorpDepartmentService.class);
  183. corpDepartmentService.deptUpdate(accessToken, id, name, parentId, order, createDeptGroup,
  184. autoAddUser, deptManagerUseridList, deptHiding, deptPerimits, userPerimits,
  185. outerDept, outerPermitDepts, outerPermitUsers, orgDeptOwner);
  186. } catch (Exception e){
  187. returnFlg = false;
  188. e.printStackTrace();
  189. }
  190. return returnFlg;
  191. }
  192. /**
  193. * 删除部门
  194. *
  195. * @param id 部门Id
  196. *
  197. * @return returnFlg 删除成败flg
  198. *
  199. */
  200. public boolean deleteDepartment(long id) {
  201. boolean returnFlg = true;
  202. if(!isServerOnline()) {
  203. return false;
  204. }
  205. try{
  206. CorpDepartmentService corpDepartmentService = ServiceFactory.getInstance().getOpenService(CorpDepartmentService.class);
  207. corpDepartmentService.deptDelete(accessToken, id);
  208. }catch(Exception e){
  209. returnFlg = false;
  210. e.printStackTrace();
  211. }
  212. return returnFlg;
  213. }
  214. /**
  215. * 新建人员
  216. *
  217. * @param userDetail 人员信息
  218. * userid String 人员编号
  219. * name String 人员姓名
  220. * department List 成员所属部门id列表
  221. * position String 职位信息
  222. * mobile String 手机号码
  223. * tel String 电话号码
  224. * workPlace String 办公地点
  225. * remark String 备注
  226. * email String 电子邮件
  227. * jobnumber String 员工工号
  228. * isHide Boolean 是否隐藏手机号码
  229. * senior Boolean 是否高管模式
  230. * extattr Map 扩展属性
  231. * @return 成功:userId
  232. */
  233. public boolean createUser(CorpUserDetail userDetail) {
  234. Map<Long, Long> orderInDepts = new HashMap<Long, Long>();
  235. orderInDepts.put(new Long(userDetail.getDepartment().get(0)), new Long(1));
  236. boolean returnFlg = true;
  237. if(!isServerOnline()) {
  238. return false;
  239. }
  240. try{
  241. CorpUserService corpUserService = ServiceFactory.getInstance().getOpenService(CorpUserService.class);
  242. corpUserService.createCorpUser(accessToken, userDetail.getUserid(), userDetail.getName(), orderInDepts,
  243. userDetail.getDepartment(), userDetail.getPosition(), userDetail.getMobile(), userDetail.getTel(), userDetail.getWorkPlace(),
  244. userDetail.getRemark(), userDetail.getEmail(), userDetail.getJobnumber(),
  245. userDetail.getIsHide(), userDetail.getSenior(), userDetail.getExtattr());
  246. }catch(Exception e){
  247. returnFlg = false;
  248. e.printStackTrace();
  249. }
  250. return returnFlg;
  251. }
  252. /**
  253. * 获取用户信息
  254. *
  255. * @param userid
  256. * @return 返回对象中的active表示该用户是否激活,false为未激活。
  257. */
  258. public CorpUserDetail getUser(String userid) {
  259. CorpUserDetail corpUserDetail = new CorpUserDetail();
  260. try{
  261. CorpUserService corpUserService = ServiceFactory.getInstance().getOpenService(CorpUserService.class);
  262. corpUserDetail = corpUserService.getCorpUser(accessToken, userid);
  263. }catch(Exception e){
  264. System.out.println(e.getMessage()+":"+userid);
  265. }
  266. return corpUserDetail;
  267. }
  268. /**
  269. * 更新用户信息
  270. *
  271. * @param userDetail
  272. * userid String 人员编号
  273. * name String 人员姓名
  274. * orderInDepts Map<Long, Long> 人员在组织中的顺序
  275. * department List 成员所属部门id列表
  276. * position String 职位信息
  277. * mobile String 手机号码
  278. * tel String 电话号码
  279. * workPlace String 办公地点
  280. * remark String 备注
  281. * email String 电子邮件
  282. * jobnumber String 员工工号
  283. * isHide Boolean 是否隐藏手机号码
  284. * senior Boolean 是否高管模式
  285. * extattr Map 扩展属性
  286. * @return
  287. */
  288. public boolean updateUser(CorpUserDetail userDetail) {
  289. // JSONObject js = (JSONObject)JSONObject.parse(userDetail.getOrderInDepts());
  290. // Map<Long, Long> orderInDepts = this.toHashMap(js);
  291. Map<Long, Long> orderInDepts = new HashMap<Long, Long>();
  292. orderInDepts.put(new Long(userDetail.getDepartment().get(0)), new Long(1));
  293. boolean returnFlg = true;
  294. if(!isServerOnline()) {
  295. return false;
  296. }
  297. try{
  298. CorpUserService corpUserService = ServiceFactory.getInstance().getOpenService(CorpUserService.class);
  299. corpUserService.updateCorpUser(accessToken, userDetail.getUserid(), userDetail.getName(), orderInDepts,
  300. userDetail.getDepartment(), userDetail.getPosition(), userDetail.getMobile(), userDetail.getTel(), userDetail.getWorkPlace(),
  301. userDetail.getRemark(), userDetail.getEmail(), userDetail.getJobnumber(),
  302. userDetail.getIsHide(), userDetail.getSenior(), userDetail.getExtattr());
  303. }catch(Exception e){
  304. returnFlg = false;
  305. e.printStackTrace();
  306. }
  307. return returnFlg;
  308. }
  309. /**
  310. * 批量删除用户
  311. *
  312. * @param useridlist
  313. * @return 如果有一个用户删除失败,都不会删除
  314. * 删除用户时,会将考勤记录一并删除,删除用户之前需要先把考勤记录同步到本地数据库
  315. */
  316. public boolean batchDeleteUser(List<String> useridlist) {
  317. boolean returnFlg = true;
  318. if(!isServerOnline()) {
  319. return false;
  320. }
  321. try{
  322. CorpUserService corpUserService = ServiceFactory.getInstance().getOpenService(CorpUserService.class);
  323. corpUserService.batchdeleteCorpUserListByUserids(accessToken, useridlist);
  324. }catch(Exception e){
  325. returnFlg = false;
  326. e.printStackTrace();
  327. }
  328. return returnFlg;
  329. }
  330. /**
  331. * 获取部门成员(详情)
  332. *
  333. * @param departmentId 部门id
  334. * @param offset 支持分页查询,与size参数同时设置时才生效,此参数代表偏移量
  335. * @param size 支持分页查询,与offset参数同时设置时才生效,此参数代表分页大小,最大100
  336. * @param order 支持分页查询,部门成员的排序规则,默认不传是按自定义排序;entry_asc代表按照进入部门的时间升序,
  337. * entry_desc代表按照进入部门的时间降序,modify_asc代表按照部门信息修改时间升序,modify_desc代表按照部门信息修改时间降序,custom代表用户定义(未定义时按照拼音)排序
  338. * @return
  339. * @throws Exception
  340. */
  341. public CorpUserDetailList getUserDetails(long departmentId,Long offset,Integer size,String order){
  342. CorpUserDetailList corpUserDetailList = new CorpUserDetailList();
  343. try{
  344. CorpUserService corpUserService = ServiceFactory.getInstance().getOpenService(CorpUserService.class);
  345. corpUserDetailList = corpUserService.getCorpUserList(accessToken, departmentId,offset, size, order);
  346. }catch(Exception e){
  347. e.printStackTrace();
  348. }
  349. return corpUserDetailList;
  350. }
  351. /**
  352. * 获取打卡原始记录
  353. *
  354. * @param userIds 用户ID列表 最大50个
  355. * @param checkDateFrom 起始时间 格式:yyyy-MM-dd hh:mm:ss
  356. * @param checkDateTo 结束时间 格式:yyyy-MM-dd hh:mm:ss(起始时间与结束时间之间最多为7天)
  357. * @return
  358. * @throws Exception
  359. */
  360. public List<KaoqinEntity> getSignRecord(List<String> userIds, String checkDateFrom, String checkDateTo){
  361. String url = "https://oapi.dingtalk.com/" + "attendance/listRecord?access_token=" + accessToken ;
  362. JSONObject json = new JSONObject();
  363. json.put("userIds", userIds);
  364. json.put("checkDateFrom", checkDateFrom);
  365. //json.put("checkDateFrom", "2021-12-20 09:00:00");
  366. json.put("checkDateTo", checkDateTo);
  367. JSONObject reponseJson = null;
  368. List<KaoqinEntity> list = new ArrayList<KaoqinEntity>();
  369. try {
  370. reponseJson = HttpHelper.httpPost(url,json);
  371. JSONArray jSONArray = reponseJson.getJSONArray("recordresult");
  372. for(int i = 0; i < jSONArray.size(); i++) {
  373. KaoqinEntity kaoqinEntity = new KaoqinEntity();
  374. kaoqinEntity = ((JSON) jSONArray.get(i)).toJavaObject(KaoqinEntity.class);
  375. list.add(kaoqinEntity);
  376. }
  377. } catch (Exception e) {
  378. e.printStackTrace();
  379. }
  380. return list;
  381. }
  382. /**
  383. * JSONObject 转化为 Map<Long, Long>
  384. *
  385. * @param js
  386. * @return
  387. */
  388. private HashMap<Long, Long> toHashMap(JSONObject js) {
  389. if(js == null){
  390. return null;
  391. }
  392. HashMap<Long, Long> data = new HashMap<Long, Long>();
  393. // 将json字符串转换成jsonObject
  394. Set<String> set = js.keySet();
  395. // 遍历jsonObject数据,添加到Map对象
  396. Iterator<String> it = set.iterator();
  397. while (it.hasNext())
  398. {
  399. String key = String.valueOf(it.next());
  400. Long keyLong = Long.valueOf(key);
  401. String value = js.getString(key);
  402. Long valueLong;
  403. if(TextUtils.isEmpty(value)){
  404. valueLong = js.getLong(key);
  405. }else{
  406. valueLong = Long.valueOf(value);
  407. }
  408. data.put(keyLong, valueLong);
  409. }
  410. return data;
  411. }
  412. /*---------------------------------------------------------------------------------------------------------------*/
  413. /**
  414. * 通过手机号获取userId
  415. */
  416. public String getUserIdByPhone(String phone){
  417. String userId = null;
  418. try {
  419. DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/getbymobile");
  420. OapiV2UserGetbymobileRequest req = new OapiV2UserGetbymobileRequest();
  421. req.setMobile(phone);
  422. OapiV2UserGetbymobileResponse rsp = client.execute(req, accessToken);
  423. userId = rsp.getResult().getUserid();
  424. } catch (Exception e){
  425. System.out.println("钉钉接口-根据手机号获取userId" + e);
  426. }
  427. return userId;
  428. }
  429. /**
  430. * 考勤统计列值获取
  431. * @param userId
  432. * @return
  433. */
  434. public List<OapiAttendanceGetcolumnvalResponse.ColumnValForTopVo> getColumnVal(String userId){
  435. List<OapiAttendanceGetcolumnvalResponse.ColumnValForTopVo> list = null;
  436. try {
  437. DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/attendance/getcolumnval");
  438. OapiAttendanceGetcolumnvalRequest req = new OapiAttendanceGetcolumnvalRequest();
  439. req.setUserid(userId);
  440. //应出勤天数:290802238 出勤天数:290802241 迟到次数:290802244 早退次数:290802249
  441. req.setColumnIdList("290802238,290802241,290802244,290802249");
  442. req.setFromDate(DateUtil.beginOfMonth(new Date()));
  443. req.setToDate(DateUtil.endOfMonth(new Date()));
  444. OapiAttendanceGetcolumnvalResponse rsp = client.execute(req, accessToken);
  445. list = rsp.getResult().getColumnVals();
  446. } catch (Exception e){
  447. System.out.println("钉钉接口-获取考勤统计列值" + e);
  448. }
  449. return list;
  450. }
  451. }