效果
import cn.hutool.core.date.DateUtil; import cn.hutool.core.exceptions.ExceptionUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.extra.spring.SpringUtil; import cn.hutool.http.HttpUtil; import cn.hutool.json.JSONUtil; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.binary.Base64; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.net.URLEncoder; import java.time.Instant; import java.util.HashMap; import java.util.Map; @Slf4j @Service public class DingMsgService { @Value("${config.dingtalk.secret}") private String dingtalkSecret; @Value("${config.dingtalk.webhook}") private String dingtalkWebhook; public void sendDingTalkMsg(Exception ex, String requestURI) { StringBuilder builder = StrUtil.builder(); builder.append("发生时间:[" + DateUtil.now() + "]\n"); builder.append("发生环境:[" + SpringUtil.getActiveProfile() + "]\n"); builder.append("请求地址:[" + requestURI + "]\n"); builder.append("异常信息:[" + ExceptionUtil.getMessage(ex) + "]\n"); StackTraceElement[] stackTrace = ex.getStackTrace(); for (StackTraceElement element : stackTrace) { if (!element.getClassName().contains("yunkeji")) { continue; } builder.append( element.getFileName() + "#" + element.getMethodName() + "#" + element.getLineNumber() + "\n"); } String content = builder.toString(); // 钉钉最大只能发送2000个字符 if (content.length() >= 1990) { content = content.substring(0, 1990); } DingTalkSendMsgRequestDTO requestDTO = new DingTalkSendMsgRequestDTO(); requestDTO.setSecret(dingtalkSecret); requestDTO.setWebhook(dingtalkWebhook); requestDTO.setContent(content); // 消息内容 Map<String, String> contentMap = new HashMap<>(); contentMap.put("content", requestDTO.getContent()); // 通知人 Map<String, Object> atMap = new HashMap<>(); // 1.是否通知所有人 atMap.put("isAtAll", true); // 2.通知具体人的手机号码列表 atMap.put("atMobiles", "18683661017"); Map<String, Object> reqMap = new HashMap<>(); reqMap.put("msgtype", "text"); // JSONObject set = // JSONUtil.createObj() // .set("title", SpringUtil.getActiveProfile() + "-" + title) // .set("text", content); reqMap.put("text", contentMap); reqMap.put("at", atMap); requestDTO.setContent(JSONUtil.toJsonStr(reqMap)); try { String secret = requestDTO.getSecret(); // 获取系统时间戳 long timestamp = Instant.now().toEpochMilli(); // 拼接 String stringToSign = timestamp + "\n" + secret; // 使用HmacSHA256算法计算签名 Mac mac = Mac.getInstance("HmacSHA256"); mac.init(new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256")); byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8")); // 进行Base64 encode 得到最后的sign,可以拼接进url里 String sign = URLEncoder.encode(new String(Base64.encodeBase64(signData)), "UTF-8"); // 钉钉机器人地址(配置机器人的webhook) String dingUrl = requestDTO.getWebhook() + "×tamp=" + timestamp + "&sign=" + sign; String result = HttpUtil.post(dingUrl, requestDTO.getContent()); log.info("re={}", result); } catch (Exception e) { log.error("钉钉推送消息出现异常", e); } } @Data public static class DingTalkSendMsgRequestDTO { private String secret; private String webhook; private String content; private boolean isAtAll; } }