概述及资源

本文是 OneLogin iOS SDK 的部署文档,用于指导 OneLogin iOS SDK 的集成,读者需具有一定 iOS 编程知识基础。

1、环境需求

条目 资源
开发目标 iOS8+
开发环境 Xcode 11+
系统依赖 libc++.1.tbdlibz.1.2.8.tbd
SDK 三方依赖 account_login_sdk_noui_core.frameworkEAccountApiSDK.frameworkTYRZSDK.framework
包增量 1M
网络制式 移动 2G/3G/4G,联通 3G/4G,电信 4G(2G/3G 网络下时延相对较高,成功率相对较低)
网络环境 打开蜂窝数据流量并且给予应用蜂窝数据权限

2、相关开发资料

条目 资源
产品结构流程 交互流程通讯流程
常见问题 常见问题
SDK 资源包 点击下载
SDK 当前版本 2.1.4
Tips:1.8.0(不含)以下版本升级到最新版本,服务端接口必须一同调整,否则会导致电信取号失败

准备工作

1、创建应用

登录极验后台创建应用获取 APPID 和 Key,具体步骤可参照账号创建。

2、快速体验 Demo

iOS 压缩包附带的 OneLoginExample 文件夹中是极验的示例工程,使用 Xcode 打开示例工程,修改 BundleID 和 AppId 为创建应用时绑定的 BundleID 和 AppId。

若体验 OneLogin(一键登录),请修改手机号获取接口 http://onepass.geetest.com/onelogin/result 为您自己搭建的服务接口,然后运行即可进行体验。

若体验 OnePass(本机号码认证),请修改本机号码认证接口 http://onepass.geetest.com/v2.0/result 为您自己搭建的服务接口 ,然后运行即可进行体验。

注:如未完成服务端搭建,则只能体验APP端功能,不能获取真实手机号。

3、开发环境搭建

3.1、CocoaPods 集成

执行pod repo update更新。

Podfile 里面添加以下代码:

# 以下两种版本选择方式示例

# 集成最新版极验 SDK:
pod 'GTOneLoginSDK'

# 集成指定版本极验 SDK,具体版本号可先执行 pod search GTOneLoginSDK,根据返回的版本信息自行决定:
pod 'GTOneLoginSDK', '~> 2.1.0'

保存并执行pod install即可,若未执行pod repo update,请执行pod install --repo-update

3.2、手动集成

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

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

添加完后, 以 Linked Frameworks and Libraries 方式导入 framework。

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

linkedlibraries

3.3、工程配置

  1. 针对静态库中的 Category, 需要在对应 target 的 Build Settings->Other Linker Flags 添加 -ObjC 编译选项。

    linkerflags

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

    linkerflags

可以直接打开 Demo 的 Info.plist 文件,将对应 xml 代码拷贝至您自己的工程的 Info.plist 文件中,如下:

<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>wap.cmpassport.com</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSAllowsArbitraryLoadsInWebContent</key>
<true/>
</dict>
<key>id6.me</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSAllowsArbitraryLoadsInWebContent</key>
<true/>
</dict>
<key>mdn.open.wo.cn</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSAllowsArbitraryLoadsInWebContent</key>
<true/>
</dict>
<key>onepass.geetest.com</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>

OneLogin (一键登录)


进阶模式和常规模式是一键登录的两种调用逻辑,如无特别需求建议直接使用进阶模式,两模式不可混合调用。

1、进阶模式

预取号逻辑封装在 SDK 内部,开发者只需控制授权页拉起时机。SDK 内部处理预取号的逻辑,包括预取号超期后的重新预取号,以及弱网状态下的重试等。使用这种方式时,请使用 OneLoginPro 类中的方法

1.1、初始化

方法原型

/**
向SDK注册AppID

@discussion `AppID`通过后台注册获得,从极验后台获取该AppID,AppID需与bundleID配套

@param appID 产品ID
*/
+ (void)registerWithAppID:(NSString *)appID;

参数描述

参数 是否必填 类型 说明
appID NSString 极验 appID

接口作用

传入极验 appID,并开始预取号

使用场景

  • 保证在拉起授权页面前至少调用一次,建议在应用启动时或进入登录页面的前一个页面调用该方法

  • 只需调用一次,多次调用不会多次初始化,与一次调用效果一致

示例代码

ObjC:

  1. 导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 在 UIViewController 的 viewDidLoad 方法中添加初始化代码

- (void)viewDidLoad {
[super viewDidLoad];
// 设置AppId,AppID通过后台注册获得,从极验后台获取该AppID,AppID需与bundleID配套
[OneLoginPro registerWithAppID:GTOneLoginAppId];
}

Swift:

  1. 创建混编桥接头文件并导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 在 UIViewController 的 viewDidLoad 方法中添加初始化代码

override func viewDidLoad() {
super.viewDidLoad()
// 设置AppId,AppID通过后台注册获得,从极验后台获取该AppID,AppID需与bundleID配套
OneLoginPro.register(withAppID: GTOneLoginAppId)
}

1.2、进入授权页面

方法原型

/**
进行用户认证授权, 获取网关 token 。

@discussion 调用限制说明

为避免授权页面多次弹出, 在调用该方法后, 授权页面弹出, 再次调用该方法时,
该方法会直接跳出, 不执行授权逻辑。

@discussion 需要用户在弹出的页面上同意服务意条款后, 才会进行免密认证。

@param viewController present 认证页面控制器的 vc
@param viewModel 自定义授权页面的视图模型
@param completion 结果处理回调

@seealso OLAuthViewModel

*/
+ (void)requestTokenWithViewController:(nullable UIViewController *)viewController
viewModel:(nullable OLAuthViewModel *)viewModel
completion:(void(^)(NSDictionary * _Nullable result))completion;

参数描述

参数 是否必填 类型 说明
viewController UIViewController 进入授权页面的上一级页面
viewModel OLAuthViewModel 授权页面UI配置参数
completion void(^)(NSDictionary * _Nullable result) 获取token回调

接口作用

拉起授权页面,用户在授权页面点击一键登录,即可获取 token,拿该 token 即可换取对应的手机号

使用场景

  • 用户进行一键登录操作时调用该方法,如果初始化成功SDK 将会拉起授权页面

  • 可以在多处调用

  • 需在调用初始化方法之后调用

示例代码

ObjC:

  1. 导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 在需要使用一键登录的地方调用极验一键登录接口

- (IBAction)normalLoginAction:(UIButton *)sender {
OLAuthViewModel *viewModel = [OLAuthViewModel new];
[OneLoginPro requestTokenWithViewController:self viewModel:viewModel completion:^(NSDictionary * _Nullable result) {
NSLog(@"OneLoginPro requestTokenWithViewController result: %@", result);
}];
}

Swift:

  1. 创建混编桥接头文件并导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 在需要使用一键登录的地方调用极验一键登录接口

@IBAction func normalLoginAction(_ sender: UIButton) {        
let viewModel = OLAuthViewModel()
// 进入授权页面
OneLoginPro.requestToken(with: self, viewModel: viewModel) { [weak self] result in
}
}

1.3、手动关闭授权页面

方法原型

/**
@abstract 关闭当前的授权页面

@param animated 是否需要动画
@param completion 关闭页面后的回调

@discussion
请不要使用其他方式关闭授权页面, 否则可能导致 OneLogin 无法再次调起
*/
+ (void)dismissAuthViewController:(BOOL)animated completion:(void (^ __nullable)(void))completion;

参数描述

参数 是否必填 类型 说明
animated BOOL 关闭授权页面时是否需要动画
completion void(^)(void) 关闭授权页面后的回调

接口作用

当开发者设置点击一键登录或者自定义控件不自动销毁授权页时,将需要自行调用此方法主动销毁授权页,建议在置换手机号成功后销毁,请不要使用其他方式关闭授权页面

关闭授权页面时机

  • 在授权页面点击切换账号按钮时

  • 在授权页面点击一键登录按钮收到 requestToken 结果回调之后

示例代码

ObjC:

  1. 导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 在需要关闭授权页面的地方调用极验关闭授权页面接口

- (void)dismissAuthVC {
[OneLoginPro dismissAuthViewController:nil];
}

Swift:

  1. 创建混编桥接头文件并导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 在需要关闭授权页面的地方调用极验关闭授权页面接口

@objc func dismissAuthVC(_ sender: UIButton) {
OneLoginPro.dismissAuthViewController {

}
}

1.4、重新开始预取号

方法原型

/**
* @abstract 重新预取号
*
* @discussion 在通过requestTokenWithCompletion方法成功登录之后,为保证用户在退出登录之后,能快速拉起授权页面,请在用户退出登录时,调用此方法
*/
+ (void)renewPreGetToken;

接口作用

在 SDK 初始化之后,调用requestTokenWithCompletion获取 token 之前,SDK 内部会一直维护预取号的结果,但是在调用requestTokenWithCompletion获取 token 之后,就不再维护预取号结果了,调用该接口,就会重新开始预取号,并维持预取号结果有效,以保证在用户退出登录之后再次登录时能快速进入授权页面

调用时机

  • 建议在用户退出登录时调用该接口

示例代码

ObjC:

  1. 导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 重新预取号

[OneLoginPro renewPreGetToken];

Swift:

  1. 创建混编桥接头文件并导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 重新预取号

OneLoginPro.renewPreGetToken()

1.5、判断预取号结果是否有效

方法原型

/**
* @abstract 判断预取号结果是否有效
*
* @return YES: 预取号结果有效,可直接拉起授权页面 NO: 预取号结果无效,需加载进度条,等待预取号完成之后拉起授权页面
*/
+ (BOOL)isPreGetTokenResultValidate;

接口作用

判断预取号结果是否有效

调用时机

  • 调用requestTokenWithCompletion时,判断是否需要加载进度条

示例代码

ObjC:

  1. 导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 判断预取号结果是否有效

// 在SDK内部预取号未成功时,建议加载进度条
if (![OneLoginPro isPreGetTokenResultValidate]) {
[GTProgressHUD showLoadingHUDWithMessage:nil];
}
[OneLoginPro requestTokenWithViewController:self viewModel:viewModel completion:^(NSDictionary * _Nullable result) {
NSLog(@"OneLoginPro requestTokenWithViewController result: %@", result);
}];

Swift:

  1. 创建混编桥接头文件并导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 判断预取号结果是否有效

// 进入授权页面
if !OneLoginPro.isPreGetTokenResultValidate() {
GTProgressHUD.showLoadingHUD(withMessage: nil)
}

OneLoginPro.requestToken(with: self, viewModel: viewModel) { [weak self] result in
if let strongSelf = self {
strongSelf.finishRequsetingToken(result: result!)
}
sender.isEnabled = true
}

2、常规模式

预取号和授权页拉起时机均由开发者自主控制。使用此调用逻辑,开发者需自主处理预取号的时机和超期重试的逻辑等。使用这种方式时,请使用 OneLogin 类中的方法。

2.1、初始化

方法原型

/**
向SDK注册AppID

@discussion `AppID`通过后台注册获得,从极验后台获取该AppID,AppID需与bundleID配套

@param appID 产品ID
*/
+ (void)registerWithAppID:(NSString *)appID;

参数描述

参数 是否必填 类型 说明
appID NSString 极验 appID

接口作用

传入极验 appID,并开始预取号

使用场景

  • 保证在拉起授权页面前至少调用一次

  • 只需调用一次,多次调用不会多次初始化,与一次调用效果一致

示例代码

ObjC:

  1. 导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 在 UIViewController 的 viewDidLoad 方法中添加初始化代码

- (void)viewDidLoad {
[super viewDidLoad];
// 设置AppId,AppID通过后台注册获得,从极验后台获取该AppID,AppID需与bundleID配套
[OneLogin registerWithAppID:GTOneLoginAppId];
}

Swift:

  1. 创建混编桥接头文件并导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 在 UIViewController 的 viewDidLoad 方法中添加初始化代码

override func viewDidLoad() {
super.viewDidLoad()
// 设置AppId,AppID通过后台注册获得,从极验后台获取该AppID,AppID需与bundleID配套
OneLogin.register(withAppID: GTOneLoginAppId)
}

2.2、预取号

方法原型

/**
预取号接口

@discussion 调用限制说明

在调用该方法后, 未回调之前, 再次调用该方法时, 方法会直接跳出, 不执行预取号逻辑。

@discussion 预取号成功后存在的有效期

有效期内需要调用 `requestTokenWithViewController:viewModel:completion:`,
否则需要重新访问 `preGetTokenWithCompletion:`。 其中中国移动和中国电信有效期为 1 小时,
中国联通为 10 分钟。

@param completion 处理回调
*/
+ (void)preGetTokenWithCompletion:(void(^)(NSDictionary *sender))completion;

参数描述

参数 是否必填 类型 说明
completion void(^)(NSDictionary * _Nullable sender) 获取临时凭证回调

接口作用

可以提前获知当前用户的手机网络环境是否符合一键登录的使用条件,成功后将得到用于一键登录使用的临时凭证,默认的凭证有效期: 60 分钟(移动) / 60 分钟(电信) / 10 分钟(联通)

应用启动时或者进入登录页的前一个页面、用户登出时是调用该方法的时机

2.3、进入授权页面

方法原型

