尊敬的用户您好!即日起本官网将启用新域名"shanyan.253.com",原域名(flash.253.com)将自动跳转至新域名,原域名后期将停用。请您及时更新浏览器收藏夹或直接使用新域名访问本官网。万分感谢您的配合!

闪验、创蓝闪验

概述



当前版本:2.3.1.4

常见问题请移步至对接问题

崩溃问题请移步至崩溃问题」

版本升级:详细说明请移步至「升级指南

如需SDK资源包下载请移步至SDK资源下载


注:用户iOS APP如使用了RSA加密,建议将读写RSA秘钥的tag值设置成自己公司命名规范字符串,尽量保证tag值在APP内唯一,如:NSString *tag = @"com_253_shanyan_RSA...Key";  


一.准备工作


前置条件


  • 闪验SDK支持Xcode 11+打包,iOS8.0+及以上版本。
  • 闪验SDK支持中国移动、联通、电信4G的取号能力。
  • 闪验SDK支持网络环境为

      a.纯数据网络

      b.数据网络与wifi网络双开

  • 对于双卡手机,闪验SDK取当前流量卡号


一键登录使用场景:

用户无需输入手机号码,只需集成并调用SDK拉起授权页方法,用户确认授权后,SDK会获取token,服务端携带token到运营商网关获取用户当前上网使用的流量卡号码,并返回给APP服务端。


本机号码校验(本机认证)使用场景:

用户通过SDK获取token,服务端携带手机号码和token去运营商网关进行校验比对,返回的校验结果为:用户当前流量卡号码与服务端携带的手机号码是否一致。




创建应用


提示:一个应用对应一个appid,多个应用(不同bundleID)需在闪验平台创建多个应用以对应多个appid

应用的创建流程及APPID/APPKEY的获取,请查看「账号创建」文档


快速体验Demo

将创建应用时获得的AppID填入Demo工程中.pch文件,修改工程BundleID为创建应用时绑定的BundleID即可


开发环境搭建

闪验SDK提供两种集成方式供iOS开发者选择:

  • 通过CocoaPods自动集成
  • 手动集成


通过CocoaPods自动集成

在工程的Podfile里面添加以下代码:以下示例pod 版本仅供参考,请按需选择或选择最新版本

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

#集成最新版闪验SDK:
pod 'CL_ShanYanSDK'

#集成指定版本闪验SDK:
pod 'CL_ShanYanSDK', '2.3.1.3'

#集成指定版本闪验SDK,并在末位小版本范围更新:
pod 'CL_ShanYanSDK', '~> 2.3.0.5'

保存并执行pod install,然后用后缀为.xcworkspace的文件打开工程。

注意:

命令行下执行pod search CL_ShanYanSDK,如显版本不是最新版,或者pod install导入的版本不是最新版,则先执行pod repo update操作更新本地repo的内容

关于CocoaPods的更多信息请查看 CocoaPods官方网站


手动集成

  1. 导入framework: 将闪验SDK压缩包中framework文件夹下所有资源添加到工程中(注意勾选Copy items if needed)

导入资源文件1.jpg


  1. Xcode配置:


  • OtherLinkerFlags中 添加**-ObjC**:xcode->BuildSetting->Other Linker Flags 添加 **-ObjC**

otherLink-ObjC.jpg


  • 添加libc++.1.tbd: 在xcode->General->Linked Frameworks and Libraries中点击 **+** ,搜索并选择添加 **libc++.1.tbd**

libc++.1.tbd.jpg


  1. Swift工程需要额外添加-force_load:
  • 在xcode->BuildSetting->Other Linker Flags 添加-force_load

swift-force_load.jpg


  • 在-force_load下方添加CL_ShanYanSDK.framework/CL_ShanYanSDK所在路径,具体操作可以将CL_ShanYanSDK.framework拖入空栏,在尾部拼接静态库名称CL_ShanYanSDK,将前缀绝对地址改成相对地址$(SRCROOT),最终为 "$(SRCROOT)/.../CL_ShanYanSDK.framework/CL_ShanYanSDK"形式

swift-sdk-path.jpg


二.SDK使用说明


1.初始化


方法原型


/**初始化*/
+(void)initWithAppId:(NSString *)appId complete:(nullable CLComplete)complete;


参数描述


参数

是否必填

类型

说明

appId 

必填

NSString

闪验appID

complete 

选填

CLComplete

初始化回调block,可以在此回调block中接收初始化情况,也可以不关心初始化结果


接口作用


