钉钉接口

2024年9月5日16:00:12
xel
This commit is contained in:
xiang2lin 2024-09-05 16:00:23 +08:00
parent ad23819b59
commit 1f2d0584e2
7 changed files with 530 additions and 1 deletions

18
pom.xml
View File

@ -62,7 +62,8 @@
<minio.version>8.0.3</minio.version>
<postgresql.version>42.2.6</postgresql.version>
<jimureport.version>1.7.4</jimureport.version>
<dingtalk-stream-sdk.version>1.3.7</dingtalk-stream-sdk.version>
<dingtalk-sdk.version>2.1.46</dingtalk-sdk.version>
<!-- <groovy.version>4.0.15</groovy.version>-->
</properties>
<parent>
@ -383,6 +384,21 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>com.dingtalk.open</groupId>
<artifactId>app-stream-client</artifactId>
<version>${dingtalk-stream-sdk.version}</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>dingtalk</artifactId>
<version>${dingtalk-sdk.version}</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>alibaba-dingtalk-service-sdk</artifactId>
<version>2.0.0</version>
</dependency>
</dependencies>
<build>

View File

@ -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;
}
}

View File

@ -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();
}

View File

@ -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<OapiV2DepartmentListsubResponse.DeptBaseResponse> getDeptList(Long deptId,String appKey,String appSecret);
}

View File

@ -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
public class DingTalkExtServiceImpl implements IDingTalkExtService {
@Resource
private ISysApplicationApiParaDao sysApplicationApiParaDao;
private final ConcurrentHashMap<String, JSONObject> dingTalkMap = new ConcurrentHashMap<>();
/**
* 调用这个方法初始化钉钉参数
*
* @param entity
* @return
*/
@Override
public SysExtensionApiEntity init(SysExtensionApiEntity entity) {
Map<String, String> 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<SysApplicationApiParaEntity> paraList = sysApplicationApiParaDao.query(paraEntity);
if (CollectionUtils.isNotEmpty(paraList)) {
List<SysApplicationApiParaEntity> appKeyList = paraList.stream().filter(p -> p.getInterfaceKey().equals("appKey")).collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(appKeyList)) {
jsonObject.put("appKey", appKeyList.get(0).getInterfaceValue());
}
List<SysApplicationApiParaEntity> 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();
}
}

View File

@ -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<OapiV2DepartmentListsubResponse.DeptBaseResponse> 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<OapiV2DepartmentListsubResponse.DeptBaseResponse> result = rsp.getResult();
return result;
}
}catch (Exception e){
logger.error("获取部门列表接口出错:{}",e);
}
return null;
}
}

View File

@ -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);
}
}