全部产品
存储与CDN 数据库 域名与网站(万网) 应用服务 数加·人工智能 数加·大数据基础服务 互联网中间件 视频服务 开发者工具 解决方案 物联网 钉钉智能硬件
CDN

iOS SDK 接入指南

更新时间:2017-11-24 10:41:41

前言

本文旨在介绍定向流量 iOS SDK的接入步骤和使用方法。

手动集成SDK

定向流量产品目前尚在内测阶段,请联系工作人员索取SDK试用。

Pod集成

  • 指定Master仓库和阿里云仓库:
  1. source 'https://github.com/CocoaPods/Specs.git'
  2. source 'https://github.com/aliyun/aliyun-specs.git'
  • 添加依赖:
  1. pod 'AlicloudTFree', '~> 1.0.0'

(~>为模糊指定版本号方式,~> 1.0.0表明引用版本位于1.0.0 <= version < 1.1.0之间的最新版本SDK,用户可参考Podfile Syntax Reference,根据项目需要指定SDK版本。)

修改编译选项

Target->Linking->Other Linker Flags中添加 -ObjC 选项。

不知道如何修改编译选项?请参考:

如何修改编译选项

注意:请注意 -ObjC 的大小写。


应用程序配置与初始化

iOS SDK已全面支持苹果ATS要求,无需在Info.plist中配置ATS。

依赖

系统公共库:

  • libresolv.tbd
  • CoreTelephony.framework
  • SystemConfiguration.framework

AMS组件包

  • UTDID.framework
  • AlicloudUtils.framework
  • AlicloudBeacon.framework
  • UTMini.framework

如果遇到 UTDID 冲突可参考:《阿里云-移动云产品SDK UTDID冲突解决方案》

获取服务实例

iOS SDK以全局service实例的方式提供域名解析服务,您可以通过以下方式获取实例:

  1. AlicloudTFreeService *TFree = [[AlicloudTFreeService alloc] initWithAppID:@"*****" pid:@"*****" desKey:@"*****" iv:@"*****"];

服务API与使用示例

服务API

AlicloudTFreeService 用来打开订购、退订、激活、查询等界面,获取token,使用方法参见最佳实践:

  1. /**
  2. SDK回调Handler定义
  3. */
  4. typedef void (^TFREEBOOLCallback)(BOOL success, NSError *error);
  5. #import "AlicloudTFreeOperationViewController.h"
  6. typedef void (^TFREEViewControllerCallback)(AlicloudTFreeOperationViewController __kindof * viewController, NSError *error);
  7. typedef void (^TFREEAuthDataCallback)(NSString *authData, NSError *error);
  8. @interface AlicloudTFreeService : NSObject
  9. @property (nonatomic, copy) NSString *appID;
  10. @property (nonatomic, copy) NSString *pid;
  11. @property (nonatomic, copy) NSString *desKey;
  12. @property (nonatomic, copy) NSString *iv;
  13. /**
  14. SDK初始化并开启定向免流
  15. * @param appID 由联通分配
  16. * @param pid packageid 免流包id,由联通分配
  17. * @param desKey 不同app使用不同的desKey,小沃下发
  18. * @param iv 加密所需初始化向量
  19. */
  20. - (instancetype)initWithAppID:(NSString *)appID
  21. pid:(NSString *)pid
  22. desKey:(NSString *)desKey
  23. iv:(NSString *)iv;
  24. ;
  25. + (instancetype)sharedInstance;
  26. /*!
  27. * 同步请求免流访问信息
  28. * @param error 访问出错的 error 信息
  29. * @return 同步请求免流访问信息
  30. * 字典里包含的数据:
  31. * TFreeHost 免流域名
  32. * AuthData 鉴权信息
  33. */
  34. - (NSString *)getAuthDataSyncByHost:(NSString *)host error:(NSError **)error;
  35. /*!
  36. * 同步请求免流访问信息
  37. * @param force 是否强制刷新
  38. * @param error 访问出错的 error 信息
  39. * @return 同步请求免流访问信息
  40. * 字典里包含的数据:
  41. * TFreeHost 免流域名
  42. * AuthData 鉴权信息
  43. */
  44. - (NSString *)getAuthDataSyncByHost:(NSString *)host force:(BOOL)force error:(NSError **)error;
  45. /*!
  46. * 异步 Callback 风格
  47. * TFreeHost 免流域名
  48. * AuthData 鉴权信息
  49. */
  50. - (void)getAuthDataAsyncByHost:(NSString *)host callback:(TFREEAuthDataCallback)callback;
  51. /*!
  52. * 异步 Callback 风格
  53. * TFreeHost 免流域名
  54. * AuthData 鉴权信息
  55. */
  56. - (void)getAuthDataAsyncByHost:(NSString *)host force:(BOOL)force callback:(TFREEAuthDataCallback)callback;
  57. /**
  58. 日志开关
  59. @param enabled YES: 打开; NO: 关闭(默认)
  60. */
  61. - (void)setLogEnabled:(BOOL)enabled;
  62. /**
  63. * 流量包订购
  64. * @param type 传入订购页面类型: 1 通用包订购页面
  65. 2 活动包订购页面
  66. 3 赛事包订购页面
  67. 4 季度包订购页面
  68. * @param callback 回调
  69. */
  70. - (void)openOrderViewControllerWithType:(AlicloudTFreeOrderOperationType)type telephone:(NSString *)telephone callback:(TFREEViewControllerCallback)callback;
  71. /**
  72. * 获取用户订购关系
  73. * @param telephone 电话号码,可选
  74. * @param callback 回调
  75. */
  76. - (void)openQueryRelationViewControllerWithTelephone:(NSString *)telephone callback:(TFREEViewControllerCallback)callback;
  77. /**
  78. * 用户激活,通过代理方式
  79. * @param telephone 电话号码,可选
  80. * @param callback 回调
  81. */
  82. - (void)openActiveUserViewControllerWithTelephone:(NSString *)telephone callback:(TFREEViewControllerCallback)callback;
  83. /**
  84. * 流量包退订
  85. * @param telephone 电话号码,可选
  86. * @param callback 回调
  87. */
  88. - (void)openUnOrderViewControllerWithTelephone:(NSString *)telephone callback:(TFREEViewControllerCallback)callback;
  89. @end

