应用快速接入与单点登录指南

WorkPlus是企业移动通信平台和企业移动应用平台的统一,它作为企业移动应用的统一入口,支持各种轻应用和原生应用的接入。各种应用在WorkPlus平台注册之后会出现在WorkPlus移动端的应用中心,供用户安装和访问。应用可以以当前登录用户的身份访问WorkPlus平台以RESTful Web Service的形式发布出来的功能API,获得消息收发、企业通信录访问等能力。

WorkPlus平台API受OAuth 2.0协议保护。要能够通过REST访问WorkPlus平台,需要经过下面的步骤:

  1. 由WorkPlus系统管理员登录到WorkPlus管理平台注册应用,生成AppKey和AppSecret;
  2. 从WorkPlus移动端获取tenant_id;
  3. 使用AppKey、AppSecret和tenant_id从WorkPlus平台获取access_token,作为应用的身份凭证;
  4. 获取WorkPlus移动端当前登录用户的标识,实现单点登录(可选)
  5. 以access_token为查询参数,访问平台API。

其中第1步是一次性的,仅在应用注册到平台时一次性生成AppKey和AppSecret(per app);第2、3、4步频率高一些,每次应用登录到WorkPlus平台时均需申请一个新的access_token(per session);第5步频率最高,应用对WorkPlus的每次REST访问都需要传入access_token(per request)。

下面详细论述各个步骤。

第一步:到WorkPlus管理平台注册应用,生成AppKey和AppSecret

如果你的应用要能够接入WorkPlus,出现在WorkPlus应用中心,必须首先由WorkPlus系统管理员在WorkPlus管理平台注册你的应用,生成AppKey和AppSecret。AppKey代表应用的标识,AppSecret代表应用的凭证,这两者可以分别类比个人用户的username和password。

获取AppKey和AppSecret

应用开发者从WorkPlus系统管理员那里获取AppKey和AppSecret之后,应保存起来,使得应用代码可以使用它们登录到WorkPlus。

第二步:从WorkPlus移动端获取tenant_id

WorkPlus是个支持多租户的云平台,每个租户(对应于WorkPlus云平台的一个客户,通常是一个公司或其他组织)通过唯一的tenant_id标识,在WorkPlus上拥有和管理它自己的组织机构、人员和应用。移动应用登录到WorkPlus平台以访问平台API时,必须提供tenant_id给平台进行验证和关联。

在为每个租户生成WorkPlus移动端App时会将该租户的tenant_id一并打包,因此,部署在应用中心中的轻应用和原生应用就可以通过与WorkPlus移动端的交互获取该tenant_id。

Android原生应用

在Launcher Activity的onCreate()方法中,通过

String tenantId = getIntent().getStringExtra("KEY_TENANT_ID");

获取tenant_id。

iOS原生应用

在AppDelegate类的

(BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url

方法中这样提取tenant_id:

//url结构
//[Scheme]&ticket=[ticket]&tenantId=[tenantId]
//[Scheme]:后台添加版本时输入的跳转协议    
//[ticket]: ticket的值    
//[tenantId]: tenant_id    
//获取url里面的参数部分    
NSString *text = [[url query] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];        
//然后按url参数的方式去解析,先找“&”    
NSArray *arr = [text componentsSeparatedByString:@"&"];        
//然后查找以ticket开头的字段    
for (int i = 0; i < arr.count; i ++) {
    NSString* str = [arr objectAtIndex:i];
    if ([str hasPrefix:@"tenantId"]) {
        //然后再按“=”拆分       
        NSArray *array = [str componentsSeparatedByString:@"="];
        NSString *tenantId = [array objectAtIndex:1];
        NSLog(@"%@", tenantId);
    }
}

tenantId变量的值就是要提取的tenant_id

轻应用

轻应用可以直接访问WorkPlus的Cordova接口获取tenant_id。

(1)在页面中引用Cordova.js:

<script src="applocal://www/cordova.js"></script>

(2)代码这样调用:

cordova.exec(
    function(result) {
        console.log("获取tenant_id成功");
    }, 
    function(error) { 
        console.log("获取tenant_id失败");
    }, 
    "WorkPlus_Auth", 
    "getTenantId",
    []
);

(3) 如果没有异常,result就是调用getTenantId()接口的结果:

{"tenant_id": "1434132518343254"}

tenant_id就是“1434132518343254”。

第三步:使用AppKey、AppSecret和tenant_id获取access_token

应用启动时,使用AppKey、AppSecret和tenant_id通过REST方式登录到API服务器,换取access_token.

POST https://api.workplus.io/token

(如果您的WorkPlus是私有化部署,请根据实际情况修改API服务器的域名/IP和端口)

参数是个JSON对象:

{
    "grant_type": "client_credentials",
    "scope" : "app",
    "tenant_id" : "租户ID",
    "client_id" : "appKey",
    "client_secret" : "appSecret"
}

其中:

  • grant_type属性:必须是"client_credentials"。
  • scope属性:必须是"app"。
  • tenant_id属性:填写你的租户标识(上文第二步中获得的)。
  • client_id属性:填写应用的AppKey。
  • client_secret属性:填写应用的AppSecret.

另外,需要设置HTTP Header:

Content-Type="application/json"

如果AppKey和AppSecret是正确的,系统会返回一个JSON对象:

{
    "status": 0,
    "message": "Everything is ok.",
    "result": {
        "access_token": "token",
        "issued_time": "token创建时间",
        "expire_time": "token过期时间"
    }
}

从结果JSON对象的"result"属性(代表另一个JSON对象)中提取“access_token”属性,保存起来备用,这就是你本次会话的access_token。

说明:

“expire_time”是这个access_token的过期时间。这个时间之后,access_token就会失效。应用必须重新登录到WorkPlus API服务器,获取新的access_token。

第四步:获取WorkPlus移动端当前登录用户的标识,实现单点登录(可选)

WorkPlus移动端的应用中心中的大部分应用,往往需要和WorkPlus用户系统集成。当用户登录WorkPlus移动端之后,访问应用中心中的移动应用时,后者可以自动识别当前用户,而不需要在应用中重新登录一次。应用此后的操作都以当前用户的身份进行。

WorkPlus实现单点登录的机制是:当用户在WorkPlus应用中心中点击打开原生应用时,WorkPlus会自动为当前登录用户生成一个ticket,移动应用可以将这个ticket和传递到后台验证其合法性,如果ticket是合法的,系统将返回当前登录用户的身份标识。

在应用代码中,实现单点登录获取当前用户标识的具体步骤是:

  1. 获取ticket;
  2. 向后台验证ticket有效性,获取当前用户标识。

具体描述如下:

1. 获取ticket

iOS、Android和轻应用获取ticket的方式各不相同。

Android原生应用

在Launcher Activity的onCreate()方法中,通过

String ticket = getIntent().getStringExtra("KEY_USER_TICKET")

获取ticket。

iOS原生应用

在AppDelegate类的

(BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url

方法中这样提取ticket:

//url结构:
//[Scheme]&ticket=[ticket]&tenantId=[tenantId]
//[Scheme]:后台添加版本时输入的跳转协议
//[ticket]: ticket的值
//[tenantId]: tenant_id
//获取url里面的参数部分
NSString *text = [[url query] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
//然后按url参数的方式去解析,先找“&”
NSArray *arr = [text componentsSeparatedByString:@"&"];
//然后查找以ticket开头的字段
for (int i = 0; i < arr.count; i ++) {
    NSString* str = [arr objectAtIndex:i];
    if ([str hasPrefix:@"ticket"]) {
        //然后再按“=”拆分
        NSArray *array = [str componentsSeparatedByString:@"="];
        NSString *ticket = [array objectAtIndex:1];
        NSLog(@"%@", ticket);
    }
}

ticket变量的值就是要提取的用户ticket。

轻应用

轻应用可以直接访问WorkPlus的Cordova接口获取ticket。

(1)在页面中引用Cordova.js:

<script src="applocal://www/cordova.js"></script>

(2)代码这样调用:

cordova.exec(
    function(result) {
        console.log("获取ticket成功");
    },
    function(error) { 
        console.log("获取ticket失败");
    }, 
    "WorkPlus_Auth", 
    "getUserTicket",
    []
);

(3) 如果没有异常,result就是调用getUserTicket()接口的结果:

{"user_ticket": "1434132514343214"}

ticket内容就是“1434132514343214”。

2. 验证ticket有效性,获取当前用户标识

iOS、Android原生应用和轻应用验证ticket并获取当前用户标识的方式基本相同,都是将ticket传送到后台,验证其合法性。如果该ticket确实存在,后台将返回当前用户身份标识和其他相关信息。

URL:

GET https://api.workplus.io/ticket/[ticket]?access_token=[access_token]

用你的ticket和access_token(从上面第三步获取)分别替换上面url的[ticket]和[access_token]占位符。如果您的WorkPlus是私有化部署,请根据实际情况修改API服务器的域名/IP和端口。

返回结果是一个JSON对象:

{
    "status": 0,
    "message": "Everything is ok.",    
    "result": {
        "tenant_id": 租户ID,
        "client_id": 当前登录用户名,
        "device_id": 设备ID
    }
}

result中的client_id就是当前登录用户的用户名。

最后一步:使用access_token访问平台API

获得access_token之后,应用就可以使用它作为查询参数,以REST的方式访问WorkPlus的平台API。

WorkPlus RESTful API统一以JSON对象作为参数对象和返回值。在下面的例子中,当需要POST或PUT一个REST资源时,都需要设置HTTP Header参数:

Content-Type="application/json"

基本上,对每个WorkPlus API访问的返回值都是一个JSON对象。该对象拥有下述属性:

  • status属性:用正整数代表的调用结果状态。0代表一切正常,不同的非0值代表发生了不同的异常情况。
  • message属性:对调用结果的文字性描述,如果调用正常,则内容是“Everything is ok.”;如果调用异常,则描述具体的异常消息。
  • result属性:通常是一个JSON对象,代表调用正常的情况下返回的真实结果。

下面是一些例子(记得将“:access_token”替换为第二步获得的access_token,如果您的WorkPlus是私有化部署,请根据实际情况修改API服务器的域名/IP和端口):

例子1:发送文本消息

如果要向用户zhangsan和lisi发送文本消息,POST到/app/mbox资源:

POST https://api.workplus.io/app/mbox?access_token=:access_token

(如果您的WorkPlus是私有化部署,请根据实际情况修改API服务器的域名/IP和端口)

参数JSON对象:

{
    "type": "TEXT",
    "body": {
        "content": "你好!"
    },
    "client_ids": ["zhangsan", "lisi"]
}

如果一切正常,服务器将返回下述JSON对象:

{
    "status": 0,
    "message": "Everything is ok.",
    "result": {
        "id": "推送计划ID",
        "app_id": "应用id",
        "tenant_id": "租户id",
        "material_id": "",
        "expects": "",
        "fails": "",
        "oks": "",
        "create_time": "创建时间",
        "refresh_time": "刷新时间",
        "expect_time": ""
    }
}

例子2:发送图文消息

如果要向用户zhangsan和lisi发送图文消息,POST到/app/mbox资源:

POST https://api.workplus.io/app/mbox?access_token=:access_token

参数JSON对象:

{
    "type": "ARTICLE",
    "body": {
        "articles": 
            [
                {
                    "url" : "文章打开地址",
                    "show_cover" : true,
                    "cover_url" : "图文封面图片url",
                    "summary" : "文章摘要",
                    "create_time" : 1433314282603,
                    "content_source" : "文章原文链接",
                    "author" : "文章作者",
                    "sort" : 0,
                    "title" : "文章标题",
                    "content" : "<p>文章内容</p>"
                }
            ]
    },
    "client_ids": ["zhangsan", "lisi"]
}

如果一切正常,服务器将返回下述JSON对象:

{
    "status": 0,
    "message": "Everything is ok.",
    "result": {
        "id": "推送计划ID",
        "app_id": "应用id",
        "tenant_id": "租户id",
        "material_id": "",
        "expects": "",
        "fails": "",
        "oks": "",
        "create_time": "创建时间",
        "refresh_time": "刷新时间",
        "expect_time": ""
    }
}

例子3:获取机构信息

GET https://api.workplus.io/organization/:org_id?access_token=:access_token

如果一切正常,服务器将返回下述JSON对象:

{
    "status": 0,
    "message": "Everything is ok.",
    "result": {
    "tenant_id" : "租户标识",
    "id" : "机构标识",
    "name" : "名字",
    "sn" : "机构编号",
    "tel" : "电话号码",
    "serial_no" : "机构唯一序列号(比如第三方的系统标识)",
    "path" : "路径",
    "type" : "类型[公司(CORP), 部门(DEPT)]",
    "root" : "是否是根公司",
    "created" : "创建时间",
    "last_modified" : "最后修改时间",
    "expired" : "过期时间",
    "disabled" : "是否有效",
    "parent_org_id" : "父机构标识",
    "parent_org_name" : "父机构名称",
    "root_comId" : "根机构标识",
    "root_comName" : "根机构名称",
    "sort_order" : "排序号"
}

results matching ""

    No results matching ""