# 集成要求

# 合规说明

请注意,在贵司的App中集成同盾提供的SDK产品时:

1.1 根据《网络安全法》《电信条例》《电信和互联网用户个人信息保护规定》等相关法律法规要求及监管实践中的标准,在贵司的最终用户首次启动App并在贵司开始采集信息之前,贵司应以交互界面或设计(如隐私政策弹窗等)向最终用户完整告知收集、使用、与第三方共享最终用户个人信息的目的、方式和范围,并征得最终用户的明示同意。

1.2 为向贵司提供业务安全和风控服务,同盾SDK将采集、处理、使用用户的手机终端唯一标志信息(IMEI/IDFA)、Android ID、IMSI、MEID、MAC 地址、SIM 卡序列号、设备序列号、设备类型、设备型号、系统类型、地理位置、登录 IP 地址等设备信息。为确保贵司使用相关服务的合规性,前述隐私政策应涵盖对同盾SDK提供服务并采集、处理、使用相关信息的授权,以下条款内容供贵司参考,具体表述可由贵司根据贵司隐私协议的整体框架和内容自行确定:

同盾SDK:为了业务安全和风控,我司使用了同盾 SDK,该 SDK 需要获取您的手机终端唯一标志信息(IMEI/IDFA)、Android ID、IMSI、MEID、MAC 地址、SIM卡序列号、设备序列号、设备类型、设备型号、系统类型、地理位置、登录 IP 地址、应用程序列表、运行中进程信息、传感器(光传感器、重力传感器、磁场传感器、加速度传感器、陀螺仪传感器)相关设备信息,用于设备欺诈风险识别。

同盾隐私协议:https://www.tongdun.cn/other/privacy/id=1

# 环境要求

条目 说明
兼容版本 支持主流机型,Android 4.4及以上系统
支持架构 armeabi-v7a, arm64-v8a, x86

# 集成步骤

# 集成SDK

注意: 已经在⼯程libs中集成SDK的客户,在升级新版本SDK时,请先删除旧版 SDK,如有旧版本集成的so库也需要同时删除。

SDK接入示例代码(sample): https://github.com/trustdecision/mobrisk-android-sample

# 添加仓库

首先, 请在项目根目录的 build.gradle加入maven库的配置

allprojects {
    repositories {
        ...
        mavenCentral()
    }
}

如果您的 Gradle 版本是 7 或更高版本,请将这些行添加到您的 settings.gradle

repositories {
        ...
        mavenCentral()
}

# 添加依赖

在项目的 app/build.gradle 中加上依赖,如图:

dependencies {
    // 设备指纹
    implementation 'com.trustdecision.android:mobrisk:4.2.4.2'
    // 验证码
    implementation 'com.trustdecision.android:captcha:2.2.0'
 }

如果遇到合规性问题,我们也可以在依赖阶段排除相关模块的采集,如下:

dependencies {
    // 设备指纹
    implementation('com.trustdecision.android:mobrisk:4.2.4.2'){
    	// 移除后sdk不获取安装包列表
        exclude group: 'com.trustdecision.android', module: 'packagelist'
        // 移除后sdk不会收集READ_PHONE_STATE相关信息
        exclude group: 'com.trustdecision.android', module: 'readphone'
    }
 }

# ABI类型

SDK目前支持 armeabi-v7a、arm64-v8a、x86三种ABI类型,建议接入方在 app/build.gradle文件内添加 abiFilters配置选择所需要的架构类型,示例

defaultConfig {
    ........
    ndk {
       abiFilters 'armeabi-v7a', 'arm64-v8a'
    }
}

具体架构,请以您自己需要支持的架构为准!

# 文件配置 AndroidManifest.xml

在应⽤module下的 AndroidManifest.xml ⽂件中声明以下权限

<manifest>
   <!--必选权限-->
   <!--网络通信-->
   <uses-permission android:name="android.permission.INTERNET"/>
   <!--获取网络状态-->
   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
   <!--获取WIFI状态-->
   <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>

   <!--以下权限是可选权限,不声明此部分权限将放弃部分设备信息的采集,对数据分析及设备指纹的精准度有一定影响-->
   <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
   <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
   <uses-permission android:name="android.permission.READ_PHONE_STATE" />
   <!-- Android11及以上获取安装包列表需要该权限,采集安装包列表涉及到⻛险合规,是否需要该权限业务⽅⾃⾏选
择 -->
   <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"
        tools:ignore="QueryAllPackagesPermission" />
</manifest>

动态申请权限: Android 6.0 及以上版本需要动态申请权限,动态申请权限代码必须放在初始化 SDK 前,代码示例如下:

//以下权限不是必须申请. 可根据业务情况选择性权限申请
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    requestPermissions(new String[]{
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.READ_PHONE_STATE
    }, 100);
}

# SDK 的使用方法

注意事项

确保在用户同意隐私协议后,再进行SDK初始化,避免出现用户未同意隐私协议就进行SDK初始化采集,引发合规风险。

SDK配置

