API授权
一、授权流程概述
服务商的生态应用访问开放平台的OpenAPI,需要从开放平台获取访问令牌(access_token),访问令牌必须传递应用的appkey、appSecret、ticket和授权企业的租户ID(tenantid)4个参数才能获取到,如下图所示:
服务商给应用开启自动推送ticket后,开放平台会向应用基本信息里填写的回调URL定期推送ticket信息,开发者需要持久化ticket,新的ticket推送会使之前的ticket失效。Ticket的自动推送需要开发者为应用开启自动推送后才开始,如下图红框部分所示:
企业租户购买应用后,开放平台会调用应用的回调url,推送购买租户的tenantId和订单信息。服务商通过调用getAccessToken接口获取授权租户数据接口的访问令牌 access_token,该令牌有效期 2 小时,过期后需重新获取。在获得了access_token后,服务商就可以访问对应租户下的数据。
上述流程中推送应用ticket和推送授权租户tenantId信息,是通过调用回调接口来实现的。回调接口即在创建应用时填写的【回调 URL】,请确保该接口能在公网环境下访问。开放平台会向回调URL定时推送ticket,以及租户授权信息。服务商在收到推送的消息后需要返回“success”字符串,否则平台会一直尝试推送。开放平台的推送都是 post json形式,使用了BASE64 + AES + SHA1 加解密,具体加解密验签方式详见 demo 中的实现。服务商在调用 getAccessToken接口时也需要加签,加签算法为HmacSHA256,具体实现请参考 demo。
二、接收应用 ticket
开放平台会推送 ticket 至应用配置的 回调url,推送方式是 POST application/json 。示例推送如下:
{
"msgSignature": "2ff5a94ca2dd9376c8dcebde690b1b8e94741ec5",
"timestamp": 1530862251583,
"nonce": "uM48M4qajlEtVCz4",
"encrypt": "9Mo8oaTFKJAdK3wnM2gS9RJxt0febE/fFJF1vhKbcPmdljs44OwHlW96qj2hJA=="
}
EncryptionHolder:加密后的消息载体对象
参数说明:
字段 | 类型 | 说明 |
---|---|---|
msgSignature | string | 消息签名 |
timestamp | Long | 消息发送 unix 时间戳 |
nonce | string | 随机值,盐 |
encrypt | string | 加密消息体 |
使用 demo 中的相关代码解密加密的消息体,获得推送的ticket事件,示例如下:
{
"type":"SUITE_TICKET",
"timestamp":1529999656469,
"eventId":" 033af2b1-96c0-4cc2-8991-3abe42aa3d0b ",
"suiteKey":"abcde859-d853-4f57-896c-6658c5920e25",
"suiteTicket":"absdfsd-d853-4f57-896c-6658c5920e25"
}
EventContent:反序列化后的消息内容对象
字段说明:
字段 | 类型 | 说明 |
---|---|---|
type | string | 事件类型,对于推送ticket事件,其类型为SUITE_TICKET |
eventId | string | 事件 uuid |
timestamp | Long | 事件创建的 unix 时间戳 |
sutieKey | string | 应用的appKey |
suiteTicket | string | 应用的ticket |
ISV需要将其中的suiteTicket 进行保存,在后续获得调用接口令牌时需要使用。
注意:
1.开放平台会向【回调URL】定期推送ticket信息,新的ticket推送会使之前的ticket失效。
2.推送 ticket 超时时间为2秒,成功获得 ticket 后请返回 success 字符串。(demo代码里有示例)
三、接收授权租户的 tenantId和订单信息
在企业租户购买应用时,开放平台会向应用的回调url推送授权事件,该事件的目的是通知服务商企业租户的购买行为,服务商可以根据收到的购买租户的tenantId获得访问令牌,初始化租户信息等操作。该事件同时会推送相关的订单信息,服务商可根据需求进行解析。
推送方式与ticket推送方式一致,只是解密后的消息体不同,示例消息体:
{
"type": "SUITE_AUTH",
"eventId": "033af2b1-96c0-4cc2-8991-3abe42aa3d0b",
"timestamp": 1540436622537,
"suiteKey": "82869879-6f5a-492a-983b-0fecd0e3db9c",
"authTenantId": "bshzbsd5",
"order": {
"email": "test@yonyou.com",
"expiredOn": 1545708505000,
"lease": 1,
"mobile": "18811116666",
"newBuy": false,
"orderId": "19741540438149078239",
"orderSkuId": "21b6f002-4071-4025-a981-b4dc99caad10",
"productName": "测试协同云",
"resCode": "diwork",
"skuName": "1.0",
"ts": 1540438152000,
"userId": "abc4a6d6-a5fa-45ae-8161-68fba6f0fabc",
"appCode": "open_12345481454161",
"appName": "测试协同云"
}
}
字段说明:
字段 | 类型 | 说明 |
---|---|---|
type | string | 事件类型,对于推送授权事件,其类型为SUITE_AUTH |
eventId | string | 事件 uuid |
timestamp | Long | 事件创建的 unix 时间戳 |
sutieKey | string | 应用的appKey |
authTenantId | string | 授权租户的 tenantId |
order | object | 与授权事件相关的订单信息 |
order.email | string | 购买用户的 email |
order.expiredOn | Long | 产品开通有效期截止时间 unix 时间戳 |
order.lease | Integer | 产品开通的租期,单位为月 |
order.mobile | string | 购买用户的手机 |
order.newBuy | boolean | 是否新购,即是首次购买该产品还是续期 |
order.orderId | string | 用户下单的订单号 |
order.orderSkuId | string | 商品的 sku id |
order.productName | string | 商品名称 |
order.resCode | string | 订单来源,diwork购买的此处为"diwork", 测试企业授权事件此处为"open-test" |
order.skuName | string | sku 名称 |
order.ts | Long | 订单时间戳 |
order.userId | string | 购买用户的友户通 id |
order.appCode | string | 应用的编码 |
order.appName | string | 应用的名称 |
注意:
- order 对象为订单信息,通常情况 ISV 不需要解析该字段,ISV 可根据实际业务选择是否解析该字段。
- order.expireOn 计算方式为: 当前时间 + lease * month, 如果 order.newBuy = false,即非新购,还需要加上当前剩余有效期。
- 推送超时为2秒,如需要进行复杂业务处理请异步进行。若推送失败,开放平台会重试推送,每分钟重试一次,直到重试60次。
- 接收到订单信息后,会通过返回值判断应用的开通状态,
- 如果直接开通则返回:"SUCCESS",
- 如果需要线下实施则返回状态:"AUTHING",当线下实施完成,可通过控制台 应用订单开通 功能,开通该订单
四、获得调用接口令牌access_token
调用接口令牌 access_token 是应用调用开放平台业务接口的凭证,有效期为2小时。获得方式为主动调用开放平台的令牌授权接口,该接口说明如下:
` | ` |
---|---|
请求地址 | https://api.diwork.com/open-auth/suiteApp/getAccessToken |
请求方法 | GET |
请求参数:
字段 | 类型 | 说明 |
---|---|---|
suiteKey | string | 应用appKey |
suiteTicket | string | 应用Ticket |
tenantId | string | 购买者租户的tenantId |
timestamp | string | 时间戳 |
signature | string | 校验签名,HmacSHA256,加签方式看下文 |
加签方式
签名字段signature计算使用HmacSHA256,具体计算方式如下:
URLEncode( Base64( HmacSHA256( parameterMap ) ) )
其中,parameterMap 按照参数名称排序,参数名称与参数值依次拼接(signature字段除外),形成待计算签名的字符串。之后对 parameterMap 使用 HmacSHA256 计算签名,Hmac 的 key 为的 suiteSecret 。计算出的二进制签名先进行 base64,之后进行 urlEncode,即得到 signatrue 字段的值。
具体请求方式请参考
ISV接入Demo
返回参数说明:
字段 | 类型 | 说明 |
---|---|---|
code | string | 结果码,正确返回 "00000" |
message | string | 结果信息,若有错误,该字段会返回具体错误信息 |
data.access_token | string | 接口令牌 access_token |
data.expire | Integer | 有效期,单位秒 |
返回数据
{
"code": "00000",
"message": "成功!",
"data": {
"access_token": "b8743244c5b44b8fb1e52a55be7e2f",
"expire": 7200
}
}
五、API接入申请
【新增API】按钮,包括【用友开放API】、【服务商开放API】、【内部API】,点击【用友开放API】按钮,弹出窗口打开【新增API授权】页面,选择要授权的API分类
用友开放API:是用友OpenAPI开放的接口
服务商开放API:是服务商新增的接口,并发布到了OpenAPI开放平台
内部API:是自己新增的接口,并没有发布
- 进入应用的API授权页面,选择自己将要授权的API,点击“确定”
接口调用的url、方式、入参及返回值,可以查看开发平台接口的具体调用调用文档
为后面第五节学习调用一个业务接口做准备