初始化SDK :传入用户的appId,请求闪验服务接口以获取运营商配置信息,接口请求成功缓存相关信息


使用场景


  • 在app启动时进行调用
  • 保证在预取号或一键登录前至少调用一次
  • 只需调用一次,多次调用不会多次初始化,与一次调用效果一致


请求示例代码


ObjC:

  1. 导入闪验SDK头文件 #import <CL_ShanYanSDK/CL_ShanYanSDK.h>
  2. 在AppDelegate中的 didFinishLaunchingWithOptions方法中添加初始化代码
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    ...
    //初始化
    [CLShanYanSDKManager initWithAppId:cl_SDK_APPID complete:nil];
    
    /**
     * 建议在退出登录时再次调用初始化方法
     */
    ...
}


Swift:

  1. 创建混编桥接头文件并导入闪验SDK头文件 #import <CL_ShanYanSDK/CL_ShanYanSDK.h>
  2. 在AppDelegate中的 didFinishLaunchingWithOptions方法中添加初始化代码


func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    ...
    //初始化
    CLShanYanSDKManager.initWithAppId("your appId") { (completeResult) in
        if ((completeResult.error) != nil) {
            print("初始化失败")
        } else {
            print("初始化成功")
        }
    }
    ...
}


2.预取号


不建议 频繁的多次调用和在拉起授权页后调用


预取号方法回调中处理UI操作需手动切换到主线程



方法原型


/**
 * 预取号
 * 此调用将有助于提高闪验拉起授权页的速度和成功率
 * 建议在一键登录前提前调用此方法,比如调一键登录的vc的viewdidload中、初始化成功的回调中
 * 不建议在拉起授权页后调用
 * 回调中如需UI操作,建议自行切到主线程
 */
+(void)preGetPhonenumber:(nullable CLComplete)complete;


接口作用


电信、联通、移动预取号 :初始化成功后,如果当前为电信/联通/移动,将调用预取号,可以提前获知当前用户的手机网络环境是否符合一键登录的使用条件,成功后将得到用于一键登录使用的临时凭证,默认的凭证有效期60min(三大运营商一致)。


使用场景


  • 建议在执行一键登录的方法前,提前一段时间调用此方法,比如调一键登录的vc的viewdidload中,或者rootVC的viewdidload中,或者app启动后,此调用将有助于提高闪验拉起授权页的速度和成功率
  • 不建议调用后立即调用拉起授权页方法(此方法是异步)
  • 此方法需要1~2s的时间取得临时凭证,因此也不建议和拉起授权页方法一起串行调用
  • 不建议频繁的多次调用和在拉起授权页后调用
  • 建议在判断当前用户属于未登录状态时使用,已登录状态用户请不要调用该方法


请求示例代码


ObjC:


#import <CL_ShanYanSDK/CL_ShanYanSDK.h>
//开发者调拉起授权页的vc
@implementation CustomLoginViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    if (YourAppLoginStatus == NO) {
        //预取号
        [CLShanYanSDKManager preGetPhonenumber:nil];
        ...
    }
}
...
//拉起授权页
- (void)shanYanAuthPageLogin{
    ...
}


3.拉起授权页


在预取号成功后调用预取号失败不建议调用。调用拉起授权页方法后将会调起运营商授权页面。该方法会拉起登录界面,已登录状态请勿调用 。


/**
 一键登录 区分拉起授权页之前和之后的回调
 
 @param clUIConfigure 闪验授权页参数配置
 @param openLoginAuthListener 拉起授权页监听:拉起授权页面成功或失败的回调,拉起成功或失败均触发。当拉起失败时,oneKeyLoginListener不会触发。此回调的内部触发时机是viewDidAppear
                    
 @param oneKeyLoginListener 一键登录监听:拉起授权页成功后的后续操作回调,包括点击SDK内置的(非外部自定义)取消登录按钮,以及点击本机号码一键登录的回调。点击授权页自定义按钮不触发此回调
 
 * 回调中如需UI操作,建议自行切到主线程
 */
+(void)quickAuthLoginWithConfigure:(CLUIConfigure *)clUIConfigure
             openLoginAuthListener:(CLComplete)openLoginAuthListener
               oneKeyLoginListener:(CLComplete)oneKeyLoginListener;


参数描述


参数

类型

说明

clUIConfigure  必填

CLUIConfigure

授权页控件属性配置对象

openLoginAuthListener  选填

CLComplete

拉起授权页的回调,拉起页面成功、失败均触发

注意:在此回调中用户UI操作必须手动切换到主线程

oneKeyLoginListener 必填