/**
进行用户认证授权, 获取网关 token 。

@discussion 调用限制说明

为避免授权页面多次弹出, 在调用该方法后, 授权页面弹出, 再次调用该方法时,
该方法会直接跳出, 不执行授权逻辑。

@discussion 需要用户在弹出的页面上同意服务意条款后, 才会进行免密认证。

@param viewController present 认证页面控制器的 vc
@param viewModel 自定义授权页面的视图模型
@param completion 结果处理回调

@seealso OLAuthViewModel

*/
+ (void)requestTokenWithViewController:(nullable UIViewController *)viewController
viewModel:(nullable OLAuthViewModel *)viewModel
completion:(void(^)(NSDictionary * _Nullable result))completion;

参数描述

参数 是否必填 类型 说明
viewController UIViewController 进入授权页面的上一级页面
viewModel OLAuthViewModel 授权页面UI配置参数
completion void(^)(NSDictionary * _Nullable result) 获取token回调

接口作用

拉起授权页面,用户在授权页面点击一键登录,即可获取 token,拿该 token 即可换取对应的手机号

调用该方法前建议先调用方法判断预取号是否成功

使用场景

  • 用户进行一键登录操作时调用该方法,如果初始化成功SDK 将会拉起授权页面

  • 可以在多处调用

  • 需在调用初始化方法之后且预取号成功之后

示例代码

ObjC:

  1. 导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 在需要使用一键登录的地方调用极验一键登录接口

- (IBAction)normalLoginAction:(UIButton *)sender {
OLAuthViewModel *viewModel = [OLAuthViewModel new];
[OneLogin requestTokenWithViewController:self viewModel:viewModel completion:^(NSDictionary * _Nullable result) {
NSLog(@"OneLoginPro requestTokenWithViewController result: %@", result);
}];
}

Swift:

  1. 创建混编桥接头文件并导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 在需要使用一键登录的地方调用极验一键登录接口

@IBAction func normalLoginAction(_ sender: UIButton) {        
let viewModel = OLAuthViewModel()
// 进入授权页面
OneLogin.requestToken(with: self, viewModel: viewModel) { [weak self] result in
}
}

2.4、手动关闭授权页面

方法原型

/**
@abstract 关闭当前的授权页面

@param animated 是否需要动画
@param completion 关闭页面后的回调

@discussion
请不要使用其他方式关闭授权页面, 否则可能导致 OneLogin 无法再次调起
*/
+ (void)dismissAuthViewController:(BOOL)animated completion:(void (^ __nullable)(void))completion;

参数描述

参数 是否必填 类型 说明
animated BOOL 关闭授权页面时是否需要动画
completion void(^)(void) 关闭授权页面后的回调

接口作用

当开发者设置点击一键登录或者自定义控件不自动销毁授权页时,将需要自行调用此方法主动销毁授权页,建议在置换手机号成功后销毁,请不要使用其他方式关闭授权页面

关闭授权页面时机

  • 在授权页面点击切换账号按钮时

  • 在授权页面点击一键登录按钮收到 requestToken 结果回调之后

示例代码

ObjC:

  1. 导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 在需要关闭授权页面的地方调用极验关闭授权页面接口

- (void)dismissAuthVC {
[OneLogin dismissAuthViewController:nil];
}

Swift:

  1. 创建混编桥接头文件并导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 在需要关闭授权页面的地方调用极验关闭授权页面接口

@objc func dismissAuthVC(_ sender: UIButton) {
OneLogin.dismissAuthViewController {

}
}

2.5、判断预取号结果是否有效

方法原型

/**
* @abstract 预取号拿到的token是否还在有效期
*
* @return YES - 还在有效期,可直接调用requestTokenWithViewController方法进行取号
* NO - 已失效,需重新调用preGetTokenWithCompletion进行预取号之后再调用requestTokenWithViewController方法进行取号
*/
+ (BOOL)isPreGettedTokenValidate;

接口作用

判断预取号结果是否有效

调用时机

  • 调用requestTokenWithCompletion时,判断是否需要先调用preGetTokenWithCompletion

示例代码

ObjC:

  1. 导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 判断预取号结果是否有效

// 根据SDK的方法判断当前预取号结果是否有效,若当前预取号结果有效,则直接调用requestTokenWithViewController方法拉起授权页面,否则,先调用预取号方法进行预取号,预取号成功后再拉起授权页面
__weak typeof(self) wself = self;
if ([OneLogin isPreGettedTokenValidate]) {
[OneLogin requestTokenWithViewController:self viewModel:viewModel completion:^(NSDictionary * _Nullable result) {
NSLog(@"requestTokenWithViewController result: %@", result);
}];
} else {
[GTProgressHUD showLoadingHUDWithMessage:nil];
[OneLogin preGetTokenWithCompletion:^(NSDictionary * _Nonnull preResult) {
[GTProgressHUD hideAllHUD];
NSLog(@"preGetTokenWithCompletion result: %@", preResult);
if (preResult.count > 0 && preResult[@"status"] && 200 == [preResult[@"status"] integerValue]) {
[OneLogin requestTokenWithViewController:wself viewModel:viewModel completion:^(NSDictionary * _Nullable result) {
NSLog(@"requestTokenWithViewController result: %@", result);
// 自定义授权页面点击登录按钮之后的loading时,调用此方法会触发stopLoadingViewBlock回调,可以在此回调中停止自定义的loading
[OneLogin stopLoading];
[wself finishRequestingToken:result];
}];
} else { // 预取号失败
[GTProgressHUD showToastWithMessage:preResult[@"msg"]?:@"预取号失败"];
}
}];
}

Swift:

  1. 创建混编桥接头文件并导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 判断预取号结果是否有效

// 根据SDK的方法判断当前预取号结果是否有效,若当前预取号结果有效,则直接调用requestTokenWithViewController方法拉起授权页面,否则,先调用预取号方法进行预取号,预取号成功后再拉起授权页面
if OneLogin.isPreGettedTokenValidate() {
OneLogin.requestToken(with: self, viewModel: viewModel) { [weak self] result in
if let strongSelf = self {
strongSelf.finishRequsetingToken(result: result!)
}
sender.isEnabled = true
}
} else {
GTProgressHUD.showLoadingHUD(withMessage: nil)
OneLogin.preGetToken { [weak self] preResult in
GTProgressHUD.hideAllHUD()
if let strongSelf = self {
let status = NSString.init(format: "%@", preResult["status"] as! NSNumber)
if 200 == status.integerValue {
OneLogin.requestToken(with: strongSelf, viewModel: viewModel) { (result) in
strongSelf.finishRequsetingToken(result: result!)
}
} else {
let message = (preResult["msg"] != nil) ? (preResult["msg"] as! String) : "预取号失败"
GTProgressHUD.showToast(withMessage: message)
}
}
sender.isEnabled = true
}
}

授权页面 UI 修改

1、设计规范

linkedlibraries

2、页面控件位置大小设置

极验支持两种方式设置授权页面控件的位置和大小:

  • 设置控件的 OLRect 属性,通过设置控件距离屏幕顶部和屏幕左边的偏移量来控制控件的位置,通过设置控件的宽高来控制控件的大小

  • 在回调中拿到授权页面所有控件,通过 masnory 或其他方式进行自动布局

2.1、 设置控件的 OLRect 属性

/**
* @abstract 1、若授权页面只支持竖屏,只设置竖屏方向偏移;
2、若授权页面只支持横屏,只设置横屏方向偏移;
3、若授权页面支持旋转自动切换横竖屏,则同时设置竖屏方向和横屏方向偏移
4、弹窗模式,同以上1、2、3
5、size默认都可以不用设置,会根据字体大小自适应
6、x轴方向偏移量有两个值可以设置,portraitCenterXOffset为控件的x轴中点到弹窗x轴中点的距离,portraitLeftXOffset为控件的左边缘到屏幕左边缘的距离,两者选其一即可
*/
typedef struct OLRect {
/**
竖屏时
导航栏隐藏时,为控件顶部到状态栏的距离;导航栏显示时,为控件顶部到导航栏底部的距离
弹窗时
为控件顶部到弹窗顶部的距离
*/
CGFloat portraitTopYOffset;

/**
竖屏时
控件的x轴中点到屏幕x轴中点的距离,默认为0
弹窗时
控件的x轴中点到弹窗x轴中点的距离,默认为0
*/
CGFloat portraitCenterXOffset;

/**
竖屏时
控件的左边缘到屏幕左边缘的距离,默认为0
弹窗时
控件的左边缘到屏幕左边缘的距离,默认为0

portraitLeftXOffset与portraitCenterXOffset设置一个即可,portraitLeftXOffset优先级大于portraitCenterXOffset,
设置此属性时,portraitCenterXOffset属性失效
*/
CGFloat portraitLeftXOffset;

/**
横屏时
导航栏隐藏时,为控件顶部到屏幕顶部的距离;导航栏显示时,为控件顶部到导航栏底部的距离
弹窗时
为控件顶部到弹窗顶部的距离
*/
CGFloat landscapeTopYOffset;

/**
横屏时
控件的x轴中点到屏幕x轴中点的距离,默认为0
弹窗时
控件的x轴中点到弹窗x轴中点的距离,默认为0
*/
CGFloat landscapeCenterXOffset;

/**
横屏时
控件的左边缘到屏幕左边缘的距离,默认为0
弹窗时
控件的左边缘到屏幕左边缘的距离,默认为0

landscapeLeftXOffset与landscapeCenterXOffset设置一个即可,landscapeLeftXOffset优先级大于landscapeCenterXOffset,
设置此属性时,landscapeCenterXOffset属性失效
*/
CGFloat landscapeLeftXOffset;

/**
控件大小,只有宽度、高度同时大于0,设置的size才会生效,否则为控件默认的size
*/
CGSize size;
} OLRect;

/**
返回按钮位置及大小,返回按钮最大size为CGSizeMake(40, 40)。
*/
@property (nonatomic, assign) OLRect backButtonRect;

/**
Logo 位置及大小。
*/
@property (nonatomic, assign) OLRect logoRect;

/**
号码预览 位置及大小
*/
@property (nonatomic, assign) OLRect phoneNumRect;

/**
授权页切换账号按钮 位置及大小。
*/
@property (nonatomic, assign) OLRect switchButtonRect;

/**
授权按钮 位置及大小。
*/
@property (nonatomic, assign) OLRect authButtonRect;

/**
Slogan 位置及大小。
*/
@property (nonatomic, assign) OLRect sloganRect;

/**
授权页面上条款勾选框大小及位置。
*/
@property (nonatomic, assign) OLRect checkBoxRect;

/**
隐私条款 位置及大小,隐私条款,宽需大于50,高需大于20,才会生效。
*/
@property (nonatomic, assign) OLRect termsRect;

/**
弹窗 位置及大小。弹窗模式时,x轴偏移只支持portraitLeftXOffset和landscapeLeftXOffset。
*/
@property (nonatomic, assign) OLRect popupRect;

示例代码

ObjC:

  1. 导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 设置控件的 OLRect 属性

OLRect backButtonRect = {0, 0, 0, 0, 0, 0, {0, 0}}; // 返回按钮偏移、大小设置,偏移量和大小设置值需大于0,否则取默认值,默认可不设置
viewModel.backButtonRect = backButtonRect;

OLRect logoRect = {0, 0, 0, 20, 0, 0, {0, 0}}; // logo偏移、大小设置,偏移量和大小设置值需大于0,否则取默认值,默认可不设置,logo大小默认为图片大小
viewModel.logoRect = logoRect;

OLRect phoneNumRect = {0, 0, 0, 0, 0, 0, {0, 0}}; // 手机号偏移设置
viewModel.phoneNumRect = phoneNumRect;

OLRect switchButtonRect = {0, 0, 0, 0, 0, 0, {0, 0}}; // 切换按钮偏移、大小设置,偏移量和大小设置值需大于0,否则取默认值,默认可不设置
viewModel.switchButtonRect = switchButtonRect;

OLRect authButtonRect = {0, 0, 0, 0, 0, 0, {300, 40}}; // 授权按钮偏移、大小设置,偏移量和大小设置值需大于0,否则取默认值,默认可不设置
viewModel.authButtonRect = authButtonRect;

OLRect sloganRect = {0, 0, 0, 0, 0, 0, {0, 0}}; // slogan偏移、大小设置,偏移量和大小设置值需大于0,否则取默认值,默认可不设置
viewModel.sloganRect = sloganRect;

OLRect checkBoxRect = {0, 0, 0, 0, 0, 0, {12, 12}};
viewModel.checkBoxRect = checkBoxRect; // 复选框尺寸,默认为12*12

OLRect termsRect = {0, 0, 0, 0, 0, 0, {0, 0}}; // 服务条款偏移、大小设置,偏移量和大小设置值需大于0,否则取默认值,默认可不设置
viewModel.termsRect = termsRect;

Swift:

  1. 创建混编桥接头文件并导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 设置控件的 OLRect 属性

let backButtonRect = OLRect(portraitTopYOffset: 0, portraitCenterXOffset: 0, portraitLeftXOffset: 0, landscapeTopYOffset: 0, landscapeCenterXOffset: 0, landscapeLeftXOffset: 0, size: CGSize(width: 0, height: 0)) // 返回按钮偏移、大小设置,偏移量和大小设置值需大于0,否则取默认值,默认可不设置
viewModel.backButtonRect = backButtonRect

