钉钉消息推送工具类

pom.xml

xml 复制代码
 <!-- HuTool 工具 -->
 <dependency>
      <groupId>cn.hutool</groupId>
      <artifactId>hutool-all</artifactId>
      <version>5.8.12</version>
  </dependency>
   <!-- commons-lang3 -->
  <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-lang3</artifactId>
      <version>3.6</version>
  </dependency>

java工具类

java 复制代码
package com.zens.doudian.utils;

import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 钉钉消息推送 - 工具类
 *
 * @author Lance
 * @since 2023-08-31 14:32
 */
public class DingTalkWebhookUtils {

    private static final Logger log = LoggerFactory.getLogger(DingTalkWebhookUtils.class);

    /**
     * 发送超时时间10s
     */
    private static final int TIME_OUT = 10000;
    // 签名密钥
    private static final String SECRET = "SECbd7fd971096ea3333e3d56bf30xxxxexxxxx";
    // 
    private static final String WEBHOOK = "https://oapi.dingtalk.com/robot/send?access_token=xxxxxxxxxxx";


    public static void main(String[] args) {
        DingTalkWebhookUtils.sendWebhook(WEBHOOK, SECRET, "测试推送!!!", Collections.singletonList("18534xxxxx"));
    }


    public static void sendMessage(String content, List<String> mobileList) {

        sendWebhook(WEBHOOK, SECRET, content, mobileList);

    }

    /**
     * 钉钉机器人文档地址:<a href="https://ding-doc.dingtalk.com/doc#/serverapi2/qf2nxq">...</a>
     *
     * @param secret     安全设置 3选1:
     *                   【方式一,自定义关键词 】
     *                   【方式二,加签 ,创建机器人时选择加签 secret以SE开头】
     *                   【方式三,IP地址(段)】
     * @param content    发送内容
     * @param mobileList 通知具体人的手机号码列表 (可选)
     */
    public static void sendWebhook(String webhook, String secret, String content, List<String> mobileList) {
        try {
            //钉钉机器人地址(配置机器人的webhook)
            if (!StringUtils.isEmpty(secret)) {
                Long timestamp = System.currentTimeMillis();
                String sign = getSign(timestamp, secret);
                webhook = new StringBuilder(webhook)
                        .append("&timestamp=")
                        .append(timestamp)
                        .append("&sign=")
                        .append(sign)
                        .toString();
            }
            System.out.println("webhook:" + webhook);
            // 是否通知所有人
            boolean isAtAll = false;
            // 组装请求内容
            String reqStr = buildReqStr(content, isAtAll, mobileList);
            // 推送消息(HTTP POST 请求)
            String result = postJson(webhook, reqStr);
            log.info("推送响应结果:{}", result);
        } catch (Exception e) {
            log.info("发送群通知异常 异常原因:{}", e.getMessage());
        }
    }

    /**
     * 组装请求报文
     *
     * @param content    内容
     * @param isAtAll    是否通知所有人
     * @param mobileList 需要通知的人:手机号
     * @return json
     */
    private static String buildReqStr(String content, boolean isAtAll, List<String> mobileList) {
        //消息内容
        Map<String, String> contentMap = new HashMap<>();
        contentMap.put("content", content);
        //通知人
        Map<String, Object> atMap = new HashMap<>();
        //1.是否通知所有人
        atMap.put("isAtAll", isAtAll);
        //2.通知具体人的手机号码列表
        atMap.put("atMobiles", mobileList);
        Map<String, Object> reqMap = new HashMap<>();
        reqMap.put("msgtype", "text");
        reqMap.put("text", contentMap);
        reqMap.put("at", atMap);
        return JSON.toJSONString(reqMap);
    }

    private static String postJson(String url, String reqStr) {
        String body = null;
        try {
            body = HttpRequest.post(url).body(reqStr).timeout(TIME_OUT).execute().body();
        } catch (Exception e) {
            log.error("钉钉消息推送异常:{}", e.getMessage());
        }
        return body;
    }

    /**
     * 自定义机器人获取签名,创建机器人时选择加签获取secret以SE开头
     * 把timestamp+"\n"+密钥当做签名字符串,使用HmacSHA256算法计算签名,然后进行Base64 encode,最后再把签名参数再进行urlEncode,得到最终的签名(需要使用UTF-8字符集)
     *
     * @param secret    机器人安全设置下的签名
     * @param timestamp 时间戳
     */
    private static String getSign(Long timestamp, String secret) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {
        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.encodeBase64(signData)), "UTF-8");
        log.info("sign:" + sign);
        return sign;
    }
}
相关推荐
考虑考虑10 小时前
Jpa使用union all
java·spring boot·后端
用户37215742613510 小时前
Java 实现 Excel 与 TXT 文本高效互转
java
浮游本尊11 小时前
Java学习第22天 - 云原生与容器化
java
渣哥13 小时前
原来 Java 里线程安全集合有这么多种
java
间彧13 小时前
Spring Boot集成Spring Security完整指南
java
间彧13 小时前
Spring Secutiy基本原理及工作流程
java
Java水解14 小时前
JAVA经典面试题附答案(持续更新版)
java·后端·面试
洛小豆16 小时前
在Java中,Integer.parseInt和Integer.valueOf有什么区别
java·后端·面试
前端小张同学17 小时前
服务器上如何搭建jenkins 服务CI/CD😎😎
java·后端
ytadpole17 小时前
Spring Cloud Gateway:一次不规范 URL 引发的路由转发404问题排查
java·后端