集成要求
合规说明
请注意,在贵司的App中集成小盾提供的SDK产品时:
1.1 根据《网络安全法》《电信条例》《电信和互联网用户个人信息保护规定》等相关法律法规要求及监管实践中的标准,在贵司的最终用户首次启动App并在贵司开始采集信息之前,贵司应以交互界面或设计(如隐私政策弹窗等)向最终用户完整告知收集、使用、与第三方共享最终用户个人信息的目的、方式和范围,并征得最终用户的明示同意。
1.2 为向贵司提供业务安全和风控服务,小盾 SDK 将采集、处理、使用用户的手机终端唯一标志信息IDFA、Android ID、OAID(包含VAID、AAID)、MAC 地址、WIFI列表、无线路由器标识(BSSID、SSID)、设备类型、设备型号、系统类型、粗略位置信息、精准位置信息、应用程序列表、运行中进程信息、网络制式、设备软件版本号、传感器(光传感器、重力传感器、磁场传感器、加速度传感器、陀螺仪传感器、心率传感器)以及传感器列表相关设备信息。为确保贵司使用相关服务的合规性,前述隐私政策应涵盖对小盾SDK提供服务并采集、处理、使用相关信息的授权,以上内容供贵司参考,具体表述可由贵司根据贵司隐私协议的整体框架和内容自行确定。
个人信息类处理规则(隐私政策):https://xiaodun.com/other/privacy/id=4
使用说明:合规使用指导
环境要求
| 说明 | |
|---|---|
| 兼容版本 | iOS9.0+ |
| 支持架构 | armv7, arm64, x86_64 |
集成步骤
SDK接入示例代码(sample):https://github.com/trustdecision/mobrisk-ios-sample
在线安装方式 CocoaPods 和 Swfit Package Manager 集成方式二选一:
安装(CocoaPods)
- 在 Podfile 文件中对应 target 中新增 pod 'TrustDecisionPro', '5.3.1.1'
- 在 Podfile 所在文件夹中执行 pod install --repo-update 命令 (arm架构mac电脑需要执行 arch -x86_64 pod install --repo-update 命令)
安装(Swfit Package Manager)
- 选择
File->Add Package Dependencies... - 输入仓库地址:
https://github.com/trustdecision/trustdevice-pro-ios.git- Dependency Rule 选择
Exact Version - Version 填写:
5.3.1-2- Add to Target 选择宿主 App Target
- 点击
Add Package
在宿主 App Target 中添加 -ObjC:
-ObjC:- 选择
TARGETS-> 宿主 App Target - 选择
Build Settings - 搜索
Other Linker Flags - 添加:
-ObjC引入头文件
在调用的位置引入头文件
#import <TDMobRisk/TDMobRisk.h>import TDMobRisk隐私文件配置
根据苹果公司公布的最新 App Store 隐私政策,自2024年春季开始,上架 App Store 的应用需要携带一份 App 的隐私清单文件。 从 2024 年 5 月 1 日开始,App Store Connect 不接受未在隐私清单文件中描述其使用所需原因 API 的应用程序。
适配措施
请根据您的实际情况选择解决方案进行处理:
- 工程目录中不存在 PrivacyInfo.xcprivacy 文件
- 在工程目录下通过 Xcode 新建 App Privacy 类型的文件,命名为 PrivacyInfo,同时勾选需要的 Targets
- 在工程目录中选中 PrivacyInfo.xcprivacy 文件并右击打开菜单,通过菜单中的 Open As -> Source Code 的方式打开文件
- 将下方 SDK 的 PrivacyInfo.xcprivacy 粘贴到工程目录的 PrivacyInfo.xcprivacy 文件中
- 工程目录中已存在 PrivacyInfo.xcprivacy 文件
- 在工程目录中选中 PrivacyInfo.xcprivacy 文件并右击打开菜单,通过菜单中的 Open As -> Source Code 的方式打开文件
- 在工程目录 PrivacyInfo.xcprivacy 文件中补充SDK 的 PrivacyInfo.xcprivacy 里有提及但工程目录 PrivacyInfo.xcprivacy 文件中仍缺失的内容
SDK 的 PrivacyInfo.xcprivacy
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrivacyCollectedDataTypes</key>
<array>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypeDeviceID</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<true/>
<key>NSPrivacyCollectedDataTypeTracking</key>
<false/>
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAnalytics</string>
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
</array>
</dict>
</array>
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryDiskSpace</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>E174.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>35F9.1</string>
</array>
</dict>
</array>
</dict>
</plist>初始化
注意事项
- 确保在用户同意隐私协议后,再进行SDK初始化。
方法定义
void (*initWithOptions)(NSDictionary *options);获取blackBox
注意事项
- 请在 initWithOptions后调用getDeviceInfo
- 不要在App内对返回的blackBox进行缓存,获取blackBox请依赖getDeviceInfo方法
- 尽量在首次获取blackBox的异步回调触发之后,再同步获取blackBox
方法定义
// 异步回调获取
void (*getDeviceInfo)(TDDeviceInfoCallback callback);
// 同步获取
TDDeviceResponse (*getDeviceInfoSync)(void);最佳实践
- 在应用程序入口处初始化
- (void)initTrustDeviceSDK {
TDMobRiskManager_t *riskManager = [TDMobRiskManager sharedManager];
NSMutableDictionary *options = [NSMutableDictionary dictionary];
/*************************** 必传 ***************************/
// 合作方(partnerCode),请填写partnerCode,不要填partnerKey
[options setValue:@"请输入您的合作方" forKey:@"partner"];
// 平台注册的应用标识,参考下方全部配置说明
[options setValue:@"请输入您的appKey" forKey:@"appKey"];
// 数据中心地区参数,参考下方全部配置说明`
[options setValue:@"请输入您接入的数据中心" forKey:@"dataCenter"];
riskManager->initWithOptions(options);
}func initTrustDeviceSDK() {
let riskManager = TDMobRiskManager.sharedManager()
var options = Dictionary<String, Any>()
/*************************** 必传 ***************************/
// 合作方(partnerCode),请填写partnerCode,不要填partnerKey
options.updateValue("请输入您的合作方", forKey: "partner")
// 平台注册的应用标识,参考下方全部配置说明
options.updateValue("请输入您的appKey", forKey: "appKey")
// 数据中心地区参数,参考下方全部配置说明
options.updateValue("请输入您接入的数据中心", forKey: "dataCenter")
riskManager?.pointee.initWithOptions(options)
}-
在实际业务节点获取blackBox
-
推荐使用异步的方式获取,不影响调用线程
TDMobRiskManager_t *riskManager = [TDMobRiskManager sharedManager]; riskManager->getDeviceInfo(^(TDDeviceResponse response) { // ❗️Attention❗️必须先做NSString类型转化,否则不允许其他线程直接使用response对象以及其中的结果 NSString *blackBox = [NSString stringWithUTF8String:response.blackBox ?: ""]; int code = response.apiStatus.code; NSString *message = [NSString stringWithUTF8String:response.apiStatus.message ?: ""]; // 使用声明的对象执行业务逻辑,code和message用于异常排查,业务接口可直接携带blackBox NSLog(@"code:%d,message:%@\nblackBox:%@",code,message,blackBox); });let riskManager = TDMobRiskManager.sharedManager() riskManager?.pointee.getDeviceInfo({ response in // ❗️Attention❗️必须先做String类型转化,否则不允许其他线程直接使用response对象以及其中的结果 let blackBox = response.blackBox.flatMap { String(cString: $0) } ?? "" let code = response.apiStatus.code let message = response.apiStatus.message.flatMap { String(cString: $0) } ?? "" // 使用声明的对象执行业务逻辑,code和message用于异常排查,业务接口可直接携带blackBox print("code:\(code),message:\(message)\nblackBox:\(blackBox)") }) -
如果此前已经通过异步的方式成功获取过blackBox,则可以使用同步的方式直接获取blackBox
// 可能耗时,谨慎在主线程调用 TDMobRiskManager_t *riskManager = [TDMobRiskManager sharedManager]; TDDeviceResponse response = riskManager->getDeviceInfoSync(); // ❗️Attention❗️必须先做NSString类型转化,不允许其他线程直接使用response对象以及其中的结果 NSString *blackBox = [NSString stringWithUTF8String:response.blackBox ?: ""];// 可能耗时,谨慎在主线程调用 let riskManager = TDMobRiskManager.sharedManager() let response = riskManager?.pointee.getDeviceInfoSync() // ❗️Attention❗️必须先做String类型转化,不允许其他线程直接使用response对象以及其中的结果 let blackBox = response?.blackBox.flatMap { String(cString: $0) } ?? ""
-
状态检查
- SDK上报数据成功,返回的blackBox结果长度为26位字符串。如: rIPGX1678775227I9NCwcuVJCb。
- 异常情况下,返回的blackBox结果长度可能达到5000字符,详情可查看正常blackBox和降级blackBox的差异
其他说明
获取SDK版本号
TDMobRiskManager_t *riskManager = [TDMobRiskManager sharedManager];
NSString *sdkVersion = riskManager->getSDKVersion();let riskManager = TDMobRiskManager.sharedManager()
let sdkVersion = riskManager?.pointee.getSDKVersion()全部配置
| 配置Key | 说明 | 示例代码 | 移除字段 |
|---|---|---|---|
| partner(必须) | 合作方编码,请联系我司运营或者从客户平台获取 | Objective C[options setValue:@"请输入您的合作方编码" forKey:@"partner"];Swift options.updateValue("请输入您的合作方编码" , forKey: "partner") | |
| appKey(必须) | 应用标识,通过客户平台创建,参考如何申请appKey | Objective C[options setValue:@"请输入您的appKey" forKey:@"appKey"];Swift options.updateValue("请输入您的appKey" , forKey: "appKey") | |
| dataCenter(必须) | 数据中心地区: cn代表中国 us代表美国 sg代表新加坡 fra代表德国 idna代表印尼 ❗️变更点:country已废弃但目前仍能生效,建议改用dataCenter | Objective C[options setValue:@"cn" forKey:@"dataCenter"];Swift options.updateValue("cn" , forKey: "dataCenter") | |
| appName | 应用名称,请联系运营获取 | Objective C[options setValue:@"请输入您的appName" forKey:@"appName"];Swift options.updateValue("请输入您的appName", forKey: "appName") | |
| channel | 渠道标识,请联系运营获取 | Objective C[options setValue:@"请输入您的channel" forKey:@"channel"];Swift options.updateValue("请输入您的channel", forKey: "channel") | |
| timeLimit | 网络请求回调的超时时间,单位秒,默认为15s | Objective C[options setValue:@(5) forKey:@"timeLimit"];Swift options.updateValue(5, forKey: "timeLimit") | |
| location | 是否采集地理位置信息,默认开启 | Objective C[options setValue:@(NO) forKey:@"location"];Swift options.updateValue(false, forKey: "location") | latitude、longitude、gps_location |
| IDFA | 是否采集广告标识符,默认开启 | Objective C[options setValue:@(NO) forKey:@"IDFA"];Swift options.updateValue(false, forKey: "IDFA") | idfa |
| IDFV | 是否采集应用开发厂商标识符,默认开启 | Objective C[options setValue:@(NO) forKey:@"IDFV"];Swift options.updateValue(false, forKey: "IDFV") | idfv |
| wifiIp | 是否采集 wifiIp,默认开启 | Objective C[options setValue:@(NO) forKey:@"wifiIp"];Swift options.updateValue(false, forKey: "wifiIp") | wifiIp |
| cellIp | 是否采集 cellIp,默认开启 | Objective C[options setValue:@(NO) forKey:@"cellIp"];Swift options.updateValue(false, forKey: "cellIp") | cellIp |
| vpnIp | 是否采集 vpnIp,默认开启 | Objective C[options setValue:@(NO) forKey:@"vpnIp"];Swift options.updateValue(false, forKey: "vpnIp") | vpnIp |
| wifiIpv6 | 是否采集 wifiIpv6,默认开启 | Objective C[options setValue:@(NO) forKey:@"wifiIpv6"];Swift options.updateValue(false, forKey: "wifiIpv6") | wifiIpv6 |
| deviceName | 是否采集设备名称,默认开启 | Objective C[options setValue:@(NO) forKey:@"deviceName"];Swift options.updateValue(false, forKey: "deviceName") | device_name |
| ssid | 是否采集ssid信息,默认开启 | Objective C[options setValue:@(NO) forKey:@"ssid"];Swift options.updateValue(false, forKey: "ssid") | ssid、bssid |
| customMessage | 自定义消息,sdk支持透传和存储 | Objective C[options setValue:@"this is a customMessage" forKey:@"customMessage"];Swift options.updateValue("this is a customMessage", forKey: "customMessage") |
响应结果
getDeviceInfo() 函数会在 回调 中返回响应数据,包含以下信息。
| 字段 | 描述 |
|---|---|
| blackBox | 调用日志查询标识 |
| fpVersion | SDK版本号 |
状态码说明
调用TDMobRiskManager getDeviceInfo()方法,回调中TDDeviceAPIStatus类型的参数保存着SDK的状态信息,它的定义如下:
typedef struct TDDeviceAPIStatus_Void {
/// code
int code;
/// message
NSString *message;
} TDDeviceAPIStatus;code和message对应值如下表:
| code | message | 备注 |
|---|---|---|
| 0 | Success. | 成功 |
| 1000 | Access error. | 准入发生异常,可能原因:初始化参数无效或网络环境异常 |
| 1001 | SDK error. | SDK 发生异常,可能原因: 未调用初始化函数 |
| 1002 | Network error. | 网络错误 |
| 1003 | API error. | 后端接口返回错误 |
| 1004 | Traffic limit. | 网关限流返回 |
| 1005 | Traffic shutdown. | 流量关停 |
| 1100 | Unknown error. | 未知错误 |
QA
Q1: 如何解决使用Archive打包上架Testflight 或 AppStore完成后报警告:The archive did not include a dSYM for the TDCorePlugin.framework with the UUIDs 的问题?
A1: 不会对当前App上架造成任何影响,请忽略这个警告
