本文为您介绍号码认证服务一键登录(IOS)的配置流程。

1. 概述

本文档仅适用于2.6.10及以下版本,全新V2.7.0SDK已发布,建议查看新版文档对接新版SDK。

iOS2.6.8版本需使用xCode11才能支持。

官网下载SDK后进行解压,解压后包含三个文件是

  • iOS SDK开发接入文档
  • AliComSDKDemo工程
  • ATAuthSDK.framework

SDK同时包含了本机号码校验和一键登录两个功能。请根据您的需要选择对应的功能进行对接。本篇主要介绍一键登录的功能:

一键登录使用场景:用户无需输入手机号码,SDK会拉起授权页,用户确认授权后,SDK会获取token,服务端携带token到运营商网关获取用户当前上网使用的号码,并返回给APP服务端。

准备工作

  • 请确保您的终端设备已经开启了4G网络(联通、移动支持3G网络,但接口耗时会增加)。
  • 请确保已经在阿里云控制台开通了号码认证服务并创建了对应的方案,点击进入阿里云控制台。
  • 您也可以登录阿里云官网查看接入流程,点击查看完整使用流程。

3. 运行demo工程

解压后包含AliComSDKDemo工程,您需要将bundleID和开发者证书修改为您自己有的。

4. 开发环境搭建

  • 添加主库
    Targets->General->Linked Frameworks and Librarie中添加主库ATAuthSDK.framework;
  • Targets->BuildSettings设置

    Targets->BuildSettings 中 , Other Linker Flags增加-Objc,一定要添加磁性,注意是大写C,不是小写c,否则工程运行会crash!!!

  • Targets->Info设置
    由于某运营商还存在http请求,所以请确保Targets->Info 中ATS 开关已开启,并设置为YES ;
  • 添加资源文件

    主项⽬右键添加下ATAuthSDK.framework 中ATAuthSDK.bundle 和TYRZResource.bundle资源⽂件,否则⼀键登录授权⻚⾯图⽚或icon显示不出来;

5. SDK 使用说明

5.1 SDK功能介绍

阿里云号码认证iOS SDK目前主要提供功能,目前仅提供静态库ATAuthSDK.framwork形式。

  • 获取SDK版本号。
  • SDK接口调用环境检查及准备,检测设备是否开启蜂窝数据网络,且配置SDK相关数据,该步骤是本机号码认证及一键登录功能可以使用的前提条件。
  • 一键登录LoginNumber接口(支持移动,电信,联通三大运营商),是预取号缓存接口,为LoginToken接口缓存前置条件,加快授权页的唤起速度。
  • 一键登录LoginToken接口(支持移动,电信,联通三大运营商),请求一键登录的凭证,可自定义超时时间,默认3.0s,单位s。 ## 1) 2) 3)

5.2 一键登录接口调用说明

  • 调用SDK接口调用环境检查及准备,同步接口checkSynGatewayVerifyEnable接口或者异步接口checkAsyncGatewayVerifyEnable
  • (可选)调用SDK预取号接口getLoginNumberWIthTimeout,调用该接口可以加快授权页唤起的速度,请先进行登录态判断后,确保用户需要登录再调用此接口,否则您的功能可能会被限流。
  • 调用SDK一键登录token接口getLoginTokenWithController。
  • 调用服务端getMobile接口获取最终号码。

6. SDK方法说明

6.1 获取认证实例(sharedInstance)

/** 
 * 函数名:sharedInstance
 * @param 无
 * @return 单例
 */  
 + (instancetype _Nonnull )sharedInstance;  
		

6.2 获取sdk版本号(getVersion)

  /**
  * 函数名:getVersion
   * @param 无
   * @return 字符串,sdk版本号
 */
  - (NSString *_Nonnull)getVersion;
		

6.3 同步检查认证环境(checkSyncGatewayVerifyEnable)