TD的sdk使用TDRisk.Builder方法对sdk初始参数进行配置设置,并将设置结果作为初始化参数提供给sdk初始化方法initWithOptions()使用。

TDRisk.Builder必须参数配置如下

配置 key 定义 说明 示例代码
partner 合作方编码 同盾的合作方编码,请联系同盾运营获取 builder.partnerCode("partner")
appKey 应用标识 同盾生成的应用标识,和app绑定,用于校验app的有效性,请联系同盾运营获取 appkey创建需要用户提供应用包名、小写的sha256 签名。 ⚠️不同应用的包名签名不要使用相同的值 builder.appKey("appKey")
appName 应用名称 同盾平台注册的应用名称,请联系同盾运营获取 builder.appName("appName")
country 国家地区 TDRisk.COUNTRY_US 北美 TDRisk.COUNTRY_FRA 欧洲 TDRisk.COUNTRY_SG 新加坡 TDRisk.COUNTRY_CN 中国 builder.country(TDRisk.COUNTRY_CN)

我们也提供了可选参数配置,详情可以见附表(初始化配置可选参数列表)

SDK使用方法示例代码:

在应用启动的时候,比如在应用的 application 的 onCreate 方法中(Android 6.0 及以上版本应确保已经申请过权限)调用以下方法:

# 方式一(推荐的方式): 通过getBlackBox() 方法获取blackbox

// SDK初始化配置
TDRisk.Builder builder = new TDRisk.Builder()
/*************************** 必传 ***************************/
.partnerCode("demo")        // 同盾的合作⽅编码,如demo,请填写⾃身的合作⽅编码
.appName("appName")         // 同盾平台注册的应⽤名称,请联系同盾运营获取
.appKey("appKey")           // 配置AppKey,请联系同盾运营获取		 
.country(TDRisk.COUNTRY_CN); // 国家地区参数,如cn、sg、us、fra
/*************************** 必传 ***************************/

// 初始化态势感知SDK
if(⽤户同意隐私协议){
   TDRisk.initWithOptions(getApplicationContext(), builder);
}

⚠️注意事项:必须保证 initWithOptions后 调用 getBlackBox

在业务需要的时候获取blackbox。

String blackbox = TDRisk.getBlackBox();

# 方式二: 通过回调方法callback,在onEvent中获取blackbox

// SDK初始化配置
TDRisk.Builder builder = new TDRisk.Builder()
/*************************** 必传 ***************************/
.partnerCode("demo")        // 同盾的合作⽅编码,如demo,请填写⾃身的合作⽅编码
.appName("appName")         // 同盾平台注册的应⽤名称,请联系同盾运营获取
.appKey("appKey")           // 配置AppKey,请联系同盾运营获取		 
.country(TDRisk.COUNTRY_CN) // 国家地区参数,如cn、sg、us、fra
/*************************** 必传 ***************************/

// 回调结果
.callback(new TDRiskCallback() {
  @Override
  public void onEvent(String blackbox) {
    // 此处回调在⼦线程
    // ⽹络正常的情况下,会在200-300ms内返回结果。
    // ⽹络异常的情况下,会在超时时间(默认最长15s)后返回。
    // 请在下⽅添加您对blackbox的处理逻辑
    Log.i("TDRiskDemo", "blackbox: " + blackbox);
  }
});

// 初始化态势感知SDK
if(⽤户同意隐私协议){
   TDRisk.initWithOptions(getApplicationContext(), builder);
}

# 两种方式的差异

  • 方式一是同步获取blackbox,优点是可以保证会获取到blackbox(一些情况下为降级blackbox),如果在主线程调用 getBlackBox需要注意耗时问题。
  • 方式二是异步获取blackbox,优点是不会阻塞进程,无耗时问题,缺点是调用getBlackBox方式时初始化尚未完成,无法获得blackbox。需要注意 回调结果不是在主线程,禁止在回调中操作UI。

SDK上报数据成功后,正常情况下,getBlackbox()返回的结果长度为26位字符串. 如: rWPGX1678775227I9NCwcuVJCb。 异常情况下,长度为5000字符左右. 详情可查看总览 (opens new window)

执行initWithOptions初始化成功会在 logcat中打印以下log:

TD_JAVA: Tongdun sdk load success
TD_JAVA: Tongdun sdk init success

# 获取SDK版本号

示例代码

// 获取SDK版本号
TDRisk.getSDKVersion()

# 其他说明

混淆打包 如果开发者需要使用 proguard 进行混淆打包,请在 proguard 配置文件添加如下代码:

#TONGDUN
-keep class cn.tongdun.**{*;}

# 验证码功能模块

# 初始化配置可选参数列表

