应用开发集成文档
应用开发
1 说明
序号 | 说明事项 | 参考文档 |
---|---|---|
1 | 在调用UC APIs 前,需要先创建应用,才能获取权限和凭证。 | 创建应用 |
2 | 在调用UC APIs 前,确保已获取 API 访问凭证。 | 获取访问凭证 |
3 | 如果开发的是浏览器应用(web),确保已了解如何获取和认证UC用户身份。 | 身份验证(免登) |
4 | 根据业务需要,选择调用具体UC APIs。 | UC开放接口文档.pdf |
2 创建应用
创建
企业管理员可登陆企业管理平台,在应用管理菜单下进行应用创建。
基础信息设置
应用基础信息(名称、描述、logo)可在应用创建时设置。
也可以在应用编辑界面的基础信息菜单下进行修改。
主页跳转设置
当应用需要 在UME工作台上展示主页入口 时,需要配置PC端和移动端地址**(协议://域名:端口号)**。
可根据PC端/移动端展示方式需要调整打开方式。pc端支持工作台窗口、独立UME浏览器窗口和系统浏览器三种打开方式;移动端支持独立UME浏览器窗口和系统浏览器两种种打开方式,请按需选择。
配置了主页地址并发布的应用即可在UME工作台上展示应用图标,点击后即可跳转至应用主页。
应用除了可以接入工作台主页,还可以接入到其他扩展场景。目前UC支持应用接入会话场景,其他场景持续更新中。
当应用需要 在UME会话中展示应用入口 时,需在 应用扩展中开启“会话快捷入口”并配置PC端和移动端的Applink地址。
【注意】若PC端要在会话中使用侧边栏打开页面,需将mode参数配置为sidebar scheme://host/ume/client/webapp/open?clientId=xxx&mode=sidebar&path=xxx/xxx
启用后,具备该应用可用性的用户即可在会话的应用盒子中看到该应用的快捷入口
机器人设置
当应用需要与UME用户进行交互时,需要开启机器人功能。
注意:若你不想接入机器人单聊的互动能力,建议保持机器人聊天的关闭,避免用户误解。该功能将隐藏机器人单聊的输入框。
开启后即可通过IM相关API实现向用户发送通知消息、自动建群等功能。
发布
发布范围代表哪些用户可使用该应用,包括接收通知消息、工作台入口展示和会话快捷入口展示等。
设置应用发布范围并发布应用后,即可开始使用该应用。
启用
控制该应用是否能使用的总开关,若该开关关闭,将无法调用接口、展示应用入口和使用机器人等能力。
3 获取访问凭证
访问凭证(access token)类型说明
UC平台提供了2种不同类型的访问凭证,用于验证调用方身份、确保调用方具有执行操作所需要的权限:
凭证类型 | 说明 | 参考文档 |
---|---|---|
企业授权凭证 | 使用该access token,应用将代表企业在UC系统中执行对应的操作,比如获取企业用户信息、添加企业子管理员等。 | 获取企业级访问凭证 |
用户授权凭证 | 使用该access token,应用将代表用户在UC系统中执行对应的操作,比如创建一个日程、预约一个会议等。 | 获取用户级访问凭证 |
获取企业级访问凭证
第一步:获取Client ID 与 Client Secret
企业管理员可登陆企业管理平台,在应用管理菜单下选择编辑对应应用。在应用编辑界面的应用凭证菜单下可获得应用唯一的Client ID 与 Client Secret。
第二步:获取access token
具体获取接口参考获取访问凭证。
token 有效期为 1 小时。建议在40分钟左右再次请求获取新token,避免token过期造成的请求失败,与此同时老的 token 依然有效。
请求消息示例
POST /open/api/v2/token HTTP/1.1
Content-Type: application/json
accept: application/json
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
timestamp: 1610544682145
nonce: aac64aa63454457294d440d8be191254
{
"grant_type": "client_credentials"
}
响应参数示例
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token": "[JWT TOKEN]",
"token_type": "bearer",
"expires_in": 3599
}
获取用户级访问凭证
详见身份验证(免登)。
4 身份验证(免登)
身份验证为应用 web 系统提供了获取正在访问的UC用户身份的能力,便于应用 web 系统构建登录流程。
应用免登整体流程
应用免登的整体流程如下:
- 用户在工作台上点击应用图标访问应用主页地址。
- UME在打开浏览器跳转时会将授权码code以参数的形式携带在url上。
- 应用前端需要获取url中的code参数并将code传递给应用后端。
- 应用后端携带code调用指定接口换取access token。
- 应用后端携带access token调用指定接口获得当前登陆用户信息。
- 应用内部维护当前登陆用户与自身账号体系的关联关系。
Web应用单点登录整体流程
Web应用免登的整体流程如下:
- 用户进行统一登录,发现用户未登录时,跳转到指定登录页。
- 用户在指定登录页完成登录。
- 用户浏览器调用指定接口获取授权码code。
- 应用前端需要获取url中的code参数并将code传递给应用后端。
- 应用后端携带code调用指定接口换取access token。
- 应用后端携带access token调用指定接口获得当前登陆用户信息。
- 应用内部维护当前登陆用户与自身账号体系的关联关系。
示例
第一步:获取Client ID 与 Client Secret
企业管理员可登陆企业管理平台,在应用管理菜单下选择编辑对应应用。在应用编辑界面的应用凭证菜单下可获得应用唯一的Client ID 与 Client Secret。
第二步:获取授权码code
获取授权码有三种方式:
第一种:从url携带的参数中获取(适用于工作台窗口、独立UME浏览器窗口、系统浏览器打开)
首先需要应用打开主页跳转配置中的应用免登开关。
打开开关后,从ume工作台打开应用主页时,会自动将授权码code携带在url上。例如:https://www.baidu.com?code=abcdefg
应用前端需要获取参数中的code字段内容来获取授权码。
第二种:主动调用jsapi获取(适用于工作台窗口和独立UME浏览器窗口打开)
在需要进行免登的页面引入UC提供的JS文件:
<script src="/ume-js-api-4.0.4.js"></script>
通过主动调用js方法获取code:
ume.permission.getCode({
clientId:"",// 应用程序对应的 Client ID
redirectUri:"",// 应用的访问地址
success: function (res) {
// 成功回调参数
// 如:{"code":"xxx"}
}
})
详情请查看 UME JS-API接口文档.zip。
第三种:访问UC免登页面获取(适用于工作台窗口和独立UME浏览器窗口打开)
UC提供了一个免登页面以帮助应用获取授权码code,然后自动携带code重定向到应用地址。
具体页面地址为:{{UC服务器地址}}+/ume/workbench/pc/authen
。
需要携带两个参数在url上:
- clientId:应用自身clientId
- redirectUri:需要重定向到的地址。(参数需要经过 URLEncode 处理)
例如https://www.yealink.com/ume/workbench/pc/authen?clientId=cli_9dff7f6ae&redirectUri=http%3A%2F%2Fwww.yealink.com
code 有效期为5分钟,且只能使用一次。
第三步:获取access token
获取到code之后,需要携带code和redirect_uri获取access token。具体获取接口参考获取访问凭证。
redirect_uri参数内容为当前浏览器访问的地址。
UC系统授信的redirect_uri地址为管理员为应用配置的PC&移动端主页地址。
token 有效期为 1 小时。建议在40分钟左右使用refresh token再次请求获取新token,避免token过期造成的请求失败,与此同时旧的 token 依然有效。
请求消息示例
POST /open/api/v2/token HTTP/1.1
Content-Type: application/json
accept: application/json
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
timestamp: 1610544682145
nonce: aac64aa63454457294d440d8be191254
{
"grant_type": "authorization_code",
"code": "XXXXXXXXXXXX",
"redirect_uri":"xxxxx"
}
响应参数示例
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token": "[JWT TOKEN]",
"token_type": "bearer",
"refresh_token": "[JWT TOKEN]",
"expires_in": 3599,
"refresh_expires_in": 86399
}
第四步:获取登陆用户信息
获取到用户级access token后,可请求用户查询接口获取当前登陆用户信息。具体获取接口参考查询登陆用户详情。
请求消息示例
GET /open/api/v2/users/me HTTP/1.1
Host: api.yealink.com
Content-Type: application/json
响应参数示例
HTTP/1.1 200
Content-Type: application/json;charset=UTF-8
{
"id": "9ecc83e4c7d44728bbb1e2ec226dffe7",
"partyId": "c22c0ab68bc74219aa894261b2d131dc",
"groupId": "65ddf0d5c0d64d4aab3bacc2cd690c28",
"type": 2,
"name": "zd3",
"email": "test@yealink.com",
"number": "145516*2222",
"status": "offline",
"extension": null,
"extAccount": "zd3",
"mobile": "13500000000",
"title": null,
"gender": 0,
"accountStatus": 0,
"emailBound": false,
"mobileBound": false,
"permissionCode": "A",
"enableMeetingNow": false,
"enableMeetingAppoinitment": true
}
第五步:刷新access token
refresh_token用途
-
免登操作成功后,因access_token有效期较短,当access_token过期时便可携带refresh_token(该refresh_token取第三步请求响应体中的refresh_token响应参数)调用接口获取新的access_token 和 refresh_token,以保证调用UC API接口时携带的access_token均为有效的,避免access_token过期导致调用UC API失败。
-
获取的access_token和refresh_token均存在有效期,前者有效期较短,后者较长。
- 通过 refresh_token获取的新 access_token 和 refresh_token 有效期与初次生成一致。具体获取接口参考获取访问凭证。
refresh token 有效期为 24 小时。使用refresh token再次请求获取新token时会得到新的refresh token,与此同时旧的refresh token失效。
请求消息示例
POST /open/api/v2/token HTTP/1.1
Content-Type: application/json
accept: application/json
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
timestamp: 1610544682145
nonce: aac64aa63454457294d440d8be191254
{
"grant_type": "refresh_token",
"refresh_token": "XXXXXXXXXXXX"
}
响应参数示例
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token": "[JWT TOKEN]",
"token_type": "bearer",
"refresh_token": "[JWT TOKEN]",
"expires_in": 3599,
"refresh_expires_in": 86399
}
5 应用发送卡片消息
实现效果
应用向用户发送卡片消息后,用户可在通知中心查看应用发送的消息,下图为具体实现效果图
实现步骤
第一步:启用机器人功能
企业管理员可登陆企业管理平台,在应用管理菜单下选择编辑对应应用。在应用编辑界面的机器人菜单下打开启用机器人开关。
第二步:获取企业级access_token
具体获取接口参考 获取访问凭证
请求参数示例
POST /open/api/v2/token HTTP/1.1
Header
Content-Type: application/json
accept: application/json
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
timestamp: 1610544682145
nonce: aac64aa63454457294d440d8be191254
Body
{
"grant_type": "client_credentials"
}
响应参数示例
{
"access_token": [JWT TOKEN],
"token_type": "bearer",
"expires_in": 3599
}
第三步:构造卡片消息结构体
卡片消息概述
- 卡片内容实际上是一个Json格式的文本内容
- 卡片消息可发送内容包括 纯文本、Markdown、分割线、图片、备注、url(包括文字链接、差异化链接)
构造卡片消息结构
-
卡片消息结构详情见 卡片消息结构协议
-
卡片消息结构体中必须包含基础结构elements,其他基础结构视卡片具体样式选填
- 注意:若卡片消息内包含图片、AppLink格式 ,还需要其他操作,后续会进行详细说明
卡片消息包含图片格式
-
卡片消息中若包含图片内容,则需先将图片上传至网盘后,使用返回的fileId进行图片标识发送卡片消息。图片上传的详细步骤:
- 发起预签上传请求:携带access_token发起预签上传请求成功后返回 文件预签地址(url) 与 文件id(fileId) ,具体调用接口及参数说明见 预签上传
请求参数示例
POST /open/api/v2/im-files/upload/pre-sign HTTP/1.1 Header Content-Type: application/json accept: application/json Authorization: Bearer [access_token] timestamp: 1610544682145 nonce: aac64aa63454457294d440d8be191254 Referer: https://10.200.122.133/open/api/v2/im-files/upload/pre-sign Body { "fileType": 1, "fileName": "xx.png", "fileSize": 1024 }
响应参数示例
{ "fileId": "08ac3e7bf8e14fdda0446f2901056241", //文件id "url": "https://10.200.112.133/ydfs/api/v1/files/12983830ad1a4d7f97dffb5f7a4534f3.png" //文件上传地址 }
- 使用PUT请求方式将图片上传至第一步获取的 文件预签地址(url)
请求示例
PUT https://10.200.112.133/ydfs/api/v1/files/12983830ad1a4d7f97dffb5f7a4534f3.png //文件上传地址
- 上传完图片后,将第一步获取的 文件id(fileId) 作为参数 imageId 的参数值即可发送上传的图片
-
包含图片的卡片消息结构体如下 (示例只包含图片组件的必填参数)
{ "elements": [ { "tag": "image", "imageId": "802e42015ffa494195b9b3505b9a6c99" //文件id } ] }
卡片消息包含AppLink格式
-
注意:若卡片消息跳转地址需要携带code的话必须使用AppLink格式进行跳转
-
AppLink协议就是一个URL协议,用于打开应用或者应用其中的一个界面,AppLink详细介绍介绍见 AppLink协议介绍
-
AppLink的URL结构如下所示
-
其中path+query部分通常格式为 /ume/client/模块/事件?参数
构造AppLink卡片消息结构体的详细步骤:
-
调用接口获取AppLink所需的host信息如下所示 具体调用接口见 获取AppLink所需的host
需要注意的是,因为当前有接口请求调用的频率限制并且服务器域名不会经常改变,不需要每次发送AppLink卡片消息时,都来请求获取host信息,在第一次查询时,可在本地进行缓存host信息。否则可能获取不到host信息从而导致卡片消息发送失败。
请求消息示例
GET /open/api/v2/messages/app-link/host HTTP/1.1 Content-Type: application/json Header Authorization: Bearer [access_token] timestamp: 1610544682145 nonce: aac64aa63454457294d440d8be191254
响应消息示例
HTTP/1.1 200 Content-Type: application/json;charset=UTF-8 { "host": "https://10.200.112.133.xip.io:443/ume/client" //具体host信息 }
-
拼接完整AppLink的URL,将第一步获取的host信息拼接上path与query部分即可。
以拼接跳转至问卷详情页面为例
-
如需跳转至应用网页,需带上参数 clientId 、 mode(打开方式) 、path(跳转的具体页面地址)
-
跳转的页面地址为 /ume/survey/pc/detail?id=d6864
-
注意:若跳转的页面地址包含参数,需将参数连接符 ? 改为 & 后进行拼接即 /ume/survey/pc/detail&id=d6864
-
拼接后的URL https://10.200.112.133.xip.io:443/ume/client/webapp/open?clientId=12e3&mode=browser&path=/ume/survey/pc/detail&id=d6864
-
点击该卡片消息即可跳转至问卷详情页面 https://uc20.yealink.com:18443/ume/survey/pc/detail?clientId=12e3&id=d686407523aa4be9b95e7b5b8a89441d&code=529a8a9
-
https://uc20.yealink.com:18443 为配置的主页跳转地址(通过参数clientId可自动转换)
-
如需进行免登,需在应用管理主页跳转配置界面打开应用免登按钮,即可将code拼接在跳转的URL中
-
-
包含AppLink的卡片消息结构体如下 (示例只包含AppLink组件的必填参数)
{ "elements": [ { "tag": "markdown", "content": "[跳转至应用页面]($urlVal)", "href": { "urlVal": { "tag": "url", "url": "https://10.200.112.133.xip.io:443/ume/client/webapp/open?clientId=12e3&mode=browser&path=/ume/survey/pc/detail&id=d6864", "pcUrl": "https://10.200.112.133.xip.io:443/ume/client/webapp/open?clientId=12e3&mode=browser&path=/ume/survey/pc/detail&id=d6864" } } } ] }
卡片消息格式校验
https://www.jsonschemavalidator.net/s/JXjhGDV3
打开网址,将构造后的卡片消息结构体复制至 Input JSON
框中。如卡片格式有误,可根据报错信息修改卡片消息结构。
第四步:获取UC用户ID
- 如果使用的是AD账号,则需要通过调用 根据用户账号查询用户 接口方法获取用户id后才能向该用户发送卡片消息
- 如果是批量获取用户id,则需调用 根据第三方账号查询用户列表
请求消息示例
GET /open/api/v2/accounts/users?accountType=13&account=yl3299 HTTP/1.1
Content-Type: application/json
- accountType=13表示第三方账号类型
响应消息示例
HTTP/1.1 200
Content-Type: application/json;charset=UTF-8
{
"id": "70af3721acb34aef8ffc7bf9fa26d5d8", //用户id
"groupId": "358fb5cfcf9b4939ad0df6baefa1f5a3",
"number": "7777771111",
"extension": "1111",
"name": "test",
"encryptedPassword": "cbeaf062187c272dc7992e5c6bb437f2"
}
第五步:调用接口发送卡片消息
-
需要将第三步构造的卡片消息结构体由Json字符串转成String字符串作为参数body的参数值
点击打开转换工具转换工具,将构造的卡片消息结构体复制进输入框中,点击压缩并转义即可转成String字符串
-
发送消息 具体调用接口参考 向单个用户发送卡片消息 、 批量发送卡片消息
以发送跳转至百度界面的卡片消息为例
请求参数示例
POST /open/api/v2/messages HTTP/1.1
Header
Content-Type: application/json
accept: application/json
Authorization: Bearer [access_token]
timestamp: 1610544682145
nonce: aac64aa63454457294d440d8be191254
Body
{
"msgType": 4,
"body": "{\"header\": {\"title\": {\"tag\": \"plainText\",\"content\": \"hello card!\"},\"theme\": \"blue\"},\"elements\": [{\"tag\": \"markdown\",\"content\": \"[跳转至百度页面]($urlVal)\",\"href\": {\"urlVal\": {\"tag\": \"url\",\"url\": \"https://www.baidu.com\",\"pcUrl\": \"https://www.baidu.com\"}}}]}",
"receiverId": "c408a12e43c34565af4800d7eb3ba65e"
}
响应参数示例
{
"bornTime": 1658748015965,
"msgId": 500603637653831680,
"receiverId": "ad94e1deef0849a99a19f109a22730f8",
"senderId": "20e683bb4cfe439d82eff1a0623006b9",
"sessionId": 4641708206034469482
}
6 事件订阅
概述
UC具有事件订阅的能力,能够将你所订阅的事件通知到应用。你需要做的是配置UC该向哪里(请求网址URL)发送事件通知,当事件发生时UC便会以HTTP POST请求的方式将事件内容以 json 格式推送给应用,应用可据此做出响应处理。
使用场景示例
- 当应用关心UC用户的状态,需要根据状态进行操作时,就可以订阅用户删除事件,便可以在用户删除时第一时间收到通知报文并及时进行相应操作。
- 当应用需要收到用户发来的消息,便可订阅接收会话消息事件,用户向应用发送消息,应用便可接收到该消息。
以上是简单的使用场景,应用可根据不同需求,进行不同的事件处理
点击 查看可订阅事件
事件订阅流程
- 一个完整的事件订阅操作包含了 配置请求网址URL及事件订阅 和 接收并响应事件
第一步 启用事件订阅功能
企业管理员登录企业管理平台,在应用管理菜单下选择编辑对应应用。在事件订阅菜单下打开事件订阅开关
第二步 配置请求地址URL
在请求网址URL输入框中输入URL,保存后,会校验该URL的可达性,避免设置无效的订阅地址。
- 请求网址URL用于接收事件并响应事件
- 当应用订阅的事件触发时,会向配置的请求网址URL发送对应的事件通知
- 当前默认,应用订阅了所有事件
第三步 接收并响应事件
-
当订阅的事件发生时,UC会将通知报文发送到你预先配置的请求地址URL,应用服务器接收并进行响应处理。
-
通知报文以
HTTPS
的方式进行传输,使用POST
方法,报文格式限定为 JSON 格式。详细报文格式见 事件通知报文格式
完成以上步骤即可订阅一个完整的事件
重试策略
在收到UC发送的通知请求后,应用服务器需要在 5s 内返回 200
或 204
的响应,如果在5s内没有响应该通知请求,UC将视此次通知失败,并重新发送通知请求
重试策略
- 采用一定时间间隔重试,支持最大重试24次,具体间隔为:30s, 5m, 10m, 30m, 1h, ... 1h(共 20 个 1h )当重试周期结束还未投递成功,将不再重试,直到有新的事件到达。
- 当重试过程中,服务器在 5s 内返回
200
或204
的响应,就认为消息投递成功,不再重试。
订阅事件数据内容
事件通知报文格式
HTTP请求头部信息
Header | 说明 |
---|---|
content-type | application/json |
content-length | 请求体的内容长度(以字节为单位) |
authorization | 订阅成功之后返回的验证 token。此数据能够唯一标识一个订阅。 |
clientid | 配置事件订阅的应用程序 ID |
x-yl-requestid | 请求的链路跟踪id |
请求 Body 格式
{
"events": [
{
"id": "6c29f04672b6492ebd0911c2da3414ac",
"type": "user.deleted",
"createTime": 1600063609555,
"partyId": "b986e6eedd6245d697d79da86d6df57c",
"userId": null,
"dataVersion": 1,
"metadataVersion": 1,
"data": [
"3c2845f908a940a29a63a3ba9602a173"
]
}
]
}
event对象
字段名称 | 字段类型 | 说明 |
---|---|---|
id | String | 事件数据唯一标识,可用于去重 |
type | String | 事件类型 |
createTime | Long | 业务服务生成事件时间 |
partyId | String | 企业ID |
userId | String | 用户ID |
dataVersion | Long | 业务数据版本号 |
metadataVersion | Long | 元数据版本号,除data字段 |
data | Object | 事件数据,由业务决定格式和内容 |
事件数据内容
接收会话消息
事件类型
im.message_receive
事件数据内容
{
"sender": {
"senderId": "84aad35d084aa403a838cf73ee18467", //发送者id
"partyId": "736588c9260f175e" //企业id
},
"message": {
"sessionId": 122333, //会话id
"rootId": 11111111, //消息根节点id
"parentId": 2222222, //父节点id
"msgId": 111111, //消息id
"msgType": 1, //消息类型 1-纯文本 2-语音 3-图片 4-卡片 5-文件 6-富文本 7-表情 8-聊天记录 9-视频
"position": 10, //消息会话内位置信息
"body": "{\"text\":\"@_user_1 hello\"}", //消息内容
"status": 11, //通用默认状态
"bornTime": 1623895862000, //消息生成时间
"version": 12314, //版本号
"seq": 124 //终端序列号
}
}
组织节点删除
事件类型
group.deleted
事件数据内容
{
"partyId":"1234",//团体id
"partySubType": 0,//团体类型,0:企业 1:个人
"groupId":"1234556",
"groupType": 1 //分组类型,1:用户分组,3:硬件设备分组, 5:vmr分组,9:外部联系人分组
}
用户删除
事件类型
user.deleted
事件数据内容
[
{
"partyId": "1234", //团体id
"partySubType": 0, //团体类型,0:企业 1:个人
"userId": "1234556"
}
]
用户修改
事件类型
user.deleted
事件数据内容
[
{
"partyId": "1234", //团体id
"partySubType": 0, //团体类型,0:企业 1:个人
"userId": "1234556"
}
]
7 接口说明
获取访问凭证
请求方法
POST
请求地址
/open/api/v2/token
请求参数
请求头
参数 | 参数类型 | 数据类型 | 是否必需 | 描述 |
---|---|---|---|---|
Authorization | Header | String | 是 | Basic base64Encode(client_id:client_secret),以冒号连接Client ID和Client Secret,然后进行Base64编码 |
timestamp | Header | String | 是 | 时间戳,从 1970 年 1 月 1 日 0 点 0 分 0 秒开始到现在的毫秒数 |
nonce | Header | String | 是 | 随机数,最大长度32位 |
请求体
参数 | 参数类型 | 数据类型 | 是否必需 | 描述 |
---|---|---|---|---|
grant_type | Body | String | 是 | 参数值当前可选值为:client_credentials、authorization_code、refresh_token。调用者根据申请token时的授权模式选择相关的值填写即可 |
code | Body | String | 否 | 服务器提供的授权码code。grant_type为authorization_code时该参数必传 |
redirect_uri | Body | String | 否 | 当前免登模式下,该参数为使用该授权码code的应用的访问地址。开发者管理平台统一提供对于该地址的校验,避免授权码code被盗用于该应用其它访问地址。grant_type为authorization_code时该参数必传 |
refresh_token | Body | String | 否 | 刷新令牌,grant_type为refresh_token时该参数必传 |
HTTP状态码
返回值 | 描述 |
---|---|
200 | 操作成功,详见响应参数 |
400 | 客户端传参异常,详见异常响应参数 |
401 | 鉴权失败,详见异常响应参数 |
500 | 服务端异常,详见异常响应参数 |
响应参数
参数 | 数据类型 | 描述 |
---|---|---|
access_token | String | 访问令牌 |
token_type | String | bearer |
expires_in | Long | 访问令牌有效时间,单位为秒 |
refresh_token | String | 更新令牌,该参数仅有authorization_code、refresh_token情况下有值 |
refresh_expires_in | Long | 刷新令牌有效时间,单位为秒,该参数仅有authorization_code、refresh_token情况下有值 |
异常响应参数
参数 | 数据类型 | 描述 |
---|---|---|
error | String | 根据OAuth2协议定义提供。表示一个错误代码字符串,可以用于对错误进行分类,并对错误进行处理 |
code | String | 服务端定义的错误码,用于快速定位问题 |
requestId | String | 服务端生成的请求ID,用于在服务端跟踪请求执行情况。能够帮助开发人员快速定位问题 |
message | String | 简单明了的错误描述,能够被终端用户所理解 |
查询登陆用户详情
请求方法
GET
请求地址
/open/api/v2/users/me
请求参数
请求头
参数 | 参数类型 | 数据类型 | 是否必需 | 描述 |
---|---|---|---|---|
Authorization | Header | String | 是 | 用户级访问凭证。格式为:Bearer [ACCESS TOKEN] |
timestamp | Header | String | 是 | 时间戳,从 1970 年 1 月 1 日 0 点 0 分 0 秒开始到现在的毫秒数 |
nonce | Header | String | 是 | 随机数,最大长度32位 |
HTTP状态码
返回值 | 描述 |
---|---|
200 | 操作成功,详见响应参数 |
400 | 客户端传参异常 |
401 | 鉴权失败 |
500 | 服务端异常 |
响应参数
参数 | 数据类型 | 描述 |
---|---|---|
id | String | 主键id |
partyId | String | 所属企业id |
groupId | String | 分组id |
name | String | 名称 |
String | 邮箱 | |
number | String | 号码 |
status | String | 在线状态,offline:离线,online:在线 |
extension | String | 分机号 |
extAccount | String | 第三方账号 |
mobile | String | 手机号 |
mobileCode | String | 手机区号 |
title | String | 职位 |
gender | Integer | 性别,0:保密;1:男;2:女 |
accountStatus | Integer | 账户状态,0:未验证;1:已验证 |
emailBound | Boolean | 是否绑定邮箱 |
mobileBound | Boolean | 是否绑定手机号 |
permissionCode | String | 可见部门类型,A:企业内全部联系人;B:所在部门及同级部分的所有联系人;C:仅可见所在部分的所有联系人;D:仅可见自己;E:自定义。目前不支持编辑为 E 类型。当为 null 时,同 A 类型 |
enableMeetingNow | Boolean | 是否启用即时会议功能 |
enableMeetingAppoinitment | Boolean | 是否启用会议预约功能 |
发送卡片消息
请求方法
POST
请求地址
/open/api/v2/messages
请求参数
参数 | 参数类型 | 数据类型 | 是否必需 | 描述 |
---|---|---|---|---|
msgType | Body | Integer | 是 | 消息类型,1:文本消息,4:卡片消息 |
body | Body | String | 是 | 消息内容 |
receiverId | Body | String | 否 | 接收用户id(sessionId为空时必填,默认以receiverId为准) |
sessionId | Body | Long | 否 | 接收会话id(receiveId为空时必填) |
HTTP状态码
返回值 | 描述 |
---|---|
200 | 操作成功,详见响应参数 |
400 | 客户端传参异常 |
401 | 鉴权失败 |
500 | 服务端异常 |
响应参数
参数 | 数据类型 | 描述 |
---|---|---|
msgId | Long | 消息id |
sessionId | Long | 会话id |
senderId | String | 发送者id |
receiverId | String | 接收者id |
bornTime | Long | 消息产生时间 |
批量发送消息
请求方法
POST
请求地址
/messages/batch-send
请求参数
参数 | 参数类型 | 数据类型 | 是否必需 | 描述 |
---|---|---|---|---|
msgType | Body | Integer | 是 | 消息类型,1:文本消息,4:卡片消息 |
body | Body | String | 是 | 消息内容 |
receiverIds | Body | List | 是 | 接收用户id,String类型(上限200) |
HTTP状态码
返回值 | 描述 |
---|---|
200 | 操作成功,详见响应参数 |
400 | 客户端传参异常 |
401 | 鉴权失败 |
500 | 服务端异常 |
请求消息示例
POST /open/api/v2/messages/batch-send HTTP/1.1
Content-Type: application/json
{
"msgType": 1,
"body": "这是一条test消息",
"receiverIds": [
"85a5b41f1b1f4d7e8feb95616927ffcc",
"ad94e1deef0849a99a19f109a22730f8"
]
}
预签上传
请求方法
POST
请求地址
/im-files/upload/pre-sign
请求头域
参数 | 参数类型 | 数据类型 | 是否必需 | 描述 |
---|---|---|---|---|
Referer | Header | String | 是 | 值为URL格式,同预签上传的请求地址一致。 |
请求参数
参数 | 参数类型 | 数据类型 | 是否必需 | 描述 |
---|---|---|---|---|
fileType | Body | Integer | 是 | 文件类型,1:图片 |
fileName | Body | String | 是 | 文件名,与待上传的文件名一致 |
fileSize | Body | Long | 是 | 文件大小(单位:字节,上限10485760),与待上传的文件大小一致 |
HTTP状态码
返回值 | 描述 |
---|---|
200 | 操作成功,详见响应参数 |
400 | 客户端传参异常 |
401 | 鉴权失败 |
500 | 服务端异常 |
响应参数
参数 | 数据类型 | 描述 |
---|---|---|
fileId | String | 文件id |
url | String | 上传地址(使用Put方法上传至该地址) |
获取AppLink所需的host
请求方法
GET
请求地址
/messages/app-link/host
HTTP状态码
返回值 | 描述 |
---|---|
200 | 操作成功,详见响应参数 |
400 | 客户端传参异常 |
401 | 鉴权失败 |
500 | 服务端异常 |
响应参数
参数 | 数据类型 | 描述 |
---|---|---|
host | String | applink所需的host |
根据用户账号查询用户
请求方法
GET
请求地址
/accounts/users
请求参数
参数 | 参数类型 | 数据类型 | 是否必需 | 描述 |
---|---|---|---|---|
account | Query | String | 是 | 账号 |
accountType | Query | Integer | 否 | 账号类型,非必填, 默认为企业成员信息的 number 类型。可填:13,第三方账号类型 |
HTTP状态码
返回值 | 描述 |
---|---|
200 | 操作成功,详见响应参数 |
400 | 客户端传参异常 |
401 | 鉴权失败 |
500 | 服务端异常 |
响应参数
参数 | 数据类型 | 描述 |
---|---|---|
id | String | 主键id |
groupId | String | 分组id |
name | String | 名称 |
number | String | 号码 |
extension | String | 分机号 |
encryptedPassword | String | MD5 算法加密后的密文密码,若系统强制使用国密,则为 SM3 算法加密 |
根据第三方账号查询用户列表
请求方法
POST
请求地址
/users/byExtAccounts
请求参数
参数 | 参数类型 | 数据类型 | 是否必需 | 描述 |
---|---|---|---|---|
accounts | Body | String[] | 否 | 查询的第三方账号列表,目前支持AD账号 |
HTTP状态码
返回值 | 描述 |
---|---|
200 | 操作成功,详见响应参数 |
400 | 客户端传参异常 |
401 | 鉴权失败 |
500 | 服务端异常 |
响应参数
参数 | 参数类型 | 描述 |
---|---|---|
users | User[] | 用户列表 |
User对象定义
参数 | 数据类型 | 描述 |
---|---|---|
id | String | 主键id,用户id |
partyId | String | 所属企业id |
groupId | String | 分组id |
name | String | 名称 |
alias | String | 用户别名 |
String | 邮箱 | |
number | String | 号码 |
status | String | 在线状态,offline:离线,online:在线 |
extension | String | 分机号 |
mobile | String | 手机号 |
mobileCode | String | 手机区号 |
title | String | 职位 |
gender | Integer | 性别,0:保密;1:男;2:女 |
accountStatus | Integer | 账户状态,0:未验证;1:已验证 |
extAccount | String | 第三方账号,如AD账号 th489211 |
请求消息示例
GET /open/api/v2/users/byExtAccounts HTTP/1.1
Host: api.yealink.com
Content-Type: application/json
响应消息示例
HTTP/1.1 200
Content-Type: application/json;charset=UTF-8
{
“users”:[
{
"id": "8d07a56207074d26b61026099625b9e2",
"partyId": "c22c0ab68bc74219aa894261b2d131dc",
"groupId": "65ddf0d5c0d64d4aab3bacc2cd690c28",
"type": 2,
"name": "zd2",
"alias": "zz",
"email": null,
"number": "145516*3333",
"extAccount": "th489211", // 第三方账号:AD账号
"status": "offline",
"extension": null,
"mobile": "17700000000",
"title": null,
"gender": null,
"accountStatus": 0
}
]
}
8 附录
卡片消息协议
下述是对卡片消息结构的详细描述
基础结构
字段 | 必填 | 类型 | 取值范围 | 描述 |
---|---|---|---|---|
config | 否 | object | 卡片属性相关配置 | |
header | 否 | object | 卡片标题 | |
elements | 是 | array | 内容块组件/markdown组件/分割线组件/图片组件/备注组件 | 正文 |
preview | 否 | string | 预览文案,用于卡片消息推送和会话列表消息预览的显示 | |
keyword | 否 | string | 关键字,用于消息搜索匹配命中,sdk层做搜索用字段,UI不需要关心 | |
link | 否 | object | url组件 | 用于卡片点击跳转 |
config结构
字段 | 必填 | 类型 | 取值范围 | 描述 |
---|---|---|---|---|
isFullUpdate | 否 | bool | true/false | 是否全量更新,默认true,服务器关心的字段,客户端可以丢弃 |
header结构
字段 | 必填 | 类型 | 取值范围 | 描述 |
---|---|---|---|---|
title | 是 | object | 文本组件 | 标题内容,仅支持plainText标签的文本组件,且行数固定最多2行 |
theme | 否 | string | main/green/orange/red/gray/pink/gold/purple/blue | 标题区主题色 |
示例
"card": {
"config": {
"isFullUpdate": true
},
"header": {
"title": {
"tag": "plainText",
"content": "hello card!"
},
"theme": "blue"
},
"elements": [
//内容块、markdown、分割线、图片、备注,五种组件
{组件},
{组件},
......
],
"preview": "hello card!",
"keyword": "hello card!",
"link": {
"tag": "url",
"url": "https://www.yealink.com.cn/",
"iosUrl": "https://www.yealink.com.cn/",
"androidUrl": "https://www.yealink.com.cn/",
"pcUrl": "https://www.yealink.com.cn/"
}
}
组件(elements)结构
基础组件只能内嵌在非基础组件中
组件 | 描述 | 是否为基础组件(可内嵌于其它组件中) |
---|---|---|
文本 | 单个文本内容 | 是 |
文本块 | 包含单个文本组件,相连的文本块能够指定其排列样式是单列还是均分并列 | 是 |
内容块 | 由文本块组成,并且能够携带配图 | 否 |
markdown | markdown格式内容否 | 否 |
分割线 | 单条分割线 | 否 |
图片 | 单个图片内容 | 是 |
备注 | 包含多个文本组件和图片组件以流式布局显示 | 否 |
url | 差异化链接,可以内嵌在文本组件和markdown组件里 | 是 |
文本组件
字段 | 必填 | 类型 | 取值范围 | 描述 |
---|---|---|---|---|
tag | 是 | string | plainText/simpleMd | 标签,内嵌于图片组件的alt字段时仅支持plainText标签 |
content | 是 | string | 文本内容 | |
lines | 否 | int | 内容显示行数,默认0自适应行数不限制,内嵌于标题header和备注组件时该字段无效 | |
href | 否 | object | key为content里指定的变量名,value为url组件 | 用于指定simpleMd标签富文本content里文本链接差异化跳转的链接 |
示例
{
"tag": "plainText",
"content": "hello text!",
"lines": 1
}
文本块组件
字段 | 必填 | 类型 | 取值范围 | 描述 |
---|---|---|---|---|
tag | 是 | string | field | 标签 |
isShort | 是 | bool | true/false | 是否允许并列,false时独占一行,相连的两个文本块组件若都为true时则两个文本块垂直均分并列一区域 |
text | 是 | object | 文本组件 | 文本块内容 |
示例
{
"tag": "field",
"isShort": false,
"text": {
"tag": "plainText",
"content": "hello field!"
}
}
内容块组件
字段 | 必填 | 类型 | 取值范围 | 描述 |
---|---|---|---|---|
tag | 是 | string | div | 标签 |
fields | 是 | array | 文本块组件 | 文本内容 |
extra | 否 | object | 图片组件 | 附属物,展示在文本内容右侧 |
示例
{
"tag": "div",
"fields": [
{
"tag": "field",
"isShort": false,
"text": {
"tag": "simpleMd",
"content": "**hello div!**"
}
},
{
"tag": "field",
"isShort": true,
"text": {
"tag": "plainText",
"content": "左侧并排文本"
}
},
{
"tag": "field",
"isShort": true,
"text": {
"tag": "plainText",
"content": "右侧并排文本"
}
}
],
"extra": {
"tag": "image",
"imageId": "******************"
}
}
markdown组件
字段 | 必填 | 类型 | 取值范围 | 描述 |
---|---|---|---|---|
tag | 是 | string | markdown | 标签 |
content | 是 | string | markdown格式内容 | |
href | 否 | object | key为content里指定的变量名,value为url组件 | 用于指定content里差异化跳转的链接 |
示例
{
"tag": "markdown",
"content": "普通文本\n标准emoji😄\n*斜体*\n**粗体**\n~~删除线~~\n<at id="******************">用户名</at>\n<at id="all"></at>\n<a>https://www.yealink.com.cn/</a>\n[文字链接](https://www.yealink.com.cn/)\n[差异化跳转]($urlVal)\n![图片](******************)\n上面是一个图片标签\n ---\n上面是一行分割线",
"href": {
"urlVal": {
"tag": "url",
"url": "https://www.yealink.com.cn/",
"iosUrl": "https://www.yealink.com.cn/",
"androidUrl": "https://www.yealink.com.cn/",
"pcUrl": "https://www.yealink.com.cn/"
}
}
}
markdown支持样式
样式 | 语法 | 效果 | 可用标签 | 备注 |
---|---|---|---|---|
换行 | \n |
换行 | 卡片属性相关配置 | |
斜体 | *斜体* |
斜体 | simpleMd/markdown | |
粗体 | **粗体** |
粗体 | simpleMd/markdown | |
删除线 | ~~删除线~~ |
~~删除线~~ | simpleMd/markdown | |
@单人 | <at id="userId">用户名</at> |
|
simpleMd/markdown | userId为用户id,引号前需加\ |
@所有人 | <at id="all"></at> |
<at id="all"></at> |
simpleMd/markdown | |
超链接 | <a>https://www.yealink.com.cn/</a> |
https://www.yealink.com.cn/ | simpleMd/markdown | 地址内容必填且前缀为https或http |
文字链接 | [文字链接](url) |
文字链接 | simpleMd/markdown | 地址内容必填且前缀为https或http |
差异化跳转 | [差异化跳转]($urlVal) |
差异化跳转 | simpleMd/markdown | 差异化跳转与文字链接跳转的区别在于差异化跳转可指定各端的链接 |
图片 | ![xxx](imageId) |
markdown | [xxx]内的文本效果为鼠标悬浮停留图片上显示的文本内容,与图片组件的alt作用一样 | |
分割线 | \n ------------\n |
markdown | ------符号必须跟在换行符后使用,且与换行符间有1个空格 |
分割线组件
字段 | 必填 | 类型 | 取值范围 | 描述 |
---|---|---|---|---|
tag | 是 | string | hr | 标签 |
示例
{
"tag": "hr"
}
图片组件
字段 | 必填 | 类型 | 取值范围 | 描述 |
---|---|---|---|---|
tag | 是 | string | image/urlImage | 标签 |
imageId | 是(image),否(urlImage) | string | 图片唯一标识 | |
imageUrl | 是(urlImage),否(image) | string | 网络图片url | |
isPreviewable | 否 | bool | true/false | 是否支持点击预览,true时点击图片会预览该图片,false时点击图片会响应卡片点击事件,默认true |
title | 否 | object | 文本组件 | 图片标题,显示在图片的上侧,仅在该组件不作为内嵌组件时生效 |
alt | 否 | object | 文本组件 | pc端鼠标悬浮停留在该图片时展示的文本内容,仅支持plainText标签的文本组件 |
mode | 否 | string | tile/cropCenter | tile平铺,cropCenter居中裁剪,默认cropCenter,仅在该组件不作为内嵌组件时生效 |
width | 否 | int | 图片宽度,当标签为image时,不需要填写,该字段无作用;当标签为urlImage时,未经过网盘处理,客户端无法知道图片的宽高,因此需要自行填写,且为真实的图片宽度 | |
height | 否 | int | 图片高度,当标签为image时,不需要填写,该字段无作用;当标签为urlImage时,未经过网盘处理,客户端无法知道图片的宽高,因此需要自行填写,且为真实的图片高度 |
示例
{
"tag": "image",
"imageId": "******************",
"isPreviewable": true,
"title": {
"tag": "plainText",
"content": "图片标题"
},
"alt": {
"tag": "plainText",
"content": "这里是鼠标悬浮停留时显示的文本内容"
},
"mode": "cropCenter"
}
{
"tag": "urlImage",
"imageUrl": "https://t7.baidu.com/it/u=1653900808,1273534310&fm=193&f=GIF",
"isPreviewable": true,
"title": {
"tag": "plainText",
"content": "图片标题"
},
"alt": {
"tag": "plainText",
"content": "这里是鼠标悬浮停留时显示的文本内容"
},
"mode": "cropCenter",
"width": 800,
"height": 532
}
备注组件
字段 | 必填 | 类型 | 取值范围 | 描述 |
---|---|---|---|---|
tag | 是 | string | note | 标签 |
elements | 是 | array | 文本组件/图片组件 | 备注内容,流式布局依次往右放置,显示不下时自动换行,文本组件行数根据内容自适应,无行数限制 |
示例
{
"tag": "note",
"elements": [
//文本、图片组件
{
"tag": "image",
"imageId": "******************"
},
{
"tag": "plainText",
"content": "hello note!"
}
]
}
url组件
字段 | 必填 | 类型 | 取值范围 | 描述 |
---|---|---|---|---|
tag | 是 | string | url | 标签 |
url | 是 | string | 默认跳转链接,前缀必须为https或http | |
iosUrl | 否 | string | iOS端跳转链接,前缀必须为https或http | |
androidUrl | 否 | string | android端跳转链接,前缀必须为https或http | |
pcUrl | 否 | string | pc端跳转链接,前缀必须为https或http |
示例
{
"tag": "url",
"url": "https://www.yealink.com.cn/",
"iosUrl": "https://www.yealink.com.cn/",
"androidUrl": "https://www.yealink.com.cn/",
"pcUrl": "https://www.yealink.com.cn/"
}
AppLink协议
一 概述
- AppLink协议就是一个URL协议。AppLink协议可以用于打开应用或者应用其中的一个界面。
二 AppLink
结构
字段 | 取值范围 | 描述 |
---|---|---|
scheme | http/https | 协议,固定值 |
host | applink.yealink.com.cn | 主机域名,固定值 |
path | 根据具体功能定义 | 通常格式为/ume/client/模块/事件,如打开某个聊天界面:/ume/client/session/open |
query | 参数 | 通常格式为key1=value1&key2=value2,如打开某个聊天界面:sessionId=xxxxxxxxxx |
图示
三 唤醒应用
通过浏览器加载一个URL scheme链接打开应用或者应用其中的一个界面
scheme约定
客户端 | 取值范围 |
---|---|
三端统一 | umeonpremise |
四 时序图
host来源
AppLink响应
打开网页应用
五 功能列表
模块 | 功能 | path | 参数说明 | 示例 |
---|---|---|---|---|
应用 | 打开应用 | /ume/client/main/open | \ | scheme://host/ume/client/main/open |
会话 | 打开会话 | /ume/client/session/open | 通过联系人ID打开: userId 通过会话ID打开: sessionId |
scheme://host/ume/client/session/open?sessionId=*** |
会话 | 群公告详情 | /ume/client/session/announcement | 会话ID: sessionId | scheme://host/ume/client/session/announcement?sessionId=*** |
网页应用 | 打开网页应用 | /ume/client/webapp/open | 应用ID: clientId 打开方式(优先级最高,链接中未带打开方式参数(mode)时取应用配置的打开方式): mode(appCenter:应用内打开加载;window:独立UME窗口打开,仅pc有效;browser:系统浏览器打开) 路径:path(访问应用页面的具体某个页面,该参数将替换url的path部分 |
scheme://host/ume/client/webapp/open?clientId=***&mode=appCenter&path=xxx/xxx |