/**
 * 函数名:checkSyncGatewayVerifyEnable
 * @brief 同步验证网关认证所需的蜂窝数据网络是否开启,且SDK初始化完成(注意:会阻塞当前线程)同原checkGatewayVerifyEnable
 * @param phoneNumber手机号码,非必传,使用本机号码校验功能时且双sim卡时必须为必传!使用一键登录功能时,设置为 nil即可
 * @return BOOL值,YES表示网关认证所需的蜂窝数据网络已开启,且SDK初始化完成; NO表示未开启,只有YES才能保障后续服务
*/
- (BOOL)checkSyncGatewayVerifyEnable:(NSString *_Nullable)phoneNumber;
		

6.4 异步检查认证环境(checkAsyncGatewayVerifyEnable)

/**
 * 函数名:checkAsyncGatewayVerifyEnable
 
 * @brief  异步验证网关认证所需的蜂窝数据网络是否开启,且SDK初始化完成(注意:不会阻塞当前线程,但是结果会异步回调)。
 * @param phoneNumber手机号码,非必传,使用本机号码校验功能时且双sim卡时必须为必传!使用一键登录功能时,设置为nil即可
 * @return complete 结果回调(注意:回调线程非调用线程)
 */  
- (void)checkAsyncGatewayVerifyEnable:(NSString *_Nullable)phoneNumber complete:(void(^_Nullable)(BOOL enable))complete;
		

6.5 一键登录预取号(getLoginNumberWithTimeout)

/** 
 * 函数名: getLoginNumberWithTimeout
 * @brief 一键登录预取号
 * @param timeout:接口超时时间,单位s,默认3.0s,值为0.0时采用默认超时时间
 * @return 字典形式 
                      resultCode:6666-成功,5555-超时,4444-失败,3344-参数异,2222-无网络, 1111-无 SIM卡,6668-登录按 钮事件,6669-切换到其他方式按钮事件;
                      msg:文案或错误提示
 */
