From 7b372f3d0bdd5a4450026ba4cd7eec73a748ee46 Mon Sep 17 00:00:00 2001 From: lvleigang <957075182@qq.com> Date: Sat, 14 Sep 2024 09:23:19 +0800 Subject: [PATCH] =?UTF-8?q?fw-dd=E5=88=86=E6=94=AF=E7=BB=93=E6=9E=84?= =?UTF-8?q?=E4=B8=8A=E4=BC=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- base-webapp/pom.xml | 10 +- fw-dd/pom.xml | 48 +++++ .../hzya/frame/dd/IDDInterfaceService.java | 31 ++++ .../frame/dd/impl/DdInterfaceServiceImpl.java | 165 ++++++++++++++++++ .../frame/dingtalk/enums/OrgEventEnum.java | 48 +++++ .../dingtalk/service/IDingTalkExtService.java | 32 ++++ .../dingtalk/service/IDingTalkService.java | 66 +++++++ .../service/impl/DingTalkExtServiceImpl.java | 100 +++++++++++ .../service/impl/DingTalkServiceImpl.java | 164 +++++++++++++++++ .../dingtalk/util/DingTalkAccessToken.java | 103 +++++++++++ fw-dd/src/main/webapp/WEB-INF/web.xml | 6 + pom.xml | 2 +- 12 files changed, 769 insertions(+), 6 deletions(-) create mode 100644 fw-dd/pom.xml create mode 100644 fw-dd/src/main/java/com/hzya/frame/dd/IDDInterfaceService.java create mode 100644 fw-dd/src/main/java/com/hzya/frame/dd/impl/DdInterfaceServiceImpl.java create mode 100644 fw-dd/src/main/java/com/hzya/frame/dingtalk/enums/OrgEventEnum.java create mode 100644 fw-dd/src/main/java/com/hzya/frame/dingtalk/service/IDingTalkExtService.java create mode 100644 fw-dd/src/main/java/com/hzya/frame/dingtalk/service/IDingTalkService.java create mode 100644 fw-dd/src/main/java/com/hzya/frame/dingtalk/service/impl/DingTalkExtServiceImpl.java create mode 100644 fw-dd/src/main/java/com/hzya/frame/dingtalk/service/impl/DingTalkServiceImpl.java create mode 100644 fw-dd/src/main/java/com/hzya/frame/dingtalk/util/DingTalkAccessToken.java create mode 100644 fw-dd/src/main/webapp/WEB-INF/web.xml diff --git a/base-webapp/pom.xml b/base-webapp/pom.xml index 79bd4cf9..15a885ff 100644 --- a/base-webapp/pom.xml +++ b/base-webapp/pom.xml @@ -28,11 +28,11 @@ - - - - - + + com.hzya.frame + fw-dd + ${revision} + diff --git a/fw-dd/pom.xml b/fw-dd/pom.xml new file mode 100644 index 00000000..ebf7aeec --- /dev/null +++ b/fw-dd/pom.xml @@ -0,0 +1,48 @@ + + + + kangarooDataCenterV3 + com.hzya.frame + ${revision} + + 4.0.0 + fw-dd + jar + ${revision} + + + + com.hzya.frame + base-service + ${revision} + + + mysql + mysql-connector-java + ${mysql-connector-java} + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + none + execute + true + + + + + repackage + + + + + + + diff --git a/fw-dd/src/main/java/com/hzya/frame/dd/IDDInterfaceService.java b/fw-dd/src/main/java/com/hzya/frame/dd/IDDInterfaceService.java new file mode 100644 index 00000000..604f8a6f --- /dev/null +++ b/fw-dd/src/main/java/com/hzya/frame/dd/IDDInterfaceService.java @@ -0,0 +1,31 @@ +package com.hzya.frame.dd; + +import com.alibaba.fastjson.JSONObject; +import com.baomidou.dynamic.datasource.annotation.DS; +import com.baomidou.dynamic.datasource.annotation.DSTransactional; +import com.hzya.frame.web.entity.JsonResultEntity; +import org.springframework.stereotype.Service; + +/*** + * 对接钉钉相关功能接口实现类,用于内部应用调用,返回指定格式数据 + * @content: + * @author 👻👻👻👻👻👻👻👻 gjh + * @date 2023-08-29 9:38 + * @param + * @return + **/ + +public interface IDDInterfaceService { + + /*** + * 推送钉钉方法 + * @content: + * @author 👻👻👻👻👻👻👻👻 gjh + * @date 2023-08-29 9:46 + * @param + * @return void + **/ + String senddd(JSONObject requestJson); + + +} diff --git a/fw-dd/src/main/java/com/hzya/frame/dd/impl/DdInterfaceServiceImpl.java b/fw-dd/src/main/java/com/hzya/frame/dd/impl/DdInterfaceServiceImpl.java new file mode 100644 index 00000000..2d4e8775 --- /dev/null +++ b/fw-dd/src/main/java/com/hzya/frame/dd/impl/DdInterfaceServiceImpl.java @@ -0,0 +1,165 @@ +package com.hzya.frame.dd.impl; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.hzya.frame.dd.IDDInterfaceService; +import com.hzya.frame.web.exception.BaseSystemException; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; +import org.springframework.util.ObjectUtils; + + +/** + * @author 👻👻👻👻👻👻👻👻👻👻 gjh + * @version 1.0 + * @content + * @date 2023-08-29 9:48 + */ +@Service(value = "ddInterfaceService") +public class DdInterfaceServiceImpl implements IDDInterfaceService { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + //TODO 此处参数暂时使用变量使用!后续应该使用应用参数动态设置 + + private final String appSecret = "DuRw6EEEvhGXfr6Q8wN_x4025qKjrffIGCXF9KeCKKIID-LVSsR6_8KWMei6sug1"; + private final String appKey = "dingxewtjaserj292ggu"; + //TODO 此处参数暂时使用变量使用!后续应该使用应用参数动态设置 + + @Override + public String senddd(JSONObject requestJson) { + JSONObject jsonStrObj = requestJson.getJSONObject("jsonStr"); + + if(ObjectUtils.isEmpty(jsonStrObj)){ + throw new BaseSystemException("请传入jsonStr参数"); + } + String code = jsonStrObj.getString("code"); + if(StringUtils.isEmpty(code)){ + throw new BaseSystemException("请传入接口编号参数:code"); + } + String url = getDdUrlByType(code); + String accessTokenCode = "0001"; + //如果请求的是token接口,不需要拼接access_token参数 + String result = null; + //如果是单据接口,需要增加access_token参数,在此处定义变量赋值 + String access_token = getToken(); + if(accessTokenCode.equalsIgnoreCase(code)){ + url+= "?appkey="+appKey+"&appsecret="+appSecret; + result = HttpUtil.get(url); + JSONObject jsonObject = analysisDDResult(result); + access_token = jsonObject.getString("access_token"); + }else{ + url+= "?access_token="+access_token; + JSONObject data = jsonStrObj.getJSONObject("data"); + if("0004".equals(code) || "0003".equals(code)|| "0005".equals(code)){ + logger.info("调用钉钉请求前参数:{}",data.toString()); + if("0003".equals(code)){ + String formInstanceId = data.getString("formInstanceId"); + //如果表单ID不等于空走编辑动作 + if(StrUtil.isNotEmpty(formInstanceId)){ + result = HttpRequest.put(url).header("x-acs-dingtalk-access-token",access_token).body(data.toString()).execute().body(); + }else{ + result = HttpRequest.post(url).header("x-acs-dingtalk-access-token",access_token).body(data.toString()).execute().body(); + } + } + + logger.info("调用钉钉返回参数:{}",result); + }else{ + result = HttpRequest.post(url).header("access_token",access_token).body(data.toJSONString()).execute().body(); + } + + } + return result; + } + + + + /***** + * 暂时写个固定获取token方法 + * @content: + * @author 👻👻👻👻👻👻👻👻 gjh + * @date 2023-08-29 14:52 + * @param + * @return java.lang.String + **/ + private String getToken(){ + String url = getDdUrlByType("0001"); + url+= "?appkey="+appKey+"&appsecret="+appSecret; + String result = HttpUtil.get(url); + JSONObject jsonObject = analysisDDResult(result); + String access_token = jsonObject.getString("access_token"); + return access_token; + } + /**** + * 解析钉钉接口返回的数据,转换成json对象 + * @content: + * @author 👻👻👻👻👻👻👻👻 gjh + * @date 2023-08-29 11:55 + * @param + * @return com.alibaba.fastjson.JSONObject + **/ + private JSONObject analysisDDResult(String result){ + //解析result + JSONObject jsonObject = JSON.parseObject(result); + //定义钉钉返回成功的标记 + String okCode = "0"; + //钉钉返回的接口成功标记 + String errorCode = jsonObject.getString("errcode"); + //钉钉接口返回的提示信息 + String errmsg = jsonObject.getString("errmsg"); + //钉钉Result + String ddResult = jsonObject.getString("result"); + //如果返回值是0,则表示调用成功了 + if(okCode.equalsIgnoreCase(errorCode)){ + return jsonObject; + }else{ + throw new BaseSystemException("调用钉钉接口失败!错误代码:"+errorCode+"错误信息:"+errmsg); + } + } + + + /***** + * 把所有做过的钉钉接口在此处做备注,通过给外部系统的编号获取 + * @content: + * @author 👻👻👻👻👻👻👻👻 gjh + * @date 2023-08-29 9:54 + * @param + * @return java.lang.String + **/ + private String getDdUrlByType(String code){ + StringBuffer urlBuffer = null; + if("0003".equals(code)|| "0004".equals(code)|| "0005".equals(code)){ + urlBuffer = new StringBuffer("https://api.dingtalk.com"); + }else{ + urlBuffer = new StringBuffer("https://oapi.dingtalk.com"); + } + switch (code){ + case "0001": + //获取钉钉tokenURL + urlBuffer.append("/gettoken") ; + break; + //通知审批通过URL + case "0002": + urlBuffer.append("/topapi/attendance/approve/finish") ; + break; + //销售合同URL,无流程表单统一Url + case "0003": + urlBuffer.append("/v1.0/yida/forms/instances") ; + break; + case "0004": + urlBuffer.append("/v1.0/yida/forms/instances/search") ; + break; + case "0005": + urlBuffer.append("/v1.0/yida/forms/instances") ; +// urlBuffer.append("/v1.0/yida/processes/instances/start") ; + break; + default: + throw new BaseSystemException("获取钉钉URL错误!请确认URL编号"); + } + return urlBuffer.toString(); + } + +} diff --git a/fw-dd/src/main/java/com/hzya/frame/dingtalk/enums/OrgEventEnum.java b/fw-dd/src/main/java/com/hzya/frame/dingtalk/enums/OrgEventEnum.java new file mode 100644 index 00000000..f01431f0 --- /dev/null +++ b/fw-dd/src/main/java/com/hzya/frame/dingtalk/enums/OrgEventEnum.java @@ -0,0 +1,48 @@ +package com.hzya.frame.dingtalk.enums; + +/** + * @Description 通讯录事件类型 + * @Author xiangerlin + * @Date 2024/8/27 15:58 + **/ +public enum OrgEventEnum { + USER_ADD_ORG("user_add_org","通讯录用户新增"), + USER_MODIFY_ORG("user_modify_org","通讯录用户更改"), + USER_LEAVE_ORG("user_leave_org","通讯录用户离职"), + USER_ACTIVE_ORG("user_active_org","加入企业后用户激活"), + ORG_DEPT_CREATE("org_dept_create","通讯录企业部门创建"), + ORG_DEPT_MODIFY("org_dept_modify","通讯录企业部门更改"), + ORG_DEPT_REMOVE("org_dept_remove","通讯录企业部门删除"), + ; + + + private String code; + private String explain; + + OrgEventEnum(String code, String explain) { + this.code = code; + this.explain = explain; + } + + public String getCode() { + return code; + } + + public String getExplain() { + return explain; + } + + /** + * 根据code获取事件类型 + * @param code + * @return + */ + public static OrgEventEnum getByCode(String code){ + for (OrgEventEnum org : OrgEventEnum.values()) { + if (org.getCode().equals(code)){ + return org; + } + } + return null; + } +} diff --git a/fw-dd/src/main/java/com/hzya/frame/dingtalk/service/IDingTalkExtService.java b/fw-dd/src/main/java/com/hzya/frame/dingtalk/service/IDingTalkExtService.java new file mode 100644 index 00000000..ffbba432 --- /dev/null +++ b/fw-dd/src/main/java/com/hzya/frame/dingtalk/service/IDingTalkExtService.java @@ -0,0 +1,32 @@ +package com.hzya.frame.dingtalk.service; + +import com.alibaba.fastjson.JSONObject; +import com.hzya.frame.sysnew.application.entity.SysApplicationEntity; +import com.hzya.frame.sysnew.application.entity.SysExtensionApiEntity; + +/** + * @Description 钉钉集成扩展类 + * @Author xiangerlin + * @Date 2024/8/28 14:25 + **/ +public interface IDingTalkExtService { + + /** + * 调用这个方法初始化钉钉参数 + * @param entity + * @return + */ + SysExtensionApiEntity init(SysExtensionApiEntity entity); + + /** + * 查询配置在应用上的钉钉参数 + * @param sysApplication + * @return + */ + JSONObject getDingTalkConfig(SysApplicationEntity sysApplication); + + /** + * 清空配置缓存 + */ + void clearDingTalkConfigCatch(); +} diff --git a/fw-dd/src/main/java/com/hzya/frame/dingtalk/service/IDingTalkService.java b/fw-dd/src/main/java/com/hzya/frame/dingtalk/service/IDingTalkService.java new file mode 100644 index 00000000..be742955 --- /dev/null +++ b/fw-dd/src/main/java/com/hzya/frame/dingtalk/service/IDingTalkService.java @@ -0,0 +1,66 @@ +package com.hzya.frame.dingtalk.service; + +import com.dingtalk.api.request.OapiV2UserListRequest; +import com.dingtalk.api.response.OapiV2DepartmentGetResponse; +import com.dingtalk.api.response.OapiV2DepartmentListsubResponse; +import com.dingtalk.api.response.OapiV2UserGetResponse; +import com.dingtalk.api.response.OapiV2UserListResponse; + +import java.util.List; + +/** + * @Description 钉钉service + * @Author xiangerlin + * @Date 2024/8/27 16:17 + **/ +public interface IDingTalkService { + + /** + * 根据userid获取用户详情 + * @param userId 钉钉userid + * @param appKey + * @param appSecret + * @return + */ + OapiV2UserGetResponse.UserGetResponse getUserById(String userId, String appKey, String appSecret); + + /** + * 根据userid获取用户详情 + * @param userId + * @return + */ + OapiV2UserGetResponse.UserGetResponse getUserById(String userId); + + /** + * 获取部门用户列表 + * @param req 请求参数 + * @param appKey + * @param appSecret + * @return + */ + OapiV2UserListResponse.PageResult getUserListByDeptId(OapiV2UserListRequest req, String appKey, String appSecret); + /** + * 根据部门id获取部门详情 + * @param deptId 钉钉部门id + * @param appKey + * @param appSecret + * @return + */ + OapiV2DepartmentGetResponse.DeptGetResponse getDeptById(Long deptId, String appKey, String appSecret); + + /** + * 根据部门id获取部门详情 + * @param deptId + * @return + */ + OapiV2DepartmentGetResponse.DeptGetResponse getDeptById(Long deptId); + + /** + * 获取部门列表,此接口只会返回下一级部门信息 + * @param deptId 部门id,如果不传则查询一级部门 + * @param appKey + * @param appSecret + * @return + */ + List getDeptList(Long deptId, String appKey, String appSecret); +} diff --git a/fw-dd/src/main/java/com/hzya/frame/dingtalk/service/impl/DingTalkExtServiceImpl.java b/fw-dd/src/main/java/com/hzya/frame/dingtalk/service/impl/DingTalkExtServiceImpl.java new file mode 100644 index 00000000..dd0267f8 --- /dev/null +++ b/fw-dd/src/main/java/com/hzya/frame/dingtalk/service/impl/DingTalkExtServiceImpl.java @@ -0,0 +1,100 @@ +package com.hzya.frame.dingtalk.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.hzya.frame.dingtalk.service.IDingTalkExtService; +import com.hzya.frame.dingtalk.util.DingTalkAccessToken; +import com.hzya.frame.sysnew.application.api.entity.SysApplicationApiEntity; +import com.hzya.frame.sysnew.application.apiPara.dao.ISysApplicationApiParaDao; +import com.hzya.frame.sysnew.application.apiPara.entity.SysApplicationApiParaEntity; +import com.hzya.frame.sysnew.application.apiPara.service.ISysApplicationApiParaService; +import com.hzya.frame.sysnew.application.entity.SysApplicationEntity; +import com.hzya.frame.sysnew.application.entity.SysExtensionApiEntity; +import org.apache.commons.collections.CollectionUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * @Description 钉钉集成扩展类 + * @Author xiangerlin + * @Date 2024/8/28 14:25 + **/ +@Service(value = "dingTalkExtService") +public class DingTalkExtServiceImpl implements IDingTalkExtService { + + + @Resource + private ISysApplicationApiParaDao sysApplicationApiParaDao; + private final ConcurrentHashMap dingTalkMap = new ConcurrentHashMap<>(); + /** + * 调用这个方法初始化钉钉参数 + * + * @param entity + * @return + */ + @Override + public SysExtensionApiEntity init(SysExtensionApiEntity entity) { + Map headers = entity.getHeaders(); + if (null == headers){ + headers = new HashMap<>(); + } + SysApplicationEntity receiveApp = entity.getReceiveApp(); + //查询应用上配置的参数 + JSONObject dingTalkConfig = getDingTalkConfig(receiveApp); + //给token赋值 + entity.setQuerys("access_token="+DingTalkAccessToken.getAccessToken(dingTalkConfig.getString("appKey"),dingTalkConfig.getString("appSecret"))); + return entity; + } + + /** + * 查询配置在应用上的钉钉参数 + * + * @param sysApplication + * @return + */ + @Override + public JSONObject getDingTalkConfig(SysApplicationEntity sysApplication) { + if (null != sysApplication && StrUtil.isNotEmpty(sysApplication.getId()) && null != sysApplication.getAppId()){ + JSONObject jsonObject = new JSONObject(); + String key = sysApplication.getAppId()+"dingTalk"; + if (null != dingTalkMap.get(key)){ + return dingTalkMap.get(key); + }else { + //查询应用上配置的参数 + SysApplicationApiParaEntity paraEntity = new SysApplicationApiParaEntity(); + paraEntity.setAppId(sysApplication.getId()); + List paraList = sysApplicationApiParaDao.query(paraEntity); + if (CollectionUtils.isNotEmpty(paraList)) { + List appKeyList = paraList.stream().filter(p -> p.getInterfaceKey().equals("appKey")).collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(appKeyList)) { + jsonObject.put("appKey", appKeyList.get(0).getInterfaceValue()); + } + List appSecretList = paraList.stream().filter(p -> p.getInterfaceKey().equals("appSecret")).collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(appSecretList)) { + jsonObject.put("appSecret", appSecretList.get(0).getInterfaceValue()); + } + dingTalkMap.put(key,jsonObject); + return dingTalkMap.get(key); + } + } + } + return null; + } + + /** + * 清空配置缓存 + */ + @Override + public void clearDingTalkConfigCatch() { + dingTalkMap.clear(); + } +} diff --git a/fw-dd/src/main/java/com/hzya/frame/dingtalk/service/impl/DingTalkServiceImpl.java b/fw-dd/src/main/java/com/hzya/frame/dingtalk/service/impl/DingTalkServiceImpl.java new file mode 100644 index 00000000..89b4bd3e --- /dev/null +++ b/fw-dd/src/main/java/com/hzya/frame/dingtalk/service/impl/DingTalkServiceImpl.java @@ -0,0 +1,164 @@ +package com.hzya.frame.dingtalk.service.impl; + +import com.alibaba.fastjson.JSONObject; +import com.dingtalk.api.DefaultDingTalkClient; +import com.dingtalk.api.DingTalkClient; +import com.dingtalk.api.request.OapiV2DepartmentGetRequest; +import com.dingtalk.api.request.OapiV2DepartmentListsubRequest; +import com.dingtalk.api.request.OapiV2UserGetRequest; +import com.dingtalk.api.request.OapiV2UserListRequest; +import com.dingtalk.api.response.OapiV2DepartmentGetResponse; +import com.dingtalk.api.response.OapiV2DepartmentListsubResponse; +import com.dingtalk.api.response.OapiV2UserGetResponse; +import com.dingtalk.api.response.OapiV2UserListResponse; +import com.hzya.frame.dingtalk.service.IDingTalkService; +import com.hzya.frame.dingtalk.util.DingTalkAccessToken; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @Description 钉钉service + * @Author xiangerlin + * @Date 2024/8/27 16:17 + **/ +@Service +public class DingTalkServiceImpl implements IDingTalkService { + Logger logger = LoggerFactory.getLogger(getClass()); + @Value("${dingtalk.appKey:}") + private String dAppKey; + @Value("${dingtalk.appSecret:}") + private String dAppSecret; + + + /** + * 根据userid获取用户详情 + * + * @param userId 钉钉userid + * @param appKey + * @param appSecret + * @return + */ + @Override + public OapiV2UserGetResponse.UserGetResponse getUserById(String userId, String appKey, String appSecret) { + DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/get"); + OapiV2UserGetRequest req = new OapiV2UserGetRequest(); + req.setUserid(userId); + req.setLanguage("zh_CN"); + try { + OapiV2UserGetResponse rsp = client.execute(req, DingTalkAccessToken.getAccessToken(appKey,appSecret)); + if (rsp.isSuccess()){ + OapiV2UserGetResponse.UserGetResponse result = rsp.getResult(); + String s = JSONObject.toJSONString(result); + logger.info("人员详情信息:{}",s); + return result; + } + }catch (Exception e){ + logger.error("根据部门id获取钉钉用户详情出错:{}",e); + } + return null; + } + + /** + * 根据userid获取用户详情 + * + * @param userId + * @return + */ + @Override + public OapiV2UserGetResponse.UserGetResponse getUserById(String userId) { + return getUserById(userId,dAppKey,dAppSecret); + } + + /** + * 获取部门用户列表 + * + * @param req 请求参数 + * @param appKey + * @param appSecret + * @return + */ + @Override + public OapiV2UserListResponse.PageResult getUserListByDeptId(OapiV2UserListRequest req, String appKey, String appSecret) { + try { + DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/list"); + req.setSize(100L);//每页最大只能查100条 + req.setOrderField("modify_desc"); + req.setContainAccessLimit(false); + req.setLanguage("zh_CN"); + OapiV2UserListResponse rsp = client.execute(req, DingTalkAccessToken.getAccessToken(appKey,appSecret)); + OapiV2UserListResponse.PageResult result = rsp.getResult(); + return result; + }catch (Exception e){ + e.printStackTrace(); + } + return null; + } + + /** + * 根据部门id获取部门详情 + * + * @param deptId 钉钉部门id + * @param appKey + * @param appSecret + * @return + */ + @Override + public OapiV2DepartmentGetResponse.DeptGetResponse getDeptById(Long deptId, String appKey, String appSecret) { + DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/department/get"); + OapiV2DepartmentGetRequest req = new OapiV2DepartmentGetRequest(); + req.setDeptId(deptId); + req.setLanguage("zh_CN"); + try { + OapiV2DepartmentGetResponse rsp = client.execute(req, DingTalkAccessToken.getAccessToken(appKey,appSecret)); + if (rsp.isSuccess()){ + OapiV2DepartmentGetResponse.DeptGetResponse result = rsp.getResult(); + String s = JSONObject.toJSONString(result); + logger.info("部门详情信息:{}",s); + return result; + } + }catch(Exception e){ + logger.error("根据部门id获取钉钉部门出错:{}",e); + } + return null; + } + + /** + * 根据部门id获取部门详情 + * + * @param deptId + * @return + */ + @Override + public OapiV2DepartmentGetResponse.DeptGetResponse getDeptById(Long deptId) { + return getDeptById(deptId,dAppKey,dAppSecret); + } + + /** + * 获取部门列表,此接口只会返回下一级部门信息 + * @param deptId 部门id,如果不传则查询一级部门 + * @param appKey + * @param appSecret + * @return + */ + @Override + public List getDeptList(Long deptId,String appKey,String appSecret) { + try { + DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/department/listsub"); + OapiV2DepartmentListsubRequest req = new OapiV2DepartmentListsubRequest(); + req.setDeptId(deptId); + req.setLanguage("zh_CN"); + OapiV2DepartmentListsubResponse rsp = client.execute(req, DingTalkAccessToken.getAccessToken(appKey,appSecret)); + if (rsp.isSuccess()){ + List result = rsp.getResult(); + return result; + } + }catch (Exception e){ + logger.error("获取部门列表接口出错:{}",e); + } + return null; + } +} diff --git a/fw-dd/src/main/java/com/hzya/frame/dingtalk/util/DingTalkAccessToken.java b/fw-dd/src/main/java/com/hzya/frame/dingtalk/util/DingTalkAccessToken.java new file mode 100644 index 00000000..eb951180 --- /dev/null +++ b/fw-dd/src/main/java/com/hzya/frame/dingtalk/util/DingTalkAccessToken.java @@ -0,0 +1,103 @@ +package com.hzya.frame.dingtalk.util; + +import cn.hutool.core.util.StrUtil; +import com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenResponse; +import com.aliyun.tea.TeaException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; + +import java.time.Instant; + +/** + * @Description 钉钉获取accessToken + * @Author xiangerlin + * @Date 2024/8/27 14:05 + **/ +public class DingTalkAccessToken { + static Logger logger = LoggerFactory.getLogger(DingTalkAccessToken.class); + //token + private static String accessToken; + //过期时间 + private static Instant expireTime; + private static final Long CACHE_EXPIRY_TIME = 7000L; // 缓存有效时间(秒) + //应用key + private static String appKey; + //应用密钥 + private static String appSecret; + @Value("${dingtalk.appKey:}") + public static void setAppKey(String appKey) { + DingTalkAccessToken.appKey = appKey; + } + @Value("${dingtalk.appSecret:}") + public static void setAppSecret(String appSecret) { + DingTalkAccessToken.appSecret = appSecret; + } + + /** + * 获取token + * @return + */ + public static String getAccessToken(){ + return getAccessToken(appKey,appSecret); + } + /** + * 获取accessToken + * + * @param appKey + * @param appSecret + * @return + */ + public static String getAccessToken(String appKey,String appSecret) { + //判断是否过期 如果没过期直接返回 + if (null != accessToken && expireTime != null && Instant.now().isBefore(expireTime)) { + return accessToken; + } + //获取新的accessToken + accessToken = fetchNewAccessToken(appKey,appSecret); + //过期时间设置成当前事件+7000s,预留200s的时间 + expireTime = Instant.now().plusSeconds(CACHE_EXPIRY_TIME); + return accessToken; + } + + /** + * 获取新的accessToken + * + * @return + */ + private static String fetchNewAccessToken(String appKey,String appSecret) { + try { + //查询应用上配置的钉钉信息 + if (StrUtil.isNotEmpty(appKey) && StrUtil.isNotEmpty(appSecret)) { + //查询应用上的信息 + com.aliyun.dingtalkoauth2_1_0.Client client = DingTalkAccessToken.createClient(); + com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenRequest getAccessTokenRequest = new com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenRequest() + .setAppKey(appKey) + .setAppSecret(appSecret); + GetAccessTokenResponse accessToken = client.getAccessToken(getAccessTokenRequest); + String accessToken1 = accessToken.getBody().getAccessToken(); + return accessToken1; + } + } 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 属性,可帮助开发定位问题 + } + logger.error("获取钉钉token出错:{}", _err); + } + return null; + } + + /** + * 使用 Token 初始化账号Client + * + * @return Client + * @throws Exception + */ + private static com.aliyun.dingtalkoauth2_1_0.Client createClient() throws Exception { + com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config(); + config.protocol = "https"; + config.regionId = "central"; + return new com.aliyun.dingtalkoauth2_1_0.Client(config); + } +} diff --git a/fw-dd/src/main/webapp/WEB-INF/web.xml b/fw-dd/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000..d80081d1 --- /dev/null +++ b/fw-dd/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index fc53bd54..cb600e9d 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ base-core - + fw-dd