1 群機器人
(1) 引言
釘釘聊天群內支持的群機器人, 類似QQ 群機器人, 可以發天氣, 講笑話那樣;
釘釘群機器人支持自定義機器人, 允許開發者管理機器人做預警消息通知;
注意: 我沒重置access_token, demo支持消息發送, 但會發送到我這個群, 建議你們使用自己的webhook
(2) 限制
- 6 個機器人/每群, 20條消息/每分鍾
- 不支持應答模式, 僅做群消息通知
(3) 消息格式
支持普通文本消息, 鏈接消息, markdown 格式(注意僅部分語法支持)文本, 圖片及鏈接, 支持FeedCard, ActionCard 等消息
(4) 官方開發文檔
https://open-doc.dingtalk.com/microapp/serverapi3/iydd5h
2 自定義機器人
2.1 創建機器人
自定義機器人依賴於釘釘群, 首先創建釘釘群(群主有權限查看access_token), 拿到webhook 信息, 通過網絡發送請求, 釘釘開放平台響應請求發送預警消息到指定access_token 的釘釘群
釘釘群創建方式是在聊天頁面, 點擊"+"添加其他人來創建一個釘釘群.
進入群, 打開設置, 選中群機器人, 創建自定義機器人, 完善機器人基本信息后創建完成, 機器人自動推送一條歡迎語到釘釘群.
2.2 Postman 通過webhook 發送消息演示
此處使用Postman 模擬請求, 如下所示, 發送普通文本消息后, 釘釘群會收到機器人的預警消息.
3 創建項目引入釘釘機器人SDK
本機開發環境win10, 已創建釘釘群, 並獲取到webhook, 本機使用的IDEA, 下載的Java SDK
3.1 創建Maven 項目引入SDK
(1)Java SDK 下載
下載SDK: https://open-doc.dingtalk.com/microapp/faquestions/vzbp02, 官方支持以下版本, 此處使用Java SDK;
- JAVA版本
- PHP版本
- .NET版
- Python版
解壓后是官方直接打好的jar 包, 也包括源碼包
(2)創建Maven 項目引入Jar
創建Maven 項目引入打好的jar 包: 本機jar 包地址: D:\download\dingtalk-sdk-java\taobao-sdk-java-auto_1479188381469-20190704.jar
- mvn 命令
mvn install:install-file
-Dfile=D:\download\dingtalk-sdk-java\taobao-sdk-java-auto_1479188381469-20190704.jar -DgroupId=com.dingtalk -DartifactId=com-dingtalk-api
-Dversion=1.0.0 -Dpackaging=jar
- 參數說明
-Dfile jar包所在路徑,需要包含jar包名.此處D:\download\dingtalk-sdk-java\taobao-sdk-java-auto_1479188381469-20190704.jar
-DgroupId 指定導入jar時的groupid,可以自定義,此處com.dingtalk
-DartifactId指定導入jar時的artifactId,可以自定義,此處com-dingtalk-api
-Dversion 指定導入jar時的版本號,可以自定義,此處1.0.0
-Dpackaging 指定文件類型 ,由於這里是jar包的形式,所以這里得是jar
3.2 預警消息發送工具類封裝
3.2.1 工具類說明
項目成功引入SDK, 支持通過SDK 指定自定義機器人去發送群消息, 前面有說明群機器人支持發送多種類型的消息, 也支持消息帶跳轉鏈接, 或者圖片帶跳轉鏈接等;
工具類創建客戶端client 實例需要擁有正確的webhook, 就是圖2-5. 群機器人管理頁面圖中群設置中可以查看或者重置的hook 標識.
/**
* 釘釘群設置 webhook, 支持重置
*/
private static final String ACCESS_TOKEN = "https://oapi.dingtalk.com/robot/send?access_token=36ba0cc82d41d3c6aaef7d2c09c9f14de0727069edbc498b5c9d88edb72db227";
/**
* 消息類型
*/
private static final String MSG_TYPE_TEXT = "text";
private static final String MSG_TYPE_LINK = "link";
private static final String MSG_TYPE_MARKDOWN = "markdown";
private static final String MSG_TYPE_ACTION_CARD = "actionCard";
private static final String MSG_TYPE_FEED_CARD = "feedCard";
/**
* 客戶端實例
*/
public static DingTalkClient client = new DefaultDingTalkClient(ACCESS_TOKEN);
util 下即封裝的工具類RobotHelperUtil.java, 其中test 包下有做單元測試
3.3.2 測試發送消息
此處單元測試測試方法sendMessageByMarkdown(), sendMessageByActionCardMulti(), sendMessageByFeedCard() 等方法, 群機器人會發送群消息, 其中方法參數title 效果如圖中左側(聯系人列表頁面)透出的消息內容, text 是進入群后的真正的消息.;
此處發送的支持單獨跳轉的消息, 初始化了三個按鈕附帶跳轉鏈接, 按鈕默認縱向排列. 點擊按鈕即可跳轉指定鏈接查看詳細內容.
此處發送的支持多個Link 的消息, 初始化了三個link , 指定標題導圖及跳轉鏈接; 首個link 效果更突出, 這個還挺好玩的.
3.3 項目源碼
- 工具類代碼:
package pers.niaonao.dingtalkrobot.util;
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.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.Arrays;
import java.util.List;
/**
* @className: RobotHelperUtil
* @description: 機器人工具類
* 每個機器人每分鍾最多發送20條
* 限制6 個機器人/群
* @author: niaonao
* @date: 2019/7/6
**/
@Slf4j
public class RobotHelperUtil {
/**
* 釘釘群設置 webhook, 支持重置
*/
private static final String ACCESS_TOKEN = "https://oapi.dingtalk.com/robot/send?access_token=36ba0cc82d41d3c6aaef7d2c09c9f14de0727069edbc498b5c9d88edb72db227";
/**
* 消息類型
*/
private static final String MSG_TYPE_TEXT = "text";
private static final String MSG_TYPE_LINK = "link";
private static final String MSG_TYPE_MARKDOWN = "markdown";
private static final String MSG_TYPE_ACTION_CARD = "actionCard";
private static final String MSG_TYPE_FEED_CARD = "feedCard";
/**
* 客戶端實例
*/
public static DingTalkClient client = new DefaultDingTalkClient(ACCESS_TOKEN);
/**
* @description: 官方演示示例
* title 是消息列表下透出的標題
* text 是進入群后看到的消息內容
*
* @author: niaonao
* @date: 2019/7/6
*/
public static void sdkDemoJava() {
DingTalkClient client = RobotHelperUtil.client;
OapiRobotSendRequest request = new OapiRobotSendRequest();
request.setMsgtype("text");
OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text();
text.setContent("測試文本消息");
request.setText(text);
OapiRobotSendRequest.At at = new OapiRobotSendRequest.At();
at.setAtMobiles(Arrays.asList("13261303345"));
request.setAt(at);
request.setMsgtype("link");
OapiRobotSendRequest.Link link = new OapiRobotSendRequest.Link();
link.setMessageUrl("https://www.dingtalk.com/");
link.setPicUrl("");
link.setTitle("時代的火車向前開");
link.setText("這個即將發布的新版本,創始人陳航(花名“無招”)稱它為“紅樹林”。\n" +
"而在此之前,每當面臨重大升級,產品經理們都會取一個應景的代號,這一次,為什么是“紅樹林");
request.setLink(link);
request.setMsgtype("markdown");
OapiRobotSendRequest.Markdown markdown = new OapiRobotSendRequest.Markdown();
markdown.setTitle("杭州天氣");
markdown.setText("#### 杭州天氣 @156xxxx8827\n" +
"> 9度,西北風1級,空氣良89,相對溫度73%\n\n" +
"> \n" +
"> ###### 10點20分發布 [天氣](http://www.thinkpage.cn/) \n");
request.setMarkdown(markdown);
try {
client.execute(request);
} catch (ApiException e) {
log.error("[ApiException]: 消息發送演示示例, 異常捕獲{}", e.getMessage());
}
}
/**
* @description: 發送普通文本消息
* @param content 文本消息
* @param mobileList 指定@ 聯系人
* @param isAtAll 是否@ 全部聯系人
* @return: com.dingtalk.api.response.OapiRobotSendResponse
* @author: niaonao
* @date: 2019/7/6
*/
public static OapiRobotSendResponse sendMessageByText(String content, List<String> mobileList, boolean isAtAll) {
if (StringUtils.isEmpty(content)) {
return null;
}
//參數 參數類型 必須 說明
//msgtype String 是 消息類型,此時固定為:text
//content String 是 消息內容
//atMobiles Array 否 被@人的手機號(在content里添加@人的手機號)
//isAtAll bool 否 @所有人時:true,否則為:false
OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text();
text.setContent(content);
OapiRobotSendRequest request = new OapiRobotSendRequest();
if (!CollectionUtils.isEmpty(mobileList)) {
// 發送消息並@ 以下手機號聯系人
OapiRobotSendRequest.At at = new OapiRobotSendRequest.At();
at.setAtMobiles(mobileList);
at.setIsAtAll(isAtAll ? "true" : "false");
request.setAt(at);
}
request.setMsgtype(RobotHelperUtil.MSG_TYPE_TEXT);
request.setText(text);
OapiRobotSendResponse response = new OapiRobotSendResponse();
try {
response = RobotHelperUtil.client.execute(request);
} catch (ApiException e) {
log.error("[發送普通文本消息]: 發送消息失敗, 異常捕獲{}", e.getMessage());
}
return response;
}
/**
* @description: 發送link 類型消息
* @param title 消息標題
* @param text 消息內容
* @param messageUrl 點擊消息后跳轉的url
* @param picUrl 插入圖片的url
* @return: com.dingtalk.api.response.OapiRobotSendResponse
* @author: niaonao
* @date: 2019/7/6
*/
public static OapiRobotSendResponse sendMessageByLink(String title, String text, String messageUrl, String picUrl) {
if (!DataValidUtil.checkNotEmpty(title, text, messageUrl)) {
return null;
}
//參數 參數類型 必須 說明
//msgtype String 是 消息類型,此時固定為:link
//title String 是 消息標題
//text String 是 消息內容。如果太長只會部分展示
//messageUrl String 是 點擊消息跳轉的URL
//picUrl String 否 圖片URL
OapiRobotSendRequest.Link link = new OapiRobotSendRequest.Link();
link.setTitle(title);
link.setText(text);
link.setMessageUrl(messageUrl);
link.setPicUrl(picUrl);
OapiRobotSendRequest request = new OapiRobotSendRequest();
request.setMsgtype(RobotHelperUtil.MSG_TYPE_LINK);
request.setLink(link);
OapiRobotSendResponse response = new OapiRobotSendResponse();
try {
response = RobotHelperUtil.client.execute(request);
} catch (ApiException e) {
log.error("[發送link 類型消息]: 發送消息失敗, 異常捕獲{}", e.getMessage());
}
return response;
}
/**
* @description: 發送Markdown 編輯格式的消息
* @param title 標題
* @param markdownText 支持markdown 編輯格式的文本信息
* @param mobileList 消息@ 聯系人
* @param isAtAll 是否@ 全部
* @return: com.dingtalk.api.response.OapiRobotSendResponse
* @author: niaonao
* @date: 2019/7/6
*/
public static OapiRobotSendResponse sendMessageByMarkdown(String title, String markdownText, List<String> mobileList, boolean isAtAll) {
if (!DataValidUtil.checkNotEmpty(title, markdownText)) {
return null;
}
//參數 類型 必選 說明
//msgtype String 是 此消息類型為固定markdown
//title String 是 首屏會話透出的展示內容
//text String 是 markdown格式的消息
//atMobiles Array 否 被@人的手機號(在text內容里要有@手機號)
//isAtAll bool 否 @所有人時:true,否則為:false
OapiRobotSendRequest.Markdown markdown = new OapiRobotSendRequest.Markdown();
markdown.setTitle(title);
markdown.setText(markdownText);
OapiRobotSendRequest request = new OapiRobotSendRequest();
request.setMsgtype(RobotHelperUtil.MSG_TYPE_MARKDOWN);
request.setMarkdown(markdown);
if (!CollectionUtils.isEmpty(mobileList)) {
OapiRobotSendRequest.At at = new OapiRobotSendRequest.At();
at.setIsAtAll(isAtAll ? "true" : "false");
at.setAtMobiles(mobileList);
request.setAt(at);
}
OapiRobotSendResponse response = new OapiRobotSendResponse();
try {
response = RobotHelperUtil.client.execute(request);
} catch (ApiException e) {
log.error("[發送link 類型消息]: 發送消息失敗, 異常捕獲{}", e.getMessage());
}
return response;
}
/**
* @description: 整體跳轉ActionCard類型的消息發送
* @param title 消息標題, 會話消息會展示標題
* @param markdownText markdown格式的消息
* @param singleTitle 單個按鈕的標題
* @param singleURL 單個按鈕的跳轉鏈接
* @param btnOrientation 是否橫向排列(true 橫向排列, false 縱向排列)
* @param hideAvatar 是否隱藏發消息者頭像(true 隱藏頭像, false 不隱藏)
* @return: com.dingtalk.api.response.OapiRobotSendResponse
* @author: niaonao
* @date: 2019/7/6
*/
public static OapiRobotSendResponse sendMessageByActionCardSingle(String title, String markdownText, String singleTitle, String singleURL, boolean btnOrientation, boolean hideAvatar) {
if (!DataValidUtil.checkNotEmpty(title, markdownText)) {
return null;
}
//參數 類型 必選 說明
// msgtype string true 此消息類型為固定actionCard
// title string true 首屏會話透出的展示內容
// text string true markdown格式的消息
// singleTitle string true 單個按鈕的方案。(設置此項和singleURL后btns無效)
// singleURL string true 點擊singleTitle按鈕觸發的URL
// btnOrientation string false 0-按鈕豎直排列,1-按鈕橫向排列
// hideAvatar string false 0-正常發消息者頭像,1-隱藏發消息者頭像
OapiRobotSendRequest.Actioncard actionCard = new OapiRobotSendRequest.Actioncard();
actionCard.setTitle(title);
actionCard.setText(markdownText);
actionCard.setSingleTitle(singleTitle);
actionCard.setSingleURL(singleURL);
// 此處默認為0
actionCard.setBtnOrientation(btnOrientation ? "1" : "0");
// 此處默認為0
actionCard.setHideAvatar(hideAvatar ? "1" : "0");
OapiRobotSendRequest request = new OapiRobotSendRequest();
request.setMsgtype(RobotHelperUtil.MSG_TYPE_ACTION_CARD);
request.setActionCard(actionCard);
OapiRobotSendResponse response = new OapiRobotSendResponse();
try {
response = RobotHelperUtil.client.execute(request);
} catch (ApiException e) {
log.error("[發送ActionCard 類型消息]: 整體跳轉ActionCard類型的發送消息失敗, 異常捕獲{}", e.getMessage());
}
return response;
}
/**
* @description: 獨立跳轉ActionCard類型 消息發送
* @param title 標題
* @param markdownText 文本
* @param btns 按鈕列表
* @param btnOrientation 是否橫向排列(true 橫向排列, false 縱向排列)
* @param hideAvatar 是否隱藏發消息者頭像(true 隱藏頭像, false 不隱藏)
* @return: com.dingtalk.api.response.OapiRobotSendResponse
* @author: niaonao
* @date: 2019/7/6
*/
public static OapiRobotSendResponse sendMessageByActionCardMulti(String title, String markdownText, List<OapiRobotSendRequest.Btns> btns, boolean btnOrientation, boolean hideAvatar) {
if (!DataValidUtil.checkNotEmpty(title, markdownText) || CollectionUtils.isEmpty(btns)) {
return null;
}
//參數 類型 必選 說明
//msgtype string true 此消息類型為固定actionCard
//title string true 首屏會話透出的展示內容
//text string true markdown格式的消息
//btns array true 按鈕的信息:title-按鈕方案,actionURL-點擊按鈕觸發的URL
//btnOrientation string false 0-按鈕豎直排列,1-按鈕橫向排列
//hideAvatar string false 0-正常發消息者頭像,1-隱藏發消息者頭像
OapiRobotSendRequest.Actioncard actionCard = new OapiRobotSendRequest.Actioncard();
actionCard.setTitle(title);
actionCard.setText(markdownText);
// 此處默認為0
actionCard.setBtnOrientation(btnOrientation ? "1" : "0");
// 此處默認為0
actionCard.setHideAvatar(hideAvatar ? "1" : "0");
actionCard.setBtns(btns);
OapiRobotSendRequest request = new OapiRobotSendRequest();
request.setMsgtype(RobotHelperUtil.MSG_TYPE_ACTION_CARD);
request.setActionCard(actionCard);
OapiRobotSendResponse response = new OapiRobotSendResponse();
try {
response = RobotHelperUtil.client.execute(request);
} catch (ApiException e) {
log.error("[發送ActionCard 類型消息]: 獨立跳轉ActionCard類型發送消息失敗, 異常捕獲{}", e.getMessage());
}
return response;
}
/**
* @description: 發送FeedCard類型消息
* @param links
* @return: com.dingtalk.api.response.OapiRobotSendResponse
* @author: niaonao
* @date: 2019/7/6
*/
public static OapiRobotSendResponse sendMessageByFeedCard(List<OapiRobotSendRequest.Links> links) {
if (CollectionUtils.isEmpty(links)) {
return null;
}
//msgtype string true 此消息類型為固定feedCard
//title string true 單條信息文本
//messageURL string true 點擊單條信息到跳轉鏈接
//picURL string true 單條信息后面圖片的URL
OapiRobotSendRequest.Feedcard feedcard = new OapiRobotSendRequest.Feedcard();
feedcard.setLinks(links);
OapiRobotSendRequest request = new OapiRobotSendRequest();
request.setMsgtype(RobotHelperUtil.MSG_TYPE_FEED_CARD);
request.setFeedCard(feedcard);
OapiRobotSendResponse response = new OapiRobotSendResponse();
try {
response = RobotHelperUtil.client.execute(request);
} catch (ApiException e) {
log.error("[發送ActionCard 類型消息]: 獨立跳轉ActionCard類型發送消息失敗, 異常捕獲{}", e.getMessage());
}
return response;
}
/*public static void main(String args[]) {
sdkDemoJava();
}*/
}