发送消息
用于应用通过协作给用户发送消息,支持文本、图片、图文混排、外链图文、Markdown、消息卡片、文件、语音、视频等消息类型,使用时需注意以下几点:
- 给用户发消息时,无论是后台发送消息还是接口推送消息,需要应用对用户可见。
- 给群聊发送消息时,需要该应用机器人在群内。
- 机器人发送的消息最多不超过 5000 个字符。
- 卡片消息在客户端不支持转发。
- 支持向 4 类对象发送消息:指定用户(to_users)、指定群聊(to_chats)、指定部门(to_depts)、指定企业(to_companies)。
- 同一次调用内,3 种发送对象的所属企业,需为同一个,否则无法发送成功。即:
to_users.company_id、to_depts.company_id和to_companies需为同一个企业 id。 - 为了避免消息干扰,应用应尽量避免使用大范围的批量消息推送。特别地,在使用指定部门(to_depts)和指定企业(to_companies)时,若所传对象与指定企业内该应用的可用范围不符,则无法发送成功。
- 当触发消息审核时,消息需要审核通过后才会发送出去,message_id 返回空字符串
请求说明
| 请求地址 | 配置域名+/o/woa/api/v2/developer/app/messages |
|---|---|
| 请求方法 | POST |
| 签名方式 | wps-4 |
| 支持应用类型 | 企业自建应用、第三方企业应用 |
| 权限要求 | 发送消息(kso.im.message.send) |
请求头
| 名称 | 是否必填 | 说明 |
|---|---|---|
| Content-Type | 是 | 固定为: application/json |
| Wps-Docs-Date | 是 | 取当前时间, 示例: Wed, 23 Jan 2013 06:43:08 GMT |
| Wps-Docs-Authorization | 是 | 计算方法参考签名说明 |
| Authorization | 是 | 授权token,格式:Bearer ${access_token},${access_token}需替换为从授权接口获取的access_token值 |
请求地址示例
http
[POST] 配置域名+/o/woa/api/v2/developer/app/messages请求体(Body)
| 名称 | 类型 | 是否必填 | 说明 |
|---|---|---|---|
| app_key | string | 是 | 指应用的 AK,即 app_id |
| to_users | object | 否 | 发送给某个企业的部分人员 |
| ∟ company_id | string | 是 | 用户归属的企业 id |
| ∟ user_ids | []string | 是 | 用户 ids |
| to_depts | object | 否 | 发送给对应部门 |
| ∟ company_id | string | 是 | 部门归属的企业 id |
| ∟ dept_ids | []string | 是 | 部门 ids |
| to_companies | []string | 否 | 发送给对应公司,当前仅支持传一个 company_id |
| to_chats | []int | 否 | 发送给对应群聊 ids |
| biz_type | string | 否 | 消息所属业务类型,并且尽量是当前 app_key 下唯一。主要用来区分具体业务,做一些业务特殊处理。对于卡片消息建议加上 |
| ctx_id | string | 否(需要后续更新消息时则必填) | app_key+ctx_id 映射到消息 id,最大长度 128,建议不要占满 |
| user_id | string | 否(需要后续更新消息时则必填) | 消息生产者 id |
| company_id | string | 否(需要后续更新消息时则必填) | 消息生产者企业 id |
| utype | int | 否(需要后续更新消息时则必填) | 后续消息更新方式,0 - 后续不更新,1-后续更新消息中 content(目前只开放更新按钮) |
| msg_type | int | 否 | 表示消息类容格式类型。1-普通文本消息,2-通知卡片消息,12-发送本地文件,13-发送图片,14-图文链接消息,18-图文混排,19-语音消息,20-视频消息,23-模板卡片消息 |
| content | object | 是 | 消息内容,不同消息类型(msg_type)的结构不同,详见“参数结构说明(Content)” |
文本消息/模板卡片消息类型支持通过在消息体 content 中插入标签的方式@人。如果不填写姓名,则服务端将自动填充姓名至@人位置:
- 使用 id@人:
<at user_id="12345">姓名</at> - @所有人:
<at user_id="-1">所有人</at>
请求体示例
json
{
"to_users": {
"company_id": "xxxxxxxxxxxx",
"user_ids": ["xxxxxxxxxxxx"]
},
"msg_type": 1,
"app_key": "your_app_id",
"content": {
"type": 1,
"body": "这是一条纯文本消息"
}
}响应体
| 名称 | 类型 | 说明 |
|---|---|---|
| result | integer | 状态码,非 ok 表示失败,参照《状态码说明》 |
| message_id | string | 消息 id |
响应体示例
json
{
"result": ok,
"message_id": "kDtGtZHmIBsmS3"
}参数结构说明(Content)
纯文本消息(type=1)
| 参数 | 参数类型 | 是否必有 | 说明 |
|---|---|---|---|
| type | integer | 是 | 消息类型,1-文本消息 |
| body | string | 是 | 消息内容 |
json
{
// ...
"content": {
"type": 1,
"body": "这是一条纯文本消息"
}
// ...
}Markdown 消息(type=1)
| 参数 | 参数类型 | 是否必填 | 说明 |
|---|---|---|---|
| type | integer | 是 | 消息类型,1-文本消息 |
| style | string | 是 | 消息内容风格,style:markdown |
| body | string | 是 | 消息内容 |
json
{
// ...
"content": {
"type": 1,
"style": "markdown",
"body": "## 标题 \n\n * 项目1 \n * 项目2 \n\n [链接](https://www.wps.cn)"
}
// ...
}带链接的卡片消息(type=2)
| 参数 | 参数类型 | 是否必填 | 说明 |
|---|---|---|---|
| type | integer | 是 | 消息类型,2-卡片消息 |
| title | string | 是 | 标题 |
| body | string | 是 | 内容 |
| href | object | 是 | 链接数据 |
| ∟ url | string | 是 | 链接 |
| ∟ text | string | 是 | 按钮文案 |
| ∟ style | string | 是 | 文案内容,normal-纯文本 |
| ∟ disable | bool | 是 | 禁止点击标识,true-禁止点击,false-可以点击 |
| ∟ platform_url | object | 是 | 客户端特异链接 |
| ∟ ios | string | 是 | iOS 客户端链接 |
| ∟ android | string | 是 | Android 客户端链接 |
| ∟ pc | string | 是 | PC/MAC 客户端链接 |
json
{
// ...
"content": {
"type": 2,
"title": "卡片消息标题",
"body": "卡片消息内容",
"href": {
"url": "https://open-xz.wps.cn/",
"text": "打开链接",
"style": "normal",
"disable": false,
"platform_url": {
"ios": "https://open-xz.wps.cn/",
"android": "https://open-xz.wps.cn/",
"pc": "https://open-xz.wps.cn/"
}
}
}
// ...
}带按钮的卡片消息(type=2)
| 参数 | 参数类型 | 是否必填 | 说明 |
|---|---|---|---|
| type | integer | 是 | 消息类型,2-卡片消息 |
| title | string | 是 | 标题 |
| body | string | 是 | 内容 |
| hrefs | []href | 是 | 按钮设置 |
| ∟ url | string | 是 | 链接 |
| ∟ text | string | 是 | 按钮文案 |
| ∟ style | string | 是 | 文案内容,normal-纯文本 |
| ∟ disable | bool | 是 | 禁止点击标识,true-禁止点击,false-可以点击 |
| ∟ platform_url | object | 是 | 客户端特异链接 |
| ∟ ios | string | 是 | iOS 客户端链接 |
| ∟ android | string | 是 | Android 客户端链接 |
| ∟ pc | string | 是 | PC/MAC 客户端链接 |
json
{
// ...
"content": {
"type": 2,
"title": "卡片消息标题",
"body": "卡片消息内容",
"hrefs": [
{
"url": "https://your.service.com/cancel/api",
"text": "取消",
"style": "secondary",
"disable": false,
"platform_url": {
"ios": "https://your.service.com/cancel/api",
"android": "https://your.service.com/cancel/api",
"pc": "https://your.service.com/cancel/api"
}
},
{
"url": "https://your.service.com/confirm/api",
"text": "确定",
"style": "normal",
"disable": false,
"platform_url": {
"ios": "https://your.service.com/confirm/api",
"android": "https://your.service.com/confirm/api",
"pc": "https://your.service.com/confirm/api"
}
}
]
}
// ...
}文件消息(type=12)
| 参数 | 参数类型 | 是否必填 | 说明 |
|---|---|---|---|
| file_name | string | 是 | 文件名 |
| file_size | integer | 是 | 文件大小(B) |
| store_key | string | 是 | 文件存储 key |
| store_key_sha1 | string | 是 | 文件存储 key 校验值 |
json
{
// ...
"content": {
"file_name": "test.mp4",
"file_size": 2288448,
"store_key": "DD1AFB29YmV0YS9kZXYvZmlsZS85NjYxMzNmZmI0MzFiNmY5ZDA1YTlmY2E3N2MzMzU0MTprczM6a29hLWltZw==",
"store_key_sha1": "8159fc6752579ee0c3a759f83a46ba20dec6a6a2"
}
// ...
}图片消息(type=13)
| 参数 | 参数类型 | 是否必填 | 说明 |
|---|---|---|---|
| width | integer | 是 | 图片宽度(px) |
| height | integer | 是 | 图片高度(px) |
| pic_type | string | 是 | 图片格式,可传值:image/png、image/jpg、image/gif、image/webp |
| pic | string | 是 | 图片存储 key |
| store_key_sha1 | string | 是 | 图片存储 key 校验值 |
json
{
// ...
"content": {
"width": 992,
"height": 484,
"pic_type": "image/png",
"pic": "DD1AFB29YmV0YS9kZXYvaW1hZ2UvNzVlYTg0NTFjNzdkN2YxY2RiZmQwZGNkNDA4MDlmMzM6a3MzOmtvYS1pbWc=",
"store_key_sha1": "d9f95714ffaa4360afe90431bb1bed316da0db68"
}
// ...
}图文混排消息(type=18)
| 参数 | 参数类型 | 是否必填 | 说明 |
|---|---|---|---|
| type | integer | 是 | 消息类型,18-图文混排 |
| elements | []element | 是 | 消息元素数组 |
| ∟ tag | string | 是 | 元素类型,img-图片,text-文字 |
| ∟ content | object | 是 | 元素内容 |
tag="img"时,content 元素内容
| 参数 | 参数类型 | 是否必填 | 说明 |
|---|---|---|---|
| width | integer | 是 | 图片宽度(px) |
| height | integer | 是 | 图片高度(px) |
| type | string | 是 | 图片格式,可传值:image/png、image/jpg、image/gif、image/webp |
| store_key | string | 是 | 图片存储 key |
| store_key_sha1 | string | 是 | 图片存储 key 校验值 |
tag="text"时,content 元素内容
| 参数 | 参数类型 | 是否必填 | 说明 |
|---|---|---|---|
| type | string | 是 | 文字类型,text-纯文本 |
| text | string | 是 | 内容 |
json
{
// ...
"content": {
"type": 18,
"elements": [
{
"tag": "img",
"content": {
"width": 492,
"height": 242,
"type": "image/png",
"store_key": "DD1AFB29YmV0YS9kZXYvaW1hZ2UvZWQzODg1YWVlNTJmMjVlNmIyNTc4MGNiNzZjZTIyODU6a3MzOmtvYS1pbWc=",
"store_key_sha1": "83982e81cd2767cb9b565ff936ee17e1e9e0c3e3"
}
},
{
"tag": "text",
"content": {
"type": "text",
"text": "上面是消息的图片元素,这里消息的纯文本元素"
}
}
]
}
// ...
}语音消息(type=19)
| 参数 | 参数类型 | 是否必填 | 说明 |
|---|---|---|---|
| store | string | 是 | 存储商,可选值:ks3 |
| store_key | string | 是 | 语音存储 key |
| store_key_sha1 | string | 是 | 语音存储 key 校验值 |
| media | object | 是 | 语音媒体文件内容 |
| ∟ format | string | 是 | 文件格式,wav 等 |
| ∟ codec | string | 是 | 编码格式,amr 等 |
| ∟ size | integer | 是 | 文件大小(B) |
| ∟ type | integer | 是 | 文件类型,1-音频 |
| ∟ audio | object | 是 | 媒体文件内容 |
| ∟ duration | integer | 是 | 长度(s) |
| ∟ sample_rate | integer | 是 | 采样率 |
| ∟ sample_bits | integer | 是 | 比特率 |
| ∟ channels | integer | 是 | 通道数 |
json
{
// ...
"content": {
"store": "ks3",
"store_key": "DD1AFB29YmV0YS9kZXYvZmlsZS81YTdhMmVhM2U4Nzc5MGMwYzc1MmNkODQ5NGM2YjFiYjprczM6a29hLWltZw==",
"store_key_sha1": "62f6333d8a237ae48d5408b546cc3cc49eacf708",
"media": {
"format": "amr",
"codec": "amr",
"size": 6231,
"type": 1,
"audio": {
"duration": 44,
"sample_rate": 16000,
"sample_bits": 16,
"channels": 1
}
}
}
// ...
}视频消息(type=20)
| 参数 | 参数类型 | 是否必填 | 说明 |
|---|---|---|---|
| store_key | string | 是 | 视频文件存储 key |
| store_key_sha1 | string | 是 | 视频文件存储 key 校验值 |
| media | object | 是 | 视频文件内容 |
| ∟ codec | string | 是 | 编码格式,h.264 等 |
| ∟ format | string | 是 | 文件格式,mp4 等 |
| ∟ size | integer | 是 | 文件大小(B) |
| ∟ type | integer | 是 | 文件类型,2-视频 |
| ∟ video | object | 是 | 媒体文件内容 |
| ∟ cover_store_key | integer | 是 | 视频封面存储 key 值 |
| ∟ duration | integer | 是 | 视频长度(s) |
| ∟ width | integer | 是 | 视频宽度 |
| ∟ height | integer | 是 | 视频高度 |
json
{
// ...
"content": {
"store_key": "DD1AFB29YmV0YS9kZXYvZmlsZS85NjYxMzNmZmI0MzFiNmY5ZDA1YTlmY2E3N2MzMzU0MTprczM6a29hLWltZw==",
"store_key_sha1": "8159fc6752579ee0c3a759f83a46ba20dec6a6a2",
"media": {
"codec": "h.264",
"format": "mp4",
"size": 2288448,
"type": 2,
"video": {
"cover_store_key": "DD1AFB29YmV0YS9kZXYvZmlsZS85NjYxMzNmZmI0MzFiNmY5ZDA1YTlmY2E3N2MzMzU0MTprczM6a29hLWltZw==",
"duration": 6,
"width": 720,
"height": 1280
}
}
}
// ...
}模板卡片消息(type=23)
| 参数 | 参数类型 | 是否必填 | 说明 |
|---|---|---|---|
| type | integer | 是 | 消息类型,23-模板卡片消息 |
| content | object | 是 | 模板卡片消息具体内容 |
| ∟ header | object | 否 | 卡片消息标题部分 |
| ∟ elements | object | 是 | 消息元素数组 |
| ∟ config | object | 否 | 模板卡片消息配置 |
具体消息元素内容见搭建卡片消息
json
{
// ...
"content": {
"type": 23,
"content": {
"header": {
"title": {
"tag": "text",
"content": {
"type": "plainText",
"text": "标题"
}
},
"subtitle": {
"tag": "text",
"content": {
"type": "plainText",
"text": "副标题"
}
}
},
"elements": [
{
"tag": "img",
"content": {
"store_key": "DD1AFB29YmV0YS9lYTliMjE4ZTNmNmM4MzJmZDlkNWNiNjc1MjliYzk0MTprczM6d29hLXN0YXRpYw=="
}
},
{
"tag": "hr",
"style": "solid"
},
{
"tag": "div",
"fields": [
{
"tag": "text",
"content": {
"type": "markdown",
"text": "**活动时间:** \n12月12日15:00"
}
},
{
"tag": "text",
"content": {
"type": "markdown",
"text": "**活动地点:** \n五楼报告厅"
}
}
],
"division": "middle"
}
]
}
}
// ...
}