CLComplete

一键登录回调,用于接收一键登录的结果,点一键登录成功、失败均触发,点自带的返回按钮也触发


使用场景


  • 用户进行一键登录操作时,调用一键登录方法,如果初始化成功,SDK将会拉起授权页面,用户授权后,SDK将返回取号 token给到应用客户端。
  • 可以在多处调用
  • 需在调用预初始化方法之后调用


一键登录逻辑说明


  • 存在调用预初始化时获取的临时凭证,调用一键登录方法将立即拉起授权页面
  • openLoginAuthListener: 拉起授权页面成功或失败的回调,拉起成功或失败均触发。当拉起失败时,oneKeyLoginListener不会触发。此回调的内部触发时机是viewDidAppear
  • oneKeyLoginListener:一键登录监听, 拉起授权页成功后的后续操作回调,包括点击SDK内置的(非外部自定义)取消登录按钮,以及点击本机号码一键登录的回调。点击授权页自定义按钮不触发此回调
  • 不存在临时凭证或临时凭证过期时(临时凭证有效期电信60min、联通60min、移动60min),调用一键登录方法,将有一个很短的时延,待取号成功后拉起授权页面
  • 取号失败时,返回失败 


请求示例代码


ObjC:

  1. 导入闪验SDK头文件 #import <CL_ShanYanSDK/CL_ShanYanSDK.h>
  2. 在需要使用一键登录的地方调用闪验一键登录接口
// 用户需要使用闪验一键登录时的方法
- (void)quickLoginBtnClick:(UIButton *)sender {

    __weak typeof(self) weakself = self;

    CGFloat screenScale = [UIScreen mainScreen].bounds.size.width/375.0;

    CLUIConfigure * baseUIConfigure = [CLUIConfigure new];
    baseUIConfigure.viewController = self;
    baseUIConfigure.clLogoImage = [UIImage imageNamed:@"your_app_logo_image"];
    
    baseUIConfigure.clAppPrivacyFirst = @[@"闪验测试连接1",[NSURL URLWithString:@"https://baidu.com"]];
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"ShanYanIndex" ofType:@"html"];
    //baseUIConfigure.clAppPrivacySecond = @[@"闪验测试连接2",[NSURL URLWithString:@"https://sina.com"]];
    baseUIConfigure.clAppPrivacySecond = @[@"本地协议地址",[NSURL fileURLWithPath:filePath]];
    
    //layout 布局
    CLOrientationLayOut * clOrientationLayOutPortrait = [CLOrientationLayOut new];
    clOrientationLayOutPortrait.clLayoutPhoneCenterY = @(0*screenScale);
    clOrientationLayOutPortrait.clLayoutPhoneLeft = @(50*screenScale);
    ...
    baseUIConfigure.clOrientationLayOutPortrait = clOrientationLayOutPortrait;
    
    // show loading...

    //闪验一键登录接口(将拉起授权页)
    [CLShanYanSDKManager quickAuthLoginWithConfigure:baseUIConfigure openLoginAuthListener:^(CLCompleteResult * _Nonnull completeResult) {
            // hide loading...
            if (completeResult.error) {
                //拉起授权页失败
                NSLog(@"openLoginAuthListener:%@",completeResult.error.userInfo);
            }else{
               //拉起授权页成功
                NSLog(@"openLoginAuthListener:%@",completeResult.yy_modelToJSONObject);
            }
        } oneKeyLoginListener:^(CLCompleteResult * _Nonnull completeResult) {
            __strong typeof(self) strongSelf = weakSelf;

            if (completeResult.error) {
                //一键登录失败
                NSLog(@"oneKeyLoginListener:%@",completeResult.error.description);
                
                //提示:错误无需提示给用户,可以在用户无感知的状态下直接切换登录方式
                if (completeResult.code == 1011){
                    //用户取消登录(点返回)
                    //处理建议:如无特殊需求可不做处理,仅作为交互状态回调,此时已经回到当前用户自己的页面
                    //点击sdk自带的返回,无论是否设置手动销毁,授权页面都会强制关闭
                }  else{
                    //处理建议:其他错误代码表示闪验通道无法继续,可以统一走开发者自己的其他登录方式,也可以对不同的错误单独处理
                    //关闭授权页,如果授权页还未拉起,此调用不会关闭当前用户vc,即不执行任何代码
                    [CLShanYanSDKManager finishAuthControllerCompletion:nil];
                }
            }else{
                //一键登录获取Token成功
                NSLog(@"oneKeyLoginListener:%@",completeResult.yy_modelDescription);
                
                //SDK成功获取到Token
                /** token置换手机号
                code
                */
            }
        }];
 }



