springboot集成钉钉通知
目录
1.通过自定义机器人方式发送群消息
1.1说明
1.2发送普通消息示例(采用加签方式)
1.3注意事项
2.通过企业内部应用发送钉钉消息
2.1说明
2.2示例
2.3注意
1.通过自定义机器人方式发送群消息
1.1说明
官网地址:
自定义机器人发送群消息 - 钉钉开放平台
自定义机器人的创建和安装 - 钉钉开放平台
自定义机器人安全设置 - 钉钉开放平台
自定义机器人在群聊场景中的使用 - 钉钉开放平台
首先创建企业内部群,按照官方文档进行创建和安装, 自定义机器人的安全设置分为一下三种:
①自定义关键词
发送的消息中至少包含其中一个关键词才可以发送成功
②加签方式
加签方式是钉钉机器人和开发者双向进行安全认证,在群内@自定义机器人时,开发者的POST地址收到机器人消息携带的headers参数,其中包含timestamp和sign字段,开发者需要在自己服务内重新计算sign签名值,最后再调用自定义机器人发送消息接口时,携带开发者服务器内系统当前timestamp和重新计算的sign签名,以此来验证安全性。
③IP地址
设定后,只有来自IP地址范围内的请求才会被正常处理,支持两种设置方式:IP地址和IP地址段,暂不支持IPv6地址白名单
1.2发送普通消息示例(采用加签方式)
①引入依赖
<dependency><groupId>com.aliyun</groupId><artifactId>alibaba-dingtalk-service-sdk</artifactId><version>2.0.0</version>
</dependency>
②创建发送消息工具类
package com.kingagroot.info.common.tools.thirdparty;import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiRobotSendRequest;
import com.kingagroot.info.common.tools.common.LogTool;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;/*** @Author linaibo* @Date 2023/11/21 9:45* @Version 1.0*/
@Component
public class DingDingTool {private static LogTool logTool;@Autowiredpublic void setLogTool(LogTool logTool) {DingDingTool.logTool = logTool;}private static String secret;private static String url;@NacosValue(value = "${ding.secret}", autoRefreshed = true)public void setSecret(String secret) {DingDingTool.secret = secret;}@NacosValue(value = "${ding.url}", autoRefreshed = true)public void setUrl(String url) {DingDingTool.url = url;}/*** 组装签名url** @return url*/public static String getURL() throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {Long timestamp = System.currentTimeMillis();String stringToSign = timestamp + "\n" + secret;Mac mac = Mac.getInstance("HmacSHA256");mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));byte[] signData = mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8));String sign = URLEncoder.encode(new String(Base64.getEncoder().encode(signData)), "UTF-8");String signResult = "×tamp=" + timestamp + "&sign=" + sign;// 得到拼接后的 URLreturn url + signResult;}/*** 获取客户端** @return*/public static DingTalkClient getClient() throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {return new DefaultDingTalkClient(getURL());}/*** 发送钉钉消息** @param msg*/public static void sendDingMsg(String msg) {try {DingTalkClient client = getClient();OapiRobotSendRequest request = new OapiRobotSendRequest();//设置发送消息类型request.setMsgtype("text");//设置消息内容OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text();text.setContent(msg);request.setText(text);//设置给谁发送消息OapiRobotSendRequest.At at = new OapiRobotSendRequest.At();// isAtAll类型如果不为Boolean,请升级至最新SDK,设置为true代表@群内的所有人at.setIsAtAll(true);//也可以指定接收人的手机号或者钉钉id,将消息发送给指定的人// at.setAtMobiles(Arrays.asList("1392xxxxx","155xxxx"));request.setAt(at);client.execute(request);} catch (Exception e) {logTool.saveExceptionLog("", "", "sendDingMsg", e);}}
}
url是创建自定义机器人是的webhook地址,secret是开启加签模式时的密钥。
使用加签方式调用自定义机器人发送消息时需要拼接当前的时间戳和签名。
签名生成方式:把timestamp+"\n"+密钥当做签名字符串,使用HmacSHA256算法计算签名,然后进行Base64 encode,最后再把签名参数再进行urlEncode,得到最终的签名。
发送消息时可以设置发送消息的类型及给谁发送
1.3注意事项
①部署到服务器后,一定要开通服务器访问钉钉的权限,否则会出现connect reset的错误
②注意对钉钉发送异常时的信息记录,可以存到日志表中或者是日志文件中
参照:SpringBoot集成钉钉自定义机器人群消息推送-CSDN博客
2.通过企业内部应用发送钉钉消息
2.1说明
官方文档:
获取企业内部应用的access_token - 钉钉开放平台
发送工作通知 - 钉钉开放平台
首先要在钉钉的开发者后台创建应用,获取应用的AppKey、AppSecret及AgentId。获取企业内部应用的token,然后再调用发送消息接口进行消息的发送。
2.2示例
package com.kingagroot.info.common.tools.common;import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.api.config.annotation.NacosValue;
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.kingagroot.info.common.tools.thirdparty.DingDingTool;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;/*** @Author linaibo* @Date 2024/1/6 16:18* @Version 1.0*/
@Component
public class DingTool {private static LogTool logTool;@Autowiredpublic void setLogTool(LogTool logTool) {DingTool.logTool = logTool;}// 权限用户名private static String accessKey;// 权限密码private static String secret;// agent_idprivate static Long agentId;// tokenUrlprivate static String tokenUrl;// 发送消息urlprivate static String sendMsgUrl;// 系统urlprivate static String sysUrl;@NacosValue(value = "${dingding.appkey}", autoRefreshed = true)public void setAccessKey(String accessKey) {DingTool.accessKey = accessKey;}@NacosValue(value = "${dingding.appsecret}", autoRefreshed = true)public void setSecret(String secret) {DingTool.secret = secret;}@NacosValue(value = "${dingding.agentId}", autoRefreshed = true)public void setAgentId(Long agentId) {DingTool.agentId = agentId;}@NacosValue(value = "${dingding.gettoken}", autoRefreshed = true)public void setTokenUrl(String tokenUrl) {DingTool.tokenUrl = tokenUrl;}@NacosValue(value = "${dingding.sendMsg}", autoRefreshed = true)public void setSendMsgUrl(String sendMsgUrl) {DingTool.sendMsgUrl = sendMsgUrl;}@NacosValue(value = "${sys.url}", autoRefreshed = true)public void setSysUrl(String sysUrl) {DingTool.sysUrl = sysUrl;}/*** 获取钉钉token** @return*/public static String getDingToken() {DingTalkClient client = new DefaultDingTalkClient(tokenUrl);OapiGettokenRequest request = new OapiGettokenRequest();request.setAppkey(accessKey);request.setAppsecret(secret);request.setHttpMethod("GET");try {OapiGettokenResponse response = client.execute(request);if (response.isSuccess()) {// 调用成功返回token信息return response.getAccessToken();}// 调用接口异常,输出异常信息,发送钉钉通知logTool.saveExceptionLog("", "DingUtils", "getDingToken", JSON.toJSONString(response));DingDingTool.sendDingMsg("获取钉钉token失败," + response.getErrcode() + response.getErrmsg());} catch (Exception e) {// 调用接口异常,输出异常信息logTool.saveExceptionLog("", "DingUtils", "getDingToken", e);}return null;}/*** 发送钉钉通知** @param token* @param pwd* @param userCode*/public static boolean sendMsg(String token, String pwd, String userCode) {DingTalkClient client = new DefaultDingTalkClient(sendMsgUrl);OapiMessageCorpconversationAsyncsendV2Request request = new OapiMessageCorpconversationAsyncsendV2Request();request.setAgentId(agentId);request.setUseridList(userCode);request.setToAllUser(false);OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();msg.setMsgtype("text");msg.setText(new OapiMessageCorpconversationAsyncsendV2Request.Text());StringBuilder content = new StringBuilder();content.append("系统地址: ");content.append(sysUrl);content.append(" ");content.append("密码: ");content.append(pwd);msg.getText().setContent(content.toString());request.setMsg(msg);try {OapiMessageCorpconversationAsyncsendV2Response result = client.execute(request, token);if (result.isSuccess()) {return true;}// 调用接口异常,输出异常信息logTool.saveExceptionLog("", "DingUtils", "sendMsg", JSON.toJSONString(result));} catch (Exception e) {// 调用接口异常,输出异常信息logTool.saveExceptionLog("", "DingUtils", "sendMsg", e);}return false;}
}
2.3注意
①获取的token有效期为2个小时,有效期内重复获取会返回相同结果并自动续期,过期后获取会返回新的access_token。开发者需要缓存access_token,用于后续接口的调用。因为每个应用的access_token是彼此独立的,所以进行缓存时需要区分应用来进行存储。不能频繁调用gettoken接口,否则会受到频率拦截。
②发送消息接口为异步发送消息,接口返回成功并不表示用户一定会收到消息,需要通过获取工作通知消息的发送结果接口查询是否给用户发送成功。
③如果获取工作通知发送结果接口返回成功但用户还是没有接收到消息,需要确认一下,此用户是否在此钉钉关联的组织结构内。
④可以给全部员工发送,也可以给某个部门的人发送,也可以给某几个人(通过指定接收人的钉钉id)发送消息。
⑤注意对异常的捕捉,并对消息进行记录。
相关文章:
springboot集成钉钉通知
目录 1.通过自定义机器人方式发送群消息 1.1说明 1.2发送普通消息示例(采用加签方式) 1.3注意事项 2.通过企业内部应用发送钉钉消息 2.1说明 2.2示例 2.3注意 1.通过自定义机器人方式发送群消息 1.1说明 官网地址: 自定义机器人发送…...
直播预告丨看零售场,如何玩转 MaaS
今年,有一个被频繁提及的词是MaaS 这类工具正在帮助千行百业实现大模型落地产业 在零售场,特别是像京东这样拥有超高并发、超复杂协同的电商场内 也沉淀出了一套通用的AI基础设施——九数算法中台 从提升客户服务体验、平台效率出发,训练各…...
高创新!EI论文复现+改进:聚合温度调控策略的综合能源系统/微电网/虚拟电厂多目标优化调度程序代码!
程序考虑供热的热惯性,并根据室内供热效果进行柔性供热,发挥热温度负荷的“储能”能力;针对普适性参数的室内空调进行集群研究,深入剖析温度设定值调整导致负荷波动的机理,并提出一种新的温度调整方法,平抑…...
详解Matlab深度学习进行波形分割
🔗 运行环境:Matlab 🚩 撰写作者:左手の明天 🥇 精选专栏:《python》 🔥 推荐专栏:《算法研究》 🔐#### 防伪水印——左手の明天 ####🔐 💗 大家…...
如何在Windows 10/11的防火墙中禁止和允许某个应用程序,这里提供详细步骤
想阻止应用程序访问互联网吗?以下是如何通过简单的步骤阻止和允许Windows防火墙中的程序。 一般来说,大多数用户永远不需要担心应用程序访问互联网。然而,在某些情况下,你需要限制应用程序访问互联网。 例如,有问题…...
vivado 添加现有IP文件、生成IP
添加现有IP文件 作为从AMD IP目录添加和自定义IP的替代方案,您可以直接添加XCI或XCIX文件。此过程不同于从按以下方式编目: •XCI或XCIX文件可能是早期版本,也可能是相同或完全自定义的版本AMD IP目录中发现的类似IP。 •XCI或XCIX文件可能…...
C++右值引用,右值引用与const引用的区别
1.右值与左值 左值:可以取地址的、有名字的变量,有持久性;右值:一般是不可寻址的常量,或在表达式求值过程中创建的无名临时对象,短暂性的。 2.右值引用 C11新增了另一种引用——右值引用。这种引用可指向…...
启英泰伦推出「离线自然说」,离线语音交互随意说,不需记忆词条
离线语音识别是指不需要依赖网络,在本地设备实现语音识别的过程,通常以端侧AI语音芯片作为载体来进行数据的采集、计算和决策。但是语音芯片的存储空间有限,通过传统的语音算法技术,最多也只能存储数百条词条,导致用户…...
Vulnhub-DC1
前言 一个比较简单的实战靶场,官方要求是找到/root下的flag,所以直接提权即可。但对于学习和训练来说还是太简略了,在打靶场的时候还是全面一些较好。 本次靶场实战涉及信息收集、漏洞查找与利用、getshell、数据库渗透、密码破解、linux提…...
【c++笔记】总结!c++与c语言的不同之处
(Θ3Θ) hi~ 众所周知\(^o^)/~,c语言和c联系密切,又相互区别,本篇文章主要介绍c与c语言的区别与联系以及一些简单的不同点的运用,很适合刚接触c的朋友,一起来瞧瞧看吧~~ 目录 一、文章内容梗概 二、概念…...
大模型PEFT技术原理(一):BitFit、Prefix Tuning、Prompt Tuning
随着预训练模型的参数越来越大,尤其是175B参数大小的GPT3发布以来,让很多中小公司和个人研究员对于大模型的全量微调望而却步,近年来研究者们提出了各种各样的参数高效迁移学习方法(Parameter-efficient Transfer Learning&#x…...
VMware vSphere运维管理手册
适用版本:VMware vSphere 7.0 VMware vSphere 是 VMware 的虚拟化平台,可将数据中心转换为包括 CPU、存储和网络资源的聚合计算基础架构。vSphere 将这些基础架构作为一个统一的运行环境进行管理,并为您提供工具来管理加入该环境的数据中心。 