From f8f94bcc9705bcc22991c0f984ba104f452b2f7a Mon Sep 17 00:00:00 2001
From: JiyangTang <18010816106@163.com>
Date: Tue, 27 Jun 2023 12:53:25 +0800
Subject: [PATCH] =?UTF-8?q?=E6=B6=88=E6=81=AF=E6=8E=A8=E9=80=81=E6=94=B9?=
=?UTF-8?q?=E4=B8=BADINGDING?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
baogutang-admin/pom.xml | 12 +-
.../admin/schedule/EdgeXNoticeSchedule.java | 33 ++++-
.../admin/utils/DingTalkMsgPushUtils.java | 122 ++++++++++++++++++
baogutang-common/pom.xml | 5 +
.../common/constants/CacheConstant.java | 5 +
.../common/constants/DingTalkMsgTypeEnum.java | 62 +++++++++
.../constants/DingTalkServerConstants.java | 53 ++++++++
.../properties/BaoGuTangConfigStrategy.java | 54 ++++++++
.../common/properties/DingTalkAppConfig.java | 36 ++++++
.../properties/DingTalkConfigFactory.java | 46 +++++++
.../properties/DingTalkConfigStrategy.java | 21 +++
11 files changed, 441 insertions(+), 8 deletions(-)
create mode 100644 baogutang-admin/src/main/java/top/baogutang/admin/utils/DingTalkMsgPushUtils.java
create mode 100644 baogutang-common/src/main/java/top/baogutang/common/constants/DingTalkMsgTypeEnum.java
create mode 100644 baogutang-common/src/main/java/top/baogutang/common/constants/DingTalkServerConstants.java
create mode 100644 baogutang-common/src/main/java/top/baogutang/common/properties/BaoGuTangConfigStrategy.java
create mode 100644 baogutang-common/src/main/java/top/baogutang/common/properties/DingTalkAppConfig.java
create mode 100644 baogutang-common/src/main/java/top/baogutang/common/properties/DingTalkConfigFactory.java
create mode 100644 baogutang-common/src/main/java/top/baogutang/common/properties/DingTalkConfigStrategy.java
diff --git a/baogutang-admin/pom.xml b/baogutang-admin/pom.xml
index 04d7452..04d8186 100644
--- a/baogutang-admin/pom.xml
+++ b/baogutang-admin/pom.xml
@@ -79,11 +79,7 @@
junit-jupiter-api
test
-
- com.aliyun
- dingtalk
- 2.0.20
-
+
cn.dev33
@@ -103,7 +99,11 @@
forest-spring-boot-starter
1.5.26
-
+
+ com.aliyun
+ alibaba-dingtalk-service-sdk
+ 2.0.0
+
diff --git a/baogutang-admin/src/main/java/top/baogutang/admin/schedule/EdgeXNoticeSchedule.java b/baogutang-admin/src/main/java/top/baogutang/admin/schedule/EdgeXNoticeSchedule.java
index 1ee174c..56e1fb4 100644
--- a/baogutang-admin/src/main/java/top/baogutang/admin/schedule/EdgeXNoticeSchedule.java
+++ b/baogutang-admin/src/main/java/top/baogutang/admin/schedule/EdgeXNoticeSchedule.java
@@ -2,15 +2,18 @@ package top.baogutang.admin.schedule;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
-import com.zjiecode.wxpusher.client.bean.Message;
+import com.dingtalk.api.request.OapiMessageCorpconversationAsyncsendV2Request;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import top.baogutang.admin.domain.EdgeXAnnouncementsDto;
import top.baogutang.admin.services.IWxMsgPushService;
+import top.baogutang.admin.utils.DingTalkMsgPushUtils;
+import top.baogutang.common.constants.DingTalkMsgTypeEnum;
import top.baogutang.common.domain.Page;
import top.baogutang.common.domain.Results;
import top.baogutang.common.properties.WxMsgPushProperties;
@@ -41,6 +44,12 @@ public class EdgeXNoticeSchedule {
@Resource
private RedisTemplate redisTemplate;
+ @Resource
+ private DingTalkMsgPushUtils dingTalkMsgPushUtils;
+
+ @Value("${dingtalk.baogutang.agentId}")
+ private String agentId;
+
private static final String REQUEST_URL = "https://art-api.edge-x.cn/api/v1/art/announcements?pageNum=1&pageSize=1";
/**
@@ -65,7 +74,27 @@ public class EdgeXNoticeSchedule {
Boolean result = redisTemplate.opsForValue().setIfAbsent(cacheKey, 1, 5, TimeUnit.DAYS);
if (Boolean.TRUE.equals(result)) {
- wxMsgPushService.msgPush(Message.CONTENT_TYPE_HTML, announcementsDto.getTitle(), announcementsDto.getContent(), wxMsgPushProperties.getTopicIds());
+ dingTalkMsgPushUtils.dingTalkMsgPush(agentId, Boolean.TRUE, null, null, this.geneMsg(announcementsDto));
+// wxMsgPushService.msgPush(Message.CONTENT_TYPE_HTML, announcementsDto.getTitle(), announcementsDto.getContent(), wxMsgPushProperties.getTopicIds());
}
}
+
+ private OapiMessageCorpconversationAsyncsendV2Request.Msg geneMsg(EdgeXAnnouncementsDto announcementsDto) {
+ // 读取消息文件
+ OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
+ msg.setMsgtype(DingTalkMsgTypeEnum.ACTION_CARD.getType());
+ OapiMessageCorpconversationAsyncsendV2Request.ActionCard actionCard = new OapiMessageCorpconversationAsyncsendV2Request.ActionCard();
+ // 透出到会话列表和通知的文案
+ actionCard.setTitle(announcementsDto.getTitle());
+ // 支持markdown格式的正文内容
+ String title = "# " + announcementsDto.getTitle() + "+\n\n";
+ String image = " + ")";
+ actionCard.setMarkdown(title + image);
+ // 跳转按钮展示
+ actionCard.setSingleTitle("查看详情");
+ // 跳转URL
+ actionCard.setSingleUrl("https://app.edge-x.cn/#/noticeDetail?noticeId=" + announcementsDto.getId());
+ msg.setActionCard(actionCard);
+ return msg;
+ }
}
diff --git a/baogutang-admin/src/main/java/top/baogutang/admin/utils/DingTalkMsgPushUtils.java b/baogutang-admin/src/main/java/top/baogutang/admin/utils/DingTalkMsgPushUtils.java
new file mode 100644
index 0000000..c63a415
--- /dev/null
+++ b/baogutang-admin/src/main/java/top/baogutang/admin/utils/DingTalkMsgPushUtils.java
@@ -0,0 +1,122 @@
+package top.baogutang.admin.utils;
+
+import com.alibaba.fastjson.JSON;
+import com.dingtalk.api.DefaultDingTalkClient;
+import com.dingtalk.api.DingTalkClient;
+import com.dingtalk.api.request.OapiGettokenRequest;
+import com.dingtalk.api.request.OapiMessageCorpconversationAsyncsendV2Request;
+import com.dingtalk.api.response.OapiGettokenResponse;
+import com.dingtalk.api.response.OapiMessageCorpconversationAsyncsendV2Response;
+import com.taobao.api.ApiException;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+import top.baogutang.common.exceptions.BusinessException;
+import top.baogutang.common.properties.DingTalkConfigFactory;
+import top.baogutang.common.properties.DingTalkConfigStrategy;
+
+import javax.annotation.Resource;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+
+import static top.baogutang.common.constants.CacheConstant.PREFIX_DING_TALK_ACCESS_TOKEN;
+import static top.baogutang.common.constants.DingTalkServerConstants.ACC_TOKEN;
+import static top.baogutang.common.constants.DingTalkServerConstants.CORP_CONVERSATION_ASYNC_SEND_V2;
+
+
+/**
+ * @description: 钉钉消息推送工具类
+ * @author: nikooh
+ * @date: 2023/04/03 : 16:29
+ */
+@Slf4j
+@Component
+public class DingTalkMsgPushUtils {
+
+ @Resource
+ private DingTalkConfigFactory dingTalkConfigFactory;
+
+ @Resource
+ private RedisTemplate redisTemplate;
+
+ /**
+ * 钉钉消息推送 {https://open.dingtalk.com/document/orgapp/work-notice-option}
+ *
+ * @param agentId 应用ID
+ * @param deptIdList 消息接收部门ID集合
+ * @param userIdList 消息接收用户ID集合
+ * @param message 具体消息内容
+ * @return 消息ID
+ */
+ public Long dingTalkMsgPush(String agentId, Boolean toAllUser, List deptIdList, List userIdList, OapiMessageCorpconversationAsyncsendV2Request.Msg message) {
+
+ // 1.获取消息所属应用及应用token
+ String accessToken = this.getAccessToken(agentId);
+ if (StringUtils.isBlank(accessToken)) {
+ throw new BusinessException("消息发送失败->未能成功生成应用token");
+ }
+
+ // 2.组装dingTalk请求参数
+ OapiMessageCorpconversationAsyncsendV2Request request = new OapiMessageCorpconversationAsyncsendV2Request();
+ request.setAgentId(Long.parseLong(agentId));
+ request.setToAllUser(toAllUser);
+ if (CollectionUtils.isNotEmpty(deptIdList)) {
+ request.setDeptIdList(StringUtils.join(deptIdList.toArray(), ","));
+ }
+ if (CollectionUtils.isNotEmpty(userIdList)) {
+ request.setUseridList(StringUtils.join(userIdList.toArray(), ","));
+ }
+ request.setMsg(message);
+
+ // 3.请求钉钉发送消息
+ DingTalkClient client = new DefaultDingTalkClient(CORP_CONVERSATION_ASYNC_SEND_V2);
+ OapiMessageCorpconversationAsyncsendV2Response response = null;
+ try {
+ response = client.execute(request, accessToken);
+ log.info(">>>>>>>>>>request dingTalk send msg res:{}<<<<<<<<<<", JSON.toJSONString(response));
+ return response.getTaskId();
+ } catch (Exception e) {
+ log.error(">>>>>>>>>>request dingTalk send msg error:{}<<<<<<<<<<", e.getMessage(), e);
+ return null;
+ }
+ }
+
+ /**
+ * 获取钉钉应用accessToken
+ *
+ * @param agentId 应用ID
+ * @return token
+ */
+ public String getAccessToken(String agentId) {
+ DingTalkConfigStrategy config = dingTalkConfigFactory.getConfigByAgentId(agentId);
+ String appKey = config.getAppKey();
+ String appSecret = config.getAppSecret();
+ String cacheKey = PREFIX_DING_TALK_ACCESS_TOKEN + appKey;
+ Object accessTokenObj = redisTemplate.opsForValue().get(cacheKey);
+ if (Objects.nonNull(accessTokenObj)) {
+ return (String) accessTokenObj;
+ }
+ // 缓存不存在,生成token
+ DingTalkClient client = new DefaultDingTalkClient(ACC_TOKEN);
+ OapiGettokenRequest request = new OapiGettokenRequest();
+ request.setAppkey(appKey);
+ request.setAppsecret(appSecret);
+ request.setHttpMethod("GET");
+ OapiGettokenResponse response;
+ try {
+ response = client.execute(request);
+ log.info(">>>>>>>>>>request dingTalk gene accessToken,request:[{}] response:[{}]<<<<<<<<<<", JSON.toJSONString(request), JSON.toJSONString(response));
+ if (Objects.nonNull(response) && Objects.nonNull(response.getAccessToken())) {
+ redisTemplate.opsForValue().set(cacheKey, response.getAccessToken(), 7000L, TimeUnit.SECONDS);
+ return response.getAccessToken();
+ }
+ } catch (Exception e) {
+ log.error(">>>>>>>>>>request dingTalk gene accessToken error! request:{},errorMsg:{}<<<<<<<<<<", JSON.toJSONString(request), e.getMessage(), e);
+ }
+ return null;
+ }
+
+}
diff --git a/baogutang-common/pom.xml b/baogutang-common/pom.xml
index ea7ae0b..49cb02d 100644
--- a/baogutang-common/pom.xml
+++ b/baogutang-common/pom.xml
@@ -144,6 +144,11 @@
hutool-all
5.7.4
+
+ com.aliyun
+ dingtalk
+ 2.0.14
+
\ No newline at end of file
diff --git a/baogutang-common/src/main/java/top/baogutang/common/constants/CacheConstant.java b/baogutang-common/src/main/java/top/baogutang/common/constants/CacheConstant.java
index 65bb54a..9b20152 100644
--- a/baogutang-common/src/main/java/top/baogutang/common/constants/CacheConstant.java
+++ b/baogutang-common/src/main/java/top/baogutang/common/constants/CacheConstant.java
@@ -34,4 +34,9 @@ public class CacheConstant {
public static final Integer ENABLE = 0;
+
+ /**
+ * 钉钉应用access_token缓存KEY前缀
+ */
+ public static final String PREFIX_DING_TALK_ACCESS_TOKEN = "top:baogutang:dingtalk:access_token:";
}
diff --git a/baogutang-common/src/main/java/top/baogutang/common/constants/DingTalkMsgTypeEnum.java b/baogutang-common/src/main/java/top/baogutang/common/constants/DingTalkMsgTypeEnum.java
new file mode 100644
index 0000000..8f151eb
--- /dev/null
+++ b/baogutang-common/src/main/java/top/baogutang/common/constants/DingTalkMsgTypeEnum.java
@@ -0,0 +1,62 @@
+package top.baogutang.common.constants;
+
+/**
+ * @description: 钉钉消息类型枚举
+ * @author: nikooh
+ * @date: 2023/04/07 : 13:41
+ */
+public enum DingTalkMsgTypeEnum {
+
+ /**
+ * 文本消息
+ */
+ TEXT("text"),
+
+ /**
+ * 图片消息
+ */
+ IMAGE("image"),
+
+ /**
+ * 语音消息
+ */
+ VOICE("voice"),
+
+ /**
+ * 文件消息
+ */
+ FILE("file"),
+
+ /**
+ * 链接消息
+ */
+ LINK("link"),
+
+ /**
+ * OA消息
+ */
+ OA("oa"),
+
+ /**
+ * markdown消息
+ */
+ MARKDOWN("markdown"),
+
+ /**
+ * 卡片消息
+ */
+ ACTION_CARD("action_card"),
+
+ ;
+
+ private final String type;
+
+ DingTalkMsgTypeEnum(String type) {
+ this.type = type;
+ }
+
+
+ public String getType() {
+ return type;
+ }
+}
diff --git a/baogutang-common/src/main/java/top/baogutang/common/constants/DingTalkServerConstants.java b/baogutang-common/src/main/java/top/baogutang/common/constants/DingTalkServerConstants.java
new file mode 100644
index 0000000..25c2bfd
--- /dev/null
+++ b/baogutang-common/src/main/java/top/baogutang/common/constants/DingTalkServerConstants.java
@@ -0,0 +1,53 @@
+package top.baogutang.common.constants;
+
+/**
+ * @description: 钉钉服务相关常量
+ * @author: nikooh
+ * @date: 2023/06/21 : 16:53
+ */
+public class DingTalkServerConstants {
+
+ private DingTalkServerConstants() {
+ // private constructor
+ }
+
+ /**
+ * token
+ */
+ public static final String ACC_TOKEN = "https://oapi.dingtalk.com/gettoken";
+
+ /**
+ * 群组创建
+ */
+ public static final String CHAT_CREATE = "https://oapi.dingtalk.com/chat/create";
+
+ /**
+ * 群组修改
+ */
+ public static final String CHAT_UPDATE = "https://oapi.dingtalk.com/chat/update";
+
+ /**
+ * 工作通知
+ */
+ public static final String CORP_CONVERSATION_ASYNC_SEND_V2 = "https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2";
+
+ /**
+ * 部门下员工
+ */
+ public static final String USER_LIST = "https://oapi.dingtalk.com/topapi/v2/user/list";
+
+ /**
+ * 部门列表
+ */
+ public static final String DEPARTMENT_LIST = "https://oapi.dingtalk.com/department/list";
+
+ /**
+ * 用户详情
+ */
+ public static final String USER_INFO = "https://oapi.dingtalk.com/user/getuserinfo";
+
+ /**
+ * 手机号搜索userId
+ */
+ public static final String USER_ID_BY_MOBILE = "https://oapi.dingtalk.com/topapi/v2/user/getbymobile";
+}
diff --git a/baogutang-common/src/main/java/top/baogutang/common/properties/BaoGuTangConfigStrategy.java b/baogutang-common/src/main/java/top/baogutang/common/properties/BaoGuTangConfigStrategy.java
new file mode 100644
index 0000000..1292f3d
--- /dev/null
+++ b/baogutang-common/src/main/java/top/baogutang/common/properties/BaoGuTangConfigStrategy.java
@@ -0,0 +1,54 @@
+package top.baogutang.common.properties;
+
+import org.springframework.stereotype.Component;
+
+/**
+ * @author niko
+ * @version 0.1.0
+ * @create 2023/3/31 19:25
+ * @since 0.1.0
+ **/
+@Component
+public class BaoGuTangConfigStrategy implements DingTalkConfigStrategy {
+ private String agentId;
+ private String appKey;
+ private String appSecret;
+ private String appCorpId;
+ private String appSource;
+
+ public BaoGuTangConfigStrategy() {
+ }
+
+ public BaoGuTangConfigStrategy(String agentId, String appKey, String appSecret, String appCorpId, String appSource) {
+ this.agentId = agentId;
+ this.appKey = appKey;
+ this.appSecret = appSecret;
+ this.appCorpId = appCorpId;
+ this.appSource = appSource;
+ }
+
+ @Override
+ public String getAgentId() {
+ return agentId;
+ }
+
+ @Override
+ public String getAppKey() {
+ return appKey;
+ }
+
+ @Override
+ public String getAppSecret() {
+ return appSecret;
+ }
+
+ @Override
+ public String getAppCorpId() {
+ return appCorpId;
+ }
+
+ @Override
+ public String getAppSource() {
+ return appSource;
+ }
+}
diff --git a/baogutang-common/src/main/java/top/baogutang/common/properties/DingTalkAppConfig.java b/baogutang-common/src/main/java/top/baogutang/common/properties/DingTalkAppConfig.java
new file mode 100644
index 0000000..0d160c7
--- /dev/null
+++ b/baogutang-common/src/main/java/top/baogutang/common/properties/DingTalkAppConfig.java
@@ -0,0 +1,36 @@
+package top.baogutang.common.properties;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author niko
+ * @version 0.1.0
+ * @create 2023/3/31 17:15
+ * @since 0.1.0
+ **/
+@Component
+@ConfigurationProperties(prefix = "dingtalk")
+@Getter
+@Setter
+public class DingTalkAppConfig {
+
+ private BaoGuTangProperties baoGuTang = new BaoGuTangProperties();
+
+ @NoArgsConstructor
+ @AllArgsConstructor
+ @Getter
+ @Setter
+ public static class BaoGuTangProperties {
+ private String agentId;
+ private String appKey;
+ private String appSecret;
+ private String appCorpId;
+ }
+
+}
+
diff --git a/baogutang-common/src/main/java/top/baogutang/common/properties/DingTalkConfigFactory.java b/baogutang-common/src/main/java/top/baogutang/common/properties/DingTalkConfigFactory.java
new file mode 100644
index 0000000..faa4e50
--- /dev/null
+++ b/baogutang-common/src/main/java/top/baogutang/common/properties/DingTalkConfigFactory.java
@@ -0,0 +1,46 @@
+package top.baogutang.common.properties;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Component;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * @author niko
+ * @version 0.1.0
+ * @create 2023/3/31 19:25
+ * @since 0.1.0
+ **/
+@Component
+public class DingTalkConfigFactory {
+
+ public static final String BAO_GU_TANG = "BAO_GU_TANG";
+
+ private Map configMap;
+
+ @Qualifier
+ public DingTalkAppConfig dingTalkAppConfig;
+
+ @Autowired
+ public DingTalkConfigFactory(DingTalkAppConfig dingTalkAppConfig) {
+ this.dingTalkAppConfig = dingTalkAppConfig;
+ this.configMap = new HashMap<>();
+ this.configMap.put(BAO_GU_TANG, new BaoGuTangConfigStrategy(dingTalkAppConfig.getBaoGuTang().getAgentId(),
+ dingTalkAppConfig.getBaoGuTang().getAppKey(), dingTalkAppConfig.getBaoGuTang().getAppSecret(),
+ dingTalkAppConfig.getBaoGuTang().getAppCorpId(), BAO_GU_TANG));
+ }
+
+ public DingTalkConfigStrategy getConfig(String appType) {
+ return configMap.get(appType);
+ }
+
+ public DingTalkConfigStrategy getConfigByAgentId(String agentId) {
+ if (Objects.equals(agentId, dingTalkAppConfig.getBaoGuTang().getAgentId())) {
+ return getConfig(BAO_GU_TANG);
+ }
+ return null;
+ }
+}
diff --git a/baogutang-common/src/main/java/top/baogutang/common/properties/DingTalkConfigStrategy.java b/baogutang-common/src/main/java/top/baogutang/common/properties/DingTalkConfigStrategy.java
new file mode 100644
index 0000000..77d5345
--- /dev/null
+++ b/baogutang-common/src/main/java/top/baogutang/common/properties/DingTalkConfigStrategy.java
@@ -0,0 +1,21 @@
+package top.baogutang.common.properties;
+
+/**
+ * @author niko
+ * @version 0.1.0
+ * @create 2023/3/31 19:23
+ * @since 0.1.0
+ **/
+public interface DingTalkConfigStrategy {
+
+ String getAgentId();
+
+ String getAppKey();
+
+ String getAppSecret();
+
+ String getAppCorpId();
+
+ String getAppSource();
+
+}
\ No newline at end of file