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

企业微信、飞书、钉钉机器人消息发送工具类

1、实例化WebClient对象

其实你也可以使用RestTemplate,我这里主要是用到了webflux框架,所以需要实例化客户端请求对象

@Bean
public WebClient webClient(){HttpClient httpClient = getHttpClient();return WebClient.builder().clientConnector(new ReactorClientHttpConnector(httpClient)).build();
}private HttpClient getHttpClient() {ConnectionProvider provider = ConnectionProvider.builder("你爱咋咋的,一般用你项目名即可").maxConnections(500).maxIdleTime(Duration.ofSeconds(10)).maxLifeTime(Duration.ofSeconds(20)).pendingAcquireTimeout(Duration.ofSeconds(30)).pendingAcquireTimer((r, d) -> {Timeout t = wheel.newTimeout(timeout -> r.run(), d.toMillis(), TimeUnit.MILLISECONDS);return () -> t.cancel();}).fifo().build();HttpClient httpClient = HttpClient.create(provider);return httpClient;
}

2、发送及有效性测试工具类


import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Map;import static com.paratera.console.notice.utils.Constants.*;/*** 机器人发送工具类(微信,飞书,钉钉)** @author huxiang*/
@Component
@Slf4j
public class RobotUtil {@Autowiredprivate WebClient webClient;/*** 机器人发送消息(markdown格式)** @param robotUrl   机器人地址* @param type       类型:1微信,2飞书,3钉钉* @param context    markdown文本内容* @param signSecret 签名校验(飞书,钉钉使用,可为空,具体要根据用户是否启用签名)*/public void sendMsg(String robotUrl, Integer type, String context, String signSecret) {JSONObject msgObj = JSONUtil.createObj();JSONObject mdObj = JSONUtil.createObj();switch (type) {case ROBOT_TYPE_WX:msgObj.set("msgtype", "markdown");mdObj.set("content", context);msgObj.set("markdown", mdObj);break;case ROBOT_TYPE_FS:if (StringUtils.isNotEmpty(signSecret)) {msgObj = getFsSignObj(signSecret);}msgObj.set("msg_type", "interactive");mdObj.set("tag", "lark_md");mdObj.set("content", context);JSONArray elements = JSONUtil.createArray();JSONObject wrapObj = JSONUtil.createObj();wrapObj.set("tag", "div");wrapObj.set("text", mdObj);elements.put(wrapObj);JSONObject cardObj = JSONUtil.createObj();cardObj.set("elements", elements);msgObj.set("card", cardObj);break;case ROBOT_TYPE_DD:if (StringUtils.isNotEmpty(signSecret)) {robotUrl = getDdRobotURL(robotUrl, signSecret);}msgObj.set("msgtype", "markdown");mdObj.set("title", "通知");mdObj.set("text", context);msgObj.set("markdown", mdObj);break;}webClient.post().uri(robotUrl).contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(msgObj)).retrieve().bodyToMono(String.class).subscribe(result -> {log.info("机器人通知发送结果:" + result);});}/*** 机器人有效性测试 0表示成功,其他表示失败** @param robotUrl   机器人地址* @param type       类型:1微信,2飞书,3钉钉* @param signSecret 签名校验(飞书,钉钉使用,可为空,具体要根据用户是否启用签名)* @return*/public Integer sendTestMsg(String robotUrl, Integer type, String signSecret) {JSONObject msgObj = JSONUtil.createObj();JSONObject mdObj = JSONUtil.createObj();ObjectMapper mapper = new ObjectMapper();switch (type) {case ROBOT_TYPE_WX:msgObj.set("msgtype", "markdown");mdObj.set("content", "机器人有效性测试!");msgObj.set("markdown", mdObj);break;case ROBOT_TYPE_FS:if (StringUtils.isNotEmpty(signSecret)) {msgObj = getFsSignObj(signSecret);}msgObj.set("msg_type", "interactive");mdObj.set("tag", "lark_md");mdObj.set("content", "机器人有效性测试!");JSONArray elements = JSONUtil.createArray();JSONObject wrapObj = JSONUtil.createObj();wrapObj.set("tag", "div");wrapObj.set("text", mdObj);elements.put(wrapObj);JSONObject cardObj = JSONUtil.createObj();cardObj.set("elements", elements);msgObj.set("card", cardObj);break;case ROBOT_TYPE_DD:if (StringUtils.isNotEmpty(signSecret)) {robotUrl = getDdRobotURL(robotUrl, signSecret);}msgObj.set("msgtype", "markdown");mdObj.set("title", "通知");mdObj.set("text", "机器人有效性测试!");msgObj.set("markdown", mdObj);break;}Mono<String> mono = webClient.post().uri(robotUrl).contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(msgObj)).retrieve().bodyToMono(String.class);String result = mono.block();try {Map res = mapper.readValue(result, Map.class);return (Integer) (res.containsKey("errcode") ? res.get("errcode") : res.get("code"));} catch (JsonProcessingException e) {log.error("类型转换异常-RobotUtil.sendTestMsg:" + e);}return -1;}/*** 飞书获取带签名的消息体** @return*/public JSONObject getFsSignObj(String signSecret) {JSONObject signObj = JSONUtil.createObj();Long timestamp = DateUtil.currentSeconds();String sign = null;try {//把timestamp+"\n"+密钥当做签名字符串String stringToSign = timestamp + "\n" + signSecret;//使用HmacSHA256算法计算签名Mac mac = Mac.getInstance("HmacSHA256");mac.init(new SecretKeySpec(stringToSign.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));byte[] signData = mac.doFinal(new byte[]{});sign = Base64.encodeBase64String(signData);} catch (Exception e) {log.error("飞书获取签名失败:" + e);}if (StringUtils.isEmpty(sign)) {return null;}signObj.set("timestamp", timestamp);signObj.set("sign", sign);return signObj;}/*** 钉钉获取带签名的机器人推送URL** @return*/public String getDdRobotURL(String robotUrl, String signSecret) {Long timestamp = System.currentTimeMillis();String stringToSign = timestamp + "\n" + signSecret;String sign = null;try {Mac mac = Mac.getInstance("HmacSHA256");mac.init(new SecretKeySpec(signSecret.getBytes("UTF-8"), "HmacSHA256"));byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));sign = URLEncoder.encode(Base64.encodeBase64String(signData), "UTF-8");} catch (Exception e) {log.error("钉钉获取签名失败:" + e);}if (StringUtils.isEmpty(sign)) {return null;}return robotUrl + "&timestamp=" + timestamp + "&sign=" + sign;}
}

相关文章:

企业微信、飞书、钉钉机器人消息发送工具类

1、实例化WebClient对象 其实你也可以使用RestTemplate&#xff0c;我这里主要是用到了webflux框架&#xff0c;所以需要实例化客户端请求对象 Bean public WebClient webClient(){HttpClient httpClient getHttpClient();return WebClient.builder().clientConnector(new R…...

手撕 视觉slam14讲 ch7 / pose_estimation_3d2d.cpp (1)

首先理清我们需要实现什么功能&#xff0c;怎么实现&#xff0c;提供一份整体逻辑&#xff1a;包括主函数和功能函数 主函数逻辑&#xff1a; 1. 读图,两张rgb&#xff08;cv::imread&#xff09; 2. 找到两张rgb图中的特征点匹配对 2.1定义所需要的参数&#xff1a;keypoints…...

Mac安装Dart时,Homebrew报错 Error: Failure while executing

前言&#xff1a; 最近准备开发Flutter项目时&#xff0c;在安装环境时&#xff0c;安装Homebew时遇到了以下报错信息&#xff0c;在这里分享一下。 报错信息&#xff1a; ~ % brew tap dart-lang/dart > Tapping dart-lang/dart Cloning into /opt/homebrew/Library/Tap…...

SSM整合~

构建并配置项目&#xff1a; 第一步&#xff1a;创建maven项目 第二步&#xff1a;配置pom.xml文件 设置打包方式&#xff1a; 为了方便部署&#xff0c;我们通常情况下&#xff0c;将项目打包为WAR&#xff0c;因为WAR文件是一种可执行的压缩文件&#xff0c;它可以将项目…...

Self-supervised 3D Human Pose Estimation from a Single Image

基于单幅图像的自监督三维人体姿态估计 主页&#xff1a; https://josesosajs.github.io/ imagepose/ 源码&#xff1a;未开源 摘要 我们提出了一种新的自我监督的方法预测三维人体姿势从一个单一的图像。预测网络是从描绘处于典型姿势的人的未标记图像的数据集和一组未配对…...

ubuntu下cups部分场景

第一章&#xff1a;部分操作指令 在计算机领域中&#xff0c;cups 是“通用UNIX打印系统”&#xff08;Common UNIX Printing System&#xff09;的缩写&#xff0c;它是一种用于在UNIX-like操作系统上管理打印任务的开源打印系统。cups 提供了一个框架&#xff0c;允许用户和…...

通过geoserver imageMosic发布多张tif数据

通过geoserver imageMosic发布多张tif数据 reference: https://zhuanlan.zhihu.com/p/132388558 https://zhuanlan.zhihu.com/p/103674876 https://docs.geoserver.org/latest/en/user/tutorials/imagemosaic_timeseries/imagemosaic_timeseries.html 步骤 下载数据 http…...

输出图元(四)8-2 OpenGL画点函数、OpenGL画线函数

4.3 OpenGL画点函数 要描述一个点的几何要素&#xff0c;我们只需在世界坐标系中指定一个位置。然后该坐标位置和场景中已有的其他几何描述一起被传递给观察子程序。除非指定其他属性值&#xff0c;OpenGL 图元按默认的大小和颜色来显示。默认的图元颜色是白色&#x…...

java八股文

6. 如何保证消息的可靠性&#xff1f; 在RabbitMq的整个消息投递过程中&#xff0c;有三种情况下&#xff0c;会存在消息丢失的问题&#xff1a; 6. RabbitMq如何保证消息的可靠性&#xff1f; 所以从这三个维度保证消息的可靠性去可靠性传递就可以了&#xff0c;从生产者发送…...

算法通关村——解析堆的应用

在数组中找第K大的元素 LeetCode21 Medium 我们要找第 K 大的元素&#xff0c;如果我们找使用大堆的话那么就会造成这个堆到底需要多大的&#xff0c;而且哪一个是第 K 的的元素我们不知道是哪一个索引&#xff0c;我们更想要的结果就是根节点就是我们要找的值&#xff0c;所以…...

爬虫源码---爬取小猫猫交易网站

前言&#xff1a; 本片文章主要对爬虫爬取网页数据来进行一个简单的解答&#xff0c;对与其中的数据来进行一个爬取。 一&#xff1a;环境配置 Python版本&#xff1a;3.7.3 IDE:PyCharm 所需库&#xff1a;requests &#xff0c;parsel 二&#xff1a;网站页面 我们需要…...

Python的由来和基础语法(一)

目录 一、Python 背景知识 1.1Python 是咋来的? 1.2Python 都能干啥? 1.3Python 的优缺点 二、基础语法 2.1常量和表达式 2.2变量和类型 变量的语法 (1) 定义变量 (2) 使用变量 变量的类型 (1) 整数 (2) 浮点数(小数) (3) 字符串 (4) 布尔 (5) 其他 动态类型…...

使用maven创建springboot项目

创建maven快速启动项目 命令行或者idea、eclipse快捷创建也可以 pom.xml下project项目下导入springboot 父工程 <!--导入springboot 父工程--> <parent><artifactId>spring-boot-starter-parent</artifactId><groupId>org.springframework.bo…...

MySQL 基本操作1

目录 Create insert 插入跟新 1 插入跟新 2 Retrive select where 子句查询 1.查找数学成绩小于 80 的同学。 2.查询数学成绩等于90分的同学。 3.查询总分大于240 的学生 4.查询空值或者非空值 5.查询语文成绩在70~80之间的同学 6.查询英语成绩是99 和 93 和 19 和…...

linux内网yum源服务器搭建

1.nginx: location / {root /usr/local/Kylin-Server-V10-SP3-General-Release-2303-X86_64;autoindex on;autoindex_localtime on;autoindex_exact_size off; } 注:指定到镜像的包名 2.修改yum源地址 cd /etc/yum.repos.d/vim kylin_x86_64.repo 注: --enabled设置为1 3.重…...

机器学习与数据分析

【数据清洗】 异常检测 孤立森林&#xff08;Isolation Forest&#xff09;从原理到实践 效果评估&#xff1a;F-score 【1】 保护隐私的时间序列异常检测架构 概率后缀树 PST – &#xff08;异常检测&#xff09; 【1】 UEBA架构设计之路5&#xff1a; 概率后缀树模型 【…...

项目总结知识点记录-文件上传下载(三)

&#xff08;1&#xff09;文件上传 代码&#xff1a; RequestMapping(value "doUpload", method RequestMethod.POST)public String doUpload(ModelAttribute BookHelper bookHelper, Model model, HttpSession session) throws IllegalStateException, IOExcepti…...

基于LinuxC语言实现的TCP多线程/进程服务器

多进程并发服务器 设计流程 框架一&#xff08;使用信号回收僵尸进程&#xff09; void handler(int sig) {while(waitpid(-1, NULL, WNOHANG) > 0); }int main() {//回收僵尸进程siganl(17, handler);//创建服务器监听套接字 serverserver socket();//给服务器地址信息…...

浅谈JVM垃圾回收机制

一、HotSpot VM中的GC分为两大类 1.部分收集(Partial GC): 新生代收集(Minor GC/Young GC):只对新生代进行垃圾收集老年代收集(Major GC/Old GC):只队老年代进行垃圾收集混合收集(Mixed GC):对整个新生代和老年代进行垃圾收集 2.整堆收集(Full GC) 收集整个Java堆和方法区 …...

【80天学习完《深入理解计算机系统》】第十二天3.6数组和结构体

专注 效率 记忆 预习 笔记 复习 做题 欢迎观看我的博客&#xff0c;如有问题交流&#xff0c;欢迎评论区留言&#xff0c;一定尽快回复&#xff01;&#xff08;大家可以去看我的专栏&#xff0c;是所有文章的目录&#xff09;   文章字体风格&#xff1a; 红色文字表示&#…...

19c补丁后oracle属主变化,导致不能识别磁盘组

补丁后服务器重启&#xff0c;数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后&#xff0c;存在与用户组权限相关的问题。具体表现为&#xff0c;Oracle 实例的运行用户&#xff08;oracle&#xff09;和集…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)

漏洞概览 漏洞名称&#xff1a;Apache Flink REST API 任意文件读取漏洞CVE编号&#xff1a;CVE-2020-17519CVSS评分&#xff1a;7.5影响版本&#xff1a;Apache Flink 1.11.0、1.11.1、1.11.2修复版本&#xff1a;≥ 1.11.3 或 ≥ 1.12.0漏洞类型&#xff1a;路径遍历&#x…...

R语言速释制剂QBD解决方案之三

本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...

【Go语言基础【12】】指针:声明、取地址、解引用

文章目录 零、概述&#xff1a;指针 vs. 引用&#xff08;类比其他语言&#xff09;一、指针基础概念二、指针声明与初始化三、指针操作符1. &&#xff1a;取地址&#xff08;拿到内存地址&#xff09;2. *&#xff1a;解引用&#xff08;拿到值&#xff09; 四、空指针&am…...

GitHub 趋势日报 (2025年06月06日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...

redis和redission的区别

Redis 和 Redisson 是两个密切相关但又本质不同的技术&#xff0c;它们扮演着完全不同的角色&#xff1a; Redis: 内存数据库/数据结构存储 本质&#xff1a; 它是一个开源的、高性能的、基于内存的 键值存储数据库。它也可以将数据持久化到磁盘。 核心功能&#xff1a; 提供丰…...

机器学习的数学基础:线性模型

线性模型 线性模型的基本形式为&#xff1a; f ( x ) ω T x b f\left(\boldsymbol{x}\right)\boldsymbol{\omega}^\text{T}\boldsymbol{x}b f(x)ωTxb 回归问题 利用最小二乘法&#xff0c;得到 ω \boldsymbol{\omega} ω和 b b b的参数估计$ \boldsymbol{\hat{\omega}}…...