let logoRect = OLRect(portraitTopYOffset: 0, portraitCenterXOffset: 0, portraitLeftXOffset: 0, landscapeTopYOffset: 20, landscapeCenterXOffset: 0, landscapeLeftXOffset: 0, size: CGSize(width: 0, height: 0)) // logo偏移、大小设置,偏移量和大小设置值需大于0,否则取默认值,默认可不设置,logo大小默认为图片大小
viewModel.logoRect = logoRect

let phoneNumRect = OLRect(portraitTopYOffset: 0, portraitCenterXOffset: 0, portraitLeftXOffset: 0, landscapeTopYOffset: 0, landscapeCenterXOffset: 0, landscapeLeftXOffset: 0, size: CGSize(width: 0, height: 0)) // 手机号偏移设置
viewModel.phoneNumRect = phoneNumRect

let switchButtonRect = OLRect(portraitTopYOffset: 0, portraitCenterXOffset: 0, portraitLeftXOffset: 0, landscapeTopYOffset: 0, landscapeCenterXOffset: 0, landscapeLeftXOffset: 0, size: CGSize(width: 0, height: 0)) // 切换按钮偏移、大小设置,偏移量和大小设置值需大于0,否则取默认值,默认可不设置
viewModel.switchButtonRect = switchButtonRect

let authButtonRect = OLRect(portraitTopYOffset: 0, portraitCenterXOffset: 0, portraitLeftXOffset: 0, landscapeTopYOffset: 0, landscapeCenterXOffset: 0, landscapeLeftXOffset: 0, size: CGSize(width: 300, height: 40)) // 授权按钮偏移、大小设置,偏移量和大小设置值需大于0,否则取默认值,默认可不设置
viewModel.authButtonRect = authButtonRect

let sloganRect = OLRect(portraitTopYOffset: 0, portraitCenterXOffset: 0, portraitLeftXOffset: 0, landscapeTopYOffset: 0, landscapeCenterXOffset: 0, landscapeLeftXOffset: 0, size: CGSize(width: 0, height: 0)) // slogan偏移、大小设置,偏移量和大小设置值需大于0,否则取默认值,默认可不设置
viewModel.sloganRect = sloganRect

let checkBoxRect = OLRect(portraitTopYOffset: 0, portraitCenterXOffset: 0, portraitLeftXOffset: 0, landscapeTopYOffset: 0, landscapeCenterXOffset: 0, landscapeLeftXOffset: 0, size: CGSize(width: 12, height: 12)) // 复选框尺寸,默认为12*12
viewModel.checkBoxRect = checkBoxRect

let termsRect = OLRect(portraitTopYOffset: 0, portraitCenterXOffset: 0, portraitLeftXOffset: 0, landscapeTopYOffset: 0, landscapeCenterXOffset: 0, landscapeLeftXOffset: 0, size: CGSize(width: 0, height: 0)) // 服务条款偏移、大小设置,偏移量和大小设置值需大于0,否则取默认值,默认可不设置
viewModel.termsRect = termsRect

2.2、控件进行自动布局

/**
* @abstract 授权页面视图控件自动布局回调,可在该回调中,对控件通过 masonry 或者其他方式进行自动布局,若需要自定义视图,请直接在该回调中添加,实现该回调后,授权页面所有视图的约束都会被删除,您需要重新设置所有视图的约束
*
* authView 为 authContentView 的父视图
* authContentView 为 authBackgroundImageView、authNavigationView、authLogoView、authPhoneView、authSwitchButton、authLoginButton、authSloganView、authAgreementView、authClosePopupButton 的父视图
* authNavigationView 为 authNavigationContainerView 的父视图
* authNavigationContainerView 为 authBackButton 和 authNavigationTitleView 的父视图
* authAgreementView 为 authCheckbox 和 authProtocolView 的父视图
*
*/
typedef void(^OLAuthVCAutoLayoutBlock)(UIView *authView, UIView *authContentView, UIView *authBackgroundImageView, UIView *authNavigationView, UIView *authNavigationContainerView, UIView *authBackButton, UIView *authNavigationTitleView, UIView *authLogoView, UIView *authPhoneView, UIView *authSwitchButton, UIView *authLoginButton, UIView *authSloganView, UIView *authAgreementView, UIView *authCheckbox, UIView *authProtocolView, UIView *authClosePopupButton);

/**
* 授权页面视图控件自动布局回调
*/
@property (nullable, nonatomic, copy) OLAuthVCAutoLayoutBlock autolayoutBlock;

示例代码

ObjC:

  1. 导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 通过回调对控件进行自动布局

viewModel.autolayoutBlock = ^(UIView *authView, UIView *authContentView, UIView *authBackgroundImageView, UIView *authNavigationView, UIView *authNavigationContainerView, UIView *authBackButton, UIView *authNavigationTitleView, UIView *authLogoView, UIView *authPhoneView, UIView *authSwitchButton, UIView *authLoginButton, UIView *authSloganView, UIView *authAgreementView, UIView *authCheckbox, UIView *authProtocolView, UIView *authClosePopupButton) {
// content
[authContentView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(authView);
}];

// background
[authBackgroundImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(authContentView);
}];

// navigation
[authNavigationView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.right.equalTo(authContentView);
make.height.mas_equalTo(64);
}];

[authNavigationContainerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(authNavigationView);
}];

[authBackButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(authNavigationContainerView).offset(20);
make.centerY.equalTo(authNavigationContainerView).offset(10);
make.size.mas_equalTo(CGSizeMake(20, 20));
}];

[authNavigationTitleView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(authNavigationContainerView);
make.centerY.equalTo(authNavigationContainerView).offset(10);
make.size.mas_equalTo(CGSizeMake(100, 40));
}];

UIButton *rightBarButton = [UIButton buttonWithType:UIButtonTypeCustom];
[rightBarButton setTitle:@"完成" forState:UIControlStateNormal];
[rightBarButton addTarget:self action:@selector(doneAction:) forControlEvents:UIControlEventTouchUpInside];
[authNavigationContainerView addSubview:rightBarButton];
[rightBarButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(authNavigationContainerView).offset(-10);
make.centerY.equalTo(authNavigationContainerView).offset(10);
make.size.mas_equalTo(CGSizeMake(60, 40));
}];

// logo
[authLogoView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(authContentView);
make.top.equalTo(authNavigationView.mas_bottom).offset(100);
make.size.mas_equalTo(CGSizeMake(107, 22));
}];

// phone
[authPhoneView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(authContentView);
make.top.equalTo(authLogoView.mas_bottom).offset(20);
make.size.mas_equalTo(CGSizeMake(200, 40));
}];

// switchbutton
[authSwitchButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(authContentView);
make.top.equalTo(authPhoneView.mas_bottom).offset(20);
make.size.mas_equalTo(CGSizeMake(200, 20));
}];

// loginbutton
[authLoginButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(authContentView);
make.top.equalTo(authSwitchButton.mas_bottom).offset(30);
make.size.mas_equalTo(CGSizeMake(260, 40));
}];

// slogan
[authSloganView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(authContentView);
make.top.equalTo(authLoginButton.mas_bottom).offset(20);
make.size.mas_equalTo(CGSizeMake(260, 20));
}];

// agreementview
[authAgreementView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(authContentView).offset(20);
make.right.equalTo(authContentView).offset(-20);
make.top.equalTo(authSloganView.mas_bottom).offset(50);
make.height.mas_equalTo(80);
}];

[authCheckbox mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(authAgreementView).offset(10);
make.top.equalTo(authAgreementView).offset(10);
}];

[authProtocolView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(authCheckbox.mas_right).offset(5);
make.right.equalTo(authAgreementView).offset(-10);
make.height.equalTo(authAgreementView);
}];

// 自定义视图
UIButton *customBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 200, 40)];
[customBtn setTitle:@"我是自定义UI" forState:UIControlStateNormal];
customBtn.backgroundColor = [UIColor lightGrayColor];
customBtn.layer.cornerRadius = 2.0;
[customBtn addTarget:self action:@selector(dismissAuthVC) forControlEvents:UIControlEventTouchUpInside];
[authContentView addSubview:customBtn];
[customBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(authContentView).offset(20);
make.right.equalTo(authContentView).offset(-20);
make.height.mas_equalTo(40);
make.top.equalTo(authAgreementView.mas_bottom).offset(30);
}];
};

Swift:

  1. 创建混编桥接头文件并导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 通过回调对控件进行自动布局