一键登录 quickAuthLoginWith:complete:正确返回示例


返回参数示例 completeResult.data
{
    token = "A3-KqvM4yO_lApRLwpv4qVNnBRF3w=="
}


字段

类型

含义

token

String

token,置换令牌,用来和后台置换手机号。一次有效,有效期3min



一键登录 quickAuthLoginWith:complete:报错处理


completeResult->_error:

  • 用户取消登录(授权页点击返回) 【处理建议:若无特殊需求可不做处理】
  • 用户选择其他方式登录(点击授权页自带的其他方式登录): 【处理建议:可根据实际情况跳转其他登录方式 】
  • 其他错误 【处理建议:使用闪验通道失败,可根据实际情况跳转其他登录方式 】


授权页销毁


注:sdk拉起授权页成功后,只允许点击一次一键登录按钮。一键登录按钮点击一次后,只有sdk自带的左上角返回按钮可以交互,效果为强制关闭授权页,其他页面元素均会被禁用,以防止多次点击导致多次回调而出现异常。


拉起授权页前 配置授权页面销毁机制属性

// 获取默认参数配置
CLUIConfigure * baseUIConfigure = [CLUIConfigure clDefaultUIConfigure];
baseUIConfigure.viewController = self;
// 是否需要手动销毁授权页面,默认自动销毁, YES->手动销毁
baseUIConfigure.manualDismiss = @(YES);


sdk获取token回调后销毁界面

//关闭页面
[CLShanYanSDKManager finishAuthControllerCompletion:^{
   //如需关闭后present/push新页面,建议在completion回调中执行
    //注:若未拉起授权页,调用此方法,block不会触发
    //用户跳转短信验证
    CustomSmsViewController * smsVc = [[CustomSmsViewController alloc]init];
    CustomNavigationController * smsNav = [[CustomNavigationController alloc]initWithRootViewController:smsVc];
    smsVc.navigationItem.title = @"短信验证";
    [self presentViewController:smsNav animated:YES completion:nil];
}];



4.置换手机号


注:移动、联通、电信分别有自己的置换手机号url,需要根据相对应的运营商url置换手机号码。详情见下方 请求示例代码


使用场景


SDK成功返回token后,开发者需自行调用置换手机号接口,此接口需要开发者调用由服务端接入闪验服务端生成的接口,上线前的调试阶段可以直接使用示例代码中的接口


请求示例代码


ObjC:

[CLShanYanSDKManager quickAuthLoginWithConfigure:baseUIConfigure openLoginAuthListener:^(CLCompleteResult * _Nonnull completeResult) {
    // UI操作建议手动切至主线程
    if (completeResult.error) {
        //拉起授权页失败
        NSLog(@"openLoginAuthListener:%@",completeResult.error.userInfo);
    }else{
       //拉起授权页成功
        NSLog(@"openLoginAuthListener:%@",completeResult.yy_modelToJSONObject);
    }
} oneKeyLoginListener:^(CLCompleteResult * _Nonnull completeResult) {
    [SVProgressHUD dismiss];
    if (completeResult.error) {
        ...
    }else{
        //SDK成功获取到Token
      
        请求用户APP服务端置换手机号
    }
}];


Swift:

CLShanYanSDKManager.quickAuthLogin(with: clUIConfigure, openLoginAuthListener: { (completeResult) in
    ...
}) { (completeResult) in 

    if completeResult.error != nil {
        ...
    }else{
      //SDK成功获取到Token

        NSLog("quickAuthLogin Success:%@",completeResult.data ?? "")

        请求用户APP服务端置换手机号
    }
  }
}



4.手动关闭授权页

当开发者设置点击一键登录或者自定义控件不自动销毁授权页时,将需要自行调用此方法主动销毁授权页,建议在置换手机号成功后销毁。如在得到回调后未销毁授权页而,使用拉起授权页方法再次拉起授权页,此页面将无法响应任何按键(除了导航栏的返回按钮)。


  • 关闭授权页时机

      a.SDK拉起授权页方法 直接回调失败时

      b.置换手机号有返回结果时


  • 当前页面直接销毁


//方式1
[self.PresentedViewController dismissViewControllerAnimated:YES completion:nil];