- (void)getLoginNumberWithTimeout:(NSTimeInterval )timeout complete:(void (^_Nullable (NSDictionary * _Nonnull resultDic))complete;
		

6.6 一键登录获取token(getLoginTokenWithController)

/** 
* 函数名: getLoginNumberWithTimeout
* @brief 一键登录获取token
* @param vc:当前vc容器,用于一键登录授权页面切换;
* @oaram model: 自定义授权页面选项,可为nil,采用默认的授权页面,具体请参考TXCustomModel.h文件
* @param timeout: 接口超时时间,单位s,默认3.0s,值为0.0时采用默认超时时间 
* @return 字典形式 
                    resultCode:6666-成功,5555-超时,4444-失败,3344-参数异,2222-无网络, 1111-无 SIM卡,6668-登录按钮事件,6669-切换到其他方式按钮事件;
                    msg:文案或错误提示
*/ 
- (void)getLoginTokenWithController:(UIViewController *_Nonnull)vc model: (TXCustomModel *_Nullable)model timeout:(NSTimeInterval)timeout complete:
- (void (^_Nullable)(NSDictionary * _Nonnull resultDic))complete;
		

6.7 一键登录注销登录页面(cancelLoginVCAnimated)

/**
 * 函数名:cancelLoginVCAnimated
 * @param flag:是否添加动画
 * @param complete成功返回
 */  
-(void)cancelLoginVCAnimated:(BOOL)flag complete:(void (^_Nullable) (void))complete;
		

6.8 一键登录获取手机号

服务端接口,当您成功获取到getLoginToken成功获取token后,将token传递至您的服务端,服务端携带token调用阿里云的getMobile接口即可进行最终的取号操作。

6.9 返回码

以下接口编码,主要是SDK层自身业务的接口编码,还有部分授权页点击事件。

运营商的异常统一为4444,具体详细编码及描述,请参考msg字段。

移动、电信、联通运营商详细的错误码及文案,请参考官网帮助文档中SDK错误码。

1111,设备无SIM卡

2222,设备无移动蜂窝网络

3344,参数为空或异常

4444,接口请求失败,具体错误见msg文案,一般是运营商SDK的异常

5555,接口请求超时 6666,接口请求成功

6665,一键登录授权页面成功被唤起事件

6667,一键登录授权页面,导航栏返回按钮点击事件

6668,一键登录授权页面,登录按钮点击事件且成功获取了登录Token

6669,一键登录授权页面,切换到其他方式按钮点击事件

7. SDK接入demo用例

7.1 一键登录预取号版本用例

3步骤有3.1与3.2两种方式,要真正达到秒拉授权页,且保障2步骤与3步骤之间有足够的时间间隔,否则2步骤的预取号未完成没有回调的话,3步骤接口会出现错误,2步骤接口即使返回异常,3步骤接口内部还会去预取号的。

// 1. 初始化接口,判断环境是否支持一键登录(参数为nil),为YES,才能执行2步骤
    self.isEnable = [[TXCommonHandler sharedInstance] checkSyncGatewayVerifyEnable:nil];
   if (!self.isEnable) {
    self.resultTextView.text = @"设备无移动数据网络 或 获取供应商信息失败";
    return;
   }
    // 2. 预取号缓存,便于授权页面迅速拉起,0等待
    __weak TXNumberCheckViewController *weakSelf = self;
    [[TXCommonHandler sharedInstance] getLoginNumberWithTimeout:0.0 complete:^(NSDictionary * _Nonnull resultDic) {
        NSString *code = [resultDic valueForKey:@"resultCode"];
        NSString *msg = [resultDic valueForKey:@"msg"];
        dispatch_async(dispatch_get_main_queue(), ^{
            if ([code isEqualToString:TX_Auth_Result_Success]) {
                NSLog(@"getLoginNumberWithTimeout success");
                weakSelf.resultTextView0.text = @"预取号成功";
                // 3.1 拉起授权页面,TXCustomModel属性自定义可参看头文件
                TXCustomModel *modelNew = [[TXCustomModel alloc] init];
                [[TXCommonHandler sharedInstance] getLoginTokenWithController:self model:modelNew timeout:self.time complete:^(NSDictionary * _Nonnull resultDic) {
                // 具体参考非缓存版本代码;
                };
            }
            else {
                NSLog(@"getLoginNumberWithTimeout fail,resultDic = %@",resultDic);
                weakSelf.resultTextView0.text = [NSString stringWithFormat:@"预取号失败,%@",msg];
            }
        });
    }];
    (3步骤,之前要确保getLoginNumberWithTimeout接口成功回调,可以block嵌套调用,也可以分开调用!!)
    // 3.2 拉起授权页面
    TXCustomModel *modelNew = [[TXCustomModel alloc] init];
    [[TXCommonHandler sharedInstance] getLoginTokenWithController:self model:modelNew timeout:self.time complete:^(NSDictionary * _Nonnull resultDic) {
    // 具体参考非缓存版本代码;
    };
		

7.2 一键登录无预取号版本用例

// 1. 初始化接口,判断环境是否支持一键登录(参数为nil),为YES,才能执行2步骤
self.isEnable = [[TXCommonHandler sharedInstance] checkSyncGatewayVerifyEnable:nil];
if (!self.isEnable) {
    self.resultTextView.text = @"设备无移动数据网络 或 获取供应商信息失败";
    return;
}

// 2. 获取登录token,用于3步骤登录取号接口参数
__weak TXNumberCheckViewController *weakSelf = self;

// 授权页面属性定制
TXCustomModel *modelNew = [[TXCustomModel alloc] init];
modelNew.navColor = UIColor.orangeColor;
modelNew.navTitle = [[NSAttributedString alloc] initWithString:@"一键登录22" attributes:@{NSForegroundColorAttributeName : UIColor.blackColor,NSFontAttributeName : [UIFont systemFontOfSize:24.0]}];
modelNew.navBackImage = [UIImage imageNamed:@"icon_nav_back_gray"];
modelNew.hideNavBackItem = YES;

//自定义nav right btn
UIButton *rightBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[rightBtn addTarget:self action:@selector(showMoreAction:) forControlEvents:UIControlEventTouchUpInside];
[rightBtn setTitle:@"跳过" forState:UIControlStateNormal];
[rightBtn.titleLabel setFont:[UIFont systemFontOfSize:15.0]];
[rightBtn setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
[rightBtn sizeToFit];
UIBarButtonItem *rightBarItem = [[UIBarButtonItem alloc] initWithCustomView:rightBtn];
modelNew.navMoreControl = rightBarItem;

//modelNew.logoImage = [self imageWithColor:UIColor.orangeColor size:CGSizeMake(300.0, 300.0) isRoundedCorner:YES];
modelNew.logoImage = [UIImage imageNamed:@"taobao"];
modelNew.logoIsHidden = NO;
modelNew.logoWidth = 200;
modelNew.logoHeight = 90.0;
modelNew.logoTopOffetY = self.ratio * 32.0;

modelNew.sloganIsHidden = NO;
modelNew.sloganText = [[NSAttributedString alloc] initWithString:@"一键登录slogan文案" attributes:@{NSForegroundColorAttributeName : UIColor.orangeColor,NSFontAttributeName : [UIFont systemFontOfSize:16.0]}];
modelNew.sloganTopOffetY = self.ratio * 150.0;

modelNew.numberColor = UIColor.orangeColor;
modelNew.numberFont = [UIFont systemFontOfSize:30.0];
modelNew.numberTopOffetY = self.ratio * 200.0;
//modelNew.numberOffetX = -50.0;

//UIImage *normalImage = [self imageWithColor:UIColor.orangeColor size:CGSizeMake(300.0, 50.0) isRoundedCorner:YES];
//UIImage *disableImage = [self imageWithColor:UIColor.grayColor size:CGSizeMake(300.0, 50.0) isRoundedCorner:YES];
//UIImage *lightedImage = [self imageWithColor:UIColor.greenColor size:CGSizeMake(300.0, 50.0) isRoundedCorner:YES];
//modelNew.loginBtnBgImgs = @[normalImage,disableImage,lightedImage]
modelNew.loginBtnText = [[NSAttributedString alloc] initWithString:@"一键登录22" attributes:@{NSForegroundColorAttributeName : UIColor.whiteColor,NSFontAttributeName : [UIFont systemFontOfSize:20.0]}];
modelNew.loginBtnTopOffetY = self.ratio * 270;
modelNew.loginBtnHeight = 50.0;
modelNew.loginBtnLRPadding = 18.0;
modelNew.autoHideLoginLoading = NO;

modelNew.privacyOne = @[@"流量App使用方法1",@"https://www.taobao.com/"];
//modelNew.privacyTwo = @[@"流量App使用方法2",@"https://www.baidu.com/"];
modelNew.privacyColors = @[UIColor.lightGrayColor,UIColor.orangeColor];
modelNew.privacyBottomOffetY = self.ratio * 25.0;
modelNew.privacyAlignment = NSTextAlignmentCenter;
//modelNew.privacyPreText = @"阅读并同意";
//modelNew.privacySufText = @"使用本机号码登录";
modelNew.privacyLRPadding = 8.0;
modelNew.privacyFont = [UIFont systemFontOfSize:12.0];

modelNew.checkBoxIsHidden = NO;
modelNew.checkBoxIsChecked = YES;
//UIImage *checkedImg = [self imageWithColor:UIColor.orangeColor size:CGSizeMake(45.0, 45.0) isRoundedCorner:NO];
//UIImage *unCheckedImg = [self imageWithColor:UIColor.grayColor size:CGSizeMake(45.0, 45.0) isRoundedCorner:NO];
//modelNew.checkBoxImages = @[unCheckedImg,checkedImg];
modelNew.checkBoxWH = 15.0;

modelNew.changeBtnTitle = [[NSAttributedString alloc] initWithString:@"切换到其他方式22" attributes:@{NSForegroundColorAttributeName : UIColor.orangeColor,NSFontAttributeName : [UIFont systemFontOfSize:18.0]}];
modelNew.changeBtnIsHidden = NO;
modelNew.changeBtnTopOffetY = self.ratio * 344;

modelNew.customViewBlock = ^(UIView * _Nonnull superCustomView) {

            UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(40, self.ratio * 430, TX_SCREEN_WIDTH - 2 * 40, self.ratio * 80)];
            btn.backgroundColor = [UIColor redColor];
            [btn setTitle:@"注销授权页" forState:UIControlStateNormal];
            [btn addTarget:self action:@selector(cancelVCBtn:) forControlEvents:UIControlEventTouchUpInside];
			
            [superCustomView addSubview:btn];
			
        };
		
[[TXCommonHandler sharedInstance] getLoginTokenWithController:self model:modelNew timeout:self.time complete:^(NSDictionary * _Nonnull resultDic) {
   
   dispatch_async(dispatch_get_main_queue(), ^{
        NSString *code = [resultDic valueForKey:@"resultCode"];
        if ([code isEqualToString:TX_Auth_Result_Success]) {
            // 接口请求成功
        }
        else if ([code isEqualToString:TX_Login_AuthPage_Show_Success]) {
              // 授权页面成功唤起
        }
        else if ([code isEqualToString:TX_Login_SSO_Action]) {
            [[TXCommonHandler sharedInstance] hideLoginLoading];
            [weakSelf dismissViewControllerAnimated:YES completion:nil];
            NSString *token = [resultDic valueForKey:@"token"];
            // 3.点击登录按钮且成功获取Token,请求开发者服务端API,进行号码获取     
        }
        else if ([code isEqualToString:TX_Login_Change_Action]) {
            [weakSelf dismissViewControllerAnimated:YES completion:nil];
            // 4.切换到其他方式,可切换到开发者自有的认证方法
        }
        else {
            [[TXCommonHandler sharedInstance] hideLoginLoading];
            [weakSelf dismissViewControllerAnimated:YES completion:nil];
            // 5.接口请求失败,切换到开发者自有的认证方法
        }
    });
}];

- (void)cancelVCBtn:(UIButton *)sender {
    [[TXCommonHandler sharedInstance] cancelLoginVCAnimated:YES complete:^{
    }];
}
		

8. 一键登录授权页面说明

8.1 授权页面设计规范

9. iOS常见问题

初始化接口checkGatewayVerifyEnable一直返回NO?

排查顺序:1、手机sim卡是否被激活或欠费,2、手机设备蜂窝数据是否开启,3、App的网络权限是否开启,4、设备是否有代理,5、云控制台上是否创建了方案号,6、创建方案号中的bundleId一定要与项目中使用的保持一致,7,最后再提供bundleId给我们进行查询日志;

移动卡返回【103101,错误的请求签名】

执行下[NSBundle mainBundle].localizedInfoDictionary语句,如果不为nil,则有国际本地化逻辑,这样的情况,目前有两种方法修复:1,如果.strings文件内容为空且无用,删除即可;2,如果.strings文件必须要使用,则需要在主工程中所有.strings文件中增加CFBundleIdentifier = “bundleId名称”;

移动卡出现crash【[UAReachability reachableType]: unrecognized selector sent to instance】

在主工程中Project -> Edit Active Target -> Build Setting -> Other Linker Flags中添加-all_load标记,前提也要添加-ObjC,即两者都要添加;

登录token存在失败吗?

肯定存在的,如果是偶现,可以理解,因为比如网络波动导致网关断开、网络不可用、供应商服务端异常,业务方服务端异常等因素有关;如果是持续出现,一般需要运营商协助排查;

iPhone双卡双待,出现5555错误码,超时失败?

此设备问题,在切换上网卡或更换sim卡,会出现设备已经呈现4G网络,但实际Safari是打不开网页的状态,也就是说实际网络并没有准备好,所以在请求认证前,请先确保Safari能正常打开网页。

什么情况下会出现异常错误码4444?

错误码4444,一般发生在运营商端异常,一般需要运营商协助排查。

一键登录服务一般只4G或者4G+Wifi情况下,如果是3G、2G会怎么样?

中国移动支持2G/3G/4G、中国联通支持3G/4G、中国电信支持4G,但2G和3G网络下接口请求失败或超时概率稍高。

经常超时?

首先确认sim卡不欠费,再确认手机网络是否正常,通过Safari打开某个网址验证为准。其次确认超时时间是否设置正确,单位是s。2G和3G网络下接口请求失败或超时概率稍高。切换网络时,设置网络不稳定,会较大概率出现超时。

返回3344错误码,参数异常

首先确认是否开通了方案,再检查App的bundleId与控制后台新建方案中的bundlId是否一致。确认是否调用了check接口。