背景:在工作中的一些告警需要发送钉钉通知,有的是发给个人,有的要发到群里,这时项目就需要接入钉钉,实现发消息的功能
1. 添加钉钉依赖
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>dingtalk</artifactId>
<version>2.0.14</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>alibaba-dingtalk-service-sdk</artifactId>
<version>2.0.0</version>
</dependency>
2. 发送工作通知
发送通知需要使用access_token,获取token需要根据AppKey、AppSecret,所以需要在钉钉后台建一个应用,获许AppKey和AppSecret
2.1. 后台建一个应用
获取token文档:
https://open.dingtalk.com/document/orgapp/obtain-the-access_token-of-an-internal-app
发消息文档:
https://open.dingtalk.com/document/orgapp/asynchronous-sending-of-enterprise-session-messages
2.2. 详细代码如下
替换相应的配置就可以直接发送了
import com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenResponse;
import com.aliyun.tea.TeaException;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiMessageCorpconversationAsyncsendV2Request;
import com.dingtalk.api.response.OapiMessageCorpconversationAsyncsendV2Response;
/**
* @author csn
* @date 2024/1/26
* @description 发送个人消息
*/
public class SimpleExample {
// 钉钉官方文档 - 获取 AccessToken
// https://open.dingtalk.com/document/orgapp/obtain-the-access_token-of-an-internal-app
// 钉钉官方文档 - 发送工作通知消息
// https://open.dingtalk.com/document/orgapp/asynchronous-sending-of-enterprise-session-messages
/**
* 应用的 AgentId
*/
private static Long AGENT_ID = 2883514974L;
/**
* 应用的 AppKey
*/
private static String APP_KEY = "dingiektffikbgglasadcs";
/**
* 应用的 AppSecret
*/
private static String APP_SECRET = "_Ha8VQMwM_Hht3jWrPR8502O3BIQ_Lzf-G7DsK4c-u2hz6y2hzFZ7WinumIy6X7khg";
/**
* 使用 Token 初始化账号Client
*
* @return Client
* @throws Exception
*/
public static com.aliyun.dingtalkoauth2_1_0.Client createClient() throws Exception {
com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config();
config.protocol = "https";
config.regionId = "central";
return new com.aliyun.dingtalkoauth2_1_0.Client(config);
}
/**
* 获取 AccessToken
*
* @return AccessToken
* @throws Exception
*/
public static String getAccessToken() throws Exception {
com.aliyun.dingtalkoauth2_1_0.Client client = createClient();
com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenRequest getAccessTokenRequest = new com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenRequest()
.setAppKey(APP_KEY)
.setAppSecret(APP_SECRET);
try {
GetAccessTokenResponse accessToken = client.getAccessToken(getAccessTokenRequest);
return accessToken.body.getAccessToken();
} catch (TeaException err) {
if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
// err 中含有 code 和 message 属性,可帮助开发定位问题
}
} catch (Exception exception) {
TeaException err = new TeaException(exception.getMessage(), exception);
if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
// err 中含有 code 和 message 属性,可帮助开发定位问题
}
}
return null;
}
/**
* 发送消息
*/
public static void sendMessage() throws Exception {
DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2");
OapiMessageCorpconversationAsyncsendV2Request request = new OapiMessageCorpconversationAsyncsendV2Request();
// 应用上可以看到
request.setAgentId(AGENT_ID);
// 发送给谁 (接收人的钉钉 userid)
request.setUseridList("0168333232323702649");
request.setToAllUser(false);
OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
// 消息类型 - markdown
msg.setMsgtype("markdown");
msg.setMarkdown(new OapiMessageCorpconversationAsyncsendV2Request.Markdown());
msg.getMarkdown().setText("##### text");
msg.getMarkdown().setTitle("### Title");
request.setMsg(msg);
// token
OapiMessageCorpconversationAsyncsendV2Response rsp = client.execute(request, getAccessToken());
System.out.println(rsp.getBody());
}
/**
* 测试发送个人消息
*/
public static void main(String[] args) throws Exception {
sendMessage();
}
}
3. 发送群消息
3.1. 群内建立机器人
获取secret和Webhook就可以发送了
文档:
https://open.dingtalk.com/document/orgapp/custom-bot-to-send-group-chat-messages
建立机器人步骤如下:
给机器人取个名字
安全设置必选选一个,这里选择加签,后面要用到,具体原因可以看文档
完成后又个Webhook,这个是发送消息用的url
3.2. 详细代码如下
替换相应的配置就可以直接发送了
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiRobotSendRequest;
import com.dingtalk.api.response.OapiRobotSendResponse;
import com.taobao.api.ApiException;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.codec.binary.Base64;
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;
/**
* @author csn
* @date 2024/1/26
* @description 机器人发送群消息
*/
@Slf4j
public class BotExample {
// 钉钉官方文档
// https://open.dingtalk.com/document/orgapp/custom-bot-to-send-group-chat-messages
/**
* 机器人的加签秘钥 (替换成自己的)
*/
private static final String SECRET = "SEC9a6b2202a0b92847fd7098630d20b4da9c02862d3696968a27b96d1e5fa073400o23412";
/**
* 机器人的webhook (替换成自己的)
*/
private static final String URL = "https://oapi.dingtalk.com/robot/send?access_token=3c3628a434166b0b9180ddba360asd06b9999270e1655a031c74b362b069ef2f328";
/**
* 组装签名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.encodeBase64(signData)), "UTF-8");
String signResult = "×tamp=" + timestamp + "&sign=" + sign;
// 得到拼接后的 URL
return URL + signResult;
}
/**
* 获取客户端
*
* @return
*/
public static DingTalkClient getClient() throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {
return new DefaultDingTalkClient(getUrl());
}
/**
* 发送消息
*
* @param content
* @throws ApiException
* @throws NoSuchAlgorithmException
* @throws UnsupportedEncodingException
* @throws InvalidKeyException
*/
public static void sendText(String content) throws ApiException, NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {
DingTalkClient client = getClient();
OapiRobotSendRequest request = new OapiRobotSendRequest();
// 消息类型 - 文本
request.setMsgtype("text");
OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text();
text.setContent(content);
request.setText(text);
// @人
OapiRobotSendRequest.At at = new OapiRobotSendRequest.At();
// isAtAll类型如果不为Boolean,请升级至最新SDK
at.setIsAtAll(false);
// 钉钉上注册的手机号就行了
at.setAtMobiles(Collections.singletonList("13123920295"));
request.setAt(at);
OapiRobotSendResponse response = client.execute(request);
log.info("success:{}, code:{}, errorCode:{}, errorMsg:{}", response.isSuccess(), response.getCode(), response.getErrcode(), response.getErrmsg());
}
/**
* 发送消息测试
*/
public static void main(String[] args) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException, ApiException {
sendText("测试消息");
}
}