viewModel.autolayoutBlock = { [weak self] (authView: UIView, authContentView: UIView, authBackgroundImageView: UIView, authNavigationView: UIView, authNavigationContainerView: UIView, authBackButton: UIView, authNavigationTitleView: UIView, authLogoView: UIView, authPhoneView: UIView, authSwitchButton: UIView, authLoginButton: UIView, authSloganView: UIView, authAgreementView: UIView, authCheckbox: UIView, authProtocolView: UIView, authClosePopupButton: UIView) in
// content
authContentView.mas_makeConstraints { (make: MASConstraintMaker?) in
make?.edges.equalTo()(authView)
}

// background
authBackgroundImageView.mas_makeConstraints { (make: MASConstraintMaker?) in
make?.edges.equalTo()(authContentView)
}

// navigation
authNavigationView.mas_makeConstraints { (make: MASConstraintMaker?) in
make?.left.top().right().equalTo()(authContentView)
make?.height.mas_equalTo()(64)
}

authNavigationContainerView.mas_makeConstraints { (make: MASConstraintMaker?) in
make?.edges.equalTo()(authNavigationView)
}

authBackButton.mas_makeConstraints { (make: MASConstraintMaker?) in
make?.left.equalTo()(authNavigationContainerView)?.offset()(20)
make?.centerY.equalTo()(authNavigationContainerView)?.offset()(10)
make?.size.mas_equalTo()(CGSize.init(width: 20, height: 20))
}

authNavigationTitleView.mas_makeConstraints { (make: MASConstraintMaker?) in
make?.centerX.equalTo()(authNavigationContainerView)
make?.centerY.equalTo()(authNavigationContainerView)?.offset()(10)
make?.size.mas_equalTo()(CGSize.init(width: 100, height: 40))
}

// 导航栏右侧控制视图
let strongSelf = self
let rightBarButton = UIButton.init(type: UIButton.ButtonType.custom)
rightBarButton.setTitle("完成", for: UIControl.State.normal)
rightBarButton.addTarget(strongSelf, action: #selector(strongSelf?.doneAction), for: UIControl.Event.touchUpInside)
authNavigationContainerView.addSubview(rightBarButton)
rightBarButton.mas_makeConstraints { (make: MASConstraintMaker?) in
make?.right.equalTo()(authNavigationContainerView)?.offset()(-10)
make?.centerY.equalTo()(authNavigationContainerView)?.offset()(10)
make?.size.mas_equalTo()(CGSize.init(width: 60, height: 40))
}

// logo
authLogoView.mas_makeConstraints { (make: MASConstraintMaker?) in
make?.centerX.equalTo()(authContentView)
make?.top.equalTo()(authNavigationView.mas_bottom)?.offset()(100)
make?.size.mas_equalTo()(CGSize.init(width: 107, height: 22))
}

// phone
authPhoneView.mas_makeConstraints { (make: MASConstraintMaker?) in
make?.centerX.equalTo()(authContentView)
make?.top.equalTo()(authLogoView.mas_bottom)?.offset()(20)
make?.size.mas_equalTo()(CGSize.init(width: 200, height: 40))
}

// switchbutton
authSwitchButton.mas_makeConstraints { (make: MASConstraintMaker?) in
make?.centerX.equalTo()(authContentView)
make?.top.equalTo()(authPhoneView.mas_bottom)?.offset()(20)
make?.size.mas_equalTo()(CGSize.init(width: 200, height: 20))
}

// loginbutton
authLoginButton.mas_makeConstraints { (make: MASConstraintMaker?) in
make?.centerX.equalTo()(authContentView)
make?.top.equalTo()(authSwitchButton.mas_bottom)?.offset()(30)
make?.size.mas_equalTo()(CGSize.init(width: 260, height: 40))
}

// slogan
authSloganView.mas_makeConstraints { (make: MASConstraintMaker?) in
make?.centerX.equalTo()(authContentView)
make?.top.equalTo()(authLoginButton.mas_bottom)?.offset()(20)
make?.size.mas_equalTo()(CGSize.init(width: 260, height: 20))
}

// agreementview
authAgreementView.mas_makeConstraints { (make: MASConstraintMaker?) in
make?.left.equalTo()(authContentView)?.offset()(20)
make?.right.equalTo()(authContentView)?.offset()(-20)
make?.top.equalTo()(authSloganView.mas_bottom)?.offset()(50)
make?.height.mas_equalTo()(80)
}

authCheckbox.mas_makeConstraints { (make: MASConstraintMaker?) in
make?.left.equalTo()(authAgreementView)?.offset()(10)
make?.top.equalTo()(authAgreementView)?.offset()(10)
}

authProtocolView.mas_makeConstraints { (make: MASConstraintMaker?) in
make?.left.equalTo()(authCheckbox.mas_right)?.offset()(5)
make?.right.equalTo()(authAgreementView)?.offset()(-10)
make?.height.equalTo()(authAgreementView);
}

// 自定义视图
let customBtn = UIButton.init(frame: CGRect.init(x: 0, y: 0, width: 200, height: 40))
customBtn.setTitle("我是自定义UI", for: UIControl.State.normal)
customBtn.backgroundColor = UIColor.red
customBtn.layer.cornerRadius = 2.0
customBtn.addTarget(strongSelf, action: #selector(strongSelf?.dismissAuthVC), for: UIControl.Event.touchUpInside)
authContentView.addSubview(customBtn)
customBtn.mas_makeConstraints { (make: MASConstraintMaker?) in
make?.left.equalTo()(authContentView)?.offset()(20)
make?.right.equalTo()(authContentView)?.offset()(-20)
make?.height.mas_equalTo()(40)
make?.top.equalTo()(authAgreementView.mas_bottom)?.offset()(30)
}
}

3、页面控件属性设置

#pragma mark - Status Bar/状态栏

/**
状态栏样式。 默认 `UIStatusBarStyleDefault`。
*/
@property (nonatomic, assign) UIStatusBarStyle statusBarStyle;

#pragma mark - Navigation/导航

/**
授权页导航的标题。默认为空字符串。
*/
@property (nullable, nonatomic, strong) NSAttributedString *naviTitle;

/**
授权页导航的背景颜色。默认白色。
*/
@property (nullable, nonatomic, strong) UIColor *naviBgColor;

/**
授权页导航左边的返回按钮的图片。默认黑色系统样式返回图片。
*/
@property (nullable, nonatomic, strong) UIImage *naviBackImage;

/**
授权页导航右边的自定义控件。
*/
@property (nullable, nonatomic, strong) UIView *naviRightControl;

/**
导航栏隐藏。默认不隐藏。
*/
@property (nonatomic, assign) BOOL naviHidden;

/**
返回按钮隐藏。默认不隐藏。
*/
@property (nonatomic, assign) BOOL backButtonHidden;

#pragma mark - Logo/图标

/**
授权页面上展示的图标。默认为 "OneLogin" 图标。
*/
@property (nullable, nonatomic, strong) UIImage *appLogo;

/**
Logo 图片隐藏。默认不隐藏。
*/
@property (nonatomic, assign) BOOL logoHidden;

/**
logo圆角,默认为0。
*/
@property (nonatomic, assign) CGFloat logoCornerRadius;

#pragma mark - Phone Number Preview/手机号预览

/**
号码预览文字的颜色。默认黑色。
*/
@property (nullable, nonatomic, strong) UIColor *phoneNumColor;

/**
号码预览文字的字体。默认粗体,24pt。
*/
@property (nullable, nonatomic, strong) UIFont *phoneNumFont;

#pragma mark - Switch Button/切换按钮

/**
授权页切换账号按钮的文案。默认为“切换账号”。
*/
@property (nullable, nonatomic, copy) NSString *switchButtonText;

/**
授权页切换账号按钮的颜色。默认蓝色。
*/
@property (nullable, nonatomic, strong) UIColor *switchButtonColor;

/**
授权页切换账号按钮背景颜色。默认为 nil。
*/
@property (nullable, nonatomic, strong) UIColor *switchButtonBackgroundColor;

/**
授权页切换账号的字体。默认字体,15pt。
*/
@property (nullable, nonatomic, strong) UIFont *switchButtonFont;

/**
隐藏切换账号按钮。默认不隐藏。
*/
@property (nonatomic, assign) BOOL switchButtonHidden;

#pragma mark - Authorization Button/认证按钮

/**
授权页认证按钮的背景图片, @[正常状态的背景图片, 不可用状态的背景图片, 高亮状态的背景图片]。默认正常状态为蓝色纯色, 不可用状态的背景图片时为灰色, 高亮状态为灰蓝色。
*/
@property (nullable, nonatomic, strong) NSArray<UIImage *> *authButtonImages;

/**
授权按钮文案。默认白色的"一键登录"。
*/
@property (nullable, nonatomic, strong) NSAttributedString *authButtonTitle;

/**
授权按钮圆角,默认为0。
*/
@property (nonatomic, assign) CGFloat authButtonCornerRadius;

#pragma mark - Slogan/口号标语

/**
Slogan 文字颜色。默认灰色。
*/
@property (nonatomic, strong) UIColor *sloganTextColor;

/**
Slogan字体。默认字体, 12pt。
*/
@property (nonatomic, strong) UIFont *sloganTextFont;

#pragma mark - CheckBox & Privacy Terms/隐私条款勾选框及隐私条款

/**
授权页面上条款勾选框初始状态。默认 YES。
*/
@property (nonatomic, assign) BOOL defaultCheckBoxState;

/**
授权页面上勾选框勾选的图标。默认为蓝色图标。推荐尺寸为12x12。
*/
@property (nullable, nonatomic, strong) UIImage *checkedImage;

/**
授权页面上勾选框未勾选的图标。默认为白色图标。推荐尺寸为12x12。
*/
@property (nullable, nonatomic, strong) UIImage *uncheckedImage;

/**
隐私条款文字属性。默认基础文字灰色, 条款蓝色高亮, 12pt。
*/
@property (nullable, nonatomic, strong) NSDictionary<NSAttributedStringKey, id> *privacyTermsAttributes;

/**
额外的条款。默认为空。
*/
@property (nullable, nonatomic, strong) NSArray<OLPrivacyTermItem *> *additionalPrivacyTerms;

/**
服务条款普通文字的颜色。默认灰色。
*/
@property (nullable, nonatomic, strong) UIColor *termTextColor;

/**
除隐私条款外的其他文案,数组大小必须为4,元素依次为:条款前的文案、条款一和条款二连接符、条款二和条款三连接符,条款后的文案。
默认为@[@"登录即同意", @"和", @"、", @"并使用本机号码登录"]
*/
@property (nullable, nonatomic, copy) NSArray<NSString *> *auxiliaryPrivacyWords;

/**
* 点击授权页面隐私协议前勾选框的回调
*/
@property (nullable, nonatomic, copy) OLClickCheckboxBlock clickCheckboxBlock;

/**
* 服务条款文案对齐方式,默认为NSTextAlignmentLeft
*/
@property (nonatomic, assign) NSTextAlignment termsAlignment;

#pragma mark - Background Image/授权页面背景图片

/**
授权页背景颜色。默认白色。
*/
@property (nullable, nonatomic, strong) UIColor *backgroundColor;

/**
授权页面背景图片
*/
@property (nullable, nonatomic, strong) UIImage *backgroundImage;

/**
横屏模式授权页面背景图片
*/
@property (nullable, nonatomic, strong) UIImage *landscapeBackgroundImage;

示例代码

ObjC:

  1. 导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 设置控件属性

// --------------状态栏设置 -------------------
viewModel.statusBarStyle = UIStatusBarStyleLightContent;

// -------------- 授权页面背景设置 -------------------
viewModel.backgroundColor = UIColor.lightGrayColor;

// -------------- 导航栏设置 -------------------
viewModel.naviTitle = [[NSAttributedString alloc] initWithString:@"一键登录"
attributes:@{NSForegroundColorAttributeName : UIColor.whiteColor,
NSFontAttributeName : [UIFont boldSystemFontOfSize:18]
}]; // 导航栏标题
viewModel.naviBgColor = UIColor.greenColor; // 导航栏背景色
viewModel.naviBackImage = [UIImage imageNamed:@"back"]; // 导航栏返回按钮
viewModel.backButtonHidden = NO; // 是否隐藏返回按钮,默认不隐藏

// -------------- logo设置 -------------------
viewModel.appLogo = [UIImage imageNamed:@"网关取号_logo"]; // 自定义logo图片
viewModel.logoHidden = NO; // 是否隐藏logo,默认不隐藏
viewModel.logoCornerRadius = 0; // logo圆角,默认为0

// -------------- 手机号设置 -------------------
viewModel.phoneNumColor = UIColor.redColor; // 颜色
viewModel.phoneNumFont = [UIFont boldSystemFontOfSize:25]; // 字体

// -------------- 切换账号设置 -------------------
viewModel.switchButtonColor = UIColor.brownColor; // 切换按钮颜色
viewModel.switchButtonFont = [UIFont systemFontOfSize:15]; // 切换按钮字体
viewModel.switchButtonText = @"自定义切换按钮文案"; // 切换按钮文案
viewModel.switchButtonHidden = NO; // 是否隐藏切换按钮,默认不隐藏

// -------------- 授权登录按钮设置 -------------------
viewModel.authButtonImages = @[
[UIImage imageNamed:@"bg_logo_launch"],
[UIImage imageNamed:@"bg_logo_launch"],
[UIImage imageNamed:@"bg_logo_launch"]
]; // 授权按钮背景图片
viewModel.authButtonTitle = [[NSAttributedString alloc] initWithString:@"授权登录"
attributes:@{NSForegroundColorAttributeName : UIColor.whiteColor,
NSFontAttributeName : [UIFont boldSystemFontOfSize:18]
}]; // 登录按钮文案
viewModel.authButtonRect = authButtonRect;
viewModel.authButtonCornerRadius = 0; // 授权按钮圆角,默认为0
viewModel.clickAuthButtonBlock = ^(void) { // 点击授权页面登录按钮回调
NSLog(@"clickAuthButtonBlock");
};

// -------------- slogan设置 -------------------
viewModel.sloganTextColor = UIColor.cyanColor; // slogan颜色
viewModel.sloganTextFont = [UIFont systemFontOfSize:14]; // slogan字体

// -------------- 服务条款设置 -------------------
viewModel.defaultCheckBoxState = YES; // 是否默认选择同意服务条款,默认同意

Swift:

  1. 创建混编桥接头文件并导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 设置控件属性

// --------------状态栏设置 -------------------
viewModel.statusBarStyle = .lightContent

// -------------- 授权页面背景图片设置 -------------------
viewModel.backgroundColor = .lightGray

// -------------- 导航栏设置 -------------------
viewModel.naviTitle = NSAttributedString.init(string: "一键登录", attributes: [NSAttributedString.Key.foregroundColor : UIColor.white, NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 18)]) // 导航栏标题
viewModel.naviBgColor = .green // 导航栏背景色
viewModel.naviBackImage = UIImage.init(named: "back") // 导航栏返回按钮
viewModel.backButtonHidden = false // 是否隐藏返回按钮,默认不隐藏

// -------------- logo设置 -------------------
viewModel.appLogo = UIImage.init(named: "网关取号_logo")
viewModel.logoHidden = false // 是否隐藏logo,默认不隐藏
viewModel.logoCornerRadius = 0

// -------------- 手机号设置 -------------------
viewModel.phoneNumColor = UIColor.red // 颜色
viewModel.phoneNumFont = UIFont.boldSystemFont(ofSize: 25) // 字体

// -------------- 切换账号设置 -------------------
viewModel.switchButtonColor = UIColor.brown // 切换按钮颜色
viewModel.switchButtonFont = UIFont.systemFont(ofSize: 15) // 切换按钮字体
viewModel.switchButtonText = "自定义切换按钮文案" // 切换按钮文案
viewModel.switchButtonHidden = false // 是否隐藏切换按钮,默认不隐藏

// -------------- 授权登录按钮设置 -------------------
viewModel.authButtonImages = [(UIImage.init(named: "bg_logo_launch") ?? UIImage.init()), (UIImage.init(named: "bg_logo_launch") ?? UIImage.init()), (UIImage.init(named: "bg_logo_launch") ?? UIImage.init())] // 授权按钮背景图片
viewModel.authButtonTitle = NSAttributedString.init(string: "授权登录", attributes: [NSAttributedString.Key.foregroundColor : UIColor.white, NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 18)]) // 登录按钮文案

viewModel.authButtonCornerRadius = 0 // 授权按钮圆角,默认为0
viewModel.clickAuthButtonBlock = { // 点击授权页面登录按钮回调
print("clickAuthButtonBlock")
}

// -------------- slogan设置 -------------------
viewModel.sloganTextColor = UIColor.cyan // slogan颜色
viewModel.sloganTextFont = UIFont.systemFont(ofSize: 14) // slogan字体

// -------------- 服务条款设置 -------------------
viewModel.defaultCheckBoxState = true

4、横竖屏设置

/**
* 授权页面支持的横竖屏方向
*/
@property (nonatomic, assign) UIInterfaceOrientationMask supportedInterfaceOrientations;

通过设置 supportedInterfaceOrientations 属性,即可控制授权页面的横竖屏,授权页面可以支持横竖屏自由组合,若设置授权页面同时支持竖屏和横屏,授权页面会跟随设备旋转自动进行横竖屏切换

示例代码

ObjC:

  1. 导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 设置 supportedInterfaceOrientations 属性

// -------------- 授权页面支持的横竖屏设置 -------------------
viewModel.supportedInterfaceOrientations = UIInterfaceOrientationMaskAllButUpsideDown;

Swift:

  1. 创建混编桥接头文件并导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 设置 supportedInterfaceOrientations 属性

// -------------- 授权页面支持的横竖屏设置 -------------------
viewModel.supportedInterfaceOrientations = UIInterfaceOrientationMask.allButUpsideDown

5、弹窗模式设置

#pragma mark - Popup

