发送消息
用于应用通过WPS协作给用户发送消息,支持文本、图片、图文混排、外链图文、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 返回空字符串
请求说明
请求地址 | https://openapi.wps.cn/kopen/woa/v2/dev/app/messages |
---|---|
请求方法 | POST |
签名方式 | wps-3,签名 URL:/kopen/woa/v2/dev/app/messages |
支持应用类型 | 企业自建应用、第三方企业应用 |
权限要求 | 通过接口发送消息(xz_message) |
请求头
Header 名称 | 是否必填 | 说明 |
---|---|---|
Content-Type | 是 | 目前固定为:"application/json" |
Content-Md5 | 是 | 当 HTTP 请求的 Body 有数据时,计算 Body 的 MD5 值,否则计算空字符串的 MD5 值。再将 MD5 值转为十六进制字符串形式。即:Format("%x", md5Byte) |
Date | 是 | RFC1123 格式的日期,例: Wed, 23 Jan 2013 06:43:08 GMT |
X-Auth | 是 | X-Auth 计算方法参考签名说明 |
查询参数(Query)
名称 | 类型 | 是否必填 | 说明 |
---|---|---|---|
company_token | string | 是 | 企业授权凭证 |
请求地址示例
[POST] https://openapi.wps.cn/kopen/woa/v2/dev/app/messages?company_token=COMPANY_TOKEN
请求体(Body)
名称 | 类型 | 是否必填 | 说明 |
---|---|---|---|
app_key | string | 是 | 指应用的 AK,即 app_id |
to_users | object | 否 | 发送给某个企业的部分人员 |
∟ company_id | string | 否 | 用户归属的企业 id |
∟ company_uids | []string | 否 | 用户 ids |
to_depts | object | 否 | 发送给对应部门 |
∟ company_id | string | 否 | 部门归属的企业 id |
∟ dept_ids | []string | 否 | 部门 ids |
to_companies | []string | 否 | 发送给对应公司,当前仅支持传一个 company_id |
to_chats | []int | 否 | 发送给对应群聊 ids |
partner_members | array | 否 | 发送给关联组织的部分人员 |
∟ ep_id | int | 否 | 关联组织 id |
∟ company_uids | []string | 否 | 关联组织的用户 id |
∟ dept_ids | []string | 否 | 关联组织的部门 id |
biz_type | string | 否 | 消息所属业务类型,并且尽量是当前 app_key 下唯一。主要用来区分具体业务,做一些业务特殊处理。对于卡片消息建议加上 |
ctx_id | string | 否(需要后续更新消息时则必填) | app_key+ctx_id 映射到消息 id,最大长度 128,建议不要占满 |
company_uid | 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>
- 使用 email@人:
<at email="somebody@wps.cn">姓名</at>
- @所有人:
<at user_id="-1">所有人</at>
- 使用 company_uid@人:
<at company_uid="0rd35Ndfr">姓名</at>
请求体示例
{
"to_users": {
"company_id": "xxxxxxxxxxxx",
"company_uids": ["xxxxxxxxxxxx"]
},
"partner_members": [
{
"ep_id": 123456,
"company_uids": ["xxxxxxxxxxxx"],
"dept_ids": ["xxxxxxxxxxxx"]
}
],
"msg_type": 1,
"app_key": "your_app_id",
"content": {
"type": 1,
"body": "这是一条纯文本消息"
}
}
响应体
名称 | 类型 | 说明 |
---|---|---|
result | integer | 状态码,非 0 表示失败,参照《状态码说明》 |
message_id | string | 消息 id |
响应体示例
{
"result": 0,
"message_id": "kDtGtZHmIBsmS3"
}
参数结构说明(Content)
纯文本消息(type=1)
参数 | 参数类型 | 是否必有 | 说明 |
---|---|---|---|
type | integer | 是 | 消息类型,1-文本消息 |
body | string | 是 | 消息内容 |
{
// ...
"content": {
"type": 1,
"body": "这是一条纯文本消息"
}
// ...
}
Markdown 消息(type=1)
参数 | 参数类型 | 是否必填 | 说明 |
---|---|---|---|
type | integer | 是 | 消息类型,1-文本消息 |
style | string | 是 | 消息内容风格,style:markdown |
body | string | 是 | 消息内容 |
{
// ...
"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 客户端链接 |
{
// ...
"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 客户端链接 |
{
// ...
"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 校验值。参考获取上传文件授权。 |
{
// ...
"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 校验值。参考获取上传文件授权。 |
{
// ...
"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) |
pic_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 | 是 | 内容 |
{
// ...
"content": {
"type": 18,
"elements": [
{
"tag": "img",
"content": {
"width": 492,
"height": 242,
"pic_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 | 是 | 通道数 |
{
// ...
"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 | 是 | 视频高度 |
{
// ...
"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 | array | 是 | 卡片消息组件列表 |
∟ i18n | map | 否 | 卡片消息多语言内容,map 类型,key 为多语言标识 简体中文 zh-CN 繁体中文 zh-TW 英文 en-US, value 格式 {"header": {...}, "elements":[...] } |
∟ header | object | 否 | 卡片消息多语言-标题部分 |
∟ elements | array | 是 | 卡片消息多语言-组件列表 |
∟ config | object | 否 | 模板卡片消息配置 |
具体消息元素内容见搭建卡片消息
{
// ...
"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"
}
],
"i18n": {
"zh-TW": {
"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"
}
]
},
"en-US": {
"header": {
"title": {
"tag": "text",
"content": {
"type": "plainText",
"text": "Title"
}
},
"subtitle": {
"tag": "text",
"content": {
"type": "plainText",
"text": "Sub title"
}
}
},
"elements": [
{
"tag": "img",
"content": {
"store_key": "DD1AFB29YmV0YS9lYTliMjE4ZTNmNmM4MzJmZDlkNWNiNjc1MjliYzk0MTprczM6d29hLXN0YXRpYw=="
}
},
{
"tag": "hr",
"style": "solid"
},
{
"tag": "div",
"fields": [
{
"tag": "text",
"content": {
"type": "markdown",
"text": "**Activity time:** \n12月12日15:00"
}
},
{
"tag": "text",
"content": {
"type": "markdown",
"text": "**Activity location:** \nLecture Hall, fifth floor"
}
}
],
"division": "middle"
}
]
}
}
}
}
// ...
}