| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- package com.jeesite.modules.mes.dingtalk;
- import com.alibaba.fastjson.JSONObject;
- import com.jeesite.common.lang.StringUtils;
- import okhttp3.MediaType;
- import okhttp3.OkHttpClient;
- import okhttp3.Request;
- import okhttp3.RequestBody;
- import okhttp3.Response;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.stereotype.Component;
- import javax.crypto.Mac;
- import javax.crypto.spec.SecretKeySpec;
- import java.net.URLEncoder;
- import java.nio.charset.StandardCharsets;
- import java.util.Base64;
- import java.util.List;
- import java.util.concurrent.TimeUnit;
- import java.util.stream.Collectors;
- import java.util.stream.Stream;
- @Component
- public class DingTalkRobotClient {
- private static final Logger logger = LoggerFactory.getLogger(DingTalkRobotClient.class);
- private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
- private final DingTalkRobotProperties properties;
- private final OkHttpClient httpClient = new OkHttpClient.Builder()
- .connectTimeout(5, TimeUnit.SECONDS)
- .readTimeout(10, TimeUnit.SECONDS)
- .build();
- public DingTalkRobotClient(DingTalkRobotProperties properties) {
- this.properties = properties;
- }
- public boolean sendMarkdown(String title, String markdownText) {
- return sendMarkdown(title, markdownText, getConfiguredAtMobiles(), properties.isAtAll());
- }
- /**
- * 按指定手机号 @ 发送,不使用 yml 全局 at-all。
- */
- public boolean sendMarkdown(String title, String markdownText, List<String> atMobiles) {
- return sendMarkdown(title, markdownText, atMobiles, false);
- }
- private boolean sendMarkdown(String title, String markdownText, List<String> atMobiles, boolean atAll) {
- if (!properties.isEnabled() || StringUtils.isBlank(properties.getUrl())) {
- logger.warn("DingTalk robot is disabled or webhook url is empty.");
- return false;
- }
- JSONObject body = new JSONObject();
- body.put("msgtype", "markdown");
- JSONObject markdown = new JSONObject();
- markdown.put("title", title);
- markdown.put("text", appendAtText(markdownText, atMobiles));
- body.put("markdown", markdown);
- body.put("at", buildAt(atMobiles, atAll));
- return post(body);
- }
- private JSONObject buildAt(List<String> atMobiles, boolean atAll) {
- JSONObject at = new JSONObject();
- at.put("isAtAll", atAll);
- List<String> mobiles = atMobiles == null ? java.util.Collections.emptyList() : atMobiles;
- if (!mobiles.isEmpty()) {
- at.put("atMobiles", mobiles);
- }
- return at;
- }
- private String appendAtText(String markdownText, List<String> atMobiles) {
- if (atMobiles == null || atMobiles.isEmpty()) {
- return markdownText;
- }
- String atText = atMobiles.stream()
- .map(mobile -> "@" + mobile)
- .collect(Collectors.joining(" "));
- return markdownText + "\n\n" + atText;
- }
- private List<String> getConfiguredAtMobiles() {
- if (StringUtils.isBlank(properties.getAtMobiles())) {
- return java.util.Collections.emptyList();
- }
- return Stream.of(properties.getAtMobiles().split(","))
- .map(String::trim)
- .filter(StringUtils::isNotBlank)
- .collect(Collectors.toList());
- }
- private boolean post(JSONObject body) {
- String requestUrl = buildSignedUrl();
- Request request = new Request.Builder()
- .url(requestUrl)
- .post(RequestBody.create(JSON, body.toJSONString()))
- .build();
- try (Response response = httpClient.newCall(request).execute()) {
- String responseBody = response.body() == null ? "" : response.body().string();
- if (!response.isSuccessful()) {
- logger.warn("DingTalk robot send failed, httpStatus={}, body={}", response.code(), responseBody);
- return false;
- }
- JSONObject result = JSONObject.parseObject(responseBody);
- boolean success = result != null && result.getIntValue("errcode") == 0;
- if (!success) {
- logger.warn("DingTalk robot returned failure: {}", responseBody);
- }
- return success;
- } catch (Exception ex) {
- logger.warn("DingTalk robot send exception: {}", ex.getMessage(), ex);
- return false;
- }
- }
- private String buildSignedUrl() {
- String url = properties.getUrl();
- if (StringUtils.isBlank(properties.getSecret())) {
- return url;
- }
- long timestamp = System.currentTimeMillis();
- String sign = sign(timestamp, properties.getSecret());
- String separator = url.contains("?") ? "&" : "?";
- return url + separator + "timestamp=" + timestamp + "&sign=" + sign;
- }
- private String sign(long timestamp, String secret) {
- try {
- 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 base64 = Base64.getEncoder().encodeToString(signData);
- return URLEncoder.encode(base64, StandardCharsets.UTF_8.name());
- } catch (Exception ex) {
- throw new IllegalStateException("Build DingTalk sign failed", ex);
- }
- }
- }
|