鉴权结果与错误码

  1. AlicloudTFreeService *TFree = [[AlicloudTFreeService alloc] initWithAppID:@"****" pid:@"****" desKey:@"****" iv:@"****"];
  2. [TFree getAuthDataAsyncByHost:@"www.xxx.com" force:YES callback:^(NSString *authData, NSError *error) {
  3. }];

其中的返回值部分:

返回值中authData : 表示鉴权信息

错误信息:error对象的组成部分:

  1. - code 失败的code
  2. - userInfo内部包含:
  3. - subCode:失败的具体code
  4. - NSLocalizedDescriptionKey;//失败的原因

失败的code和msg:

code 意义 subcode 意义
“5001” 需要订购
“0001” 用户无权限(未订购指定套餐)
”2103“ 未订购产品用户
“5002” 需要激活
“0004” 用户的deviceid不正确
“2101” 产品未激活,请激活产品
“2111” 用户手机号码或订单号码错误
“2113” 该订单号码没有对应的用户
“-1002 SIM卡改变
“5003” 需要订购或激活
“-1000” 没有免流信息,需要先订购或激活
“5004” 不用走免流
“2104” 用户流量已用完
“-1001” 不是联通网络
“-1003” 免流关闭
“5005” 需要联系小沃客服
“2102” 用户行为异常,请重新鉴权
“2112” 该订单存在异常
“5100” 其他错误
“2110” 设备标识码未上传
“9001” 请求签名有误
”9002“ 请求参数有误
”9999“ 系统异常

TFREEBOOLCallback

TFREEBOOLCallback 为流量包订购、退订、激活的回调。

  1. typedef void (^TFREEBOOLCallback)(BOOL success, NSError *error);
  2. @interface AlicloudTFreeOperationViewController : UIViewController<UIWebViewDelegate>
  3. - (void)setCallbackBlock:(TFREEBOOLCallback)callback;
  4. @end