/**
* 是否为弹窗模式
*/
@property (nonatomic, assign) BOOL isPopup;

/**
弹窗 位置及大小。弹窗模式时,x轴偏移只支持portraitLeftXOffset和landscapeLeftXOffset。
*/
@property (nonatomic, assign) OLRect popupRect;

/**
弹窗圆角,默认为6。
*/
@property (nonatomic, assign) CGFloat popupCornerRadius;

/**
当只需要设置弹窗的部分圆角时,通过popupCornerRadius设置圆角大小,通过popupRectCorners设置需要设置圆角的位置。
popupRectCorners数组元素不超过四个,超过四个时,只取前四个。比如,要设置左上和右上为圆角,则传值:@[@(UIRectCornerTopLeft), @(UIRectCornerTopRight)]
*/
@property (nonatomic, strong) NSArray<NSNumber *> *popupRectCorners;

/**
* 弹窗动画类型,当popupAnimationStyle为OLAuthPopupAnimationStyleStyleCustom时,动画为用户自定义,用户需要传一个CATransition对象来设置动画
*/
@property (nonatomic, assign) OLAuthPopupAnimationStyle popupAnimationStyle;

/**
* 弹窗自定义动画
*/
@property (nonatomic, strong) CAAnimation *popupTransitionAnimation;

/**
弹窗关闭按钮图片,弹窗关闭按钮的尺寸跟图片尺寸保持一致。
弹窗关闭按钮位于弹窗右上角,目前只支持设置其距顶部偏移和距右边偏移。
*/
@property (nullable, nonatomic, strong) UIImage *closePopupImage;

/**
弹窗关闭按钮距弹窗顶部偏移。
*/
@property (nonatomic, strong) NSNumber *closePopupTopOffset;

/**
弹窗关闭按钮距弹窗右边偏移。
*/
@property (nonatomic, strong) NSNumber *closePopupRightOffset;

/**
是否需要通过点击弹窗的背景区域以关闭授权页面。
*/
@property (nonatomic, assign) BOOL canClosePopupFromTapGesture;

/**
* 点击授权页面弹窗背景的回调
*/
@property (nonatomic, copy) OLTapAuthBackgroundBlock tapAuthBackgroundBlock;

通过设置 isPopup 属性为 YES,即可以弹窗模式弹出授权页面,可自定义弹窗的大小、弹窗弹出动画形式及弹窗圆角,弹窗中各控件大小、位置、属性的设置同上

示例代码

ObjC:

  1. 导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 设置弹窗

OLAuthViewModel *viewModel = [OLAuthViewModel new];
viewModel.isPopup = YES;
viewModel.switchButtonHidden = YES;

// --------------点击弹窗背景收起弹窗 -------------------
viewModel.canClosePopupFromTapGesture = YES;

// -------------- 弹窗设置 -------------------

// 自定义弹窗动画
viewModel.popupAnimationStyle = OLAuthPopupAnimationStyleCoverVertical; // 弹窗动画风格,支持CoverVertical、StyleFlipHorizontal、CrossDissolve和自定义模式,默认为CoverVertical
CATransition *animation = [CATransition animation];
animation.duration = 1;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation.type = @"rippleEffect";
animation.subtype = kCATransitionFromLeft;
viewModel.popupTransitionAnimation = animation; // 只有在popupAnimationStyle为OLAuthPopupAnimationStyleCustom时生效

// 弹窗位置、大小设置,弹窗默认大小为300*340,居于屏幕中间,假如要弹窗居于底部,可做如下设置
OLRect popupRect = {[self ol_screenHeight] - 340, 0, 0, 0, 0, 0, {[self ol_screenWidth], 340}}; // 弹窗偏移、大小设置
viewModel.popupRect = popupRect;
viewModel.popupCornerRadius = 8; // 弹窗圆角,默认为6
viewModel.popupRectCorners = @[@(UIRectCornerTopLeft), @(UIRectCornerTopRight)]; // 设置部分圆角
viewModel.closePopupImage = [UIImage imageNamed:@"back"]; // 关闭按钮
viewModel.closePopupTopOffset = @(3); // 关闭按钮距弹窗顶部偏移
viewModel.closePopupRightOffset = @(-8); // 关闭按钮距弹窗右边偏移

viewModel.tapAuthBackgroundBlock = ^{
NSLog(@"tapAuthBackgroundBlock");
};

__weak typeof(self) wself = self;
// 在SDK内部预取号未成功时,建议加载进度条
if (![OneLoginPro isPreGetTokenResultValidate]) {

}
// --------------授权页面生命周期回调 -------------------
viewModel.viewLifeCycleBlock = ^(NSString *viewLifeCycle, BOOL animated) {
NSLog(@"viewLifeCycle: %@, animated: %@", viewLifeCycle, animated ? @"YES" : @"NO");
if ([viewLifeCycle isEqualToString:@"viewDidDisappear:"]) {

} else if ([viewLifeCycle isEqualToString:@"viewDidLoad"]) {
// 授权页面出现时,关掉进度条
}
};

Swift:

  1. 创建混编桥接头文件并导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 设置弹窗

let viewModel = OLAuthViewModel()
// 设置为弹窗模式
viewModel.isPopup = true
// 隐藏切换账号按钮
viewModel.switchButtonHidden = true
// 点击弹窗之外的空白处关闭弹窗
viewModel.canClosePopupFromTapGesture = true

viewModel.tapAuthBackgroundBlock = {
print("tapAuthBackgroundBlock")
}

viewModel.supportedInterfaceOrientations = UIInterfaceOrientationMask.allButUpsideDown

// -------------- 弹窗设置 -------------------
viewModel.popupAnimationStyle = OLAuthPopupAnimationStyle.coverVertical

let animation = CATransition.init()
animation.duration = 1
animation.timingFunction = CAMediaTimingFunction.init(name: CAMediaTimingFunctionName.easeInEaseOut)
animation.type = CATransitionType.init(rawValue: "rippleEffect")
animation.subtype = CATransitionSubtype.fromLeft
viewModel.popupTransitionAnimation = animation

let popupRect = OLRect(portraitTopYOffset: self.ol_screenHeight() - 340, portraitCenterXOffset: 0, portraitLeftXOffset: 0, landscapeTopYOffset: 0, landscapeCenterXOffset: 0, landscapeLeftXOffset: 0, size: CGSize(width: self.ol_screenWidth(), height: 340))
viewModel.popupRect = popupRect
viewModel.popupCornerRadius = 5
viewModel.closePopupTopOffset = NSNumber.init(value: 3) // 关闭按钮距弹窗顶部偏移
viewModel.closePopupRightOffset = NSNumber.init(value: -8)
viewModel.popupRectCorners = [NSNumber.init(value: UIRectCorner.topLeft.rawValue), NSNumber.init(value: UIRectCorner.topRight.rawValue)]

// --------------授权页面生命周期回调 -------------------
viewModel.viewLifeCycleBlock = { (viewLifeCycle : String, animated : Bool) in
print("viewLifeCycle: %@, animated: %@", viewLifeCycle, animated ? "true" : "false")
if viewLifeCycle == "viewDidDisappear:" {
sender.isEnabled = true
} else if viewLifeCycle == "viewDidLoad" {
// 授权页面出现时,关掉进度条
GTProgressHUD.hideAllHUD()
}
}

// 进入授权页面

if !OneLoginPro.isPreGetTokenResultValidate() {
}

OneLoginPro.requestToken(with: self, viewModel: viewModel) { [weak self] result in
if let strongSelf = self {

}
}

6、授权页面中添加自定义控件

/**
* @abstract 授权登录页面自定义视图,customAreaView为授权页面的view,如,可将三方登录添加到授权登录页面
*/
typedef void(^OLCustomUIHandler)(UIView *customAreaView);

/**
自定义区域视图的处理block

@discussion
提供的视图容器使用NSLayoutConstraint与相关的视图进行布局约束。
如果导航栏没有隐藏, 顶部与导航栏底部对齐, 左边与屏幕左边对齐, 右边与屏幕右边对齐, 底部与屏幕底部对齐。
如果导航栏隐藏, 顶部与状态栏底部对齐, 左边与屏幕左边对齐, 右边与屏幕右边对齐, 底部与屏幕底部对齐。
*/
@property (nullable, nonatomic, copy) OLCustomUIHandler customUIHandler;

示例代码

ObjC:

  1. 导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 添加自定义控件

// -------------- 自定义UI设置,如,可以在授权页面添加三方登录入口 -------------------
UIButton *customBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 200, 40)];
[customBtn setTitle:@"我是自定义UI" forState:UIControlStateNormal];
customBtn.backgroundColor = [UIColor redColor];
customBtn.layer.cornerRadius = 2.0;
[customBtn addTarget:self action:@selector(dismissAuthVC) forControlEvents:UIControlEventTouchUpInside];
__block CGFloat customAreaWidth = 0;
__block CGFloat customAreaHeight = 0;
viewModel.customUIHandler = ^(UIView * _Nonnull customAreaView) {
[customAreaView addSubview:customBtn];
customBtn.center = CGPointMake(customAreaView.bounds.size.width/2, customAreaView.bounds.size.height/2 + 150);
customAreaWidth = customAreaView.bounds.size.width > customAreaView.bounds.size.height ? customAreaView.bounds.size.height : customAreaView.bounds.size.width;
customAreaHeight = customAreaView.bounds.size.width < customAreaView.bounds.size.height ? customAreaView.bounds.size.height : customAreaView.bounds.size.width;
};

Swift:

  1. 创建混编桥接头文件并导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 添加自定义控件