配置 key 定义 说明 场景 示例代码
language 语言类型 可选项: 1-简体中文、2-繁体中文、3-英 文、4-日文、5-韩文、6-⻢来语、7-泰语、8-印尼语、9-俄语 默认: 1-简体中文 客户根据需要设置语言类型,国内支持1-5,海外支持1-9 builder.language(1)
tapToClose 点击验证码视图外面,是否关闭验证码 可选项: true、false 默认: false 开启后,点击界面空白处,会关闭验证码弹窗,关闭弹窗更加便捷 builder.tapToClose(true)
needSeqid 失败回调信息中是否携带seqid 可选项: true、false 默认: false 开启后,失败信息中会携带seqid序列号,将seqid提供给同盾,方便排查失败原因 builder.needSeqId(true)
hideLoadHud 是否跳过加载动画 可选项: true、false 默认: false 开启后,弹出验证码弹窗时不会再显示加载动画,缩短验证时间 builder.hideLoadHud(true)
hideWebCloseButton 是否隐藏webview的关闭按钮 可选项: true、false 默认: false 需要强制完成验证码验证的场景 builder.hideWebCloseButton(true)
openLog 是否打开log 可选项: true、false 默认: false 开启后,调试时控制台会输出更多的log信息,方便排查问题 builder.openLog(true)
skipCaptcha 是否跳过同盾验证码验证 可选项: true、false 默认: false 开启将不会进行验证码的验证,同时返回4000错误码,用于动态设置是否使用同盾验证码SDK验证的场景 builder.skipCaptcha(true)
mfaId MFA产品 可选项: string 默认: null 如果您接入了MFA产品(未对接MFA,可忽略该说明),请将MFA流程中获取的 mfaid传递给验证码配置参数。 builder.mfaId("mfaid")

# 弹出验证码弹窗

showCaptcha方法

TDRisk.showCaptcha(activity, new TDCaptchaCallBack(){
  // 验证码加载完毕准备弹出 验证码
  public void Ready() {}

  // 只有当验证码验证成功或者后台系统认为设备可信时才会调用此接口
  // 返回一个String 类型的token
  public void Success(String token) {}

  // 验证过程中出现的所有错误信息都会调此接口
  public void Failed(int errorCode, String errorMsg) {}
});

验证码showCaptcha操作请务必放在主线程中执行

示例代码

...
public void loginClick() {
    TDRisk.showCaptcha(activity, new TDRiskCaptchaCallback() {
        @Override
        public void onReady() {
          Log.d("TD","验证码弹窗成功,等待验证!");
        }

        @Override
        public void onSuccess(String token) {
          Log.d("TD","验证成功!,validateToken:" + token);
        }

        @Override
        public void onFailed(int errorCode, String errorMsg) {
          Log.d("TD","验证失败!, 错误码:"+ errorCode + ", 错误内容:" + errorMsg);
        }
    });
}

TDCaptchaCallBack 是验证码的回调接口,您需要自行实现以下接口:

# 错误码

验证码功能模块的错误码会通过 TDCaptchaCallBack 方法输出

错误码 错误信息 处理方式
1001 关闭验证码窗口 弹出验证码后,手动取消了验证码(返回键或空白区域)
2001 请求参数异常,请检查参数 请检查应用标识和和合作方编码
2100 请求参数异常,请检查参数 请检查传递参数
2101 请求参数异常,请检查参数 请求过程出错,联系技术支持
2102 请求参数异常,请检查参数 参数缺失,请检查参数
2111 验证页面网络错误 稍后再试,或者联系技术支持
2112 验证页面操作太频繁 稍后再试
2113 未知错误 未知错误,联系技术支持
2114 关闭验证码窗口 点击了验证码关闭按钮
2115 验证页面网络错误 网络资源加载失败
2116 验证页面网络错误 网络资源加载失败
2202 验证成功 验证结果成功
2301 未购买此服务 请联系技术支持
2302 流量已被禁用 请联系技术支持
2303 流量不足 请联系技术支持
2304 服务已过期 请联系技术支持
2305 日流量已封顶 请联系技术支持
2600 系统繁忙,请稍后再试 系统繁忙,请稍后再试
2601 验证失败,稍后重试 验证失败,请稍后重试
2602 验证失败,稍后重试 验证失败,请稍后重试
2603 验证失败,稍后重试 验证失败,请稍后重试
2604 验证失败,稍后重试 刷新频繁,请稍后重试
2605 验证失败,稍后重试 获取验证码信息失败
2702 验证失败,稍后重试 解析错误,请稍后重试
3001 SSL证书校验失败 请关闭代理工具
3002 验证页面加载出错 刷新网络后重试
3003 验证页面加载超时 检查网络后重试
4000 验证逻辑跳过 开发者手动处理验证跳过逻辑
9000 设备指纹没有挂载 集成验证码需要先集成设备指纹
9001 没有网络 请检查网络连接
9002 请求超时 检查网络,稍后重试
9003 返回结果异常 服务端错误,返回结果异常,联系技术支持
9004 全局加载超时 检查网络,稍后重试

# FAQ

Q1: 用户在使用代理时,加载验证码异常

A1: sdk内部不允许抓包,在证书出现错误时,无法加载验证码,会回调 SSL证书校验失败的错误码

: 2023/06/07 16:19:48