当前位置: 首页 > news >正文

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 = "&timestamp=" + 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发送普通消息示例&#xff08;采用加签方式&#xff09; 1.3注意事项 2.通过企业内部应用发送钉钉消息 2.1说明 2.2示例 2.3注意 1.通过自定义机器人方式发送群消息 1.1说明 官网地址&#xff1a; 自定义机器人发送…...

直播预告丨看零售场,如何玩转 MaaS

今年&#xff0c;有一个被频繁提及的词是MaaS 这类工具正在帮助千行百业实现大模型落地产业 在零售场&#xff0c;特别是像京东这样拥有超高并发、超复杂协同的电商场内 也沉淀出了一套通用的AI基础设施——九数算法中台 从提升客户服务体验、平台效率出发&#xff0c;训练各…...

高创新!EI论文复现+改进:聚合温度调控策略的综合能源系统/微电网/虚拟电厂多目标优化调度程序代码!

程序考虑供热的热惯性&#xff0c;并根据室内供热效果进行柔性供热&#xff0c;发挥热温度负荷的“储能”能力&#xff1b;针对普适性参数的室内空调进行集群研究&#xff0c;深入剖析温度设定值调整导致负荷波动的机理&#xff0c;并提出一种新的温度调整方法&#xff0c;平抑…...

详解Matlab深度学习进行波形分割

&#x1f517; 运行环境&#xff1a;Matlab &#x1f6a9; 撰写作者&#xff1a;左手の明天 &#x1f947; 精选专栏&#xff1a;《python》 &#x1f525; 推荐专栏&#xff1a;《算法研究》 &#x1f510;#### 防伪水印——左手の明天 ####&#x1f510; &#x1f497; 大家…...

如何在Windows 10/11的防火墙中禁止和允许某个应用程序,这里提供详细步骤

想阻止应用程序访问互联网吗&#xff1f;以下是如何通过简单的步骤阻止和允许Windows防火墙中的程序。​ 一般来说&#xff0c;大多数用户永远不需要担心应用程序访问互联网。然而&#xff0c;在某些情况下&#xff0c;你需要限制应用程序访问互联网。 例如&#xff0c;有问题…...

vivado 添加现有IP文件、生成IP

添加现有IP文件 作为从AMD IP目录添加和自定义IP的替代方案&#xff0c;您可以直接添加XCI或XCIX文件。此过程不同于从按以下方式编目&#xff1a; •XCI或XCIX文件可能是早期版本&#xff0c;也可能是相同或完全自定义的版本AMD IP目录中发现的类似IP。 •XCI或XCIX文件可能…...

C++右值引用,右值引用与const引用的区别

1.右值与左值 左值&#xff1a;可以取地址的、有名字的变量&#xff0c;有持久性&#xff1b;右值&#xff1a;一般是不可寻址的常量&#xff0c;或在表达式求值过程中创建的无名临时对象&#xff0c;短暂性的。 2.右值引用 C11新增了另一种引用——右值引用。这种引用可指向…...

启英泰伦推出「离线自然说」,离线语音交互随意说,不需记忆词条

离线语音识别是指不需要依赖网络&#xff0c;在本地设备实现语音识别的过程&#xff0c;通常以端侧AI语音芯片作为载体来进行数据的采集、计算和决策。但是语音芯片的存储空间有限&#xff0c;通过传统的语音算法技术&#xff0c;最多也只能存储数百条词条&#xff0c;导致用户…...

Vulnhub-DC1

前言 一个比较简单的实战靶场&#xff0c;官方要求是找到/root下的flag&#xff0c;所以直接提权即可。但对于学习和训练来说还是太简略了&#xff0c;在打靶场的时候还是全面一些较好。 本次靶场实战涉及信息收集、漏洞查找与利用、getshell、数据库渗透、密码破解、linux提…...

【c++笔记】总结!c++与c语言的不同之处