// -------------- 自定义UI设置,如,可以在授权页面添加三方登录入口 -------------------
let customBtn = UIButton.init(frame: CGRect.init(x: 0, y: 0, width: 200, height: 40))
customBtn.setTitle("我是自定义UI", for: UIControl.State.normal)
customBtn.backgroundColor = UIColor.red
customBtn.layer.cornerRadius = 2.0
customBtn.addTarget(self, action: #selector(dismissAuthVC), for: UIControl.Event.touchUpInside)

var customAreaWidth = 0.0
var customAreaHeight = 0.0

viewModel.customUIHandler = { (customAreaView: UIView) in
customAreaView.addSubview(customBtn)
customBtn.center = CGPoint.init(x: customAreaView.bounds.size.width/2, y: customAreaView.bounds.size.height/2 + 150)
customAreaWidth = Double(customAreaView.bounds.size.width > customAreaView.bounds.size.height ? customAreaView.bounds.size.height : customAreaView.bounds.size.width)
customAreaHeight = Double(customAreaView.bounds.size.width < customAreaView.bounds.size.height ? customAreaView.bounds.size.height : customAreaView.bounds.size.width)
}

7、自定义授权页面 loading

/**
* 授权页自定义Loading,会在点击登录按钮之后触发
* containerView为loading的全屏蒙版view
* 请自行在containerView添加自定义loading
* 设置block后,默认loading将无效
*/
typedef void(^OLLoadingViewBlock)(UIView *containerView);

/**
* 停止授权页自定义Loading,会在调用[OneLogin stopLoading]时触发
* containerView为loading的全屏蒙版view
*/
typedef void(^OLStopLoadingViewBlock)(UIView *containerView);

/**
* 授权页面,自定义加载进度条,点击登录按钮之后的回调
*/
@property (nonatomic, copy, nullable) OLLoadingViewBlock loadingViewBlock;

/**
* 授权页面,停止自定义加载进度条,调用[OneLogin stopLoading]之后的回调
*/
@property (nonatomic, copy, nullable) OLStopLoadingViewBlock stopLoadingViewBlock;

示例代码

ObjC:

  1. 导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 添加自定义 loading

// -------------- 授权页面自动旋转时的回调,在该回调中调整自定义视图的frame,若授权页面不支持自动旋转,或者没有添加自定义视图,可不用实现该block -------------------
viewModel.authVCTransitionBlock = ^(CGSize size, id<UIViewControllerTransitionCoordinator> _Nonnull coordinator, UIView * _Nonnull customAreaView) {
if (size.width > size.height) { // 横屏
customBtn.center = CGPointMake(customAreaHeight/2, customAreaWidth/2 - 15);
} else { // 竖屏
customBtn.center = CGPointMake(customAreaWidth/2, customAreaHeight/2 + 150);
}
};

// -------------- 授权页面点击登录按钮之后的loading设置 -------------------
viewModel.loadingViewBlock = ^(UIView * _Nonnull containerView) {
if ([OneLogin isProtocolCheckboxChecked]) {
UIActivityIndicatorView *indicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
[containerView addSubview:indicatorView];
indicatorView.center = CGPointMake(containerView.bounds.size.width/2, containerView.bounds.size.height/2);
[indicatorView startAnimating];
}
};

Swift:

  1. 创建混编桥接头文件并导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 添加自定义 loading

// -------------- 授权页面点击登录按钮之后的loading设置 -------------------
viewModel.loadingViewBlock = { (containerView: UIView) in
if OneLogin.isProtocolCheckboxChecked() {
let indicatorView = UIActivityIndicatorView.init(style: UIActivityIndicatorView.Style.whiteLarge)
containerView.addSubview(indicatorView)
indicatorView.center = CGPoint.init(x: containerView.bounds.size.width/2, y: containerView.bounds.size.height/2)
indicatorView.startAnimating()
}
}

viewModel.stopLoadingViewBlock = { (containerView: UIView) in
for subview in containerView.subviews {
if subview is UIActivityIndicatorView {
(subview as! UIActivityIndicatorView).stopAnimating()
subview.removeFromSuperview()
break
}
}
}

8、设置服务条款

#pragma mark - CheckBox & Privacy Terms/隐私条款勾选框及隐私条款

/**
授权页面上条款勾选框初始状态。默认 YES。
*/
@property (nonatomic, assign) BOOL defaultCheckBoxState;

/**
授权页面上勾选框勾选的图标。默认为蓝色图标。推荐尺寸为12x12。
*/
@property (nullable, nonatomic, strong) UIImage *checkedImage;

/**
授权页面上勾选框未勾选的图标。默认为白色图标。推荐尺寸为12x12。
*/
@property (nullable, nonatomic, strong) UIImage *uncheckedImage;

/**
授权页面上条款勾选框大小。
*/
@property (nonatomic, assign) CGSize checkBoxSize __attribute__((deprecated("use checkBoxRect instead.")));

/**
授权页面上条款勾选框大小及位置。
*/
@property (nonatomic, assign) OLRect checkBoxRect;

/**
隐私条款文字属性。默认基础文字灰色, 条款蓝色高亮, 12pt。
*/
@property (nullable, nonatomic, strong) NSDictionary<NSAttributedStringKey, id> *privacyTermsAttributes;

/**
额外的条款。默认为空。
*/
@property (nullable, nonatomic, strong) NSArray<OLPrivacyTermItem *> *additionalPrivacyTerms;

/**
服务条款普通文字的颜色。默认灰色。
*/
@property (nullable, nonatomic, strong) UIColor *termTextColor;

/**
隐私条款 位置及大小,隐私条款,宽需大于50,高需大于20,才会生效。
*/
@property (nonatomic, assign) OLRect termsRect;

/**
除隐私条款外的其他文案,数组大小必须为4,元素依次为:条款前的文案、条款一和条款二连接符、条款二和条款三连接符,条款后的文案。
默认为@[@"登录即同意", @"和", @"、", @"并使用本机号码登录"]
*/
@property (nullable, nonatomic, copy) NSArray<NSString *> *auxiliaryPrivacyWords;

/**
* 点击授权页面隐私协议前勾选框的回调
*/
@property (nullable, nonatomic, copy) OLClickCheckboxBlock clickCheckboxBlock;

/**
* 服务条款文案对齐方式,默认为NSTextAlignmentLeft
*/
@property (nonatomic, assign) NSTextAlignment termsAlignment;

/**
* 点击授权页面运营商隐私协议的回调
*/
@property (nullable, nonatomic, copy) OLViewPrivacyTermItemBlock carrierTermItemBlock;

/**
* 是否在运营商协议名称上加书名号《》
*/
@property (nonatomic, assign) BOOL hasQuotationMarkOnCarrierProtocol;

示例代码

ObjC:

  1. 导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 设置服务条款

// 隐私条款文字属性
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineSpacing = 1.33;
paragraphStyle.alignment = NSTextAlignmentLeft;
paragraphStyle.paragraphSpacing = 0.0;
paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
paragraphStyle.firstLineHeadIndent = 0.0;
viewModel.privacyTermsAttributes = @{
NSForegroundColorAttributeName : UIColor.orangeColor,
NSParagraphStyleAttributeName : paragraphStyle,
NSFontAttributeName : [UIFont systemFontOfSize:12]
};
// 额外自定义服务条款,注意index属性,默认的index为0,SDK会根据index对多条服务条款升序排列,假如想设置服务条款顺序为 自定义服务条款1 默认服务条款 自定义服务条款2,则,只需将自定义服务条款1的index设为-1,自定义服务条款2的index设为1即可
OLPrivacyTermItem *item1 = [[OLPrivacyTermItem alloc] initWithTitle:@"自定义服务条款1"
linkURL:[NSURL URLWithString:@"https://docs.geetest.com/onelogin/overview/start"]
index:0
block:^(OLPrivacyTermItem * _Nonnull termItem, UIViewController *controller) {
NSLog(@"termItem.termLink: %@, controller: %@", termItem.termLink, controller);
// 自定义操作,可进入自定义服务条款页面
}];
OLPrivacyTermItem *item2 = [[OLPrivacyTermItem alloc] initWithTitle:@"自定义服务条款2"
linkURL:[NSURL URLWithString:@"https://docs.geetest.com/"]
index:0];
// 加载本地的html
NSURL *URL = [[NSBundle mainBundle] URLForResource:@"index.html" withExtension:nil];
NSURLRequest *URLRequest = [NSURLRequest requestWithURL:URL];
OLPrivacyTermItem *item3 = [[OLPrivacyTermItem alloc] initWithTitle:@"自定义服务条款3"
urlRequest:URLRequest
index:0
block:nil];
viewModel.additionalPrivacyTerms = @[item1, item2, item3];
OLRect termsRect = {0, 0, 0, 0, 0, 0, {0, 0}}; // 服务条款偏移、大小设置,偏移量和大小设置值需大于0,否则取默认值,默认可不设置
viewModel.termsRect = termsRect;
viewModel.auxiliaryPrivacyWords = @[@"条款前文案", @"&", @"&", @"条款后的文案"]; // 条款之外的文案,默认可不设置

viewModel.clickCheckboxBlock = ^(BOOL isChecked) { // 点击隐私条款前勾选框回调
NSLog(@"clickCheckboxBlock isChecked: %@", isChecked ? @"YES" : @"NO");
};

viewModel.termsAlignment = NSTextAlignmentCenter;

Swift:

  1. 创建混编桥接头文件并导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 设置服务条款

let paragraphStyle = NSMutableParagraphStyle.init()
paragraphStyle.lineSpacing = 1.33
paragraphStyle.alignment = NSTextAlignment.left
paragraphStyle.paragraphSpacing = 0.0
paragraphStyle.lineBreakMode = NSLineBreakMode.byWordWrapping
paragraphStyle.firstLineHeadIndent = 0.0
viewModel.privacyTermsAttributes = [NSAttributedString.Key.foregroundColor : UIColor.orange, NSAttributedString.Key.font : UIFont.systemFont(ofSize: 12), NSAttributedString.Key.paragraphStyle : paragraphStyle]

let item1 = OLPrivacyTermItem.init(title: "自定义服务条款1", linkURL: URL.init(string: "https://docs.geetest.com/onelogin/overview/start")!, index: 0) { (termItem: OLPrivacyTermItem, controller: UIViewController) in
print("termItem.termLink: %@, controller: %@", termItem.termLink, controller)
}
let item2 = OLPrivacyTermItem.init(title: "自定义服务条款2", linkURL: URL.init(string: "https://docs.geetest.com/")!, index: 0)
// 加载本地的html
let url = Bundle.main.url(forResource: "index.html", withExtension: nil, subdirectory: nil)
let item3 = OLPrivacyTermItem.init(title: "自定义服务条款2", linkURL: url!, index: 0)
viewModel.additionalPrivacyTerms = [item1, item2, item3]
let termsRect = OLRect(portraitTopYOffset: 0, portraitCenterXOffset: 0, portraitLeftXOffset: 0, landscapeTopYOffset: 0, landscapeCenterXOffset: 0, landscapeLeftXOffset: 0, size: CGSize(width: 0, height: 0)) // 服务条款偏移、大小设置,偏移量和大小设置值需大于0,否则取默认值,默认可不设置
viewModel.termsRect = termsRect
viewModel.auxiliaryPrivacyWords = ["条款前文案", "&", "&", "条款后的文案"] // 条款之外的文案,默认可不设置

viewModel.clickCheckboxBlock = { (isChecked) in // 点击隐私条款前勾选框回调
print("clickCheckboxBlock isChecked: %@", isChecked ? "true" : "false")
}

viewModel.termsAlignment = NSTextAlignment.center

9、设置授权页面弹出模式

授权页面弹出模式与 iOS UIViewController 的弹出模式保持一致,支持两种方式弹出授权页面,默认以模态方式弹出授权页面

/**
* @abstract 进入授权页面的方式,默认为 modal 方式,即 present 到授权页面,从授权页面进入服务条款页面的方式与此保持一致
*
* @discussion push 模式时,不支持弹窗模式,进入授权页面时,会隐藏导航栏,退出授权页面时,会显示导航栏,如果您进入授权页面的当前页面导航栏为隐藏状态,在授权页面消失时,请注意将导航栏隐藏
*/
typedef NS_ENUM(NSInteger, OLPullAuthVCStyle) {
OLPullAuthVCStyleModal,
OLPullAuthVCStylePush
};

#pragma mark - OLPullAuthVCStyle

/**
* @abstract 进入授权页面的方式,默认为 modal 方式,即 present 到授权页面,从授权页面进入服务条款页面的方式与此保持一致
*/
@property (nonatomic, assign) OLPullAuthVCStyle pullAuthVCStyle;

示例代码

ObjC:

  1. 导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 设置 pullAuthVCStyle

viewModel.pullAuthVCStyle = OLPullAuthVCStylePush; // 默认为 modal

Swift:

  1. 创建混编桥接头文件并导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 设置 pullAuthVCStyle

viewModel.pullAuthVCStyle = OLPullAuthVCStyle.push // 默认为 modal

10、设置状态栏

授权页面状态栏已默认适配黑夜模式,若您使用 SDK 默认的授权页面,可以无需设置状态栏,若您需要改变授权页面的背景,请您根据实际情况设置状态栏

/**
状态栏样式。 默认 `UIStatusBarStyleDefault`。
*/
@property (nonatomic, assign) UIStatusBarStyle statusBarStyle;

示例代码

ObjC:

  1. 导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 设置状态栏

olAuthViewModel.statusBarStyle = UIStatusBarStyleDefault;

Swift:

  1. 创建混编桥接头文件并导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 设置状态栏

viewModel.statusBarStyle = .lightContent

其他接口说明

1、设置日志开关

设置日志开关,建议开发调试时打开日志,上线时关闭日志

/**
* @abstract 设置是否允许打印日志
*
* @param enabled YES,允许打印日志 NO,禁止打印日志
*/
+ (void)setLogEnabled:(BOOL)enabled;

2、获取当前网络信息和运营商信息

获取当前网络信息和运营商信息,该接口可判断当前是否开启了 Wifi 和 蜂窝移动网络,并能准确判断当前蜂窝移动网络是 4G、3G 还是 2G,还能判断当前对应的运营商

/**
获取当前 OneLogin 可用的网络信息

@discussion
当使用的是非移动、联通、电信三大运营商, 则返回nil。
OneLogin 仅在大陆支持移动、联通、电信三大运营商。

@seealso
OLNetworkInfo 中有属性的详细描述
*/
+ (nullable OLNetworkInfo *)currentNetworkInfo;

3、设置超时时长

设置请求超时时长

/**
设置请求超时时长。默认时长5s。

@param timeout 超时时长
*/
+ (void)setRequestTimeout:(NSTimeInterval)timeout;

4、服务条款复选框是否勾选

判断服务条款左边复选框是否勾选

/**
* @abstract 服务条款左边复选框是否勾选
*/
+ (BOOL)isProtocolCheckboxChecked;

5、获取SDK版本号

获取 SDK 版本号

/**
获取SDK版本号

@return SDK当前的版本号
*/
+ (NSString *)sdkVersion;

6、获取当前授权页面

获取当前授权页面对应的 Controller

/**
* @abstract 获取当前授权页面对应的ViewController
*
* @return 当前授权页面对应的ViewController
*/
+ (UIViewController * _Nullable)currentAuthViewController;

7、回调接口

7.1、加载授权页面进度条回调

/**
* 授权页自定义Loading,会在点击登录按钮之后触发
* containerView为loading的全屏蒙版view
* 请自行在containerView添加自定义loading
* 设置block后,默认loading将无效
*/
typedef void(^OLLoadingViewBlock)(UIView *containerView);

7.2、停止授权页面进度条回调

/**
* 停止授权页自定义Loading,会在调用[OneLogin stopLoading]时触发
* containerView为loading的全屏蒙版view
*/
typedef void(^OLStopLoadingViewBlock)(UIView *containerView);

7.3、授权页面视图生命周期回调

/**
* 授权页面视图生命周期回调
* @param viewLifeCycle 值为viewDidLoad、viewWillAppear、viewWillDisappear、viewDidAppear、viewDidDisappear
* @param animated 是否有动画
*/
typedef void(^OLAuthViewLifeCycleBlock)(NSString *viewLifeCycle, BOOL animated);

7.4、监听授权按钮点击的回调

/**
* 点击授权页面授权按钮的回调,用于监听授权页面登录按钮的点击
*/
typedef void(^OLClickAuthButtonBlock)(void);

7.5、点击授权页面勾选框的回调

/**
* 点击授权页面隐私协议前勾选框的回调
*/
typedef void(^OLClickCheckboxBlock)(BOOL isChecked);

7.6、点击授权页面弹窗背景的回调

/**
* 点击授权页面弹窗背景的回调
*/
typedef void(^OLTapAuthBackgroundBlock)(void);

7.7、授权页面旋转时的回调

/**
* @abstract 授权页面旋转时的回调,可在该回调中修改自定义视图的frame,以适应新的布局
*/
typedef void(^OLAuthVCTransitionBlock)(CGSize size, id<UIViewControllerTransitionCoordinator> coordinator, UIView *customAreaView);

7.8、接管授权按钮点击事件的回调

/**
* 是否自定义授权页面登录按钮点击事件,用于完全接管授权页面点击事件,当返回 YES 时,可以在 block 中添加自定义操作
*/
typedef BOOL(^OLCustomAuthActionBlock)(void);

7.9、点击切换账号按钮的回调

/**
* 点击授权页面切换账号按钮的回调
*/
typedef void(^OLClickSwitchButtonBlock)(void);

7.10、点击运营商隐私协议的回调

typedef void(^OLViewPrivacyTermItemBlock)(OLPrivacyTermItem *termItem, UIViewController *controller);

/**
* 点击授权页面运营商隐私协议的回调
*/
@property (nullable, nonatomic, copy) OLViewPrivacyTermItemBlock carrierTermItemBlock;

OneLogin接入行为验证

一键登录 SDK 提供两种方式接入极验的 行为验证 能力,当且仅当您在接入极验一键登录的同时需要结合行为验证时,您才需要搭建您自己的服务来处理行为验证的 api1 和 api2 请求,若您不需要接入行为验证功能,请直接略过本节

1、SDK 内集成行为验证

您只需要传入行为验证的 api1、api2,即可实现集成行为验证功能

示例代码

ObjC:

  1. 导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 设置 captchaAPI1、captchaAPI2 属性

viewModel.captchaAPI1 = GTCaptchaAPI1;
viewModel.captchaAPI2 = GTCaptchaAPI2;

Swift:

  1. 创建混编桥接头文件并导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 设置 captchaAPI1、captchaAPI2 属性

viewModel.captchaAPI1 = GTCaptchaAPI1
viewModel.captchaAPI2 = GTCaptchaAPI2

2、应用内集成行为验证

您需要实现 customAuthActionBlock,接管授权页面一键登录按钮的点击事件,在该 block 中进行行为验证(行为验证集成) ,行为验证完成之后,再调用 startRequestToken 方法获取 token

示例代码

ObjC:

  1. 导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 集成行为验证

- (GT3CaptchaManager *)gt3CaptchaManager {
if (!_gt3CaptchaManager) {
_gt3CaptchaManager = [[GT3CaptchaManager alloc] initWithAPI1:GTCaptchaAPI1 API2:GTCaptchaAPI2 timeout:10.f];
_gt3CaptchaManager.viewDelegate = self;
_gt3CaptchaManager.delegate = self;
}
return _gt3CaptchaManager;
}

- (IBAction)normalLoginAction:(UIButton *)sender {
OLAuthViewModel *viewModel = [OLAuthViewModel new];
viewModel.customAuthActionBlock = ^BOOL{
[wself.gt3CaptchaManager registerCaptcha:nil];
[wself.gt3CaptchaManager startGTCaptchaWithAnimated:YES];
return YES;
};

[OneLoginPro requestTokenWithViewController:self viewModel:viewModel completion:^(NSDictionary * _Nullable result) {
NSLog(@"OneLoginPro requestTokenWithViewController result: %@", result);
[wself finishRequestingToken:result];
sender.enabled = YES;
}];
}


// MARK: GT3CaptchaManagerViewDelegate

- (void)gtCaptchaWillShowGTView:(GT3CaptchaManager *)manager {
NSLog(@"gtCaptchaWillShowGTView");
}

// MARK: GT3CaptchaManagerDelegate

- (void)gtCaptcha:(GT3CaptchaManager *)manager errorHandler:(GT3Error *)error {
NSLog(@"gtCaptcha errorHandler: %@", error);
}

- (void)gtCaptcha:(GT3CaptchaManager *)manager didReceiveSecondaryCaptchaData:(NSData *)data response:(NSURLResponse *)response error:(GT3Error *)error decisionHandler:(void (^)(GT3SecondaryCaptchaPolicy))decisionHandler {
if (!error) {
// 处理验证结果
NSLog(@"\ndata: %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
decisionHandler(GT3SecondaryCaptchaPolicyAllow);
[OneLoginPro startRequestToken];
} else {
// 二次验证发生错误
decisionHandler(GT3SecondaryCaptchaPolicyForbidden);
}
}

Swift:

  1. 创建混编桥接头文件并导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 集成行为验证

private lazy var gt3CaptchaManager: GT3CaptchaManager = {
let manager = GT3CaptchaManager.init(api1: GTCaptchaAPI1, api2: GTCaptchaAPI2, timeout: 5.0)
manager!.delegate = self as GT3CaptchaManagerDelegate
manager!.viewDelegate = self as GT3CaptchaManagerViewDelegate
return manager!
}()

func normalLoginAction(_ sender: UIButton) {
let viewModel = OLAuthViewModel()

viewModel.customAuthActionBlock = { [weak self] () -> Bool in
if let strongSelf = self {
strongSelf.gt3CaptchaManager.registerCaptcha(nil)
strongSelf.gt3CaptchaManager.startGTCaptchaWith(animated: true)
}
return true
}

OneLoginPro.requestToken(with: self, viewModel: viewModel) { [weak self] result in
if let strongSelf = self {
strongSelf.finishRequsetingToken(result: result!)
}
}
}

extension SwiftNewLoginViewController: GT3CaptchaManagerDelegate {
func gtCaptcha(_ manager: GT3CaptchaManager!, errorHandler error: GT3Error!) {
print("gtCaptcha errorHandler: %@", error!)
}

func gtCaptcha(_ manager: GT3CaptchaManager!, didReceiveSecondaryCaptchaData data: Data!, response: URLResponse!, error: GT3Error!, decisionHandler: ((GT3SecondaryCaptchaPolicy) -> Void)!) {
if nil == error {
// 处理验证结果
print("\ndata: %@", String.init(data: data!, encoding: String.Encoding.utf8)!);
decisionHandler(GT3SecondaryCaptchaPolicy.allow);
OneLoginPro.startRequestToken()
} else {
// 二次验证发生错误
decisionHandler(GT3SecondaryCaptchaPolicy.forbidden);
}
}
}

extension SwiftNewLoginViewController: GT3CaptchaManagerViewDelegate {
func gtCaptchaWillShowGTView(_ manager: GT3CaptchaManager!) {
print("gtCaptchaWillShowGTView")
}
}

OnePass(本机号码认证)


注:若只需集成本机号码认证功能,可删除掉 account_login_sdk_noui_core.frameworkEAccountApiSDK.frameworkOneLoginResource.bundle

1、初始化

方法原型

/**
Initializes and returns a newly allocated GOPManager object.

@discussion Register customID from `geetest.com`, and configure your verifyUrl
API base on Server SDK. Check Docs on `docs.geetest.com`. If OnePass
fail, GOPManager will request SMS URL that you set.
@param customID custom ID, nonull
@param timeout timeout interval
@return A initialized GOPManager object.
*/
- (instancetype)initWithCustomID:(NSString * _Nonnull)customID timeout:(NSTimeInterval)timeout;

参数描述

参数 是否必填 类型 说明
initWithCustomID NSString 极验 appID
timeout NSTimeInterval 请求超时

接口作用

传入极验 appID,设置请求超时时长

使用场景

  • 保证在进行本机号码认证之前至少调用一次

示例代码

ObjC:

  1. 导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 在进行本机号码认证之前,初始化,此处使用懒加载方式

- (GOPManager *)gopManager {
if (!_gopManager) {
_gopManager = [[GOPManager alloc] initWithCustomID:GTOnePassAppId timeout:10.f];
_gopManager.delegate = self;
}
return _gopManager;
}

Swift:

  1. 创建混编桥接头文件并导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 在进行本机号码认证之前,初始化,此处使用懒加载方式

private lazy var gopManager: GOPManager = {
let manager = GOPManager.init(customID: GTOnePassAppId, timeout: 10.0)
manager.delegate = self as GOPManagerDelegate
return manager
}()

2、本机号码认证

方法原型

/**
Verify phone number through OnePass.
See a sample result from `https://github.com/GeeTeam/gop-ios-sdk/blob/master/SDK/gop-ios-dev-doc.md#verifyphonenumcompletionfailure`

@param phoneNumber phone number
*/
- (void)verifyPhoneNumber:(NSString * _Nullable)phoneNumber;

参数描述

参数 是否必填 类型 说明
phoneNumber NSString 需进行认证的手机号码

接口作用

获取认证传入的手机号码是否为本机号码、是否与本机 SIM 卡一致(对于双卡手机,则认证是否为当前流量对应的本机号码)需要的 token,具体认证需调用服务端接口,传入该接口获取到的 token 进行验证

使用场景

  • 初始化之后调用

  • 输入手机号后进行认证

示例代码

ObjC:

  1. 导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 进行本机号码认证

- (void)startOnePass {
NSString *phoneNumber = self.phoneNumberTF.text;
phoneNumber = [phoneNumber stringByReplacingOccurrencesOfString:@" " withString:@""];
if ([self checkPhoneNumFormat:phoneNumber]) {
[GTProgressHUD showLoadingHUDWithMessage:nil];
[self.gopManager verifyPhoneNumber:phoneNumber];
} else {
self.phoneNumberTF.text = nil;
[self.phoneNumberTF gtm_shake:9 witheDelta:2.f speed:0.1 completion:nil];
[GTProgressHUD showToastWithMessage:@"不合法的手机号"];
}
}

Swift:

  1. 创建混编桥接头文件并导入极验 SDK 头文件 #import <OneLoginSDK/OneLoginSDK.h>

  2. 进行本机号码认证

func startOnepass() {
var phoneNumber = self.phoneNumberTF.text
phoneNumber = phoneNumber?.replacingOccurrences(of: " ", with: "")
if self.checkPhoneNumFormat(phoneNumber) {
GTProgressHUD.showLoadingHUD(withMessage: nil)
self.gopManager.verifyPhoneNumber(phoneNumber)
} else {
self.phoneNumberTF.text = nil
self.phoneNumberTF.gtm_shake(9, witheDelta: 2.0, speed: 0.1, completion: nil)
GTProgressHUD.showToast(withMessage: "不合法的手机号")
}
}

返回码

1、OneLogin(一键登录)

错误码 描述 处理方式
-20101 app_id 未传 请先调用 registerWithAppID: 方法传入 appId
-20102 没有预取号就进行取号 1、常规逻辑,请先调用 preGetTokenWithCompletion: 方法进行预取号,再调用 requestTokenWithViewController:viewModel:completion: 方法进行取号
2、进阶逻辑,请先调用 registerWithAppID: 方法,再调用 requestTokenWithViewController:viewModel:completion: 方法进行取号
-20105 预取号超时或者拉起授权页超时 1、在网络信号较好的地方重试
2、修改 SDK 超时时间配置,适当延长超时时间
-20106 取号时更换了 SIM 卡 更换到预取号时使用的 SIM 卡或者重新进行预取号
-20402 正在拉起授权页面,仍然调用 requestTokenWithViewController:viewModel:completion: 方法进入授权页面 若要重新拉起授权页面,请先关闭当前授权页面
-20403 AuthViewController 已经拉起的情况下,仍然调用 requestTokenWithViewController:viewModel:completion: 方法进入授权页面 若要重新拉起授权页面,请先关闭当前授权页面
-20404 当前正在预取号,再次调预取号接口 预取号结束后再调预取号接口
-20405 当前正在调用运营商接口取号,再次调取号方法 取号结束后再调用取号方法
-20200 当前网络不可用 请检查您的网络状态
-20202 当前没有开启蜂窝网路 请打开蜂窝移动网络
-20203 不支持的运营商,只支持中国移动、中国电信、中国联通三大运营商 请查看是否有插入 SIM 卡
-20302 点击授权页面按返回按钮退出授权页面 关闭授权页,等待用户重新拉起授权页登录
-20303 点击授权页面切换账号按钮 关闭授权页,等待用户重新拉起授权页登录或者直接使用其他方式进行登录
-40101 移动运营商预取号失败 参考移动运营商错误码处理方式处理
-40201 联通运营商预取号失败 参考联通运营商错误码处理方式处理
-40301 电信运营商预取号失败 参考电信运营商错误码处理方式处理
-40102 移动运营商取号失败 参考移动运营商错误码处理方式处理
-40202 联通运营商取号失败 参考联通运营商错误码处理方式处理
-40302 电信运营商取号失败 参考电信运营商错误码处理方式处理
-50100 SDK 内部请求 pre_get_token 接口返回异常 1、检测网络访问情况,正常上网时重试
2、检测产品 APPID 与后台配置的包名包签名是否匹配
-50101 SDK 内部请求 pre_get_token 接口解密失败 1、检测网络访问情况,正常上网时重试
2、检测产品 APPID 与后台配置的包名包签名是否匹配

无法使用数据网络(2G, 3G, 4G)的可能原因:

  1. 应用没有提供数据网络权限, 导致无法访问
  2. 手机卡欠费, 导致无法访问数据网络
  3. 所在区域的数据网络信号不佳, 导致访问超时
  4. 如果设备连接的数据网络自动降级了, 部分运营商对较旧的网络制式支持并不稳定
  5. 设备没有使用有效的 SIM 卡

2、OnePass(本机号码认证)

错误码 描述 处理方式
-20301 GOPErrorInvalidPhoneNumber 手机号码不可用 请传入合法的手机号
-20302 GOPErrorUnsupportedNetwork 网络不支持 请打开蜂窝移动网络
-20303 GOPErrorUnsupportedOperator 运营商不支持 请查看是否有插入 SIM 卡
-39901 GOPErrorSocketError Socket 错误 请检查应用是否拥有蜂窝网络数据权限,蜂窝数据网络是否通畅,在网络信号较好的地方重试
-40101 移动运营商预取号失败 参考移动运营商错误码处理方式处理
-40201 联通运营商预取号失败 参考联通运营商错误码处理方式处理
-40301 电信运营商预取号失败 参考电信运营商错误码处理方式处理
-50100 GOPErrorInvalidPreGatewayReturns pregateway 返回结果有误 1、检测网络访问情况,正常上网时重试
2、检测产品 APPID 与后台配置的包名包签名是否匹配

3、运营商错误码

移动

错误码 描述 处理方式
102101 无网络 开启网络后重试
102203 输入参数缺失(缺少appid、appkey、capaId其中任何一个时返回) 检查输入参数后重试
102506 请求出错 检查网络后重试
102507 请求超时 检查网络后重试
102508 数据网络切换失败 开启数据网络后重试
102509 未知错误,错误详情请看异常堆栈信息 查看错误信息后重试
103101 请求签名错误 1、检查appid和appkey是否有传对
2、iOS工程中的Infoplist.strings国际化文件,添加bundleId对应的key-value。如果app存在本地国际化文件,请在每个本地国际化文件中添加CFBundleIdentifier,各个语言版本文件中都需要添加
103102 包签名/Bundle ID错误 1、后台配置信息与移动保存信息不符
2、iOS本地国际化文件问题
103111 网关IP错误 wifi切数据通道失败
电信或联通发送取号请求,但被误判为移动运营商
网关取号出错
使用了vpn/代理,导致检查ip为非移动网关ip
103119 appid不存在 请联系工程师处理
103125 短验下发时,手机号填写格式错误 请联系工程师处理
103901 短验下发次数已达上限(5次/min,30次/day) 请联系工程师处理
103902 scrip失效 请联系工程师处理
103911 token请求过于频繁,10分钟内获取token且未使用的数量不超过30个 token请求过于频繁,请过半小时后重试
103273 预取号联通重定向(暂不支持联通取号) 请联系工程师处理
103414 参数校验异常 请联系工程师处理
103412 无效的请求 请联系工程师处理
103401 消息签名为空 请联系工程师处理
103404 加密失败 请联系工程师处理
103408 此sourceId注册已达上限99次 请联系工程师处理
103409 query参数为空 请联系工程师处理
105002 移动取号失败 物联网卡,不允许取号
105003 电信取号失败 请联系工程师处理
105021 已达当天取号限额 请第二天再尝试取号
105302 appid不在白名单 请联系工程师处理
105313 非法请求 请联系工程师处理
200002 没有sim卡 插入sim卡后重试
200005 用户未授权 授予READ_PHONE_STATE权限后重试
200009 应用合法性校验失败 检查正在请求的应用的签名、包名是否是与后台登的信息一致
200010 未开启移动网络 检查手机移动网络是否开启
200021 数据解析异常 请联系工程师处理
200022 无网络 请检查网络后重试
200023 请求超时 如果用户所处网络信号较差也容易导致超时增加,请检查网络后重试
200026 输入参数错误 请检查参数后重试
200027 未开启数据网络 请开启移动网络后重试
200028 网络请求出错 网络请求出错,一般出现在网络安全策略限制了不能使用http、设备开启了代理或连接的WiFi有网络链接安全策略限制的场景,建议结合SDK日志具体分析
200030 没有初始化参数 请联系工程师处理
200038 异网取号网络请求失败 请联系工程师处理
200048 用户未安装sim卡 请联系工程师处理
200050 EOF异常 请联系工程师处理
200060 切换账号(未使用SDK短验时返回) 请联系工程师处理
200062 预取号不支持联通 请联系工程师处理
200063 预取号不支持电信 请联系工程师处理
200064 服务端返回数据异常 请联系工程师处理
200072 CA根证书校验失败 CA根证书校验失败,常见于开启了代理抓包的场景
200080 本机号码校验仅支持移动手机号 请检查插入的SIM是否为移动制式
200082 服务器繁忙 请稍后重试

电信

错误码 描述 处理方式
-64 permission-denied(无权限访问) 电信方权限问题,请联系工程师处理
-65 API-request-rates-Exceed-Limitations(调用接口超限) 检查网络状况后重试
-10001 取号失败 请联系工程师处理
-10002 参数错误 检查参数后重试
-10003 解密失败 请联系工程师处理
-10004 ip 受限 ip白名单;电信网关数据更新未及时同步到系统
-10005 异网取号回调参数异常 请联系工程师处理
-10006 Mdn 取号失败,且属于电信网络 请联系工程师处理
-10007 重定向到异网取号 请联系工程师处理
-10008 超过预设取号阈值 第二天重试,或增加阈值
-10009 时间戳过期 检查手机端系统时间后重试
-20005 sign-invalid(签名错误) 1、Android签名配置错误
2、iOS topclass出错
3、在平台修改后未生效(1小时生效)
-20006 应用不存在 请联系工程师处理
-20007 公钥数据不存在 请联系工程师处理
-20100 内部解析错误 请联系工程师处理
-20102 加密参数解析失败 请联系工程师处理
-30001 时间戳非法 检查手机端系统时间后重试
-30003 topClass 失效 topclass无效
-8000 responseCode非200(网络错误,http状态码错误) 请联系工程师处理
-8001 请求网络异常 网络异常;未获取权限;wifi设置level代理;预取号的时候走http,但是app设置了只能走https;没有添加so库
-8001 请求网络异常 请检查网络后重试
-8002 请求参数异常 请检查网络后重试
-8003 请求超时 请检查网络后重试,建议开启手机4G功能
-8004 移动网络未开启 请检查移动网络是否开启
-8005 请先初始化SDK 请先初始化SD
-8100 网络无连接 请检查网络后重试
-8101 获取失败(切换失败) 请检查网络后重试
-8100 无网络连接(网络错误) 请检查网络后重试
-8102 Socket超时异常(读取超时、连接超时) 请检查网络后重试
-8103 域名解析异常 电信DNS解析异常
-8104 IO异常 请联系工程师处理
-8201 响应码错误 请联系工程师处理
-9999 网络故障(networkauth-fail) 请检查网络后重试
-720001 切换异常 切换流量卡时网络不稳定,开启移动网络后重试
-720002 切换异常超时 切换流量卡时网络不稳定,开启移动网络后重试

联通

错误码 描述 处理方式
100 应用未授权 请联系工程师处理
101 应用秘钥错误 请联系工程师处理
102 应用无效 请联系工程师处理
103 应用未授权该IP访问 请联系工程师处理
104 应用访问次数不足 请联系工程师处理
105 应用包名不正确 请联系工程师处理
106 应用状态非法 请联系工程师处理
107 商户状态非法 请联系工程师处理
108 商户请求次数超限额 请联系工程师处理
200 tokenId无效 请联系工程师处理
201 token已失效 请联系工程师处理
202 token未授权该应用访问 请联系工程师处理
203 登录鉴权级别不满足接口鉴权要求 请联系工程师处理
300 接口未开放 请联系工程师处理
301 应用未授权码访问该接口 请联系工程师处理
302 IP未授权码访问该接口 请联系工程师处理
303 应用访问接口次数超日限额 请联系工程师处理
400 请求参数为空 请联系工程师处理
401 请求参数不完整 请联系工程师处理
402 请求参数非法 请联系工程师处理
600 请求非法 请联系工程师处理
1000 请求解析错误 请联系工程师处理
1001 请求已失效 请联系工程师处理
1002 验签失败 请联系工程师处理
1003 授权码已过期 请联系工程师处理
1004 加密方式不支持 请联系工程师处理
1005 RSA加密错误 请联系工程师处理
1010 服务间访问失败 请联系工程师处理
1011 服务间访问错误 请联系工程师处理
2004 用户不存在 请联系工程师处理
3002 跳转异网取号 请联系工程师处理
3003 本网执行取号失败,不需要重定向 请联系工程师处理
3004 NET取号失败 请联系工程师处理
3005 上网方式为WIFI,无法取号 请联系工程师处理
3006 urlencode编码失败 请联系工程师处理
3007 请求认证接口异常 请联系工程师处理
3009 非联通号码 请联系工程师处理
3010 网关取号错误 请联系工程师处理
3011 源IP鉴权失败 请联系工程师处理
3012 网关取号失败 请联系工程师处理
3013 电信网关取号失败 请联系工程师处理
3014 电信网关取号错误 请联系工程师处理
3015 回调消息缓存已失效 请联系工程师处理
3016 移动网关取号失败 请联系工程师处理
3017 移动网关取号错误 请联系工程师处理
3018 生成授权码失败 请联系工程师处理
3032 APPID不存在 请联系工程师处理
3050 取号网关内部错误 请联系工程师处理
3051 公网IP校验错误 请联系工程师处理
3052 公网IP无法找到对应省份 请联系工程师处理
3053 公网IP省份编码与输入不符 请联系工程师处理
3054 私网IP校验错误 请联系工程师处理
3055 私网IP查找号码失败 请联系工程师处理
3056 省份暂不支持取号 请联系工程师处理
3057 网关鉴权码查找号码失败 请联系工程师处理
3058 网关鉴权码格式错误 请联系工程师处理
3059 网关鉴权码已失效 请联系工程师处理
3060 网关账号认证失败 请联系工程师处理
3061 网关取号配额不足 请联系工程师处理
3062 IP未授权访问网关 请联系工程师处理
3063 网关并发连接数受限 请联系工程师处理
3064 访问网关参数非法 请检查参数后重试
3065 未授权访问该网关能力 请联系工程师处理
3066 网关服务暂时不可用 请检查网络后重试
170001 网络错误 请检查网络后重试
170002 获取Token失败 请联系工程师处理
170003 运营商未支持 请联系工程师处理
170004 运营商 sdk 为空 请将运营商 SDK 集成到工程中
170005 没有手机卡 请插入 SIM 卡后重试
170102 Appkey不存在 请传入appKey
170201 未知数据错误 请联系工程师处理
170202 超时 请检查网络后重试
170203 预登录失败 请联系工程师处理
170204 取消一键登录 请联系工程师处理
170205 一键登录失败 请联系工程师处理
170206 一键登录入口为空 请联系工程师处理
170301 切换登录方式 请联系工程师处理
170500 try块捕捉到异常 请联系工程师处理
170601 蜂窝网络未开启 开启移动网络后重试
170606 获取验证码次数超限 请联系工程师处理

4、Cocoa

metaData 中可能含有 Cocoa 的错误码, 来自 NSURLErrorDomain 的错误

ErrorCode Description
-999 NSURLErrorCancelled请求被取消
-1000 NSURLErrorBadURLURL异常
-1001 NSURLErrorTimedOut请求超时
-1002 NSURLErrorUnsupportedURL不支持的URL
-1003 NSURLErrorCannotFindHost无法找到主机
-1004 NSURLErrorCannotConnectToHost无法连接到服务器
-1005 NSURLErrorNetworkConnectionLost网络丢失, 一般弱网或者网络突然中断导致
-1006 NSURLErrorDNSLookupFailedDNS查询失败
-1007 NSURLErrorHTTPTooManyRedirects过多的请求跳转, 服务器返回过多的302
-1008 NSURLErrorResourceUnavailable访问的资源不可用
-1009 NSURLErrorNotConnectedToInternet未连接到互联网
-1010 NSURLErrorRedirectToNonExistentLocation重定向到不存在的地址
-1011 NSURLErrorBadServerResponse服务器无响应
-1012 NSURLErrorUserCancelledAuthentication客户端取消了安全认证, 或者证书不匹配或服务端不支持ssl和tls
-1013 NSURLErrorUserAuthenticationRequired客户端要求安全认证, 服务端不支持ssl或tls
-1014 NSURLErrorZeroByteResource返回字节流为空
-1015 NSURLErrorCannotDecodeRawData无法解析的原始数据
-1016 NSURLErrorCannotDecodeContentData解析返回内容错误
-1017 NSURLErrorCannotParseResponse无法解析响应体
-1102 NSURLErrorNoPermissionsToReadFile无资源访问权限, 一般为challenge等参数有误, challenge只可被用来请求一次, 失效后可能会遇到该问题
-1200 NSURLErrorSecureConnectionFailed创建安全连接失败
-1201 NSURLErrorServerCertificateHasBadDate服务端证书异常
-1202 NSURLErrorServerCertificateUntrusted服务端证书不可信
-1203 NSURLErrorServerCertificateHasUnknownRoot服务端使用未知的根证书

插件资源

1.客户端集成插件(除了原生的 iOS SDK 之外,OneLogin 提供主流的开发工具集成插件)

React Native: https://github.com/GeeTeam/gt-onelogin-rn-example

Flutter: https://github.com/GeeTeam/gt-onelogin-flutter-example

2.更详细示例代码见 Demo

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