SDK说明
适用版本
本文匹配的 SDK 版本:2.0.5及以上版本。 使用 Xcode 10.0 及以上版本
资源文件
待定??
创建应用
在 创蓝万数平台的闪验 上创建应用,通过审核后将会得到appKey
和appID
集成闪验SDK基本步骤:
- 导入SDK
- 预初始化
- 调起一键登录并获取Token
注: Token用于获取真实手机号,开发者需在SDK外部,将SDK获取到的Token及其附带信息作为参数,以form-data格式发送,自行调用查询手机号接口
。此接口可参考闪验后台接入文档
一. 导入SDK
方式 1:手动导入:
-
导入framework: 将闪验SDK压缩包中framework文件夹下所有资源添加到工程中(注意勾选
copyItems if need
) -
Xcode配置:
- 关闭
BitCode
:在xcode->BuildSetting->EnableBitcode
设置为 NO - 添加
OtherLinkerFlags
项 -ObjC:在xcode->BuildSetting->Other Linker Flags
添加 -ObjC - 添加
libc++.1.tdb
: 在xcode->General->Linked Frameworks and Libraries
中点击 + ,搜索并选择添加 libc++.1.tdb
- 关闭
-
SWIFT工程需要额外添加
-force_load
:- 在
xcode->BuildSetting->Other Linker Flags
添加-force_load
- 在
-force_load
下方添加CL_ShanYanSDK.framework/CL_ShanYanSDK
所在路径,具体操作可以将CL_ShanYanSDK.framework
拖入空栏,在尾部拼接静态库名称CL_ShanYanSDK
,将前缀绝对地址改成相对地址$(SRCROOT)
,最终为"$(SRCROOT)/.../CL_ShanYanSDK.framework/CL_ShanYanSDK"
形式
- 在
方式 2:CocoaPods导入:即将开放
二. 预初始化
2.0.5 版本开始,API 类名为 CLShanYanSDKManager,使用类方法直接调用,不再需要开发者维护实例化对象
SDK API说明
- 接口名称
/**预初始化*/
+(void)initWithAppId:(NSString *)appId AppKey:(NSString *)appKey timeOut:(NSTimeInterval)timeOut complete:(nullable CLComplete)complete;
复制代码
- 接口参数详细说明
appId
: 必填 闪验appIDappKey
: 必填 闪验appKeytimeOut
: 选填 超时时间,单位s,传大于0有效,传小于等于0使用默认,默认5scomplete
: 选填 预初始化回调block,可以在此回调block中接收预初始化情况,也可以不关心预初始化结果
使用场景
- 建议在app启动时调用
- 必须在一键登录前至少调用一次
- 只需调用一次
请求示例代码
- 导入闪验SDK头文件
#import <CL_ShanYanSDK/CL_ShanYanSDK.h>
- 在AppDelegate中的
didFinishLaunchingWithOptions
方法中添加预初始化代码
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
...
//预初始化
[CLShanYanSDKManager initWithAppId:cl_SDK_APPID AppKey:cl_SDK_APPKEY timeOut:4 complete:nil];
...
复制代码
三. 调起一键登录并获取Token
一键登录流程简介
- 开发者在用户登录时调用认证SDK的
初始化方法
,初始化成功时,获取到脱敏手机号并进入授权页。 - 进入授权页后,开发者点击
免密登录
按钮,认证SDK将返回取号token给应用客户端。 - 应用服务器携带本次会话的token前往认证服务器获取用户的手机号码信息
SDK API说明
- 接口名称
/**
一键登录(授权页)
@param cuccConfigure 联通配置
@param timeOut 超时时间,单位s,传大于0有效,传小于等于0使用默认,默认5s
@param complete 回调block
*/
+(void)quickAuthLoginWithConfigureCUCC:(CLCUCCUIConfigure *)cuccConfigure
timeOut:(NSTimeInterval)timeOut
complete:(nonnull CLComplete)complete;
复制代码
- 接口参数详细说明
-
cuccConfigure
: 必填 联通配置对象.viewController
:必填 调一键登录的vc- 其他属性为授权页页面微调属性,均为选填,不传则使用默认
-
timeOut:选填 超时时间,单位s,传大于0有效,传小于等于0使用默认,默认5s
-
complete:必填 回调block,用于接收一键登录的结果
-
使用场景
- 用户进行一键登录操作时,调用一键登录方法,如果初始化成功,SDK将会拉起授权页面,用户授权后,SDK将返回取号 token给到应用客户端。
- 可以在多处调用
- 需在调用预初始化方法之后调用
- 注: Token用于获取真实手机号,开发者需在SDK外部,将SDK获取到的Token及其附带信息作为参数,以form-data格式发送,自行调用
查询手机号接口
。此接口可参考闪验后台接入文档
请求示例代码
- 导入闪验SDK头文件
#import <CL_ShanYanSDK/CL_ShanYanSDK.h>
- 在需要使用一键登录的地方调用闪验一键登录接口
// 用户需要使用闪验一键登录时的方法
- (void)quickLoginBtnClick:(UIButton *)sender {
__weak typeof(self) weakself = self;
//联通配置
CLCUCCUIConfigure * cuccUIConfigure = [CLCUCCUIConfigure new];
cuccUIConfigure.viewController = self;
//用户自己的loading
[SVProgressHUD setContainerView:self.view];
[SVProgressHUD show];
//闪验一键登录接口(将拉起授权页)
[CLShanYanSDKManager quickAuthLoginWithConfigureCUCC:cuccUIConfigure timeOut:4 complete:^(CLCompleteResult * _Nonnull completeResult) {
if (completeResult.error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (completeResult.code == 1009){
// 无SIM卡或不是联通卡
}else if (completeResult.code == 1011 || completeResult.code == 1012){
// 用户取消登录
}else if (completeResult.code == 1013){
// 用户选择其他方式登录
}else if (completeResult.code == -99999){
//未打开蜂窝移动网络
}else {
//网络状况不稳定,切换至验证码登录
}
});
}else{
//开发者需将此data字典作为参数,以form-data格式完整地发送到开发者后台配置的查询手机号API,在调试阶段也可以使用已下示例
//example:
NSString * telecom = [completeResult.data valueForKey:@"telecom"];
NSString * urlStr = nil;
if ([telecom isEqualToString:@"CUCC"]) {
urlStr = [cl_SDK_URL stringByAppendingString:@"open/flashsdk/mobile-query-u"];
}else{
//失败
[SVProgressHUD showInfoWithStatus:@"此手机无SIM卡或不是联通卡"];
return;
}
if (urlStr) {
NSLog(@"tokenParamr:%@",completeResult.data);
[NetWorkManager POST_url:urlStr withParameter:completeResult.data complete:^(NSDictionary * _Nonnull responseObject, NSError * _Nonnull error) {
if (error) {
NSLog(@"%@",error);
}else{
NSInteger chargeStatus = [[responseObject valueForKey:@"chargeStatus"] integerValue];
if (chargeStatus == 1) {
NSString * mobileName = responseObject[@"data"][@"mobileName"];
NSString * mobileCode = [mobileName decryptUseDESKey:cl_SDK_APPKEY];
dispatch_async(dispatch_get_main_queue(), ^{
[SVProgressHUD showSuccessWithStatus:[NSString stringWithFormat:@"免密登录成功,手机号:%@",mobileCode]];
});
NSLog(@"免密登录成功,手机号:%@",mobileCode);
} else {
dispatch_async(dispatch_get_main_queue(), ^{
[SVProgressHUD showSuccessWithStatus:[NSString stringWithFormat:@"免密登录失败"]];
});
NSLog(@"免密登录失败:%@",responseObject);
}
}
}];
}
}
}];
}
复制代码
-quickAuthLoginWith:complete:正确返回示例
completeResult->_data:
{
accessToken = 453039d47fa7e10a3624763d49606e44;
appId = XXXXXXXX;
device = iPhone6sPlus;
randoms = "34988845-27cb-4b6d-b433-15cde08d009c";
sign = "0uhhHU6CBT9eifq9iuL7UNxAhQA=";
telecom = CUCC;
timestamp = 1542607996672;
version = "2.0.5";
}
复制代码
开发者需将此data字典作为参数,以form-data格式完整地发送到开发者后台配置的查询手机号API
,在调试阶段也可以使用Demo中的API
-quickAuthLoginWith:complete:报错处理
completeResult->_error
:
- 用户取消登录(授权页点击返回) 【处理建议:若无特殊需求可不做处理】
- 用户选择其他方式登录(点击授权页自带的其他方式登录): 【处理建议:可根据实际情况跳转其他登录方式 】
- 其他错误 【处理建议:使用闪验通道失败,可根据实际情况跳转其他登录方式 】
token查询手机号API
正确返回示例
{
"chargeStatus": 1,
"message": "成功",
"data": {
"tradeNo": "18112115031414011",
"mobileName": "OaLj8kkXPwFGp/eRk+3vQQ\u003d\u003d"
},
"code": "200000"
}
复制代码
- chargeStatus:1成功,其他失败
- tradeNo:交易流水号
- mobileName:DES加密的真实手机号,使用CBC模式,PKCS5Padding填充原则。CBC模式对应的iv偏移向量为:byte[] iv = { 1, 2, 3, 4, 5, 6, 7, 8 },key为appKey
授权页页面调整说明
联通授权页页面可调整属性:
//联通配置
**CLCUCCUIConfigure**:
UIImage * UAPageNavLeftLogo;//设置导航栏返回图标
UIColor * UAPageNavBackgroundColor;//设置导航栏背景色
NSString * UAPageNavTitle;//设置导航栏标题文字内容
NSNumber * UAPageNavHelpHidden;//设置帮助按钮显示或隐藏,YES隐藏,NO显示
NSNumber * UAPageNavLineHidden;//设置导航栏头部横线显示或隐藏,YES隐藏,NO显示
UIImage * UAPageContentLogo;//设置logo图片,默认为联通logo
UIColor * UAPageContentLoginButtonBGColor;//设置登录按钮的底色
UIImage * UAPageContentLoginButtonBGImage;//设置登录按钮背景图(如果同时设置按钮底色,底色将覆盖背景图)
NSNumber * UAPageContentLoginButtonCornerRadius;//设置登录按钮圆角(根据按钮高度调整圆角)
UIFont * UAPageContentLoginButtonTitleFont;//设置登录按钮字体和大小
UIColor * UAPageContentLoginButtonTitleColor;//设置登录按钮字体颜色
NSString * UAPageContentLoginButtonTitle;//设置登录按钮文字
NSNumber * UAPageLoadingBackgroundWidth;//设置Loading背景宽度
NSNumber * UAPageLoadingBackgroundHeight;//设置Loading背景高度
UIColor * UAPageLoadingBackgroundColor;//设置Loading背景颜色
NSNumber * UAPageLoadingBackgroundRadius;//设置Loading背景圆角
NSString * UAPageLoadingTitle;//设置Loading提示文字内容
UIColor * UAPageLoadingTitleColor;//设置Loading提示文字颜色
UIFont * UAPageLoadingTitleFont;//设置Loading提示文字大小
NSNumber * UAPageLoadingTitleHeight;//设置Loading提示文字高度
NSMutableArray * UAPageLoadingResArray;//设置Loading动画帧图片数组(必须为UIImage对象
NSNumber * UAPageLoadingResDuration;//设置Loading动画一次完整效果的持续时间
NSNumber * UAPageLoadingResWidth;//设置Loading动画宽度
NSNumber * UAPageLoadingResHeight;//设置Loading动画高度
//添加自定义控件
void (^cuccCustomAreaView)(UIView *customAreaView);
复制代码
联通授权页添加自定义控件示例:
// 快捷登录
- (void)quickLoginBtnClick:(UIButton *)sender {
...
//联通定制界面
CLCUCCUIConfigure * cuccUIConfigure = [CLCUCCUIConfigure new];
cuccUIConfigure.viewController = self;
//授权页添加自定义视图示例,可选
cuccUIConfigure.cuccCustomAreaView = ^(UIView * _Nonnull customAreaView) {
UIButton *otherLoginWayBtn = [[UIButton alloc] init];
[otherLoginWayBtn.titleLabel setFont:[UIFont systemFontOfSize:15.0*WIDTHRADIU]];
[otherLoginWayBtn setTitle:@"其他方式登录" forState:UIControlStateNormal];
otherLoginWayBtn.titleLabel.textAlignment = NSTextAlignmentCenter;
// 根据字体得到NSString的尺寸
CGSize otherLoginWayBtnSize = [otherLoginWayBtn.titleLabel.text sizeWithAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIFont systemFontOfSize:15.0*WIDTHRADIU],NSFontAttributeName, nil]];
CGFloat otherLoginWayBtnOffsetX = 0.5*(UIScreen.mainScreen.bounds.size.width - otherLoginWayBtnSize.width*WIDTHRADIU);
CGFloat otherLoginWayBtnOffsetY = 30*WIDTHRADIU;
otherLoginWayBtn.frame = CGRectMake(otherLoginWayBtnOffsetX, otherLoginWayBtnOffsetY, otherLoginWayBtnSize.width*WIDTHRADIU, otherLoginWayBtnSize.height*WIDTHRADIU);
[otherLoginWayBtn setTitleColor:[UIColor colorWithRed:139/255.0 green:142/255.0 blue:149/255.0 alpha:1] forState:UIControlStateNormal];
[customAreaView addSubview:otherLoginWayBtn];
[otherLoginWayBtn addTarget:weakself action:@selector(otherLoginWayBtnClicedCUCC:) forControlEvents:UIControlEventTouchUpInside];
};
//开发者自己的Loading
[SVProgressHUD setContainerView:self.view];
[SVProgressHUD show];
[CLShanYanSDKManager quickAuthLoginWithConfigureCUCC:cuccUIConfigure timeOut:4 complete:^(CLCompleteResult* _Nonnull completeResult) {
...
}
//自定义界面绑定的方法
-(void)otherLoginWayBtnClicedCUCC:(UIButton *)sender{
dispatch_async(dispatch_get_main_queue(), ^{
//建议用联通传入的viewcontroller来dismiss
[[UIApplication sharedApplication].delegate.window.rootViewController dismissViewControllerAnimated:YES completion:nil];
});
[SVProgressHUD showInfoWithStatus:@"用户使用手机验证码进行注册登录"];
}
复制代码
修改联通授权页中的图片:
uni_account_login_sdk_res.bundle
文件夹为联通资源文件夹,可用同名图片替换(bundle中无法直接查看原图片尺寸,可以将图片复制到外部查看)
SDK 错误代码对照表
外层错误码:用于快速分类问题,同一外层码可能对应不同的内层码
外层返回码 | 返回码描述 |
---|---|
1000 | 一键登录成功,解析result,可得到网络请求参数 |
1001 | SDK初始化失败 |
1002 | 运营商信息获取失败 |
1003 | 一键登录联通获取token失败 |
1007 | 网络请求失败 |
1008 | 未开启移动网络 |
1009 | 未检测到sim卡 |
1011 | 移动/联通取消免密登录 |
1013 | 用户使用验证码进行注册登录 |
1014 | 未知错误 |
1015 | 签名验证不通过 |
1016 | APPID为空 |
1017 | AppKey为空 |
1018 | 无网络(缺少时间参数) |
1019 | 系统异常/余额不足/请求非法超时 |
1020 | 非三大运营商,无法使用一键登录功能 |
1021 | 运营商信息获取失败(accessToken失效) |
内层code返回码:用于精确定位问题
- 外层Code为1003或者1103时,内层code返回码(联通返回码)
状态码 | 信息(msg) | 示例说明 |
---|---|---|
100 | 成功 | |
101 | 鉴权失败 | 公钥或者apiKey不正确 |
103 | 成功(无数据返回) | |
104 | 系统繁忙 | |
100000 | 通用,未明确定义的其他错误 | |
100001 | 网络出错 | apiKey配置错误或者404错误 |
100002 | 参数错误 | 服务未初始化 |
100003 | 数据格式错误 | 服务器返回结果在客户端解析出错 |
100004 | 无结果 | 服务器返回null |
100005 | 数据不匹配 | 短信上行的认证结果与填入的不匹配计为认证失败 |
100006 | 包名不匹配 | 服务器返回的结果非本app计为失败 |
100007 | apikey为空 | 应用未填入apiKey密钥 |
100008 | 超时 | 取号或认证时间超过超时时间 |
100009 | 取消 | 用户取消操作,计为失败 |
100012 | 无公钥 | 应用未填入公钥 |
100016 | 公钥出错 | |
2001 | 取号/认证失败 | |
5001 | 序列号不存在 | seq过期或已使用(seq只能使用一次) |
6001 | 参数出错 | 配置信息填写错误 |
6002 | 应用信息错误 | |
6003 | SDK信息错误 | |
6005 | 接入信息错误 | |
6006 | 获取接入信息流控类型错误 | |
6008 | 流控超限 | |
6009 | 设备信息未注册 | |
6010 | 应用秘钥信息不匹配 | |
7004 | 公司或应用ID信息出错 | |
8001 | 无支付权限 | |
8002 | 余额不足 |
- 外层Code为1019或者1002时,内层返回码(java后台返回码)
返回码 | 返回码描述 |
---|---|
0 | 成功 |
403000 | 网关校验失败(例如验签等等) |
6006 | 鉴权失败(例如验签等等) |
6007 | 账户余额不足 |
10022 | 参数校验不通过 |
000102 | SDK未初始化完成,请联系客服 |
9999 | 系统异常 |
常见问题
-
运行报
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[CLSDKInitModel cl_modelInitWithCoder:]: unrecognized selector sent to instance
错误- 解决方案:添加
OtherLinkerFlags
项-force_load
,参考 Xcode配置添加-force_load
- 解决方案:添加
-
报 403000 6006 请求非法,签名验证不通过
- 解决方案:
- 替换Demo中appid/appkey和bundleID为自己申请的,运行Demo确定Demo是否可以正常完成流程,如果不能,请联系客服。
- 如果Demo正常运行,用开发者自己的工程运行报403000,请检查最后一步用获取到的token调用
手机号查询API
是,是否是以form-data格式发送参数:使用AFN或者Alamofire直接发送completeResult.data,使用原生NSURLSession请将completeResult.data的每个字段值进行URLEncode编码再拼接成form-data格式字符串("key1=value1&key2=value2&...")再发送,Demo内有两种方式发送的示例代码 - 关于如何确定最终是否以formData形式发送,可以使用charls抓包工具,查看request的headers里的Content-Type是否为
application/x-www-form-urlencoded
,以及completeResult.data的sign字段带有 + 号时 + 号丢失的情况 - 如果开发者后台已经接入
手机号查询API
,请开发者后台也确认后台的发送格式
- 解决方案:
-
如何修改授权页返回按钮和logo图标
- 解决方案:参考修改联通授权页中的图片