2025-12-06 13:07:16 +08:00
|
|
|
|
# V1 API 文档
|
|
|
|
|
|
|
|
|
|
|
|
V1 API 提供基于任务的消息推送接口,支持多渠道、多格式发送。
|
|
|
|
|
|
|
|
|
|
|
|
::: tip 💡 推荐使用 V2 API(模板)
|
|
|
|
|
|
对于**所有新项目**,我们强烈推荐使用 [V2 API(模板)](/api/v2):
|
|
|
|
|
|
- ✅ **内容复用** - 模板可以在多个场景中复用,无需每次传递完整内容
|
|
|
|
|
|
- ✅ **完全动态** - 通过占位符可以实现完全动态内容(甚至可以只用一个占位符)
|
|
|
|
|
|
- ✅ **统一管理** - 在管理后台统一管理消息模板,便于维护
|
|
|
|
|
|
- ✅ **版本控制** - 模板内容修改不影响 API 调用代码
|
|
|
|
|
|
- ✅ **更安全** - 使用加密 Token,不暴露模板 ID
|
|
|
|
|
|
|
|
|
|
|
|
::: warning 关于 V1 API
|
|
|
|
|
|
V1 API 仅为兼容历史数据而保留,不推荐在新项目中使用。后续的功能优化和维护重点都在 V2 API(模板)上。
|
|
|
|
|
|
:::
|
|
|
|
|
|
|
|
|
|
|
|
## 接口地址
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
POST /api/v1/message/send
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 请求参数
|
|
|
|
|
|
|
|
|
|
|
|
### 基本参数
|
|
|
|
|
|
|
|
|
|
|
|
| 参数 | 类型 | 必填 | 说明 |
|
|
|
|
|
|
|------|------|------|------|
|
|
|
|
|
|
| token | string | 是 | 推送令牌(加密),在管理后台查看 |
|
|
|
|
|
|
| task_id | string | 否 | 任务ID(明文),与 token 二选一 |
|
|
|
|
|
|
| title | string | 是 | 消息标题 |
|
|
|
|
|
|
| text | string | 否 | 纯文本格式内容 |
|
|
|
|
|
|
| html | string | 否 | HTML 格式内容 |
|
|
|
|
|
|
| markdown | string | 否 | Markdown 格式内容 |
|
|
|
|
|
|
|
|
|
|
|
|
::: tip 提示
|
|
|
|
|
|
- `token` 和 `task_id` 二选一,推荐使用加密的 `token`
|
|
|
|
|
|
- `text`、`html`、`markdown` 至少提供一种格式
|
|
|
|
|
|
- 多种格式可以同时提供,系统会根据渠道自动选择
|
|
|
|
|
|
:::
|
|
|
|
|
|
|
|
|
|
|
|
### @提醒参数(可选)
|
|
|
|
|
|
|
|
|
|
|
|
| 参数 | 类型 | 必填 | 说明 |
|
|
|
|
|
|
|------|------|------|------|
|
|
|
|
|
|
| at_mobiles | array | 否 | @手机号列表,如 `["13800138000", "13900139000"]` |
|
|
|
|
|
|
| at_userids | array | 否 | @用户ID列表,如 `["user001", "user002"]` |
|
|
|
|
|
|
| at_all | boolean | 否 | 是否@所有人,默认 `false` |
|
|
|
|
|
|
|
|
|
|
|
|
::: warning 注意
|
|
|
|
|
|
@提醒功能仅在支持的渠道(钉钉、企业微信)中生效。
|
|
|
|
|
|
:::
|
|
|
|
|
|
|
2025-12-14 12:43:09 +08:00
|
|
|
|
### 动态接收者参数(可选)🆕
|
|
|
|
|
|
|
|
|
|
|
|
| 参数 | 类型 | 必填 | 说明 |
|
|
|
|
|
|
|------|------|------|------|
|
|
|
|
|
|
| recipients | array | 否 | 动态接收者列表,如 `["user1@example.com", "user2@example.com"]` |
|
|
|
|
|
|
|
|
|
|
|
|
::: tip 群发模式
|
|
|
|
|
|
动态接收者功能允许在 API 调用时指定接收者列表,实现群发功能。
|
|
|
|
|
|
|
|
|
|
|
|
**支持的渠道:**
|
|
|
|
|
|
- ✅ **邮件** - 支持多个收件人,实现邮件群发
|
|
|
|
|
|
- ✅ **微信公众号** - 支持多个 OpenID,实现公众号群发
|
|
|
|
|
|
|
|
|
|
|
|
**使用条件:**
|
|
|
|
|
|
1. 任务实例必须配置为"动态接收者模式"
|
|
|
|
|
|
2. 一个任务只能配置一个动态接收实例
|
|
|
|
|
|
3. 动态接收实例不能与固定接收实例混合使用
|
|
|
|
|
|
|
|
|
|
|
|
**配置方式:**
|
|
|
|
|
|
在任务编辑页面,添加实例时勾选"动态接收者模式",此时无需配置固定接收者。
|
|
|
|
|
|
|
|
|
|
|
|
**注意事项:**
|
|
|
|
|
|
- 如果任务配置了动态接收实例,`recipients` 参数为必填
|
|
|
|
|
|
- 不支持动态接收的渠道会忽略此参数
|
|
|
|
|
|
- 建议控制接收者数量,避免触发渠道限流
|
|
|
|
|
|
:::
|
|
|
|
|
|
|
2025-12-06 13:07:16 +08:00
|
|
|
|
## 请求示例
|
|
|
|
|
|
|
|
|
|
|
|
### 基本示例(纯文本)
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"token": "a3541c2f0d3e1b4a5c6d7e8f9a0b1c2d3e",
|
|
|
|
|
|
"title": "系统通知",
|
|
|
|
|
|
"text": "Hello World!"
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 多格式示例
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"token": "a3541c2f0d3e1b4a5c6d7e8f9a0b1c2d3e",
|
|
|
|
|
|
"title": "系统通知",
|
|
|
|
|
|
"text": "您好,系统检测到异常登录。",
|
|
|
|
|
|
"html": "<h2>系统通知</h2><p>您好,系统检测到<strong>异常登录</strong>。</p>",
|
|
|
|
|
|
"markdown": "## 系统通知\n\n您好,系统检测到**异常登录**。"
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 带@提醒示例
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"token": "a3541c2f0d3e1b4a5c6d7e8f9a0b1c2d3e",
|
|
|
|
|
|
"title": "紧急告警",
|
|
|
|
|
|
"text": "服务器CPU使用率超过90%,请及时处理!",
|
|
|
|
|
|
"markdown": "## 紧急告警\n\n服务器CPU使用率超过**90%**,请及时处理!",
|
|
|
|
|
|
"at_mobiles": ["13800138000", "13900139000"],
|
|
|
|
|
|
"at_all": false
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2025-12-14 12:43:09 +08:00
|
|
|
|
### 动态接收者示例(群发)🆕
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"token": "a3541c2f0d3e1b4a5c6d7e8f9a0b1c2d3e",
|
|
|
|
|
|
"title": "系统维护通知",
|
|
|
|
|
|
"text": "系统将于今晚22:00进行维护,预计持续2小时。",
|
|
|
|
|
|
"html": "<h2>系统维护通知</h2><p>系统将于今晚<strong>22:00</strong>进行维护,预计持续<strong>2小时</strong>。</p>",
|
|
|
|
|
|
"recipients": [
|
|
|
|
|
|
"user1@example.com",
|
|
|
|
|
|
"user2@example.com",
|
|
|
|
|
|
"user3@example.com"
|
|
|
|
|
|
]
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2025-12-06 13:07:16 +08:00
|
|
|
|
### cURL 示例
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
curl -X POST http://your-domain/api/v1/message/send \
|
|
|
|
|
|
-H "Content-Type: application/json" \
|
|
|
|
|
|
-d '{
|
|
|
|
|
|
"token": "a3541c2f0d3e1b4a5c6d7e8f9a0b1c2d3e",
|
|
|
|
|
|
"title": "系统通知",
|
|
|
|
|
|
"text": "Hello World!"
|
|
|
|
|
|
}'
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 响应格式
|
|
|
|
|
|
|
|
|
|
|
|
### 成功响应
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"code": 200,
|
|
|
|
|
|
"msg": "success",
|
|
|
|
|
|
"data": {
|
|
|
|
|
|
"status": "sent"
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 失败响应
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"code": 400,
|
|
|
|
|
|
"msg": "error message",
|
|
|
|
|
|
"data": null
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 获取 Token
|
|
|
|
|
|
|
|
|
|
|
|
1. 登录 Message Nest 管理后台
|
|
|
|
|
|
2. 进入"发送任务"页面
|
|
|
|
|
|
3. 创建新的发送任务
|
|
|
|
|
|
4. 配置推送渠道(邮件、钉钉、企业微信等)
|
|
|
|
|
|
5. 保存后获得推送令牌(Token)
|
|
|
|
|
|
|
|
|
|
|
|
## 消息格式优先级
|
|
|
|
|
|
|
|
|
|
|
|
V1 API 支持三种消息格式,系统会根据任务实例配置的格式类型自动选择对应的内容。
|
|
|
|
|
|
|
|
|
|
|
|
### 格式选择规则
|
|
|
|
|
|
|
|
|
|
|
|
当任务实例配置了特定格式类型时,系统按以下优先级选择内容:
|
|
|
|
|
|
|
|
|
|
|
|
| 实例配置格式 | 优先级顺序 | 说明 |
|
|
|
|
|
|
|------------|-----------|------|
|
|
|
|
|
|
| **HTML** | html → markdown → text | 优先使用 HTML,其次 Markdown,最后纯文本 |
|
|
|
|
|
|
| **Markdown** | markdown → text → html | 优先使用 Markdown,其次纯文本,最后 HTML |
|
|
|
|
|
|
| **Text** | text → markdown → html | 优先使用纯文本,其次 Markdown,最后 HTML |
|
|
|
|
|
|
|
|
|
|
|
|
### 示例说明
|
|
|
|
|
|
|
|
|
|
|
|
**场景 1:邮件渠道(配置为 HTML 格式)**
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"text": "纯文本内容",
|
|
|
|
|
|
"html": "<h1>HTML内容</h1>",
|
|
|
|
|
|
"markdown": "# Markdown内容"
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
发送结果:使用 `html` 内容
|
|
|
|
|
|
|
|
|
|
|
|
**场景 2:钉钉渠道(配置为 Markdown 格式)**
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"text": "纯文本内容",
|
|
|
|
|
|
"markdown": "# Markdown内容"
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
发送结果:使用 `markdown` 内容
|
|
|
|
|
|
|
|
|
|
|
|
**场景 3:只提供纯文本**
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"text": "纯文本内容"
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
发送结果:所有渠道都使用 `text` 内容(兼容性最好)
|
|
|
|
|
|
|
|
|
|
|
|
::: tip 最佳实践
|
|
|
|
|
|
- **邮件渠道**:推荐提供 `html` 格式,视觉效果更好
|
|
|
|
|
|
- **钉钉/企业微信**:推荐提供 `markdown` 格式,支持富文本
|
|
|
|
|
|
- **通用场景**:至少提供 `text` 格式,确保所有渠道都能正常发送
|
|
|
|
|
|
- **多渠道任务**:同时提供多种格式,让系统自动选择最佳格式
|
|
|
|
|
|
:::
|
|
|
|
|
|
|
|
|
|
|
|
## @提醒功能
|
|
|
|
|
|
|
|
|
|
|
|
@提醒功能允许在钉钉、企业微信等支持的渠道中@特定用户或所有人。
|
|
|
|
|
|
|
|
|
|
|
|
### 支持的渠道
|
|
|
|
|
|
|
|
|
|
|
|
| 渠道 | @手机号 | @用户ID | @所有人 |
|
|
|
|
|
|
|------|--------|--------|--------|
|
|
|
|
|
|
| 钉钉 | ✅ | ✅ | ✅ |
|
|
|
|
|
|
| 企业微信 | ✅ | ✅ | ✅ |
|
|
|
|
|
|
| 邮件 | ❌ | ❌ | ❌ |
|
|
|
|
|
|
| 其他 | ❌ | ❌ | ❌ |
|
|
|
|
|
|
|
|
|
|
|
|
### 使用示例
|
|
|
|
|
|
|
|
|
|
|
|
#### @指定手机号
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"token": "...",
|
|
|
|
|
|
"title": "系统告警",
|
|
|
|
|
|
"text": "服务器异常,请及时处理",
|
|
|
|
|
|
"at_mobiles": ["13800138000", "13900139000"]
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### @指定用户ID
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"token": "...",
|
|
|
|
|
|
"title": "任务通知",
|
|
|
|
|
|
"text": "您的任务已完成",
|
|
|
|
|
|
"at_userids": ["user001", "user002"]
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### @所有人
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"token": "...",
|
|
|
|
|
|
"title": "重要通知",
|
|
|
|
|
|
"text": "系统将于今晚22:00进行维护",
|
|
|
|
|
|
"at_all": true
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 组合使用
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"token": "...",
|
|
|
|
|
|
"title": "紧急告警",
|
|
|
|
|
|
"markdown": "## 紧急告警\n\n生产环境出现严重问题!",
|
|
|
|
|
|
"at_mobiles": ["13800138000"],
|
|
|
|
|
|
"at_userids": ["admin"],
|
|
|
|
|
|
"at_all": false
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
::: warning 注意事项
|
|
|
|
|
|
1. @提醒只在支持的渠道中生效,其他渠道会忽略这些参数
|
|
|
|
|
|
2. 钉钉机器人需要配置相应的权限才能使用@功能
|
|
|
|
|
|
3. @所有人功能需谨慎使用,避免打扰群成员
|
|
|
|
|
|
4. 手机号和用户ID格式需符合对应平台的要求
|
|
|
|
|
|
:::
|
|
|
|
|
|
|
|
|
|
|
|
## 支持的推送渠道
|
|
|
|
|
|
|
2025-12-14 12:43:09 +08:00
|
|
|
|
| 渠道 | 支持格式 | @提醒 | 动态接收者 | 说明 |
|
|
|
|
|
|
|------|---------|------|-----------|------|
|
|
|
|
|
|
| **邮件** | Text, HTML | ❌ | ✅ | SMTP邮件发送,支持群发多个收件人 |
|
|
|
|
|
|
| **钉钉** | Text, Markdown | ✅ | ❌ | 钉钉机器人,支持 Markdown 富文本 |
|
|
|
|
|
|
| **企业微信** | Text, Markdown | ✅ | ❌ | 企业微信机器人,支持 Markdown |
|
|
|
|
|
|
| **微信公众号** | Text | ❌ | ✅ | 微信测试公众号,支持多个 OpenID 群发 |
|
|
|
|
|
|
| **自定义Webhook** | Text, HTML, Markdown | ❌ | ❌ | 自定义HTTP请求,格式取决于配置 |
|
|
|
|
|
|
| **自托管消息** | Text, HTML, Markdown | ❌ | ❌ | 站内消息,支持多种格式 |
|
2025-12-06 13:07:16 +08:00
|
|
|
|
|
|
|
|
|
|
## 使用流程
|
|
|
|
|
|
|
|
|
|
|
|
1. **创建推送渠道**
|
|
|
|
|
|
- 在管理后台配置各种推送渠道
|
|
|
|
|
|
- 填写相应的配置信息(如邮箱、Webhook地址等)
|
|
|
|
|
|
|
|
|
|
|
|
2. **创建发送任务**
|
|
|
|
|
|
- 选择要使用的推送渠道
|
|
|
|
|
|
- 可以选择多个渠道同时推送
|
|
|
|
|
|
- 获得唯一的推送令牌(Token)
|
|
|
|
|
|
|
|
|
|
|
|
3. **调用API发送消息**
|
|
|
|
|
|
- 使用获得的 Token
|
|
|
|
|
|
- 发送标题和内容
|
|
|
|
|
|
- 消息会自动推送到配置的所有渠道
|
|
|
|
|
|
|
|
|
|
|
|
## 工作流程
|
|
|
|
|
|
|
|
|
|
|
|
1. **Token 解析** - 解密 Token 获取任务 ID(或直接使用 task_id)
|
|
|
|
|
|
2. **任务查询** - 根据任务 ID 查询任务信息
|
|
|
|
|
|
3. **实例遍历** - 获取任务关联的所有启用实例
|
|
|
|
|
|
4. **格式选择** - 根据实例配置的格式类型选择对应内容
|
|
|
|
|
|
5. **@提醒处理** - 如果提供了@参数且渠道支持,添加@提醒
|
|
|
|
|
|
6. **消息发送** - 向每个实例发送消息
|
|
|
|
|
|
7. **返回结果** - 返回发送状态
|
|
|
|
|
|
|
|
|
|
|
|
## 注意事项
|
|
|
|
|
|
|
|
|
|
|
|
::: warning 重要
|
|
|
|
|
|
- **Token 安全**:Token 是唯一的,请妥善保管,不要在公开代码中硬编码
|
|
|
|
|
|
- **格式兼容**:至少提供一种格式(text/html/markdown),推荐提供多种格式
|
|
|
|
|
|
- **异步调用**:建议使用异步方式调用 API,避免阻塞主流程
|
|
|
|
|
|
- **@提醒限制**:@功能仅在钉钉、企业微信等支持的渠道中生效
|
|
|
|
|
|
- **格式优先级**:系统会根据实例配置自动选择最合适的格式
|
|
|
|
|
|
:::
|
|
|
|
|
|
|
|
|
|
|
|
## 最佳实践
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 多格式支持
|
|
|
|
|
|
|
|
|
|
|
|
为了确保消息在不同渠道都有良好的展示效果,建议同时提供多种格式:
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"token": "...",
|
|
|
|
|
|
"title": "订单通知",
|
|
|
|
|
|
"text": "您的订单已发货,订单号:20241206001",
|
|
|
|
|
|
"html": "<h2>订单通知</h2><p>您的订单已发货</p><p>订单号:<strong>20241206001</strong></p>",
|
|
|
|
|
|
"markdown": "## 订单通知\n\n您的订单已发货\n\n订单号:**20241206001**"
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 合理使用@提醒
|
|
|
|
|
|
|
|
|
|
|
|
只在需要紧急通知时使用@提醒:
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"token": "...",
|
|
|
|
|
|
"title": "紧急告警",
|
|
|
|
|
|
"text": "生产环境出现严重问题",
|
|
|
|
|
|
"at_mobiles": ["13800138000"], // 只@相关负责人
|
|
|
|
|
|
"at_all": false // 避免@所有人
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 错误处理
|
|
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
|
import requests
|
|
|
|
|
|
import json
|
|
|
|
|
|
|
|
|
|
|
|
def send_message(token, title, text):
|
|
|
|
|
|
url = "http://your-domain/api/v1/message/send"
|
|
|
|
|
|
data = {
|
|
|
|
|
|
"token": token,
|
|
|
|
|
|
"title": title,
|
|
|
|
|
|
"text": text
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
response = requests.post(url, json=data, timeout=10)
|
|
|
|
|
|
result = response.json()
|
|
|
|
|
|
|
|
|
|
|
|
if result['code'] == 200:
|
|
|
|
|
|
print("发送成功")
|
|
|
|
|
|
else:
|
|
|
|
|
|
print(f"发送失败:{result['msg']}")
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
print(f"请求异常:{e}")
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 错误码说明
|
|
|
|
|
|
|
|
|
|
|
|
| 错误码 | 说明 |
|
|
|
|
|
|
|--------|------|
|
|
|
|
|
|
| 200 | 成功 |
|
|
|
|
|
|
| 400 | 请求参数错误 |
|
|
|
|
|
|
| 401 | 未授权 |
|
|
|
|
|
|
| 404 | Token不存在 |
|
|
|
|
|
|
| 500 | 服务器内部错误 |
|
|
|
|
|
|
|
|
|
|
|
|
## 常见问题
|
|
|
|
|
|
|
|
|
|
|
|
### Q: V1 和 V2 API 有什么区别?应该选择哪个?
|
|
|
|
|
|
|
|
|
|
|
|
**A:**
|
|
|
|
|
|
|
|
|
|
|
|
| 特性 | V1 API(任务) | V2 API(模板)⭐ 推荐 |
|
|
|
|
|
|
|------|--------------|-------------------|
|
|
|
|
|
|
| **内容定义** | API 调用时传递 | 预定义在模板中 |
|
|
|
|
|
|
| **动态内容** | 完全动态 | 通过占位符替换 |
|
|
|
|
|
|
| **内容复用** | 每次都要传递完整内容 | 模板可复用 |
|
|
|
|
|
|
| **维护成本** | 修改内容需要改代码 | 只需修改模板 |
|
|
|
|
|
|
| **适用场景** | 完全动态、不重复的内容 | 有固定格式的通知消息 |
|
|
|
|
|
|
|
|
|
|
|
|
**推荐使用 V2 API(模板)的原因:**
|
|
|
|
|
|
1. **提高开发效率** - 一次定义模板,多处使用
|
|
|
|
|
|
2. **降低维护成本** - 内容修改无需改代码
|
|
|
|
|
|
3. **统一管理** - 所有消息模板集中管理
|
|
|
|
|
|
4. **更好的协作** - 运营人员可以直接修改模板内容
|
|
|
|
|
|
5. **版本控制** - 模板支持启用/禁用,方便灰度发布
|
|
|
|
|
|
6. **完全动态** - 通过占位符同样可以实现完全动态内容
|
|
|
|
|
|
|
|
|
|
|
|
::: warning V1 API 的定位
|
|
|
|
|
|
V1 API 仅为兼容历史数据而保留,**不推荐在任何新项目中使用**。即使是完全动态的内容,也可以通过模板 + 占位符的方式实现,且更易于后期维护。
|
|
|
|
|
|
|
|
|
|
|
|
后续的功能优化和维护重点都在 V2 API(模板)上。
|
|
|
|
|
|
:::
|
|
|
|
|
|
|
|
|
|
|
|
### Q: 如何选择使用哪种格式?
|
|
|
|
|
|
|
|
|
|
|
|
**A:** 根据渠道特性选择:
|
|
|
|
|
|
- **邮件**:推荐 HTML,视觉效果好
|
|
|
|
|
|
- **钉钉/企业微信**:推荐 Markdown,支持富文本
|
|
|
|
|
|
- **通用**:使用 Text,兼容性最好
|
|
|
|
|
|
- **多渠道**:同时提供多种格式,让系统自动选择
|
|
|
|
|
|
|
|
|
|
|
|
### Q: @提醒不生效怎么办?
|
|
|
|
|
|
|
|
|
|
|
|
**A:** 检查以下几点:
|
|
|
|
|
|
1. 渠道是否支持@提醒(仅钉钉、企业微信支持)
|
|
|
|
|
|
2. 机器人是否有@权限
|
|
|
|
|
|
3. 手机号或用户ID格式是否正确
|
|
|
|
|
|
4. 参数名称是否正确(`at_mobiles`、`at_userids`、`at_all`)
|
|
|
|
|
|
|
|
|
|
|
|
### Q: 可以只发送 HTML 格式吗?
|
|
|
|
|
|
|
|
|
|
|
|
**A:** 可以,但建议同时提供 text 格式作为备选,确保不支持 HTML 的渠道也能正常发送。
|
|
|
|
|
|
|
|
|
|
|
|
### Q: Token 和 task_id 有什么区别?
|
|
|
|
|
|
|
|
|
|
|
|
**A:**
|
|
|
|
|
|
- **token**:加密的任务标识,更安全,推荐使用
|
|
|
|
|
|
- **task_id**:明文的任务ID,不推荐在生产环境使用
|
|
|
|
|
|
|
|
|
|
|
|
## 各语言调用示例
|
|
|
|
|
|
|
|
|
|
|
|
本节提供各种编程语言的完整调用示例代码。
|
|
|
|
|
|
|
|
|
|
|
|
### cURL
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
curl -X POST --location 'http://127.0.0.1:8000/api/v1/message/send' \
|
|
|
|
|
|
--header 'Content-Type: application/json' \
|
|
|
|
|
|
--data '{
|
|
|
|
|
|
"token": "a3541c2f0d3e1b4a5c6d7e8f9a0b1c2d3e",
|
|
|
|
|
|
"title": "message title",
|
|
|
|
|
|
"text": "Hello World!"
|
|
|
|
|
|
}'
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Python
|
|
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
|
import requests
|
|
|
|
|
|
|
|
|
|
|
|
headers = {
|
|
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
json_data = {
|
|
|
|
|
|
"token": "a3541c2f0d3e1b4a5c6d7e8f9a0b1c2d3e",
|
|
|
|
|
|
"title": "message title",
|
|
|
|
|
|
"text": "Hello World!"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
response = requests.post(
|
|
|
|
|
|
'http://127.0.0.1:8000/api/v1/message/send',
|
|
|
|
|
|
headers=headers,
|
|
|
|
|
|
json=json_data
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
print("response:", response.json())
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**安装依赖:**
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
pip install requests
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Go
|
|
|
|
|
|
|
|
|
|
|
|
```go
|
|
|
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"fmt"
|
|
|
|
|
|
"io"
|
|
|
|
|
|
"log"
|
|
|
|
|
|
"net/http"
|
|
|
|
|
|
"strings"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
|
|
client := &http.Client{}
|
|
|
|
|
|
var data = strings.NewReader(`{
|
|
|
|
|
|
"token": "a3541c2f0d3e1b4a5c6d7e8f9a0b1c2d3e",
|
|
|
|
|
|
"title": "message title",
|
|
|
|
|
|
"text": "Hello World!"
|
|
|
|
|
|
}`)
|
|
|
|
|
|
req, err := http.NewRequest("POST", "http://127.0.0.1:8000/api/v1/message/send", data)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
log.Fatal(err)
|
|
|
|
|
|
}
|
|
|
|
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
|
|
resp, err := client.Do(req)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
log.Fatal(err)
|
|
|
|
|
|
}
|
|
|
|
|
|
defer resp.Body.Close()
|
|
|
|
|
|
bodyText, err := io.ReadAll(resp.Body)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
log.Fatal(err)
|
|
|
|
|
|
}
|
|
|
|
|
|
fmt.Printf("%s\n", bodyText)
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Java
|
|
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
|
import java.net.URI;
|
|
|
|
|
|
import java.net.http.HttpClient;
|
|
|
|
|
|
import java.net.http.HttpRequest;
|
|
|
|
|
|
import java.net.http.HttpRequest.BodyPublishers;
|
|
|
|
|
|
import java.net.http.HttpResponse;
|
|
|
|
|
|
|
|
|
|
|
|
public class MessageNestExample {
|
|
|
|
|
|
public static void main(String[] args) throws IOException, InterruptedException {
|
|
|
|
|
|
HttpClient client = HttpClient.newBuilder()
|
|
|
|
|
|
.followRedirects(HttpClient.Redirect.NORMAL)
|
|
|
|
|
|
.build();
|
|
|
|
|
|
|
|
|
|
|
|
String jsonData = """
|
|
|
|
|
|
{
|
|
|
|
|
|
"token": "a3541c2f0d3e1b4a5c6d7e8f9a0b1c2d3e",
|
|
|
|
|
|
"title": "message title",
|
|
|
|
|
|
"text": "Hello World!"
|
|
|
|
|
|
}
|
|
|
|
|
|
""";
|
|
|
|
|
|
|
|
|
|
|
|
HttpRequest request = HttpRequest.newBuilder()
|
|
|
|
|
|
.uri(URI.create("http://127.0.0.1:8000/api/v1/message/send"))
|
|
|
|
|
|
.POST(BodyPublishers.ofString(jsonData))
|
|
|
|
|
|
.setHeader("Content-Type", "application/json")
|
|
|
|
|
|
.build();
|
|
|
|
|
|
|
|
|
|
|
|
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
|
|
|
|
|
|
|
|
|
|
|
System.out.println(response.body());
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Node.js
|
|
|
|
|
|
|
|
|
|
|
|
#### 使用 request 库
|
|
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
|
var request = require('request');
|
|
|
|
|
|
|
|
|
|
|
|
var headers = {
|
|
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
var dataString = JSON.stringify({
|
|
|
|
|
|
"token": "a3541c2f0d3e1b4a5c6d7e8f9a0b1c2d3e",
|
|
|
|
|
|
"title": "message title",
|
|
|
|
|
|
"text": "Hello World!"
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
var options = {
|
|
|
|
|
|
url: 'http://127.0.0.1:8000/api/v1/message/send',
|
|
|
|
|
|
method: 'POST',
|
|
|
|
|
|
headers: headers,
|
|
|
|
|
|
body: dataString
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
function callback(error, response, body) {
|
|
|
|
|
|
if (!error && response.statusCode == 200) {
|
|
|
|
|
|
console.log(body);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
request(options, callback);
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 使用 axios 库
|
|
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
|
const axios = require('axios');
|
|
|
|
|
|
|
|
|
|
|
|
const data = {
|
|
|
|
|
|
token: "a3541c2f0d3e1b4a5c6d7e8f9a0b1c2d3e",
|
|
|
|
|
|
title: "message title",
|
|
|
|
|
|
text: "Hello World!"
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
axios.post('http://127.0.0.1:8000/api/v1/message/send', data, {
|
|
|
|
|
|
headers: {
|
|
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
.then(response => {
|
|
|
|
|
|
console.log('response:', response.data);
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch(error => {
|
|
|
|
|
|
console.error('error:', error);
|
|
|
|
|
|
});
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 使用 fetch (Node.js 18+)
|
|
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
|
const data = {
|
|
|
|
|
|
token: "a3541c2f0d3e1b4a5c6d7e8f9a0b1c2d3e",
|
|
|
|
|
|
title: "message title",
|
|
|
|
|
|
text: "Hello World!"
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
fetch('http://127.0.0.1:8000/api/v1/message/send', {
|
|
|
|
|
|
method: 'POST',
|
|
|
|
|
|
headers: {
|
|
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
|
|
},
|
|
|
|
|
|
body: JSON.stringify(data)
|
|
|
|
|
|
})
|
|
|
|
|
|
.then(response => response.json())
|
|
|
|
|
|
.then(data => {
|
|
|
|
|
|
console.log('response:', data);
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch(error => {
|
|
|
|
|
|
console.error('error:', error);
|
|
|
|
|
|
});
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### PHP
|
|
|
|
|
|
|
|
|
|
|
|
```php
|
|
|
|
|
|
<?php
|
|
|
|
|
|
$ch = curl_init();
|
|
|
|
|
|
|
|
|
|
|
|
$data = array(
|
|
|
|
|
|
"token" => "a3541c2f0d3e1b4a5c6d7e8f9a0b1c2d3e",
|
|
|
|
|
|
"title" => "message title",
|
|
|
|
|
|
"text" => "Hello World!"
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
curl_setopt($ch, CURLOPT_URL, 'http://127.0.0.1:8000/api/v1/message/send');
|
|
|
|
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
|
|
|
|
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
|
|
|
|
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
|
|
|
|
|
'Content-Type: application/json',
|
|
|
|
|
|
]);
|
|
|
|
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
|
|
|
|
|
|
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
|
|
|
|
|
|
|
|
|
|
|
$response = curl_exec($ch);
|
|
|
|
|
|
|
|
|
|
|
|
if (curl_errno($ch)) {
|
|
|
|
|
|
echo 'Error:' . curl_error($ch);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
echo $response;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
curl_close($ch);
|
|
|
|
|
|
?>
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### C#
|
|
|
|
|
|
|
|
|
|
|
|
```csharp
|
|
|
|
|
|
using System;
|
|
|
|
|
|
using System.Net.Http;
|
|
|
|
|
|
using System.Text;
|
|
|
|
|
|
using System.Text.Json;
|
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
|
|
|
|
|
|
class Program
|
|
|
|
|
|
{
|
|
|
|
|
|
static async Task Main(string[] args)
|
|
|
|
|
|
{
|
|
|
|
|
|
using var client = new HttpClient();
|
|
|
|
|
|
|
|
|
|
|
|
var data = new
|
|
|
|
|
|
{
|
|
|
|
|
|
token = "a3541c2f0d3e1b4a5c6d7e8f9a0b1c2d3e",
|
|
|
|
|
|
title = "message title",
|
|
|
|
|
|
text = "Hello World!"
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
var json = JsonSerializer.Serialize(data);
|
|
|
|
|
|
var content = new StringContent(json, Encoding.UTF8, "application/json");
|
|
|
|
|
|
|
|
|
|
|
|
var response = await client.PostAsync(
|
|
|
|
|
|
"http://127.0.0.1:8000/api/v1/message/send",
|
|
|
|
|
|
content
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
var responseString = await response.Content.ReadAsStringAsync();
|
|
|
|
|
|
Console.WriteLine(responseString);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Ruby
|
|
|
|
|
|
|
|
|
|
|
|
```ruby
|
|
|
|
|
|
require 'net/http'
|
|
|
|
|
|
require 'json'
|
|
|
|
|
|
require 'uri'
|
|
|
|
|
|
|
|
|
|
|
|
uri = URI('http://127.0.0.1:8000/api/v1/message/send')
|
|
|
|
|
|
http = Net::HTTP.new(uri.host, uri.port)
|
|
|
|
|
|
|
|
|
|
|
|
request = Net::HTTP::Post.new(uri.path, {
|
|
|
|
|
|
'Content-Type' => 'application/json'
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
request.body = {
|
|
|
|
|
|
token: 'a3541c2f0d3e1b4a5c6d7e8f9a0b1c2d3e',
|
|
|
|
|
|
title: 'message title',
|
|
|
|
|
|
text: 'Hello World!'
|
|
|
|
|
|
}.to_json
|
|
|
|
|
|
|
|
|
|
|
|
response = http.request(request)
|
|
|
|
|
|
puts response.body
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 示例说明
|
|
|
|
|
|
|
|
|
|
|
|
::: tip 提示
|
|
|
|
|
|
- 将示例中的 `http://127.0.0.1:8000` 替换为你的实际服务地址
|
|
|
|
|
|
- 将 `a3541c2f0d3e1b4a5c6d7e8f9a0b1c2d3e` 替换为你在管理后台创建的实际 Token
|
|
|
|
|
|
- 建议在生产环境中使用 HTTPS
|
|
|
|
|
|
- 所有示例都使用基本的纯文本格式,实际使用时可以添加 `html`、`markdown` 等参数
|
|
|
|
|
|
:::
|
|
|
|
|
|
|
|
|
|
|
|
## 下一步
|
|
|
|
|
|
|
|
|
|
|
|
- 查看 [V2 API 文档](/api/v2) 了解基于模板的发送方式
|
|
|
|
|
|
- 查看 [消息模板](/guide/template) 了解如何使用模板功能
|