package cn.com.lzt.common.util.dingding; import java.util.*; import cn.hutool.core.date.DateUtil; import com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenRequest; import com.aliyun.tea.TeaException; import com.aliyun.teaopenapi.models.Config; import com.dingtalk.api.DefaultDingTalkClient; import com.dingtalk.api.DingTalkClient; import com.dingtalk.api.request.OapiAttendanceGetcolumnvalRequest; import com.dingtalk.api.request.OapiGetJsapiTicketRequest; import com.dingtalk.api.request.OapiV2UserGetbymobileRequest; import com.dingtalk.api.response.OapiAttendanceGetcolumnvalResponse; import com.dingtalk.api.response.OapiGetJsapiTicketResponse; import com.dingtalk.api.response.OapiV2UserGetbymobileResponse; import org.apache.http.util.TextUtils; import org.jeecgframework.core.constant.Globals; import org.jeecgframework.core.util.ResourceUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.dingtalk.open.client.ServiceFactory; import com.dingtalk.open.client.api.model.corp.CorpUserDetail; import com.dingtalk.open.client.api.model.corp.CorpUserDetailList; import com.dingtalk.open.client.api.model.corp.Department; import com.dingtalk.open.client.api.service.corp.CorpDepartmentService; import com.dingtalk.open.client.api.service.corp.CorpUserService; import com.dingtalk.open.client.common.SdkInitException; import com.dingtalk.open.client.common.ServiceException; import com.dingtalk.open.client.common.ServiceNotExistException; import cn.com.lzt.common.util.Constants; import cn.com.lzt.common.util.dingding.entity.KaoqinEntity; public class DingTool { private String accessToken; private String jsTicket; public DingTool() { // ResourceBundle bundle = java.util.ResourceBundle.getBundle("config"); // corpId = bundle.getString("corpId"); // corpSecret= bundle.getString("corpSecret"); // 获取accessTokenID try { /*ServiceFactory serviceFactory = ServiceFactory.getInstance(); CorpConnectionService corpConnectionService = serviceFactory.getOpenService(CorpConnectionService.class); accessToken = corpConnectionService.getCorpToken(Constants.CORP_ID, Constants.CORP_SECRET); if(accessToken.length() > 0) { JsapiService jsapiService = serviceFactory.getOpenService(JsapiService.class); JsapiTicket JsapiTicket = jsapiService.getJsapiTicket(accessToken, "jsapi"); jsTicket = JsapiTicket.getTicket(); }*/ // 新版获取accessToken方法, sdk方式 Config config = new Config(); config.protocol = "https"; config.regionId = "central"; com.aliyun.dingtalkoauth2_1_0.Client client = new com.aliyun.dingtalkoauth2_1_0.Client(config); GetAccessTokenRequest getAccessTokenRequest = new GetAccessTokenRequest() .setAppKey(Constants.APP_KEY) .setAppSecret(Constants.APP_SECRET); accessToken = client.getAccessToken(getAccessTokenRequest).getBody().getAccessToken(); // 获取jsapi_ticket DingTalkClient talkClient = new DefaultDingTalkClient("https://oapi.dingtalk.com/get_jsapi_ticket"); OapiGetJsapiTicketRequest req = new OapiGetJsapiTicketRequest(); req.setHttpMethod("GET"); OapiGetJsapiTicketResponse rsp = talkClient.execute(req, accessToken); jsTicket = rsp.getBody(); } catch (SdkInitException e) { e.printStackTrace(); } catch (ServiceException e) { e.printStackTrace(); } catch (ServiceNotExistException e) { e.printStackTrace(); } catch (TeaException err) { if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) { // err 中含有 code 和 message 属性,可帮助定位问题 } } catch (Exception _err) { TeaException err = new TeaException(_err.getMessage(), _err); if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) { // err 中含有 code 和 message 属性,可帮助定位问题 } } } private boolean isServerOnline() { return ResourceUtil.getConfigByName(Globals.SERVER_TYPE).equals(Globals.SERVER_TYPE_LINE); } /** * 创建部门 * * @param name 部门名称 * @param parentId 父部门ID * @param order 顺序 * @param createDeptGroup 是否创建一个关联此部门的企业群 (默认false) * @return 部门ID(创建失败,返回"") */ public String createDepartment(String name, String parentId, String order, boolean createDeptGroup){ String returnStr = ""; if(name.indexOf("-") > -1) { name = name.replaceAll("-", "_"); } if(!isServerOnline()) { return returnStr; } try{ CorpDepartmentService corpDepartmentService = ServiceFactory.getInstance().getOpenService(CorpDepartmentService.class); returnStr = corpDepartmentService.deptCreate(accessToken, name, parentId, order, createDeptGroup); } catch (Exception e) { e.printStackTrace(); } return returnStr; } /** * 查询部门详情 * * @param deptId 部门ID * */ public Department getDepartment(String deptId) { String url = "https://oapi.dingtalk.com/department/get?access_token=" + accessToken + "&id=" + deptId ; JSONObject reponseJson = null; Department department = new Department(); try { reponseJson = HttpHelper.httpGet(url); if(null != reponseJson) { department = reponseJson.toJavaObject(Department.class); } System.out.print(reponseJson); } catch (Exception e) { e.printStackTrace(); } return department; } /** * 查询子部门信息 * * @param parentDeptId 父部门ID * @return deptList 子部门信息List */ public List listDepartments(String parentDeptId) { List deptList = new ArrayList(); try { CorpDepartmentService corpDepartmentService = ServiceFactory.getInstance().getOpenService(CorpDepartmentService.class); deptList = corpDepartmentService.getDeptList(accessToken, parentDeptId); } catch (Exception e) { e.printStackTrace(); } return deptList; } /** * 更新部门信息 * * @param id 部门Id * @param name 部门名 * @param parentId 父部门Id * @param order 顺序 * @param createDeptGroup 是否创建一个关联此部门的企业群 (默认false) * @param autoAddUser 如果有新人加入部门是否会自动加入部门群 (默认true) * @param deptManagerUseridList 部门的主管列表,取值为由主管的userid组成的字符串,不同的userid使用’| 符号进行分割 (不需要 "") * @param deptHiding 是否隐藏部门, true表示隐藏, false表示显示 (默认false) * @param deptPerimits 可以查看指定隐藏部门的其他部门列表,如果部门隐藏,则此值生效,取值为其他的部门id组成的的字符串,使用 | 符号进行分割(不需要 "") * @param userPerimits 可以查看指定隐藏部门的其他人员列表,如果部门隐藏,则此值生效,取值为其他的人员userid组成的的字符串,使用| 符号进行分割(不需要 "") * @param outerDept 是否本部门的员工仅可见员工自己, 为true时,本部门员工默认只能看到员工自己 (默认false) * @param outerPermitDepts 本部门的员工仅可见员工自己为true时,可以配置额外可见部门,值为部门id组成的的字符串,使用|符号进行分割(不需要 "") * @param outerPermitUsers 本部门的员工仅可见员工自己为true时,可以配置额外可见人员,值为userid组成的的字符串,使用|符号进行分割(不需要 "") * @param orgDeptOwner 企业群群主(不需要 "") * * @return returnFlg 更新成败flg * * */ public boolean updateDepartment(long id, String name, String parentId, String order, boolean createDeptGroup, boolean autoAddUser, String deptManagerUseridList, boolean deptHiding, String deptPerimits, String userPerimits, boolean outerDept, String outerPermitDepts, String outerPermitUsers, String orgDeptOwner) { boolean returnFlg = true; if(name.indexOf("-") > -1) { name = name.replaceAll("-", "_"); } if(!isServerOnline()) { return false; } try { CorpDepartmentService corpDepartmentService = ServiceFactory.getInstance().getOpenService(CorpDepartmentService.class); corpDepartmentService.deptUpdate(accessToken, id, name, parentId, order, createDeptGroup, autoAddUser, deptManagerUseridList, deptHiding, deptPerimits, userPerimits, outerDept, outerPermitDepts, outerPermitUsers, orgDeptOwner); } catch (Exception e){ returnFlg = false; e.printStackTrace(); } return returnFlg; } /** * 删除部门 * * @param id 部门Id * * @return returnFlg 删除成败flg * */ public boolean deleteDepartment(long id) { boolean returnFlg = true; if(!isServerOnline()) { return false; } try{ CorpDepartmentService corpDepartmentService = ServiceFactory.getInstance().getOpenService(CorpDepartmentService.class); corpDepartmentService.deptDelete(accessToken, id); }catch(Exception e){ returnFlg = false; e.printStackTrace(); } return returnFlg; } /** * 新建人员 * * @param userDetail 人员信息 * userid String 人员编号 * name String 人员姓名 * department List 成员所属部门id列表 * position String 职位信息 * mobile String 手机号码 * tel String 电话号码 * workPlace String 办公地点 * remark String 备注 * email String 电子邮件 * jobnumber String 员工工号 * isHide Boolean 是否隐藏手机号码 * senior Boolean 是否高管模式 * extattr Map 扩展属性 * @return 成功:userId */ public boolean createUser(CorpUserDetail userDetail) { Map orderInDepts = new HashMap(); orderInDepts.put(new Long(userDetail.getDepartment().get(0)), new Long(1)); boolean returnFlg = true; if(!isServerOnline()) { return false; } try{ CorpUserService corpUserService = ServiceFactory.getInstance().getOpenService(CorpUserService.class); corpUserService.createCorpUser(accessToken, userDetail.getUserid(), userDetail.getName(), orderInDepts, userDetail.getDepartment(), userDetail.getPosition(), userDetail.getMobile(), userDetail.getTel(), userDetail.getWorkPlace(), userDetail.getRemark(), userDetail.getEmail(), userDetail.getJobnumber(), userDetail.getIsHide(), userDetail.getSenior(), userDetail.getExtattr()); }catch(Exception e){ returnFlg = false; e.printStackTrace(); } return returnFlg; } /** * 获取用户信息 * * @param userid * @return 返回对象中的active表示该用户是否激活,false为未激活。 */ public CorpUserDetail getUser(String userid) { CorpUserDetail corpUserDetail = new CorpUserDetail(); try{ CorpUserService corpUserService = ServiceFactory.getInstance().getOpenService(CorpUserService.class); corpUserDetail = corpUserService.getCorpUser(accessToken, userid); }catch(Exception e){ System.out.println(e.getMessage()+":"+userid); } return corpUserDetail; } /** * 更新用户信息 * * @param userDetail * userid String 人员编号 * name String 人员姓名 * orderInDepts Map 人员在组织中的顺序 * department List 成员所属部门id列表 * position String 职位信息 * mobile String 手机号码 * tel String 电话号码 * workPlace String 办公地点 * remark String 备注 * email String 电子邮件 * jobnumber String 员工工号 * isHide Boolean 是否隐藏手机号码 * senior Boolean 是否高管模式 * extattr Map 扩展属性 * @return */ public boolean updateUser(CorpUserDetail userDetail) { // JSONObject js = (JSONObject)JSONObject.parse(userDetail.getOrderInDepts()); // Map orderInDepts = this.toHashMap(js); Map orderInDepts = new HashMap(); orderInDepts.put(new Long(userDetail.getDepartment().get(0)), new Long(1)); boolean returnFlg = true; if(!isServerOnline()) { return false; } try{ CorpUserService corpUserService = ServiceFactory.getInstance().getOpenService(CorpUserService.class); corpUserService.updateCorpUser(accessToken, userDetail.getUserid(), userDetail.getName(), orderInDepts, userDetail.getDepartment(), userDetail.getPosition(), userDetail.getMobile(), userDetail.getTel(), userDetail.getWorkPlace(), userDetail.getRemark(), userDetail.getEmail(), userDetail.getJobnumber(), userDetail.getIsHide(), userDetail.getSenior(), userDetail.getExtattr()); }catch(Exception e){ returnFlg = false; e.printStackTrace(); } return returnFlg; } /** * 批量删除用户 * * @param useridlist * @return 如果有一个用户删除失败,都不会删除 * 删除用户时,会将考勤记录一并删除,删除用户之前需要先把考勤记录同步到本地数据库 */ public boolean batchDeleteUser(List useridlist) { boolean returnFlg = true; if(!isServerOnline()) { return false; } try{ CorpUserService corpUserService = ServiceFactory.getInstance().getOpenService(CorpUserService.class); corpUserService.batchdeleteCorpUserListByUserids(accessToken, useridlist); }catch(Exception e){ returnFlg = false; e.printStackTrace(); } return returnFlg; } /** * 获取部门成员(详情) * * @param departmentId 部门id * @param offset 支持分页查询,与size参数同时设置时才生效,此参数代表偏移量 * @param size 支持分页查询,与offset参数同时设置时才生效,此参数代表分页大小,最大100 * @param order 支持分页查询,部门成员的排序规则,默认不传是按自定义排序;entry_asc代表按照进入部门的时间升序, * entry_desc代表按照进入部门的时间降序,modify_asc代表按照部门信息修改时间升序,modify_desc代表按照部门信息修改时间降序,custom代表用户定义(未定义时按照拼音)排序 * @return * @throws Exception */ public CorpUserDetailList getUserDetails(long departmentId,Long offset,Integer size,String order){ CorpUserDetailList corpUserDetailList = new CorpUserDetailList(); try{ CorpUserService corpUserService = ServiceFactory.getInstance().getOpenService(CorpUserService.class); corpUserDetailList = corpUserService.getCorpUserList(accessToken, departmentId,offset, size, order); }catch(Exception e){ e.printStackTrace(); } return corpUserDetailList; } /** * 获取打卡原始记录 * * @param userIds 用户ID列表 最大50个 * @param checkDateFrom 起始时间 格式:yyyy-MM-dd hh:mm:ss * @param checkDateTo 结束时间 格式:yyyy-MM-dd hh:mm:ss(起始时间与结束时间之间最多为7天) * @return * @throws Exception */ public List getSignRecord(List userIds, String checkDateFrom, String checkDateTo){ String url = "https://oapi.dingtalk.com/" + "attendance/listRecord?access_token=" + accessToken ; JSONObject json = new JSONObject(); json.put("userIds", userIds); json.put("checkDateFrom", checkDateFrom); //json.put("checkDateFrom", "2021-12-20 09:00:00"); json.put("checkDateTo", checkDateTo); JSONObject reponseJson = null; List list = new ArrayList(); try { reponseJson = HttpHelper.httpPost(url,json); JSONArray jSONArray = reponseJson.getJSONArray("recordresult"); for(int i = 0; i < jSONArray.size(); i++) { KaoqinEntity kaoqinEntity = new KaoqinEntity(); kaoqinEntity = ((JSON) jSONArray.get(i)).toJavaObject(KaoqinEntity.class); list.add(kaoqinEntity); } } catch (Exception e) { e.printStackTrace(); } return list; } /** * JSONObject 转化为 Map * * @param js * @return */ private HashMap toHashMap(JSONObject js) { if(js == null){ return null; } HashMap data = new HashMap(); // 将json字符串转换成jsonObject Set set = js.keySet(); // 遍历jsonObject数据,添加到Map对象 Iterator it = set.iterator(); while (it.hasNext()) { String key = String.valueOf(it.next()); Long keyLong = Long.valueOf(key); String value = js.getString(key); Long valueLong; if(TextUtils.isEmpty(value)){ valueLong = js.getLong(key); }else{ valueLong = Long.valueOf(value); } data.put(keyLong, valueLong); } return data; } /*---------------------------------------------------------------------------------------------------------------*/ /** * 通过手机号获取userId */ public String getUserIdByPhone(String phone){ String userId = null; try { DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/getbymobile"); OapiV2UserGetbymobileRequest req = new OapiV2UserGetbymobileRequest(); req.setMobile(phone); OapiV2UserGetbymobileResponse rsp = client.execute(req, accessToken); userId = rsp.getResult().getUserid(); } catch (Exception e){ System.out.println("钉钉接口-根据手机号获取userId" + e); } return userId; } /** * 考勤统计列值获取 * @param userId * @return */ public List getColumnVal(String userId){ List list = null; try { DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/attendance/getcolumnval"); OapiAttendanceGetcolumnvalRequest req = new OapiAttendanceGetcolumnvalRequest(); req.setUserid(userId); //应出勤天数:290802238 出勤天数:290802241 迟到次数:290802244 早退次数:290802249 req.setColumnIdList("290802238,290802241,290802244,290802249"); req.setFromDate(DateUtil.beginOfMonth(new Date())); req.setToDate(DateUtil.endOfMonth(new Date())); OapiAttendanceGetcolumnvalResponse rsp = client.execute(req, accessToken); list = rsp.getResult().getColumnVals(); } catch (Exception e){ System.out.println("钉钉接口-获取考勤统计列值" + e); } return list; } }