//方式二
[CLShanYanSDKManager finishAuthControllerCompletion:^{
   //如需关闭后present/push新页面,建议在completion回调中执行
    //注:若未拉起授权页,调用此方法,block不会触发
    //用户跳转短信验证
    CustomSmsViewController * smsVc = [[CustomSmsViewController alloc]init];
    CustomNavigationController * smsNav = [[CustomNavigationController alloc]initWithRootViewController:smsVc];
    smsVc.navigationItem.title = @"短信验证";
    [self presentViewController:smsNav animated:YES completion:nil];
}];


  • 找到topVC进行dismiss
dispatch_async(dispatch_get_main_queue(), ^{
    //建议使用授权页面配置对象传入的viewcontroller 调 dismiss
    if (self.navigationController.viewControllers.lastObject.navigationController) {
        [self.navigationController.viewControllers.lastObject dismissViewControllerAnimated:YES completion:nil];
    } else {
        UIViewController *topRootViewController = [[UIApplication  sharedApplication] keyWindow].rootViewController;
        // 在这里加一个这个样式的循环
        while (topRootViewController.presentedViewController) {
            // 这里固定写法
            topRootViewController = topRootViewController.presentedViewController;
        }
        // 然后再进行present操作
        [topRootViewController dismissViewControllerAnimated:YES completion:nil];
    }
});


5.登录按钮、协议、勾选框控件点击监听


控件点击的监听是通过代理实现,在授权页面显示前触发代理进行监听。不监听协议点击可不实现代理,按需配置。

注意实现协议:@interface xxxController ()<CLShanYanSDKManagerDelegate>


在拉起授权页之前设置代理

//弹窗添加蒙版或点击协议回调 代理设置,不监听协议点击或不使用蒙版可不设置代理
[CLShanYanSDKManager setCLShanYanSDKManagerDelegate:self];


一键登录按钮、协议、勾选框点击监听

/**
 * 统一事件监听方法
 * type:事件类型(1,2,3)
 * 1:隐私协议点击
 * - 同-clShanYanSDKManagerWebPrivacyClicked:privacyIndex:currentTelecom
 * code:0,1,2,3(协议页序号),message:协议名_当前运营商类型
 * 2:协议勾选框点击
 * code:0,1(0为未选中,1为选中)
 * 3:"一键登录"按钮点击
 * code:0,1(0为协议勾选框未选中,1为选中)
 * UI操作建议手动切至主线程
*/
-(void)clShanYanActionListener:(NSInteger)type code:(NSInteger)code  message:(NSString *_Nullable)message;


协议点击监听方式二

#pragma mark - CLShanYanSDKManagerDelegate
- (void)clShanYanSDKManagerWebPrivacyClicked:(NSString *)privacyName privacyIndex:(NSInteger)index currentTelecom:(NSString *)telecom{
    NSLog(@"协议名称:%@---协议位置:%lu---当前运营商:%@",privacyName,index,telecom);
}


6.多次点击一键登录按钮、手动关闭授权页面上的loading


使用场景:授权页面“一键登录”按钮点击后oneKeyLoginListener失败回调中或用户APP端向服务端置换手机号码接口失败回调中调用该方法,以达到隐藏loading 再次点击"一键登录"按钮的效果(按钮最多只能被点击4次)。


// 隐藏授权页面上的loading框
+(void)hideLoading;



三.授权界面修改


1.设计规范


规范.jpg


开发者不得通过任何技术手段,将授权页面的隐私栏、品牌露出内容隐藏、覆盖,对于接入闪验SDK并上线的应用,我方和运营商会对上线的应用授权页面做审查,如果有出现未按要求设计授权页面,将隐私栏、运营商品牌、授权登录按钮隐去不可见的设计,我方有权将应用的登录功能下线。


2.页面可调整属性


注:授权页基本控件均支持上、下、左、右、宽、高、水平中心、竖直中心布局设置,布局通过布局对象设置,布局定位更加方便快捷,建议使用最新布局对象进行设置。每个控件对象需要设置4个方向上的数值。


注:2.3.1.1版本开始更新隐私协议控件,提高点击响应灵敏度。隐私协议控件由UITextView更换为UILabel控件,

删除隐私协议 clAppPrivacyLineFragmentPaddingclAppPrivacyContentInset属性,目前只要设置clAppPrivacyTextContainerInset属性即可达到设置文本内边距的效果


//要拉起授权页的vc [必填项] (注:SDK不持有接入方VC)
@property (nonatomic,weak)UIViewController * viewController;

/**
 *外部手动管理关闭界面
 *BOOL,default is NO
 *eg.@(YES)
 */
@property (nonatomic,strong)NSNumber * manualDismiss;

