赞
踩
邀请自定义机器人入群:进入你的目标群组,打开会话设置,找到群机器人,并点击添加机器人,选择自定义机器人加入群聊。
为机器人输入一个合适的名字和描述,也可以为机器人设置一个合适的头像,然后点击下一步。
获取该机器人的 webhook 地址,格式如下:
https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxxxxxxxxxxxx
用任意方式向该 webhook 发起 HTTP POST 请求,即可向这个自定义机器人所在的群聊发送消息。
注意
你需要一定的服务端开发基础,通过服务端请求方式调用webhook地址。
以curl指令为例,请求示例如下:curl -X POST -H "Content-Type: application/json" \ -d '{"msg_type":"text","content":{"text":"request example"}}' \ https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxxxxxxxxxxxx
- 1
- 2
- 3
请将上述代码中
https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxxxxxxxxxxxx
更换为真实webhook的地址。
若测试出错,请先检查复制的指令是否和测试指令结构一致。
如请求成功,返回体为:
{
"code": 0,
"msg": "success",
"data": {},
"Extra": null,//冗余字段,用于兼容存量历史逻辑,不建议使用
"StatusCode": 0,//冗余字段,用于兼容存量历史逻辑,不建议使用
"StatusMessage": "success"//冗余字段,用于兼容存量历史逻辑,不建议使用
}
如请求体格式错误,返回体如下。请检查:
{
"code": 9499,
"msg": "Bad Request",
"data": {}
}
如果未妥善保管webhook地址,可能存在webhook地址泄露后,被恶意开发者调用,发送垃圾信息的风险,我们强烈建议对其进行安全设置。安全设置目前提供了 3 种方式,可根据需求选择一种及以上方式进行配置。
最多设置 10 个关键词。设定后,只有包含至少一个关键词的消息才会被发送。如,将自定义关键词设为“应用报警”和“项目更新”后,自定义机器人发送的消息至少包含其中一个词,才会被发送到群聊。
发送请求后,若自定义关键词校验失败,将返回以下信息:
// 关键词校验失败
{
"code": 19024,
"msg": "Key Words Not Found"
}
最多设置 10 个 IP 地址或地址段。设定后,只处理来自所设 IP 地址范围的请求。支持段输入,如 123.12.1.* 或 123.1.1.1/24
// IP校验失败
{
"code": 19022,
"msg": "Ip Not Allowed"
}
设定后,发送的请求是需要签名验证来保障来源可信。
签名的算法:把 timestamp + “\n” + 密钥 当做签名字符串,使用 HmacSHA256 算法计算签名,再进行 Base64 编码。
- timestamp为距当前时间不超过 1 小时(3600)的时间戳,时间单位s,如:1599360473
- 密钥自动生成,可直接从界面上复制
Java示例代码如下:
package sign; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import org.apache.commons.codec.binary.Base64; public class SignDemo { public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException { String secret = "demo"; int timestamp = 100; System.out.printf("sign: %s", GenSign(secret, timestamp)); } private static String GenSign(String secret, int timestamp) throws NoSuchAlgorithmException, InvalidKeyException { //把timestamp+"\n"+密钥当做签名字符串 String stringToSign = timestamp + "\n" + secret; //使用HmacSHA256算法计算签名 Mac mac = Mac.getInstance("HmacSHA256"); mac.init(new SecretKeySpec(stringToSign.getBytes(StandardCharsets.UTF_8), "HmacSHA256")); byte[] signData = mac.doFinal(new byte[]{}); return new String(Base64.encodeBase64(signData)); } }
获得签名后,在发送请求时需加上 timestamp 和 sign (即获得的签名)字段。发送文本消息的请求例如下:
// 开启签名验证后发送文本消息
{
"timestamp": "1599360473",
"sign": "xxxxxxxxxxxxxxxxxxxxx",
"msg_type": "text",
"content": {
"text": "request example"
}
}
发送请求后,若签名校验失败,请排查以下原因:
- 时间戳距发送时已超过 1 小时,签名已过期;
- 服务器时间与标准时间有比较大的偏差,导致签名过期。请注意检查、校准你的服务器时间;
- 签名不匹配,校验不通过。将返回以下信息:
// 签名校验失败 { "code": 19021, "msg": "sign match fail or timestamp is not within one hour from current time" }
- 1
- 2
- 3
- 4
- 5
自定义机器人添加完成后,就能向其 webhook 地址发送 POST 请求,从而在群聊中推送消息了。支持推送的消息格式有文本、富文本、图片消息和群名片等。
在消息体中,参数msg_type和对应的消息类型的映射关系如下:
请求的消息体示例:
{
"msg_type": "text",
"content": {
"text": "新更新提醒"
}
}
请求的消息体示例:
{ "msg_type": "post", "content": { "post": { "zh_cn": { "title": "项目更新通知", "content": [ [{ "tag": "text", "text": "项目有更新: " }, { "tag": "a", "text": "请查看", "href": "http://www.example.com/" }, { "tag": "at", "user_id": "ou_18eac8********17ad4f02e8bbbb" } ] ] } } } }
请求的消息体示例:
{
"msg_type":"image",
"content":{
"image_key": "img_ecffc3b9-8f14-400f-a014-05eca1a4310g"
}
}
image_key
的获取方法,可参考上传图片说明文档。
消息卡片可由按钮、图片等多种组件类型搭建而成。关于消息卡片的设计规范、格式等信息,请详见开放平台文档-消息卡片。
- 自定义机器人发送的消息卡片,只支持通过按钮、文字链方式跳转url,不支持点击后回调信息到服务端的 回传交互
- 在消息卡片中如果要@提到某用户,请注意:自定义机器人仅支持通过
open_id
(什么是open_id?)的方式实现,暂不支持email、user_id等其他方式。
请求的消息体示例:
注意:发送消息卡片时,需要将消息体的content
字符串替换为card
结构体
{ "msg_type": "interactive", "card": { "elements": [{ "tag": "div", "text": { "content": "**西湖**,位于浙江省杭州市西湖区龙井路1号,杭州市区西部,景区总面积49平方千米,汇水面积为21.22平方千米,湖面面积为6.38平方千米。", "tag": "lark_md" } }, { "actions": [{ "tag": "button", "text": { "content": "更多景点介绍 :玫瑰:", "tag": "lark_md" }, "url": "https://www.example.com", "type": "default", "value": {} }], "tag": "action" }], "header": { "title": { "content": "今日旅游推荐", "tag": "plain_text" } } } }
可以在机器人发送的普通文本消息(text)、富文本消息(post)、消息卡片(interactive)中,使用at标签实现@人效果。具体请求示意如下
at
标签说明:
// at 指定用户
<at user_id="ou_xxx">Name</at> //取值必须使用ou_xxxxx格式的 open_id 来at指定人
// at 所有人
<at user_id="all">所有人</at>
请求体示意:
{
"msg_type": "text",
"content": {
"text": "<at user_id = \"ou_f43d7bf0bxxxxxxxxxxxxxxx\">Tom</at> text content"
}
}
at
标签说明:
// at 指定用户
{
"tag": "at",
"user_id": "ou_xxxxxxx",//取值必须使用ou_xxxxx格式的 open_id 来at指定人
"user_name": "tom"
}
// at 所有人
{
"tag": "at",
"user_id": "all",//取值使用"all"来at所有人
"user_name": "所有人"
}
请求体示意:
{ "msg_type": "post", "content": { "zh_cn": { "title": "我是一个标题", "content": [ [{ "tag": "text", "text": "第一行 :" }, { "tag": "at", "user_id": "ou_xxxxxx", "user_name": "tom" } ], [{ "tag": "text", "text": "第二行:" }, { "tag": "at", "user_id": "all", "user_name": "所有人" } ] ] } } }
可以使用消息卡片Markdown内容中的at人标签,标签示意:
// at 指定用户
<at id=ou_xxx></at> //取值必须使用ou_xxxxx格式的 open_id 来at指定人
// at 所有人
<at id=all></at>
请求体中的 card
内容示意:
{
"msg_type": "interactive",
"card": {
"elements": [{
"tag": "div",
"text": {
"content": "at所有人<at id=all></at> \n at指定人<at id=ou_xxxxxx></at>",
"tag": "lark_md"
}
}]
}
}
以上消息内容可支持 markdown 格式的语法
飞书 Java 代码示例
import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; import javax.annotation.Resource; import java.text.SimpleDateFormat; import java.util.HashMap; import java.util.Map; /** * 飞书消息提醒 */ @Component public class FeiShuUtils { @Resource private RestTemplate restTemplate; // 发送文本消息 public void sendTextMessage() { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Map<String, Object> text = new HashMap<>(); text.put("msg_type", "text"); Map<String, Object> content = new HashMap<>(); // content.put("text", "项目告警通知:" + sdf.format(new Date())); content.put("text", "项目告警通知 <at user_id =\"all\">所有人</at>"); text.put("content", content); String url = "https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxx-xxxxx"; String response = restTemplate.postForObject(url, text, String.class); System.out.println(response); } // 发送富文本消息 public void sendRichTextMessage() { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String str = "{\n" + " \"msg_type\": \"post\",\n" + " \"content\": {\n" + " \"post\": {\n" + " \"zh_cn\": {\n" + " \"title\": \"项目更新通知\",\n" + " \"content\": [\n" + " [\n" + " {\n" + " \"tag\": \"text\",\n" + " \"text\": \"项目有更新: \"\n" + " },\n" + " {\n" + " \"tag\": \"a\",\n" + " \"text\": \"请查看\",\n" + " \"href\": \"http://www.baidu.com/\"\n" + " },\n" + " {\n" + " \"tag\": \"at\",\n" + " \"user_id\": \"all\",\n" + " \"user_name\": \"所有人\"\n" + " }\n" + " ]\n" + " ]\n" + " }\n" + " }\n" + " }\n" + "}"; HttpHeaders headers = new HttpHeaders(); // 设置请求头编码格式防止乱码 headers.add("Content-Type", "application/json; charset=UTF-8"); HttpEntity<String> requestEntity = new HttpEntity<>(str, headers); String url = "https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxx-xxxxx"; String response = restTemplate.postForObject(url, requestEntity, String.class); System.out.println(response); } // 发送图片消息 public void sendImage() { String str = "{\n" + " \"msg_type\":\"image\",\n" + " \"content\":{\n" + " \"image_key\": \"img_ecffc3b9-8f14-400f-a014-05eca1a4310g\"\n" + " }\n" + "} "; String url = "https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxx-xxxxx"; String response = restTemplate.postForObject(url, str, String.class); System.out.println(response); } // 发送卡片消息 public void sendCard() { String str = "{\n" + " \"msg_type\": \"interactive\",\n" + " \"card\": {\n" + " \"config\": {\n" + " \"wide_screen_mode\": true\n" + " },\n" + " \"elements\": [\n" + " {\n" + " \"tag\": \"markdown\",\n" + " \"content\": \"这里是卡片文本,支持使用markdown标签设置文本格式。例如:\\n*斜体* 、**粗体**、~~删除线~~、[文字链接](https://www.feishu.cn)、<at id=all></at>、<font color='red'> 彩色文本 </font>\"\n" + " },\n" + " {\n" + " \"alt\": {\n" + " \"content\": \"\",\n" + " \"tag\": \"plain_text\"\n" + " },\n" + " \"img_key\": \"img_v2_041b28e3-5680-48c2-9af2-497ace79333g\",\n" + " \"tag\": \"img\"\n" + " },\n" + " {\n" + " \"tag\": \"action\",\n" + " \"actions\": [\n" + " {\n" + " \"tag\": \"button\",\n" + " \"text\": {\n" + " \"tag\": \"plain_text\",\n" + " \"content\": \"这是跳转按钮\"\n" + " },\n" + " \"type\": \"primary\",\n" + " \"url\": \"https://feishu.cn\"\n" + " }\n" + " ]\n" + " }\n" + " ],\n" + " \"header\": {\n" + " \"template\": \"blue\",\n" + " \"title\": {\n" + " \"content\": \"这里是卡片标题\",\n" + " \"tag\": \"plain_text\"\n" + " }\n" + " }\n" + " }\n" + "}"; HttpHeaders headers = new HttpHeaders(); // 设置请求头编码格式防止乱码 headers.add("Content-Type", "application/json; charset=UTF-8"); HttpEntity<String> requestEntity = new HttpEntity<>(str, headers); String url = "https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxx-xxxxx"; String response = restTemplate.postForObject(url, requestEntity, String.class); System.out.println(response); } }
发送结果
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。