|
|
@@ -0,0 +1,554 @@
|
|
|
+# 飞书机器人推送接口文档
|
|
|
+
|
|
|
+## 概述
|
|
|
+
|
|
|
+本模块提供了飞书机器人消息推送功能,支持向飞书群组或个人发送消息。通过简单的 HTTP 接口调用,前端可以轻松实现飞书消息推送。
|
|
|
+
|
|
|
+## 前置准备
|
|
|
+
|
|
|
+### 1. 创建飞书机器人
|
|
|
+
|
|
|
+在使用接口之前,需要先在飞书群组中创建自定义机器人:
|
|
|
+
|
|
|
+1. 打开飞书群组
|
|
|
+2. 点击群设置 → 群机器人 → 添加机器人
|
|
|
+3. 选择"自定义机器人"
|
|
|
+4. 配置机器人名称、描述等信息
|
|
|
+5. 获取 Webhook URL(格式:`https://open.feishu.cn/open-apis/bot/v2/hook/xxx`)
|
|
|
+
|
|
|
+**重要提示:**
|
|
|
+- 每个群组可以创建多个机器人
|
|
|
+- Webhook URL 包含机器人的访问凭证,请妥善保管
|
|
|
+- 机器人发送的消息会显示机器人的名称和头像
|
|
|
+
|
|
|
+### 2. 配置安全设置(可选)
|
|
|
+
|
|
|
+飞书机器人支持以下安全设置:
|
|
|
+- **签名验证**:通过签名验证请求来源
|
|
|
+- **IP 白名单**:限制只有特定 IP 可以调用
|
|
|
+- **关键词验证**:消息必须包含特定关键词
|
|
|
+
|
|
|
+本接口暂不支持签名验证,如需使用请在飞书后台配置 IP 白名单或关键词验证。
|
|
|
+
|
|
|
+## 接口列表
|
|
|
+
|
|
|
+### 基础 URL
|
|
|
+
|
|
|
+```
|
|
|
+http://your-server:3000/api/feishu
|
|
|
+```
|
|
|
+
|
|
|
+### 1. 通用消息发送接口
|
|
|
+
|
|
|
+**接口地址:** `POST /api/feishu/send`
|
|
|
+
|
|
|
+**功能说明:** 支持发送所有类型的飞书消息,灵活性最高。
|
|
|
+
|
|
|
+**请求参数:**
|
|
|
+
|
|
|
+| 参数名 | 类型 | 必填 | 说明 |
|
|
|
+|--------|------|------|------|
|
|
|
+| webhook_url | string | 是 | 飞书机器人的 Webhook URL |
|
|
|
+| msg_type | string | 是 | 消息类型:text(文本)、post(富文本)、interactive(卡片) |
|
|
|
+| content | object | 是 | 消息内容,根据 msg_type 不同而不同 |
|
|
|
+
|
|
|
+**请求示例:**
|
|
|
+
|
|
|
+```javascript
|
|
|
+// 发送文本消息
|
|
|
+fetch('http://your-server:3000/api/feishu/send', {
|
|
|
+ method: 'POST',
|
|
|
+ headers: {
|
|
|
+ 'Content-Type': 'application/json',
|
|
|
+ },
|
|
|
+ body: JSON.stringify({
|
|
|
+ webhook_url: 'https://open.feishu.cn/open-apis/bot/v2/hook/xxx',
|
|
|
+ msg_type: 'text',
|
|
|
+ content: {
|
|
|
+ text: '这是一条测试消息'
|
|
|
+ }
|
|
|
+ })
|
|
|
+})
|
|
|
+.then(res => res.json())
|
|
|
+.then(data => console.log(data));
|
|
|
+```
|
|
|
+
|
|
|
+**响应示例:**
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "success": true,
|
|
|
+ "data": {
|
|
|
+ "message": "消息发送成功",
|
|
|
+ "feishu_response": {
|
|
|
+ "code": 0,
|
|
|
+ "msg": "success"
|
|
|
+ }
|
|
|
+ },
|
|
|
+ "timestamp": "2026-03-09T11:45:00.000Z"
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 2. 文本消息发送接口(简化版)
|
|
|
+
|
|
|
+**接口地址:** `POST /api/feishu/send/text`
|
|
|
+
|
|
|
+**功能说明:** 快速发送纯文本消息,接口更简洁。
|
|
|
+
|
|
|
+**请求参数:**
|
|
|
+
|
|
|
+| 参数名 | 类型 | 必填 | 说明 |
|
|
|
+|--------|------|------|------|
|
|
|
+| webhook_url | string | 是 | 飞书机器人的 Webhook URL |
|
|
|
+| text | string | 是 | 消息文本内容 |
|
|
|
+
|
|
|
+**请求示例:**
|
|
|
+
|
|
|
+```javascript
|
|
|
+fetch('http://your-server:3000/api/feishu/send/text', {
|
|
|
+ method: 'POST',
|
|
|
+ headers: {
|
|
|
+ 'Content-Type': 'application/json',
|
|
|
+ },
|
|
|
+ body: JSON.stringify({
|
|
|
+ webhook_url: 'https://open.feishu.cn/open-apis/bot/v2/hook/xxx',
|
|
|
+ text: '这是一条简单的文本消息'
|
|
|
+ })
|
|
|
+})
|
|
|
+.then(res => res.json())
|
|
|
+.then(data => console.log(data));
|
|
|
+```
|
|
|
+
|
|
|
+**响应示例:**
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "success": true,
|
|
|
+ "data": {
|
|
|
+ "message": "文本消息发送成功",
|
|
|
+ "feishu_response": {
|
|
|
+ "code": 0,
|
|
|
+ "msg": "success"
|
|
|
+ }
|
|
|
+ },
|
|
|
+ "timestamp": "2026-03-09T11:45:00.000Z"
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 3. 富文本消息发送接口(支持 @用户)
|
|
|
+
|
|
|
+**接口地址:** `POST /api/feishu/send/post`
|
|
|
+
|
|
|
+**功能说明:** 发送富文本消息,支持标题、多段落、@用户、链接等丰富格式。
|
|
|
+
|
|
|
+**请求参数:**
|
|
|
+
|
|
|
+| 参数名 | 类型 | 必填 | 说明 |
|
|
|
+|--------|------|------|------|
|
|
|
+| webhook_url | string | 是 | 飞书机器人的 Webhook URL |
|
|
|
+| title | string | 否 | 消息标题 |
|
|
|
+| content | array | 是 | 消息内容数组,详见下方说明 |
|
|
|
+
|
|
|
+**content 格式说明:**
|
|
|
+
|
|
|
+content 是一个二维数组,第一层代表段落,第二层代表段落内的元素。
|
|
|
+
|
|
|
+支持的元素类型:
|
|
|
+- `text`:普通文本
|
|
|
+- `a`:链接
|
|
|
+- `at`:@用户
|
|
|
+
|
|
|
+**请求示例 1:发送带标题的富文本消息**
|
|
|
+
|
|
|
+```javascript
|
|
|
+fetch('http://your-server:3000/api/feishu/send/post', {
|
|
|
+ method: 'POST',
|
|
|
+ headers: {
|
|
|
+ 'Content-Type': 'application/json',
|
|
|
+ },
|
|
|
+ body: JSON.stringify({
|
|
|
+ webhook_url: 'https://open.feishu.cn/open-apis/bot/v2/hook/xxx',
|
|
|
+ title: '系统通知',
|
|
|
+ content: [
|
|
|
+ [
|
|
|
+ { tag: 'text', text: '您有一条新的任务待处理' }
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ { tag: 'text', text: '任务详情:' },
|
|
|
+ { tag: 'a', text: '点击查看', href: 'https://example.com/task/123' }
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ })
|
|
|
+})
|
|
|
+.then(res => res.json())
|
|
|
+.then(data => console.log(data));
|
|
|
+```
|
|
|
+
|
|
|
+**请求示例 2:@单个用户**
|
|
|
+
|
|
|
+```javascript
|
|
|
+fetch('http://your-server:3000/api/feishu/send/post', {
|
|
|
+ method: 'POST',
|
|
|
+ headers: {
|
|
|
+ 'Content-Type': 'application/json',
|
|
|
+ },
|
|
|
+ body: JSON.stringify({
|
|
|
+ webhook_url: 'https://open.feishu.cn/open-apis/bot/v2/hook/xxx',
|
|
|
+ title: '任务提醒',
|
|
|
+ content: [
|
|
|
+ [
|
|
|
+ { tag: 'at', user_id: 'ou_xxxxxx' },
|
|
|
+ { tag: 'text', text: ' 您有一个新任务需要处理' }
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ })
|
|
|
+})
|
|
|
+.then(res => res.json())
|
|
|
+.then(data => console.log(data));
|
|
|
+```
|
|
|
+
|
|
|
+**请求示例 3:@所有人**
|
|
|
+
|
|
|
+```javascript
|
|
|
+fetch('http://your-server:3000/api/feishu/send/post', {
|
|
|
+ method: 'POST',
|
|
|
+ headers: {
|
|
|
+ 'Content-Type': 'application/json',
|
|
|
+ },
|
|
|
+ body: JSON.stringify({
|
|
|
+ webhook_url: 'https://open.feishu.cn/open-apis/bot/v2/hook/xxx',
|
|
|
+ title: '重要通知',
|
|
|
+ content: [
|
|
|
+ [
|
|
|
+ { tag: 'at', user_id: 'all' },
|
|
|
+ { tag: 'text', text: ' 系统将于今晚 22:00 进行维护,请提前保存工作' }
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ })
|
|
|
+})
|
|
|
+.then(res => res.json())
|
|
|
+.then(data => console.log(data));
|
|
|
+```
|
|
|
+
|
|
|
+**请求示例 4:@多个用户**
|
|
|
+
|
|
|
+```javascript
|
|
|
+fetch('http://your-server:3000/api/feishu/send/post', {
|
|
|
+ method: 'POST',
|
|
|
+ headers: {
|
|
|
+ 'Content-Type': 'application/json',
|
|
|
+ },
|
|
|
+ body: JSON.stringify({
|
|
|
+ webhook_url: 'https://open.feishu.cn/open-apis/bot/v2/hook/xxx',
|
|
|
+ title: '项目进度更新',
|
|
|
+ content: [
|
|
|
+ [
|
|
|
+ { tag: 'at', user_id: 'ou_user1' },
|
|
|
+ { tag: 'text', text: ' ' },
|
|
|
+ { tag: 'at', user_id: 'ou_user2' },
|
|
|
+ { tag: 'text', text: ' 请查看最新的项目进度' }
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ { tag: 'text', text: '详情:' },
|
|
|
+ { tag: 'a', text: '项目看板', href: 'https://example.com/project' }
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ })
|
|
|
+})
|
|
|
+.then(res => res.json())
|
|
|
+.then(data => console.log(data));
|
|
|
+```
|
|
|
+
|
|
|
+**响应示例:**
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "success": true,
|
|
|
+ "data": {
|
|
|
+ "message": "富文本消息发送成功",
|
|
|
+ "feishu_response": {
|
|
|
+ "code": 0,
|
|
|
+ "msg": "success"
|
|
|
+ }
|
|
|
+ },
|
|
|
+ "timestamp": "2026-03-09T11:45:00.000Z"
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+## 错误处理
|
|
|
+
|
|
|
+### 错误响应格式
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "success": false,
|
|
|
+ "error": "错误信息",
|
|
|
+ "timestamp": "2026-03-09T11:45:00.000Z"
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 常见错误码
|
|
|
+
|
|
|
+| HTTP 状态码 | 错误信息 | 说明 |
|
|
|
+|------------|---------|------|
|
|
|
+| 400 | webhook_url 是必填项 | 未提供 webhook_url |
|
|
|
+| 400 | msg_type 是必填项 | 未提供 msg_type |
|
|
|
+| 400 | content 是必填项 | 未提供 content |
|
|
|
+| 400 | webhook_url 格式不正确 | webhook_url 不是有效的飞书 Webhook URL |
|
|
|
+| 500 | 飞书消息发送失败 | 飞书 API 返回错误 |
|
|
|
+| 500 | 消息发送失败 | 网络错误或其他异常 |
|
|
|
+
|
|
|
+## 使用场景示例
|
|
|
+
|
|
|
+### 场景 1:系统告警通知
|
|
|
+
|
|
|
+```javascript
|
|
|
+// 当系统检测到异常时,发送告警消息
|
|
|
+async function sendAlert(errorMessage) {
|
|
|
+ const response = await fetch('http://your-server:3000/api/feishu/send/post', {
|
|
|
+ method: 'POST',
|
|
|
+ headers: { 'Content-Type': 'application/json' },
|
|
|
+ body: JSON.stringify({
|
|
|
+ webhook_url: 'https://open.feishu.cn/open-apis/bot/v2/hook/xxx',
|
|
|
+ title: '⚠️ 系统告警',
|
|
|
+ content: [
|
|
|
+ [
|
|
|
+ { tag: 'at', user_id: 'all' },
|
|
|
+ { tag: 'text', text: ' 系统检测到异常' }
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ { tag: 'text', text: `错误信息:${errorMessage}` }
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ { tag: 'text', text: `时间:${new Date().toLocaleString()}` }
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ })
|
|
|
+ });
|
|
|
+ return response.json();
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 场景 2:任务分配通知
|
|
|
+
|
|
|
+```javascript
|
|
|
+// 当任务分配给用户时,发送通知
|
|
|
+async function notifyTaskAssignment(userId, taskName, taskUrl) {
|
|
|
+ const response = await fetch('http://your-server:3000/api/feishu/send/post', {
|
|
|
+ method: 'POST',
|
|
|
+ headers: { 'Content-Type': 'application/json' },
|
|
|
+ body: JSON.stringify({
|
|
|
+ webhook_url: 'https://open.feishu.cn/open-apis/bot/v2/hook/xxx',
|
|
|
+ title: '📋 新任务分配',
|
|
|
+ content: [
|
|
|
+ [
|
|
|
+ { tag: 'at', user_id: userId },
|
|
|
+ { tag: 'text', text: ` 您有一个新任务:${taskName}` }
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ { tag: 'text', text: '查看详情:' },
|
|
|
+ { tag: 'a', text: '点击这里', href: taskUrl }
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ })
|
|
|
+ });
|
|
|
+ return response.json();
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 场景 3:批量通知
|
|
|
+
|
|
|
+```javascript
|
|
|
+// 向多个用户发送通知
|
|
|
+async function notifyMultipleUsers(userIds, message) {
|
|
|
+ // 构建 @用户 的内容
|
|
|
+ const atUsers = userIds.flatMap(userId => [
|
|
|
+ { tag: 'at', user_id: userId },
|
|
|
+ { tag: 'text', text: ' ' }
|
|
|
+ ]);
|
|
|
+
|
|
|
+ const response = await fetch('http://your-server:3000/api/feishu/send/post', {
|
|
|
+ method: 'POST',
|
|
|
+ headers: { 'Content-Type': 'application/json' },
|
|
|
+ body: JSON.stringify({
|
|
|
+ webhook_url: 'https://open.feishu.cn/open-apis/bot/v2/hook/xxx',
|
|
|
+ title: '通知',
|
|
|
+ content: [
|
|
|
+ atUsers,
|
|
|
+ [
|
|
|
+ { tag: 'text', text: message }
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ })
|
|
|
+ });
|
|
|
+ return response.json();
|
|
|
+}
|
|
|
+
|
|
|
+// 使用示例
|
|
|
+notifyMultipleUsers(
|
|
|
+ ['ou_user1', 'ou_user2', 'ou_user3'],
|
|
|
+ '会议将于 10 分钟后开始,请准时参加'
|
|
|
+);
|
|
|
+```
|
|
|
+
|
|
|
+## 注意事项
|
|
|
+
|
|
|
+1. **Webhook URL 安全**
|
|
|
+ - Webhook URL 包含访问凭证,请勿在前端代码中硬编码
|
|
|
+ - 建议将 Webhook URL 存储在后端配置或数据库中
|
|
|
+ - 可以为不同的群组或场景配置不同的机器人
|
|
|
+
|
|
|
+2. **消息频率限制**
|
|
|
+ - 飞书机器人有消息发送频率限制(通常为 20 条/分钟)
|
|
|
+ - 超过限制会返回错误,请合理控制发送频率
|
|
|
+ - 建议实现消息队列机制,避免短时间内大量发送
|
|
|
+
|
|
|
+3. **用户 ID 获取**
|
|
|
+ - @用户需要提供用户的 Open ID(格式:`ou_xxxxxx`)
|
|
|
+ - 可以通过飞书开放平台 API 获取用户 ID
|
|
|
+ - @所有人使用 `user_id: 'all'`
|
|
|
+
|
|
|
+4. **消息格式**
|
|
|
+ - 富文本消息的 content 必须是二维数组
|
|
|
+ - 每个段落是一个数组,包含多个元素
|
|
|
+ - 元素必须包含 `tag` 字段,根据不同 tag 提供对应的字段
|
|
|
+
|
|
|
+5. **错误处理**
|
|
|
+ - 建议在前端实现重试机制
|
|
|
+ - 记录发送失败的消息,便于排查问题
|
|
|
+ - 对用户友好地展示错误信息
|
|
|
+
|
|
|
+## 完整的前端封装示例
|
|
|
+
|
|
|
+```javascript
|
|
|
+// feishu-bot.js
|
|
|
+class FeishuBot {
|
|
|
+ constructor(baseUrl = 'http://your-server:3000/api/feishu') {
|
|
|
+ this.baseUrl = baseUrl;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 发送文本消息
|
|
|
+ */
|
|
|
+ async sendText(webhookUrl, text) {
|
|
|
+ return this._request('/send/text', {
|
|
|
+ webhook_url: webhookUrl,
|
|
|
+ text
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 发送富文本消息
|
|
|
+ */
|
|
|
+ async sendPost(webhookUrl, title, content) {
|
|
|
+ return this._request('/send/post', {
|
|
|
+ webhook_url: webhookUrl,
|
|
|
+ title,
|
|
|
+ content
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @单个用户
|
|
|
+ */
|
|
|
+ async mentionUser(webhookUrl, userId, message, title = '通知') {
|
|
|
+ return this.sendPost(webhookUrl, title, [
|
|
|
+ [
|
|
|
+ { tag: 'at', user_id: userId },
|
|
|
+ { tag: 'text', text: ` ${message}` }
|
|
|
+ ]
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @所有人
|
|
|
+ */
|
|
|
+ async mentionAll(webhookUrl, message, title = '重要通知') {
|
|
|
+ return this.sendPost(webhookUrl, title, [
|
|
|
+ [
|
|
|
+ { tag: 'at', user_id: 'all' },
|
|
|
+ { tag: 'text', text: ` ${message}` }
|
|
|
+ ]
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @多个用户
|
|
|
+ */
|
|
|
+ async mentionMultiple(webhookUrl, userIds, message, title = '通知') {
|
|
|
+ const atUsers = userIds.flatMap(userId => [
|
|
|
+ { tag: 'at', user_id: userId },
|
|
|
+ { tag: 'text', text: ' ' }
|
|
|
+ ]);
|
|
|
+
|
|
|
+ return this.sendPost(webhookUrl, title, [
|
|
|
+ atUsers,
|
|
|
+ [{ tag: 'text', text: message }]
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 内部请求方法
|
|
|
+ */
|
|
|
+ async _request(endpoint, data) {
|
|
|
+ try {
|
|
|
+ const response = await fetch(`${this.baseUrl}${endpoint}`, {
|
|
|
+ method: 'POST',
|
|
|
+ headers: {
|
|
|
+ 'Content-Type': 'application/json',
|
|
|
+ },
|
|
|
+ body: JSON.stringify(data)
|
|
|
+ });
|
|
|
+
|
|
|
+ const result = await response.json();
|
|
|
+
|
|
|
+ if (!result.success) {
|
|
|
+ throw new Error(result.error || '发送失败');
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+ } catch (error) {
|
|
|
+ console.error('飞书消息发送失败:', error);
|
|
|
+ throw error;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 使用示例
|
|
|
+const bot = new FeishuBot();
|
|
|
+
|
|
|
+// 发送文本消息
|
|
|
+bot.sendText(
|
|
|
+ 'https://open.feishu.cn/open-apis/bot/v2/hook/xxx',
|
|
|
+ '这是一条测试消息'
|
|
|
+);
|
|
|
+
|
|
|
+// @单个用户
|
|
|
+bot.mentionUser(
|
|
|
+ 'https://open.feishu.cn/open-apis/bot/v2/hook/xxx',
|
|
|
+ 'ou_xxxxxx',
|
|
|
+ '您有新的任务'
|
|
|
+);
|
|
|
+
|
|
|
+// @所有人
|
|
|
+bot.mentionAll(
|
|
|
+ 'https://open.feishu.cn/open-apis/bot/v2/hook/xxx',
|
|
|
+ '系统维护通知'
|
|
|
+);
|
|
|
+
|
|
|
+// @多个用户
|
|
|
+bot.mentionMultiple(
|
|
|
+ 'https://open.feishu.cn/open-apis/bot/v2/hook/xxx',
|
|
|
+ ['ou_user1', 'ou_user2'],
|
|
|
+ '会议即将开始'
|
|
|
+);
|
|
|
+```
|
|
|
+
|
|
|
+## 参考资料
|
|
|
+
|
|
|
+- [飞书开放平台 - 自定义机器人指南](https://open.feishu.cn/document/client-docs/bot-v3/add-custom-bot)
|
|
|
+- [飞书开放平台 - 消息类型说明](https://open.feishu.cn/document/ukTMukTMukTM/ucTM5YjL3ETO24yNxkjN)
|
|
|
+
|
|
|
+## 更新日志
|
|
|
+
|
|
|
+- 2026-03-09:初始版本,支持文本消息和富文本消息发送
|