/**授权页-背景图片*/
@property (nonatomic,strong) UIImage *clBackgroundImg;

//导航栏
/**导航栏 是否隐藏 BOOL default is NO, 设置优先级高于clNavigationBackgroundClear eg.@(NO)*/
@property (nonatomic,strong)NSNumber * clNavigationBarHidden;
/**导航栏 背景透明 BOOL eg.@(YES)*/
@property (nonatomic,strong)NSNumber * clNavigationBackgroundClear;
/**导航栏标题*/
@property (nonatomic,strong)NSAttributedString * clNavigationAttributesTitleText;

/**导航栏右侧自定义按钮*/
@property (nonatomic,strong)UIBarButtonItem * clNavigationRightControl;
/**导航栏左侧自定义按钮*/
@property (nonatomic,strong)UIBarButtonItem * clNavigationLeftControl;

// 返回按钮
/**导航栏左侧返回按钮图片*/
@property (nonatomic,strong)UIImage   * clNavigationBackBtnImage;
/**导航栏自带返回按钮隐藏,默认显示 BOOL eg.@(YES)*/
@property (nonatomic,strong)NSNumber  * clNavigationBackBtnHidden;
/**************新增******************/
/**返回按钮图片缩进 btn.imageInsets = UIEdgeInsetsMake(0, 0, 20, 20)*/
@property (nonatomic,strong)NSValue * clNavBackBtnImageInsets;
/**自带返回(关闭)按钮位置 默认NO 居左,设置为YES居右显示*/
@property (nonatomic,strong)NSNumber * clNavBackBtnAlimentRight;

/*translucent 此属性已失效*/
//@property (nonatomic,strong)NSNumber * cl_navigation_translucent;

/**导航栏分割线 是否隐藏
 * set backgroundImage=UIImage.new && shadowImage=UIImage.new
 * BOOL, default is NO
 * eg.@(YES)
 */
@property (nonatomic,strong)NSNumber * clNavigationBottomLineHidden;
/**导航栏 文字颜色*/
@property (nonatomic,strong)UIColor  * clNavigationTintColor;
/**导航栏 背景色 default is white*/
@property (nonatomic,strong)UIColor  * clNavigationBarTintColor;
/**导航栏 背景图片*/
@property (nonatomic,strong)UIImage  * clNavigationBackgroundImage;
/**导航栏 配合背景图片设置,用来控制在不同状态下导航栏的显示(横竖屏是否显示) UIBarMetrics eg.@(UIBarMetricsCompact)*/
@property (nonatomic,strong)NSNumber * clNavigationBarMetrics;
/**导航栏 导航栏底部分割线(图片)*/
@property (nonatomic,strong)UIImage  * clNavigationShadowImage;


/*状态栏样式
 *Info.plist: View controller-based status bar appearance = YES
 *
 *UIStatusBarStyleDefault:状态栏显示 黑
 *UIStatusBarStyleLightContent:状态栏显示 白
 *UIStatusBarStyleDarkContent:状态栏显示 黑 API_AVAILABLE(ios(13.0)) = 3
 **eg. @(UIStatusBarStyleLightContent)
 */
@property (nonatomic,strong)NSNumber * clPreferredStatusBarStyle;
/*状态栏隐藏 eg.@(NO)*/
@property (nonatomic,strong)NSNumber * clPrefersStatusBarHidden;

/**
 *NavigationBar.barStyle:默认UIBarStyleBlack
 *Info.plist: View controller-based status bar appearance = YES

 *UIBarStyleDefault:状态栏显示 黑
 *UIBarStyleBlack:状态栏显示 白
 *
 *eg. @(UIBarStyleBlack)
 */
@property (nonatomic,strong)NSNumber * clNavigationBarStyle;



//LOGO图片
/**LOGO图片*/
@property (nonatomic,strong)UIImage  * clLogoImage;
/**LOGO圆角 CGFloat eg.@(2.0)*/
@property (nonatomic,strong)NSNumber * clLogoCornerRadius;
/**LOGO显隐 BOOL eg.@(NO)*/
@property (nonatomic,strong)NSNumber * clLogoHiden;

/**手机号显示控件*/
/**手机号颜色*/
@property (nonatomic,strong)UIColor  * clPhoneNumberColor;
/**手机号字体*/
@property (nonatomic,strong)UIFont   * clPhoneNumberFont;
/**手机号对齐方式 NSTextAlignment eg.@(NSTextAlignmentCenter)*/
@property (nonatomic,strong)NSNumber * clPhoneNumberTextAlignment;

