概述及资源

环境需求

条目 资源
开发目标 iOS8+
开发环境 Xcode 10
系统依赖 libc++.1.tbdlibz.1.2.8.tbd
SDK 三方依赖 account_login_sdk_noui_core.frameworkEAccountApiSDK.frameworkTYRZSDK.frameworkTYRZResource.bundle

相关开发资料

条目 资源
产品结构流程 交互流程, 通讯流程
接口文档 OneLogin iOS API Ref 或查看头文件注释
错误码 Error Code 列表

安装

获取 SDK 及 Demo

下载获取

点击下载

导入 SDK 到项目工程并配置开发环境

  1. 将下载获取的OneLogin.framework, account_login_sdk_noui_core.frameworkEAccountApiSDK.frameworkTYRZSDK.framework以及在OneLoginResource.bundleTYRZResource.bundle共6个文件添加到工程中, 确保Copy items if needed已被勾选。

    此外, 需要添加libc++.1.tbdlibz.1.2.8.tbd库进行依赖。

    添加完后, 以Linked Frameworks and Libraries方式导入 framework。在拖入OneLogin.framework, account_login_sdk_noui_core.frameworkEAccountApiSDK.frameworkTYRZSDK.framework到工程后, 请检查所有的.framework是否被添加到PROJECT -> Build Phases -> Linked Frameworks and Libraries, 以确保正常编译。

    linkedlibraries

  2. 针对静态库中的Category, 需要在对应 target 的Build Settings->Other Linker Flags添加-ObjC编译选项。如果依然有问题,再添加-all_load

    linkerflags

  3. 目前运营商个别接口为http请求,对于全局禁用http的项目,需要设置http白名单。以下为运营商http接口域名和ip名单:cmpassport.com、id6.me、mdn.open.wo.cn。配置ATS,在 info.plist 文件中添加 App Transport Security Settings 项,并在其中添加 Exception Domains 子项,设置如下:

    linkerflags

Cocoapods安装

执行pod repo update更新

Podfile里面添加一行

# 具体版本号可先执行pod search GTOneLoginSDK,根据返回的版本信息自行决定
pod 'GTOneLoginSDK', '~> 1.7.0'

执行pod install即可,若未执行pod repo update,请执行pod install –repo-update

Demo请到Github上查看

配置接口

开发者集成客户端 SDK 前, 必须先在您的服务器上搭建相应的服务端获取登录信息的接口,并配置从极验后台获取的AppID。这里以服务端配置成功,客户端开发步骤为例,如下:

1. 用 AppID 注册 OneLogin

[OneLogin registerWithAppID:@"---<申请的AppID>---"];

2. 调用预取号接口

预取号,从回调中可以获取到预取号是否成功的状态

[OneLogin preGetTokenWithCompletion:^(NSDictionary * _Nonnull sender) {
NSLog(@"sender: %@", sender.description);
}];

3. 调用取号接口

开发者在完成预取号后, 通过该接口获取用于获取该用户手机号信息的访问令牌, 使用该访问令牌去查询用户的手机号及相关信息

[OneLogin requestTokenWithViewController:self viewModel:viewModel completion:^(NSDictionary * _Nullable result) {
NSNumber *status = [result objectForKey:@"status"];
if ([@(200) isEqualToNumber:status]) { // 获取token成功
// TO-DO
// 校验和获取登录的用户的数据

}
else {
NSLog(@"result: %@", result);
}
}];

预取号接口调用时机

  1. 为优化用户体验,建议在AppDelegate的 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 方法中就进行预取号,预取号接口会返回预取号拿到的token的有效时长,keyexpire_time,在有效时长内,可不必重复进行预取号;
  2. 另外,首次安装APP时,网络是未开启的,在AppDelegate中无法预取号成功,故,在需要进入授权页面的页面的viewDidLoad中也需要进行预取号;
  3. 拿到预取号结果之后,可本地记录一个preGetToken成功的时间,在调用 requestTokenWithViewController方法之前,可根据当前时间与preGetToken成功的时间的差值是否大于预取号拿到的token的有效时长来判断是否需要重新预取号,或者,您也可以直接使用SDK提供的方法isPreGettedTokenValidate来判断是否需要重新预取号,具体实现方式请参考Demo
  4. 对于preGetToken有效期的判断,推荐直接使用SDK的isPreGettedTokenValidate方法

集成代码参考下方的代码示例。更进一步的示例, 见相关Demo。

代码示例

在工程中的文件头部导入静态库 OneLoginSDK.framework

#import <OneLoginSDK/OneLoginSDK.h>

注册及预取号

在相应的控制页初始化方法中对OneLoginSDK实例调用注册方法:

[OneLogin registerWithAppID:@"---<申请的AppID>---"];

预取号

在每次获取免密登录的token之前, 需要调用预取号接口