(Θ&#xff13;Θ) hi~ 众所周知\(^o^)/~&#xff0c;c语言和c联系密切&#xff0c;又相互区别&#xff0c;本篇文章主要介绍c与c语言的区别与联系以及一些简单的不同点的运用&#xff0c;很适合刚接触c的朋友&#xff0c;一起来瞧瞧看吧~~ 目录 一、文章内容梗概 二、概念…...

大模型PEFT技术原理(一):BitFit、Prefix Tuning、Prompt Tuning

随着预训练模型的参数越来越大&#xff0c;尤其是175B参数大小的GPT3发布以来&#xff0c;让很多中小公司和个人研究员对于大模型的全量微调望而却步&#xff0c;近年来研究者们提出了各种各样的参数高效迁移学习方法&#xff08;Parameter-efficient Transfer Learning&#x…...

VMware vSphere运维管理手册

适用版本:VMware vSphere 7.0 VMware vSphere 是 VMware 的虚拟化平台,可将数据中心转换为包括 CPU、存储和网络资源的聚合计算基础架构。vSphere 将这些基础架构作为一个统一的运行环境进行管理,并为您提供工具来管理加入该环境的数据中心。 ![[Pasted image 20231212132…...

学习笔记-mysql-各种函数的基本使用

1. 聚合函数 count , sum , min , max ,avg , group_concat() -- 将所有员工的名字合并成一行 select group_concat(emp_name) from emp; -- 指定分隔符合并 select department,group_concat(emp_name separator ; ) from emp group by department; -- 指定排序方式和分隔…...

DD小桔高级数分 2面挂

偏业务分析一点&#xff0c;注重AB实验在实际业务中的操作、业务方交流方式 一面|同事面 中规中矩&#xff0c;面试内容偏简单&#xff0c;不知道是不是因为晚8点面试的原因项目没有进行深究 自我介绍项目介绍1.你在实际项目中是怎么设计AB实验2.你在实际业务场景中是怎么判…...

居中面试问题

前端常问居中面试问题 css文本居中 文本水平居中 <div class"father"><div class"child"><div> <div>子类元素为行内元素&#xff0c;则给父类元素定义text-align:center 如果子元素是块元素&#xff0c;则给子元素定义margin&…...

网页设计-用户体验

Use Cases (用例) 用例是用户如何在网站上执行任务的书面描述&#xff0c;从用户的角度描述了系统响应请求时的行为。每个用例都是用户实现目标的一系列简单的步骤。简言之&#xff0c;用例是一种用于描述系统如何满足用户需求的方法。 用例的好处 1. 明确需求&#xff1a; Use…...

docker应用:vocechat

简介&#xff1a;VoceChat是一款超轻量级的Rust聊天应用程序、API和SDK&#xff0c;优先考虑私人托管。使用VoceChat建立您自己的聊天功能&#xff01;作为一款非常好用的通讯应用程序&#xff0c;它可以让你与朋友、家人和同事进行即时消息聊天&#xff0c;支持图片视频的分享…...

linux 02 vmware的快照,文件管理

01.快照 使用快照&#xff1a; 同时的快照管理器&#xff1a; 如果想要返回快照&#xff0c;选择要选择的快照&#xff0c;跳转 02. 文件管理&#xff1a; cd 修改当前路径 02.touch 创建文件 03. mkdir 创建文件夹 mkdir -p 文件夹 &#xff08;创建之前没有的上级文件…...

项目架构之Zabbix部署

1 项目架构 1.1 项目架构的组成 业务架构&#xff1a;客户端 → 防火墙 → 负载均衡&#xff08;四层、七层&#xff09; → web缓存/应用 → 业务逻辑&#xff08;动态应用&#xff09; → 数据缓存 → 数据持久层 运维架构&#xff1a;运维客户端 → 跳板机/堡垒机&#x…...

RocketMQ源码阅读-Message消息存储

RocketMQ源码阅读-Message消息存储 1. CommitLog的作用2. CommitLog 存储消息3. 时序图4. 小结 在Broker消息接收一篇中&#xff0c;分析到Broker接收到消息&#xff0c;最终会调用CommitLong#putMessage方法存储消息。 本篇来分析CommitLong#putMessage存储消息的流程。 1. C…...

Vue3+Three.js实战:拆解Xtreme1点云标注工具的技术架构

Vue3Three.js深度实战&#xff1a;构建工业级3D点云标注工具的技术解析 在自动驾驶、工业检测和机器人视觉领域&#xff0c;3D点云标注工具正成为AI训练数据生产的核心基础设施。Xtreme1作为开源多模态标注平台的代表&#xff0c;其pc-tool模块采用Vue3Three.js技术栈实现了专…...

PCIe设备树深度解析:从RK3588实例看Linux内核地址与中断映射(九)

1. PCIe设备树基础概念与RK3588实战背景 第一次接触PCIe设备树配置时&#xff0c;我被那些密密麻麻的十六进制数字和嵌套属性搞得头晕眼花。直到在RK3588平台上实际调试PCIe设备时&#xff0c;才真正理解设备树如何成为连接硬件与操作系统的桥梁。PCIe设备树不同于普通外设的简…...

IntelliJ IDEA 安装与环境配置指南(2026 最新)

IntelliJ IDEA 是 Java 开发首选 IDE&#xff0c;社区版免费开源、旗舰版功能更全&#xff1b;IDE 内置 JBR 运行环境&#xff0c;开发 Java 项目需单独配置 JDK。以下是完整安装与配置流程。 一、安装前准备 1. 系统要求&#xff08;2026 官方&#xff09; 表格 配置项最低…...

Anthropic 又双叒翻车了:Claude Code源代码打包失误,这已经是第几次了?

今天&#xff08;2026-03-31&#xff09;上午&#xff0c;Anthropic的Claude Code CLI又出大糗了。 安全研究员 Chaofan Shou发现&#xff1a; 他们的 npm 包里多塞了一个 60MB 的 cli.js.map 文件。 结果呢&#xff1f;完整源代码直接公开——1900多个 TypeScript 文件&#x…...

实测,用 AI (Stitch + Codex) 给产品做个官网

作为一个写了 10 年代码的老程序员&#xff0c;这几年听得最多的一句话就是&#xff1a; “AI 已经可以写代码、做设计了。” 但说实话&#xff0c;我一直是半信半疑的状态&#xff08;停留在 Cursor 刚出来的那会儿&#xff09;。 于是&#xff0c;今天我决定不看别人说&…...

3步掌握Vortex:让250+游戏模组管理像专业开发者一样简单

3步掌握Vortex&#xff1a;让250游戏模组管理像专业开发者一样简单 【免费下载链接】Vortex Vortex: Nexus-Mods开发的游戏模组管理器&#xff0c;用于简化模组的安装和管理过程。 项目地址: https://gitcode.com/gh_mirrors/vor/Vortex 价值定位&#xff1a;重新定义游…...

AI与数据库融合:从经典论文到前沿实践

1. AI与数据库融合的起源与演进 数据库和人工智能这两个看似独立的领域&#xff0c;其实早在计算机科学发展的初期就已经产生了交集。上世纪70年代&#xff0c;当关系型数据库理论刚刚确立时&#xff0c;研究者们就开始探索如何让数据库系统具备一定的"智能"。当时的…...

实战避坑:用Playwright+Selenium绕过电商网站验证码的3种方法(附Python代码)

实战避坑&#xff1a;用PlaywrightSelenium绕过电商网站验证码的3种方法&#xff08;附Python代码&#xff09; 电商平台的反爬虫机制日益复杂&#xff0c;验证码作为核心防线之一&#xff0c;已经从简单的图文识别升级到行为验证、智能风控等多维度拦截。本文将聚焦淘宝、京东…...

应用篇,在Silverlight中使用Virtual Earth地图服务

ilverlight应用中使用地图服务是否能够得心应手呢&#xff1f; 答案是肯定的&#xff0c;我们操作Earth服务只需执行简单的服务调用&#xff0c;就可完成坐地日行八万里的壮举了&#xff0c;而这一切是由VIEWs组件封装了Javascript脚本来完成的&#xff0c;通过对Virtual Eart…...

BACnet4j实战:从模拟设备到点位数据采集的完整流程解析

1. BACnet4j与工业物联网数据采集入门 第一次接触BACnet协议时&#xff0c;我被各种专业术语搞得晕头转向。直到用BACnet4j成功读取到第一个温度传感器的数据&#xff0c;才真正理解这个协议的价值。BACnet/IP就像工业设备间的普通话&#xff0c;而BACnet4j就是让Java程序能说这…...