用法如下:

  1. AlicloudTFreeService *TFree = [[AlicloudTFreeService alloc] initWithAppID:@"****" pid:@"****" desKey:@"****" iv:@"****"];
  2. [TFree openOrderViewControllerWithType:AlicloudTFreeOrderOperationTypeOrder telephone:@"*****" callback:^(__kindof AlicloudTFreeOperationViewController *viewController, NSError *error) {
  3. [viewController setCallbackBlock:^(BOOL success, NSError *error) {
  4. //TODO:
  5. }];
  6. }];

error中错误码:

code 意义
1001 激活失败
1002 订购失败
1003 退订失败
1004 结果解析失败
1005 其他失败

TFREEAuthDataCallback

TFREEAuthDataCallback为异步获取授权信息的回调。

  1. typedef void (^TFREEAuthDataCallback)(NSString *authData, NSError *error);

最佳实践

初始化

调用初始化方法,设置appid、packageid、desKey、iv,这些参数由小沃提供,该方法只需要调用一次,建议在- [AppDelegate application:didFinishLaunchingWithOptions:] 中调用:

  1. AlicloudTFreeService *TFree = [[AlicloudTFreeService alloc] initWithAppID:@"****" pid:@"****" desKey:@"****" iv:@"****"];
  2. [TFree getAuthDataAsyncByHost:@"www.xxx.com" force:YES callback:^(NSString *authData, NSError *error) {
  3. }];

提示订购或激活流量包

根据用户的选择调用 AlicloudTFreeService 中的接口。

发起免流请求

通过上面的接口获取鉴权信息成功后,将鉴权信息放入请求的header 的 UserAgent 中,以 WKWebView 为例:

  1. self.wkWebView = [[WKWebView alloc] initWithFrame:self.view.bounds];
  2. [self.wkWebView setBackgroundColor:[UIColor blueColor]];
  3. [self.view addSubview:self.wkWebView];
  4. __weak typeof(self) weakSelf = self;
  5. [self.wkWebView evaluateJavaScript:@"navigator.userAgent" completionHandler:^(id result, NSError *error) {
  6. NSString *newAgent = [self newAgentWithOldUA:result];
  7. //regist the new agent
  8. NSDictionary *dictionnary = [[NSDictionary alloc] initWithObjectsAndKeys:newAgent, @"UserAgent", nil];
  9. [[NSUserDefaults standardUserDefaults] synchronize];
  10. if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9.f) {
  11. [self.wkWebView setCustomUserAgent:newAgent];
  12. }
  13. [[NSUserDefaults standardUserDefaults] registerDefaults:dictionnary];
  14. __strong typeof(weakSelf) strongSelf = weakSelf;
  15. // needs retain because `evaluateJavaScript:` is asynchronous
  16. [strongSelf.wkWebView loadRequest:strongSelf.request];
  17. }];

如果鉴权通过,正常情况是返回200;如果鉴权失败,会返回403,原因会出现在响应头 X-Tengine-Error 中,类似(X-Tengine-Error: tfree auth failed: json decode error),可能有如下几种情况:

原因 详情
no user-agent 没有user-agent
no Alitfree user-agent中没有Alitfree()包裹的鉴权信息
decode base64 error Alitfree()包裹的鉴权信息base64 decode失败
json decode error Alitfree()包裹的鉴权信息base64 decode之后,做json decode失败
invalid expired expired值无效,如不为数字
expired url url的鉴权信息过期
no verify 没有verify值
invalid verify 计算的verify值不相等,鉴权失败

如果鉴权失败,建议调用强制刷新接口,重新请求。

Q&A

Q: 上网的SIM卡不是订购流量包的手机号

A:目前无法对SIM卡和手机号进行校验,所以无法判断出使用的SIM卡与订购流量包的手机号是否一致。

如果是联通网络,只会对订购流量包的手机进行计费。如果非联通网络,则不会走免流。

Q: 鉴权成功后如果查询流量失败会怎样处理?

A:这种情况会走免流

Q: 对于不同上网网络怎么处理的?

A:sdk会判断当前上网的网络情况,只有在联通网络是才会正常获取鉴权信息,如果非联通网络则获取不到鉴权信息。

Q: app卸载后重装是否需要重新激活?

A:需要重新激活,app通过sdk可以判断出当前没有订购或者没有激活,自行提示用户。

本文导读目录