[OneLogin preGetTokenWithCompletion:^(NSDictionary * _Nonnull sender) {
NSLog(@"sender: %@", sender.description);
NSNumber *status = [sender objectForKey:@"status"];
if (status && [@(200) isEqualToNumber:status]) {
// 预取号成功

}
else {
#warning 请处理预取号的错误, 更多错误码请参考错误码文档
NSString *errCode = [sender objectForKey:@"errorCode"];
NSString *msg = [sender objectForKey:@"msg"];
NSString *processID = [sender objectForKey:@"processID"];
NSString *appID = [sender objectForKey:@"appID"];
NSString *operator = [sender objectForKey:@"operatorType"];

NSLog(@"[Operator: %@] - [Error Code: %@] - [Message: %@] - [ProccesID: %@] - [APPID: %@]", operator, errCode, msg, processID, appID);

// 预取号失败
if ([@"-20101" isEqualToString:errCode]) {
// TO-DO
// 未配置 AppID,请通过 registerWithAppID: 配置 AppID
}
else if ([@"-20102" isEqualToString:errCode]) {
// TO-DO
// 重复调用 preGetTokenWithCompletion:
}
else if ([@"-20202" isEqualToString:errCode]) {
// TO-DO
// 检测到未开启蜂窝网络
}
else if ([@"-20203" isEqualToString:errCode]) {
// TO-DO
// 不支持的运营商类型
}
else {
// TO-DO
// 其他错误类型
}
}
}];

获取免密登录 token 并使用 token 获取用户登录信息

通过requestTokenWithViewController:viewModel:completion:获取免密登录token后, 在使用token获取用户登录信息。在此过程中, 需要设置UIViewController, 以展示授权页面, 并让用户接受使用条款

自定义部分见Demo和接口文档

- (void)requestToken {
OLAuthViewModel *viewModel = [[OLAuthViewModel alloc] init];
// TO-DO 自定义viewModel
// viewModel...

[OneLogin requestTokenWithViewController:self viewModel:viewModel completion:^(NSDictionary * _Nullable result) {
NSLog(@"token result: %@", result);
NSNumber *status = [result objectForKey:@"status"];
if ([@(200) isEqualToNumber:status]) {
// TO-DO
// 获取到token, 并进行手机号查询
NSString *processID = [result objectForKey:@"processID"];
NSString *appID = [result objectForKey:@"appID"];
NSString *token = [result objectForKey:@"token"];

[self validateTokenAndGetLoginInfo:token appID:appID processID:processID];
}
else {
#warning 请处理获取token的错误, 更多错误码请参考错误码文档
NSString *errCode = [result objectForKey:@"errorCode"];
NSString *msg = [result objectForKey:@"msg"];
NSString *processID = [result objectForKey:@"processID"];
NSString *appID = [result objectForKey:@"appID"];
NSString *operator = [result objectForKey:@"operatorType"];

// 获取网关token失败
if ([@"-20103" isEqualToString:errCode]) {
// TO-DO
// 重复调用 requestTokenWithViewController:viewModel:completion:
}
else if ([@"-20202" isEqualToString:errCode]) {
// TO-DO
// 检测到未开启蜂窝网络
}
else if ([@"-20203" isEqualToString:errCode]) {
// TO-DO
// 不支持的运营商类型
}
else if ([@"-20204" isEqualToString:errCode]) {
// TO-DO
// 未获取有效的 `accessCode`, 请确保先调用过 preGetTokenWithCompletion:
}
else if ([@"-20302" isEqualToString:errCode]) {
// TO-DO
// 用户点击了授权页面上的返回按钮, 授权页面将自动关闭
}
else if ([@"-20303" isEqualToString:errCode]) {
// TO-DO
// 用户点击了授权页面上的切换账号按钮, 授权页面不会自动给关闭。如需关闭, 需调用 [OneLogin dismissAuthViewController]。
}
else {
// TO-DO
// 其他错误类型
}

NSLog(@"[Operator: %@] - [Error Code: %@] - [Message: %@] - [ProccesID: %@] - [APPID: %@]", operator, errCode, msg, processID, appID);

// 一键登录失败手动关闭授权页面
[OneLogin dismissAuthViewController];
}
}];
}

// 使用token进行校验, 并获取用户的登录信息
- (void)validateTokenAndGetLoginInfo:(NSString *)token appID:(NSString *)appID processID:(NSString *)processID {

// 根据用户自己接口构造
// 下面以POST, application/json 为例
NSURL *url = [NSURL URLWithString:@"---<您的校验接口地址>---"];

NSMutableURLRequest *mRequest = [[NSMutableURLRequest alloc] initWithURL:url cachePolicy:(NSURLRequestCachePolicy)0 timeoutInterval:10.0];

NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
[params setValue:processID forKey:@"process_id"];
[params setValue:appID forKey:@"id_2_sign"];
[params setValue:token forKey:@"token"];

NSData *data = [NSJSONSerialization dataWithJSONObject:params options:(NSJSONWritingOptions)0 error:nil];

mRequest.HTTPMethod = @"POST";
mRequest.HTTPBody = data;

[[[NSURLSession sharedSession] dataTaskWithRequest:mRequest
completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
// TO-DO
// 处理用户信息
NSLog(@"result data: %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
}] resume];

}

更详细示例代码见 Demo

更详细的接口说明见接口文档或 SDK 头文件