/*一键登录按钮 控件
 注: 一键登录授权按钮 不得隐藏
 **/
/**按钮文字*/
@property (nonatomic,copy)NSString   * clLoginBtnText;
/**按钮文字颜色*/
@property (nonatomic,strong)UIColor  * clLoginBtnTextColor;
/**按钮背景颜色*/
@property (nonatomic,strong)UIColor  * clLoginBtnBgColor;
/**按钮文字字体*/
@property (nonatomic,strong)UIFont   * clLoginBtnTextFont;
/**按钮背景图片*/
@property (nonatomic,strong)UIImage  * clLoginBtnNormalBgImage;
/**按钮背景高亮图片*/
@property (nonatomic,strong)UIImage  * clLoginBtnHightLightBgImage;
/**按钮背景不可用图片*/
@property (nonatomic,strong)UIImage  * clLoginBtnDisabledBgImage;
/**按钮边框颜色*/
@property (nonatomic,strong)UIColor  * clLoginBtnBorderColor;
/**按钮圆角 CGFloat eg.@(5)*/
@property (nonatomic,strong)NSNumber * clLoginBtnCornerRadius;
/**按钮边框 CGFloat eg.@(2.0)*/
@property (nonatomic,strong)NSNumber * clLoginBtnBorderWidth;

/*隐私条款Privacy
 注: 运营商隐私条款 不得隐藏
 用户条款不限制
 **/
/**隐私条款 下划线设置,默认隐藏,设置clPrivacyShowUnderline = @(YES)显示下划线*/
@property (nonatomic,strong)NSNumber * clPrivacyShowUnderline;
/**隐私条款名称颜色:@[基础文字颜色UIColor*,条款颜色UIColor*] eg.@[[UIColor lightGrayColor],[UIColor greenColor]]*/
@property (nonatomic,strong) NSArray<UIColor*> *clAppPrivacyColor;
/**隐私条款文字字体*/
@property (nonatomic,strong)UIFont  * clAppPrivacyTextFont;
/**隐私条款文字对齐方式 NSTextAlignment eg.@(NSTextAlignmentCenter)*/
@property (nonatomic,strong)NSNumber * clAppPrivacyTextAlignment;
/**运营商隐私条款书名号 默认NO 不显示 BOOL eg.@(YES)*/
@property (nonatomic,strong)NSNumber * clAppPrivacyPunctuationMarks;
/**多行时行距 CGFloat eg.@(2.0)*/
@property (nonatomic,strong)NSNumber* clAppPrivacyLineSpacing;
/**是否需要sizeToFit,设置后与宽高约束的冲突请自行考虑 BOOL eg.@(YES)*/
@property (nonatomic,strong)NSNumber* clAppPrivacyNeedSizeToFit;
/**UITextView.textContainerInset 文字与TextView控件内边距 UIEdgeInset  eg.[NSValue valueWithUIEdgeInsets:UIEdgeInsetsMake(2, 2, 2, 2)]*/
@property (nonatomic,strong)NSValue* clAppPrivacyTextContainerInset;
/**隐私条款--APP名称简写 默认取CFBundledisplayname 设置描述文本四后此属性无效*/
@property (nonatomic,copy) NSString  * clAppPrivacyAbbreviatedName;
/*
 *隐私条款Y一:需同时设置Name和UrlString eg.@[@"条款一名称",条款一URL]
 *@[NSSting,NSURL];
 */
@property (nonatomic,strong)NSArray * clAppPrivacyFirst;
/*
 *隐私条款二:需同时设置Name和UrlString eg.@[@"条款一名称",条款一URL]
 *@[NSSting,NSURL];
 */
@property (nonatomic,strong)NSArray * clAppPrivacySecond;
/*
 *隐私条款三:需同时设置Name和UrlString eg.@[@"条款一名称",条款一URL]
 *@[NSSting,NSURL];
 */
@property (nonatomic,strong)NSArray * clAppPrivacyThird;
/*
 隐私协议文本拼接: DesTextFirst+运营商条款+DesTextSecond+隐私条款一+DesTextThird+隐私条款二+DesTextFourth+隐私条款三+DesTextLast
 **/
/**描述文本 首部 default:"同意"*/
@property (nonatomic,copy)NSString *clAppPrivacyNormalDesTextFirst;
/**描述文本二 default:"和"*/
@property (nonatomic,copy)NSString *clAppPrivacyNormalDesTextSecond;
/**描述文本三 default:"、"*/
@property (nonatomic,copy)NSString *clAppPrivacyNormalDesTextThird;
/**描述文本四 default:"、"*/
@property (nonatomic,copy)NSString *clAppPrivacyNormalDesTextFourth;
/**描述文本 尾部 default: "并授权AppName使用认证服务"*/
@property (nonatomic,copy)NSString *clAppPrivacyNormalDesTextLast;

/**运营商协议后置 默认@(NO)"*/
@property (nonatomic,strong)NSNumber *clOperatorPrivacyAtLast;

/**用户隐私协议WEB页面导航栏标题 默认显示用户条款名称*/
@property (nonatomic,strong)NSAttributedString * clAppPrivacyWebAttributesTitle;
/**自定义协议标题-按自定义协议对应顺序*/
@property (nonatomic,strong)NSArray<NSString*> * clAppPrivacyWebTitleList;
/**运营商隐私协议WEB页面导航栏标题 默认显示运营商条款名称*/
@property (nonatomic,strong)NSAttributedString * clAppPrivacyWebNormalAttributesTitle;
/**隐私协议标题文本属性(用户协议&&运营商协议)*/
@property (nonatomic,strong)NSDictionary * clAppPrivacyWebAttributes;
/**隐私协议WEB页面导航返回按钮图片*/
@property (nonatomic,strong)UIImage * clAppPrivacyWebBackBtnImage;

/*协议页状态栏样式 默认:UIStatusBarStyleDefault*/
@property (nonatomic,strong)NSNumber * clAppPrivacyWebPreferredStatusBarStyle;

/**UINavigationTintColor*/
@property (nonatomic,strong)UIColor  * clAppPrivacyWebNavigationTintColor;
/**UINavigationBarTintColor*/
@property (nonatomic,strong)UIColor  * clAppPrivacyWebNavigationBarTintColor;
/**UINavigationBackgroundImage*/
@property (nonatomic,strong)UIImage  * clAppPrivacyWebNavigationBackgroundImage;
/**UINavigationBarMetrics*/
@property (nonatomic,strong)NSNumber * clAppPrivacyWebNavigationBarMetrics;
/**UINavigationShadowImage*/
@property (nonatomic,strong)UIImage  * clAppPrivacyWebNavigationShadowImage;
/**UINavigationBarStyle*/
@property (nonatomic,strong)NSNumber * clAppPrivacyWebNavigationBarStyle;

/*SLOGAN
 注: 运营商品牌标签("中国**提供认证服务"),不得隐藏
 **/
/**slogan文字字体*/
@property (nonatomic,strong) UIFont   * clSloganTextFont;
/**slogan文字颜色*/
@property (nonatomic,strong) UIColor  * clSloganTextColor;
/**slogan文字对齐方式 NSTextAlignment eg.@(NSTextAlignmentCenter)*/
@property (nonatomic,strong) NSNumber * clSlogaTextAlignment;

/*闪验SLOGAN
 注: 供应商品牌标签("闪验提供认技术支持")
 **/
/**slogan文字字体*/
@property (nonatomic,strong) UIFont   * clShanYanSloganTextFont;
/**slogan文字颜色*/
@property (nonatomic,strong) UIColor  * clShanYanSloganTextColor;
/**slogan文字对齐方式 NSTextAlignment eg.@(NSTextAlignmentCenter)*/
@property (nonatomic,strong) NSNumber * clShanYanSloganTextAlignment;
/**slogan默认不隐藏 eg.@(NO)*/
@property (nonatomic,strong) NSNumber  * clShanYanSloganHidden;

/*CheckBox
 *协议勾选框,默认选中且在协议前显示
 *可在sdk_oauth.bundle中替换checkBox_unSelected、checkBox_selected图片
 *也可以通过属性设置选中和未选择图片
 **/
/**协议勾选框(默认显示,放置在协议之前)BOOL eg.@(YES)*/
@property (nonatomic,strong) NSNumber *clCheckBoxHidden;
/**协议勾选框默认值(默认选中)BOOL eg.@(YES)*/
@property (nonatomic,strong) NSNumber *clCheckBoxValue;
/**协议勾选框 尺寸 NSValue->CGSize eg.[NSValue valueWithCGSize:CGSizeMake(25, 25)]*/
@property (nonatomic,strong) NSValue *clCheckBoxSize;
/**协议勾选框 UIButton.image图片缩进 UIEdgeInset eg.[NSValue valueWithUIEdgeInsets:UIEdgeInsetsMake(2, 2, 2, 2)]*/
@property (nonatomic,strong) NSValue *clCheckBoxImageEdgeInsets;