产品文档 > 智能风控 > 设备指纹

顶象设备指纹(UNIFYID®)介绍

一、快速入门指南

1. 产品简介

顶象设备指纹通过用户上网设备的硬件、网络、环境等特征信息生成设备的唯一标识,覆盖安卓、iOS、Web/H5、公众号、小程序,可有效侦测模拟器、刷机改机、root越狱、劫持注入等风险,配合顶象风控系统使用,可有效对抗设备伪造、自动注册、羊毛党等恶意行为。

2. 名词解释

名称释义
AppId公钥,长度为32位字符串,接入渠道唯一标识。开通服务后可在设备指纹的二级菜单“应用管理”中获取,AppId在客户端接入时使用。
AppSecret私钥,长度为32位字符串,与公钥对应,开通服务后可在设备指纹的二级菜单“应用管理”中获取,请妥善保管,勿泄漏给他人 。AppSecret在后台查询设备详情时使用。
token设备指纹SDK采集上报后返回的标识,token不是设备指纹,通过token可以查询设备指纹
hardId设备指纹
用户前端Web端或集成SDK的Android端、iOS端
用户后端指企业的后台服务器

➡️ ➡️ ➡️ 开发者请注意

快速开发使用AppId专属AppId
开发测试接口连通可使用:
AppId: d7eb51437ed189ae6a42ef3cccf69cec
❌ 缺点:多人共用,无法进行统计数据查询
专属AppId请登录获取
✅ 优点:可以在控制台通过图形化界面
查询统计数据及风险标签

3. 交互流程

单独使用顶象设备指纹服务时的调用过程

image.png

  • 客户端接入,业务客户端需要集成顶象指纹客户端SDK,包括安卓,iOS,H5,小程序等;通过顶象客户端SDK可以获取到设备指纹token(注:token不是设备指纹)。
  • 业务接口扩展,业务客户端在需要设备指纹token的时候,可以通过相应的api获取到。业务接口需要把前端拿到的指纹token一并传入后台。
  • 后台接入,顶象提供后端SDK来查询设备详细信息,SDK涵盖Java,PHP等。
    重要:因终端用户的设备网络环境和设备版本等因素,设备指纹采集率并不能一定达到100%,可能会存在极少部分未能正常采集到的情况。所以在集成指纹服务的时候,请尽量避免对指纹信息强依赖。

4. FAQ及版本记录

点击查看FAQ (https://www.dingxiang-inc.com/docs/preview/detail/const-id-faq)

二、前端接入

1 Web接入

第一步:引入

在页面 HTML 中引入 const-id.js,代码形如:

<script src="https://cdn.dingxiang-inc.com/ctu-group/constid-js/index.js"></script>

因js文件会定期更新,为避免js失效影响您的使用,请不要将js下载到本地服务器上引入

第二步:生成并使用

页面加载后,初始化设备指纹,需要在 JavaScript 中调用 _dx.ConstID(options, callback) 方法获取设备指纹token,代码形如:

var options = {
  appId: '【这里填写 AppID】', // 唯一标识,必填
  server: 'https://constid.dingxiang-inc.com/udid/c1', // constId web端服务接口
  userId: '【这里填写 userID】' // 用户标识,可选
};

_dx.ConstID(options, function (err, token) {
  if (err) {
    // console.log('error: ' + err);
    return;
  }
  // console.log('const-id token is ' + token);
});

同时也支持Promise的用法

_dx.ConstID(options).then(function(token) {
  console.log(token)
}).catch(function(err) {
  console.log(err)
})

options 字段说明

字段类型是否必填说明
appIdString当前应用的标识
serverStringconstId 服务接口,可选,如不填,则默认会用云服务接口
sceneString场景标识,例如 loginsurvey
userIdString业务方的用户唯一标识,例如用户名、用户ID、手机号、Email等
timeoutnumber超时失败时间,单位为毫秒
cacheboolean默认为 true,表示会缓存采集结果;改为 false 则每次会重新采集

PC浏览器兼容

浏览器最低版本
IE8
Edge20
Chrome60
Safari11
Firefox60
36010
Sougou8
QQ4

移动端浏览器兼容

浏览器最低版本
Chrome60
UC12
QQ8
Safari11
原生安卓4.0及以上


2 Android接入

一、 环境要求

条目说明
开发目标Android 5.0-13.x, 14.0
CPU架构armeabi-v7a arm64-v8a x86 x86_64

若您需要额外的支持范围,请联系顶象技术以获取支持。

(默认不支持)Android 4.1-4.4的webview组件支持Tlsv1.2,但并未默认启动。顶象的服务器基于安全考虑已经禁用不安全的TLS协议,包括Android 4.0-4.4需要的Tls1.0Tls1.1

目前(2023-02-03), android 5.0及以上占比为99.3%。

早期Android版本无法支持全部CPU架构(e.g. Android 4.0只支持armeabi)。

二、 集成SDK

合规指南
请务必确保您已将顶象设备指纹SDK升级到满足监管新规的新版本。

顶象设备指纹最新版本(安卓版) 见 2.1

请务必在您App的隐私政策条款中向用户告知使用顶象设备指纹SDK,条款参考如下:

SDK名称:顶象设备指纹SDK

使用目的:进行设备标识,用于判断设备是否安全

运营方:北京顶象科技技术有限公司

收集个人信息类型:设备信息(IMEI/MAC/Android ID/IDFA/SIM卡IMSI/ICCID)、位置信息、网络信息

隐私权政策连接:https://www.dingxiang-inc.com/about/privacy

请务必确保用户同意您App的《隐私政策》后,再初始化顶象设备指纹SDK

【1】初始化步骤详见 第三大章中 Setup 小节

【2】确保App首次冷启动时,用户完整阅读您的《隐私政策》,并通过正当方式获得用户授权后,才调用DXRisk.setup函数进行初始化。否则,不能调用DXRisk.setup函数进行设备指纹SDK初始化

【3】一旦您的App通过正当方式引导用户同意《隐私政策》,在后续的App冷启动中,开发者都应该调用DXRisk.setup函数进行初始化,以保证SDK的正常运行,调用时机可根据适当的业务场景和开发者意愿进行调用。

2.1 下载SDK
条目说明
SDK名称顶象设备指纹dx-risk SDK(Android)
开发者顶象技术有限公司
版本号v7.3.15r
主要功能详见设备指纹产品简介
个人信息处理规则及隐私合规说明详见隐私政策
SDK 下载地址dx-risk-v7_3_15r_6c51874e.aar
示例DEMO下载地址dx-risk-auto-test.apk
权限申请清单详见 隐私条款 中2.7.3
合规指南详见 合规指南

2.2 Android Studio 集成

SDK包集成内容:

  • dx-risk-vx_x_x.aar
2.2.1 把aar文件放到相应模块的libs目录下

Demo工程结构如下

.
├── app
│   ├── build.gradle
│   ├── libs
│   │   └── dx-risk-vx_x_xxr_xxxxxxxx.aar
│   ├── proguard-rules.pro
│   └── src
│       └── main
├── build.gradle
├── gradle
├── gradle.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
2.2.2 在该Module的build.gradle中如下配置:
android {

  packagingOptions {
      doNotStrip "**/lib*Risk*.so"
  }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.aar'])
}

2.3 (可选)添加SDK所需权限

必选权限

<uses-permission android:name="android.permission.INTERNET"/>

可选权限

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_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.ACCESS_BACKGROUND_LOCATION"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>

2.4 Proguard混淆配置

-dontskipnonpubliclibraryclassmembers
-keepattributes *Annotation*,EnclosingMethod

-dontwarn com.dx.mobile.**
-dontwarn *.com.dx.mobile.**
-dontwarn *.com.mobile.strenc.**
-keep class com.dx.mobile.risk.**{*;}
-keep class com.security.inner.**{*;}
-keep class *.com.dx.mobile.**{*;}
-keep class *.com.mobile.strenc.**{*;}

2.5 API 6.0或以上动态权限申请说明

需要动态申请权限如下:

android.permission.WRITE_EXTERNAL_STORAGE
android.permission.READ_EXTERNAL_STORAGE
android.permission.READ_PHONE_STATE
android.permission.ACCESS_COARSE_LOCATION
android.permission.ACCESS_FINE_LOCATION

动态申请代码实例(Activity下):

protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_demo);

   // 该设置请参考下方 3.1章节中 隐私采集白名单
   DXRisk.setAllowPrivacyList(PrivacyFlag.ALL);


   // API 23或以上的动态申请权限
   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
       String[] permissionArray = {
               "android.permission.ACCESS_COARSE_LOCATION",
               "android.permission.ACCESS_FINE_LOCATION",
               "android.permission.ACCESS_BACKGROUND_LOCATION",
               "android.permission.WRITE_EXTERNAL_STORAGE",
               "android.permission.READ_EXTERNAL_STORAGE",
               "android.permission.READ_PHONE_STATE",
       };
       this.requestPermissions(permissionArray, 1);
   }

}


@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
   super.onRequestPermissionsResult(requestCode, permissions, grantResults);
   // start getToken
   new Thread(new Runnable() {
       @Override
       public void run() {
           HashMap<String, String> params = new HashMap<String, String>();
           String token = DXRisk.getToken("appid", params);
       }
   }).start();

}

三. 接口使用说明

3.1 方法和参数说明
功能描述

采集端的设备指纹信息,上传至风控后台,再由风控后台返回token。 该API为耗时操作,因此必须在非主线程上调用,否则会抛异常。

方法说明

DXRisk.java 该类是DxRisk SDK的风控组件接口,负责采集本地信息并返回用户前端token。

隐私采集白名单

自v6.1.18r开始,SDKsetup前,可以调用setAllowPrivacyList进行隐私采集白名单的设置,默认关闭所有涉及隐私规范红线的采集项

public static void setAllowPrivacyList(long privacyFlag)

使用示例

setAllowPrivacyList(PrivacyFlag.ANDROID_ID); //只采集ANDROID_ID
//自定义列表模式
setAllowPrivacyList(PrivacyFlag.X | PrivacyFlag.Y | ...); //表示既采集X又采集Y,X、Y表示具体某项采集的FLAG值,如下表

以下为提供的白名单采集项

FLAG描述
DEFAULT默认值,关闭所有隐私采集项
ALL打开所有隐私采集项
IMEI加入该FLAG则采集手机IMEI值,否则不采集
IMSI加入该FLAG则采集手机IMSI值,否则不采集
MEID加入该FLAG则采集手机MEID值,否则不采集
SERIAL_NUMBER加入该FLAG则采集手机SERIAL_NUMBER值,否则不采集
MAC_ADDRESS加入该FLAG则采集手机MAC_ADDRESS值,否则不采集
ICCID加入该FLAG则采集手机ICCID值,否则不采集
ANDROID_ID加入该FLAG则采集手机ANDROID_ID值,否则不采集
DEVICE_ID加入该FLAG则采集手机DEVICE_ID值,否则不采集
GET_INSTALLED_PACKAGES加入该FLAG则采集手机的应用安装列表,否则不采集
初始化setup

SDK使用前必须调用先setupsetup主要用于数据/环境初始化,一般在ApplicationonCreate下调用:

/**
* 初始化参数,环境
* @param context
* @return
*/
public static boolean setup(Context context)

PS:下列两种方式获取token在网络通畅的情况下没有任何的不同。

常规Token
/**
 * @return token 通常返回长度为40的字符串。在网络卡顿或不通的情况下,返回4-5k的字符串。
 * @throws DXRiskErrorException 如在主线程调用本API,或者appId为空等等,则会抛出该异常
 */
public static String getToken(String appId, HashMap<String, String> paramsMap) throws DXRiskErrorException
精简Token

获取轻量级Token可获取的设备信息信息远少于getToken(),可能会造成在判断设备是否有风险时出现较大误差,请谨慎使用。

/**
 `* @return token 通常返回长度为40的字符串。在网络卡顿或不通的情况下,返回1k的字符串。
 `* @throws DXRiskErrorException 如在主线程调用本API,或者appId为空等等,则会抛出该异常
 */
public static String getLightToken(String appId, HashMap<String, String> paramsMap) throws DXRiskErrorException

3.2 使用示例

3.2.1 初始化setup

建议Application.onCreate下调用

@Override
public void onCreate() {
  super.onCreate();	
  // 环境初始化
  DXRisk.setup(this);
}
3.2.2 获取token

整个过程由于是耗时操作,必须要在非主线程上执行,否则会crash

new Thread(){

    @Override
    public void run() {
      /* 私有化配置 */
      HashMap<String, String> params = new HashMap<String, String>();
      // 这里请填写对应的服务端url,注意SAAS和私有化的区别
      params.put(DXRisk.KEY_URL, "https://constid.dingxiang-inc.com");
      // 开启线上数据备份 
      // params.put(DXRisk.KEY_BACKUP, DXRisk.VALUE_ENABLE_BACKUP);
      // 设置请求token超时时长ms,不设置默认为500ms
      params.put(DXRisk.KEY_DELAY_MS_TIME, "2000");
      //此配置关闭SDK缓存,表示每次调用接口都是强制采集信息
      // params.put("PRIVATE_CLEAR_TOKEN", "clear");
      // 开通服务后可在应用管理菜单中获取;私有化版本请填写私有化appId
      String appId = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
       // 获取设备指纹token
      final String token = DXRisk.getToken(appId, params);

      // TODO 把token通过Post请求,传到用户后端
  }
}.start();

3.3 异常说明

在获取token过程中,如果因为网络超时或者加解密失败,该接口有可能会返回为null,同时会输出tag为DXRISK的错误信息,具体描述如下:

DXRISK_REQUEST_NETWORK_ERR            -1001         //网络链接失败
DXRISK_REQUEST_DECRYPT_ERR            -1002         //数据解密错误
DXRISK_REQUEST_UNCOMPRESS_ERR         -1003         //解压错误
DXRISK_REQUEST_RESPONSE_EMPTY_ERR     -1004         //返回为空
DXRISK_REQUEST_DATA_PARSE_ERR         -1005         //数据解析失败
DXRISK_REQUEST_DIRTY_DATA_ERR         -1006         //脏数据
DXRISK_CONST_ID_EMPTY                 -1007         //constid为空

如果出现上述错误信息,请联系顶象技术人员。

3 iOS接入

合规指南
请务必确保您已将顶象设备指纹SDK升级到满足监管新规的新版本。

顶象设备指纹最新版本(IOS版) 见 2.1

请务必在您App的隐私政策条款中向用户告知使用顶象设备指纹SDK,条款参考如下:

SDK名称:顶象设备指纹SDK

使用目的:进行设备标识,用于判断设备是否安全

运营方:北京顶象科技技术有限公司

收集个人信息类型:设备信息(IMEI/MAC/Android ID/IDFA/SIM卡IMSI/ICCID)、位置信息、网络信息

隐私权政策连接:https://www.dingxiang-inc.com/about/privacy

请务必确保用户同意您App的《隐私政策》后,再初始化顶象设备指纹SDK

【1】初始化步骤详见 第三大章中 3.1 方法和参数说明 小节

【2】确保App首次冷启动时,用户完整阅读您的《隐私政策》,并通过正当方式获得用户授权后,才调用DXRiskManager setup函数进行初始化。否则,不能调用DXRiskManager setup函数进行设备指纹SDK初始化

【3】一旦您的App通过正当方式引导用户同意《隐私政策》,在后续的App冷启动中,开发者都应该调用DXRiskManager setup函数进行初始化,以保证SDK的正常运行,调用时机可根据适当的业务场景和开发者意愿进行调用。

一、环境需求

条目说明
兼容平台iOS 12.0-16.x, 17.0-17.2.1
开发环境Xcode 14, 15
CPU架构arm64(真机), x86_64(模拟器)
SDK依赖libz, libresolv, libc++ , SystemConfiguration.framework , CoreLocation.framework , CoreTelephony.framework

二、集成SDK

2.1 下载SDK
条目说明
SDK名称顶象设备指纹dx-risk SDK(IOS)
开发者顶象技术有限公司
版本号v7.3.11r
主要功能详见设备指纹产品简介
个人信息处理规则及隐私合规说明详见隐私政策
SDK 下载地址dx-risk-iOS-v7_3_11r_2ee4e543.zip
示例DEMO下载地址dx-risk-demo-v7_3_11r_2ee4e543.zip
权限申请清单详见 隐私条款 中2.7.4
合规指南详见 合规指南

SDK的目录结构如下:

  • dx-risk-iOS-x.x.x-xxxxxxx目录 DXRisk sdk
    • DXRisk.framework 不带idfa获取逻辑的Dynamic Library Framework
    • DXRiskWithIDFA.framework 带idfa获取逻辑的Dynamic Library Framework
    • DXRiskStatic.framework 不带idfa获取逻辑的Static Library Framework
    • DXRiskStaticWithIDFA.framework 带idfa获取逻辑的Static Library Framework
2.2 将SDK接入Xcode
2.2.1 导入Framework

DXRisk.framework,DXRiskWithIDFA.framework,DXRiskStatic.framework,DXRiskStaticWithIDFA.framework`其中之一直接拖入工程目录中,或者右击总文件夹添加文件。

  • 如果App中包含广告相关的功能,则选择DXRiskWithIDFA.framework 或者 DXRiskStaticWithIDFA.framework,该版本可以提供更精准的token
  • 如果没有广告,获取idfa可能导致拒绝上架,此时请选择DXRisk.framework 或者 DXRiskStatic.framework
2.2.2 添加FrameWork到工程

若在项目中添加DXRisk.framework或者DXRiskWithIDFA.framework其中之一,选择Target -> General,在Frameworks,Libraries,and Embedded Content中,将DXRisk.framework或者DXRiskWithIDFA.framework 对应的 Embed 切换到Embed & Sign。如下图:

若在项目中添加DXRiskStatic.framework或者DXRiskStaticWithIDFA.framework其中之一,需要在Build Settings -> Other Linker Flags 设置 -ObjC 如下图:

4A23453213E696EC12C2AE2A1070EA0C.jpg

2.2.3 配置打包脚本

以下的操作仅限导入DXRisk.framework ,DXRiskWithIDFA.framework动态库

此步骤主要是解决上传Store架构不符合的问题,如项目中已配置过Carthage或有其他相关的打包Framework调整脚本,可略过此步自行调整 选择Target -> Build Phases,点击+按钮,添加如下脚本:


APP_PATH="${TARGET_BUILD_DIR}/${WRAPPER_NAME}"

# This script loops through the frameworks embedded in the application and
# removes unused architectures.
find "$APP_PATH" -name '*.framework' -type d | while read -r FRAMEWORK
do
FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)
FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"
echo "Executable is $FRAMEWORK_EXECUTABLE_PATH"

EXTRACTED_ARCHS=()

for ARCH in $ARCHS
do
echo "Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME"
lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH"
EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH")
done

echo "Merging extracted architectures: ${ARCHS}"
lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[@]}"
rm "${EXTRACTED_ARCHS[@]}"

echo "Replacing original executable with thinned version"
rm "$FRAMEWORK_EXECUTABLE_PATH"
mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"

done
2.2.4 权限注意

在iOS 12的环境最好在Capabilities->Access WiFi Information 进行开启操作,这样方便设备指纹数据采集。 F1B9CF2A-6E7A-491F-8DD7-8ACFAAD996D2.png

三、接口使用说明

3.1 方法和参数说明
// 风控组件:DXRiskManager类
@interface DXRiskManager : NSObject

// 字符串常量
extern NSString* const DXRiskManagerKeyUserId;
extern NSString* const DXRiskManagerKeyEmail;
extern NSString* const DXRiskManagerKeyPhone;
extern NSString* const DXRiskManagerKeyUserExtend1;
extern NSString* const DXRiskManagerKeyUserExtend2;
extern NSString* const DXRiskManagerKeyURL;//私有化服务器地址
extern NSString* const DXRiskManagerKeyBackup;//私有化下使用,将数据备份到顶象服务器(开启为DXRiskManagerKeyBackupEnable 值)
extern NSString* const DXRiskManagerKeyBackupAppId; // 私有化下使用,指定数据备份到顶象服务器的AppId 
  
extern NSString* const DXRiskManagerKeyDegradeNotify;//数据降级通知,若打开,服务端会有响应的降级统计
extern NSString* const DXRiskManagerKeyCountry;//国家地区设置,默认中国

extern NSString* const DXRiskManagerKeyDelayMsTime; //可填设置请求超时毫秒时间(默认值为 500 ,范围是:【100 : 3000】)
// NoticeDegrade参数
/* The NoticeDegrade Value. This value only be used pair with key:DXRiskManagerKeyDegradeNotify to notify token degrade. */
extern NSString* const DXRiskManagerKeyDegradeNotifyEnable;
// Backup参数
/* The Backup Value. This value only be used pair with key:DXRiskManagerKeyBackup to set data backup. */
extern NSString* const DXRiskManagerKeyBackupEnable;
// Country参数
/* The Country Value. This value only be used pair with key:DXRiskManagerKeyCountry to set country. */
extern NSString* const DXRiskManagerCountryChina;
/* The Country Value. This value only be used pair with key:DXRiskManagerKeyCountry to set country. */
extern NSString* const DXRiskManagerCountryIndonesia;

/**
 采集端的设备指纹信息,上传至风控后台,再由风控后台返回token。
 该API为耗时操作,因此必须在非主线程上调用。

 @param appId appId   开通服务后可在二级菜单“应用管理”中获取
 @param extendsParams 配置项
 @return token
 */
+ (NSString *)getToken:(NSString *)appId extendParams:(NSDictionary *)extendsParams;

/** 
 DXRiskManager -- 初始化方法
 */
+ (BOOL)setup;  
@end
3.2 使用示例
// 整个过程由于是耗时操作,必须要在非主线程上执行,否则会阻塞UI。如果本身已经在非UI线程上执行,则不需要另开线程
    dispatch_queue_t dxrisk_queue = dispatch_queue_create("com.dingxiang.dxrisk", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(dxrisk_queue, ^{
        NSMutableDictionary *dic = [NSMutableDictionary dictionary];
        // 根据业务逻辑,填充自定义字段
        [dic setObject:@"123456" forKey:DXRiskManagerKeyUserId];
      
        // 如需设置海外服务器, 可选值请参考头文件字段
        [dic setObject:DXRiskManagerServiceAreaSoutheastAsia forKey:DXRiskManagerKeyServiceArea];
        // 如需自定义服务端URL,填充DXRiskManagerKeyURL字段(私有化部署的情况)
        // 如有需要则添加DXRiskManagerKeyBackup参数,Value固定为DXRiskManagerKeyBackupEnable
        // DXRiskManagerKeyBackupAppId参数可不填,参数为顶象备份数据库提供的备份Appid
        [dic setObject:@"http://xxxxxxx" forKey:DXRiskManagerKeyURL];
        // [dic setObject:DXRiskManagerKeyBackupEnable forKey:DXRiskManagerKeyBackup];
        [dic setObject:@"xxxxxxxxxxxxxxxxxxxx" forKey:DXRiskManagerKeyBackupAppId];
        // 此配置关闭SDK缓存,表示每次调用接口都强制采集信息
        // [dic setObject:@"clear" forKey:@"PRIVATE_CLEAR_TOKEN"];
        
        // 获取token
        // 注意:token最好不要保存在某个局部变量或者字段,每次使用时,都通过API获取。
        BOOL isSuccess = [DXRiskManager setup];
        NSLog(@"setup success: %@" , isSuccess ? @"YES":@"NO");
        NSString *constID = [DXRiskManager getToken:@"xxxxxxxxxxxxxxxxxxxx" extendsParams:dic];
        NSLog(@"constID: %@", constID);
        // TODO 把constid通过Post请求,传到业务后台。
        // 下面是模拟频繁调用的过程
        while(TRUE) {
            NSLog(@"constID: %@", [DXRiskManager getToken:@"xxxxxxxxxxxxxxxxxxxx" extendsParams:dic]);
            [NSThread sleepForTimeInterval:.5];
        }
    });
3.3 异常说明

在获取token过程中,如果因为网络超时或者加解密失败,该接口有可能会返回为null,同时会输出tag为DXRISK的错误信息,具体描述如下:

DXRISK_REQUEST_NETWORK_ERR            -1001         //网络链接失败
DXRISK_REQUEST_DECRYPT_ERR            -1002         //数据解密错误
DXRISK_REQUEST_UNCOMPRESS_ERR         -1003         //解压错误
DXRISK_REQUEST_RESPONSE_EMPTY_ERR     -1004         //返回为空
DXRISK_REQUEST_DATA_PARSE_ERR         -1005         //数据解析失败
DXRISK_REQUEST_DIRTY_DATA_ERR         -1006         //脏数据
DXRISK_CONST_ID_EMPTY                 -1007         //constid为空

如果出现上述错误信息,请联系顶象技术人员。

4 微信小程序接入

4.1 下载设备指纹js

SaaS版本下载

私有化版本下载

请注意选择对应的版本,下载完成后放到本地项目中。

4.2 获取密钥

未注册用户可在顶象官网进行账号注册,创建应用获取应用密钥AppID和AppSecret。

4.3 使用

  1. 代码接入
const ConstId = require('本地设备指纹js存放路径')
Page({
    onLoad: function () {
      new ConstId({
        appId: '【这里填写在顶象官网申请到的 AppID】', // 唯一标识,必填
        server: 'https://host/udid/w1' // 服务接口地址,请注意私有化客户填写自有域名
      }, (e, id) => {
        if (e) {
          console.log(e)
          return
        }
        console.log('constId:', id)
      })
    }
})
  1. SaaS用户在小程序后台配置业务域名https://constid.dingxiang-inc.com,私有化用户配置本地部署域名,测试阶段可以开启微信开发者工具右上角详情->本地设置->“不校验域名”。

5 支付宝小程序接入

5.1 下载设备指纹js

SaaS版本下载

私有化版本下载

请注意选择对应的版本,下载完成后放到本地项目中。

5.2 获取密钥

未注册用户可在顶象官网进行账号注册,创建应用获取应用密钥AppID和AppSecret。

5.3 使用

const ConstId = require('本地设备指纹js存放路径')
Page({
    onLoad: function () {
      new ConstId({
        appId: '【这里填写在顶象官网申请到的 AppID】', // 唯一标识,必填
        server: 'https://host/udid/w1' // 服务接口地址,请注意私有化客户填写自有域名
      }, (e, id) => {
        if (e) {
          console.log(e)
          return
        }
        console.log('constId:', id)
      })
    }
})

6 百度小程序接入

6.1 下载设备指纹js

SaaS版本下载

私有化版本下载

请注意选择对应的版本,下载完成后放到本地项目中。

6.2 获取密钥

未注册用户可在顶象官网进行账号注册,创建应用获取应用密钥AppID和AppSecret。

6.3 使用

const ConstId = require('本地设备指纹js存放路径')
Page({
    onLoad: function () {
      new ConstId({
        appId: '【这里填写在顶象官网申请到的 AppID】', // 唯一标识,必填
        server: 'https://host/udid/w1' // 服务接口地址,请注意私有化客户填写自有域名
      }, (e, id) => {
        if (e) {
          console.log(e)
          return
        }
        console.log('constId:', id)
      })
    }
})

7 抖音小程序接入

7.1 下载设备指纹js

SaaS版本下载

私有化版本下载

请注意选择对应的版本,下载完成后放到本地项目中。

7.2 获取密钥

未注册用户可在顶象官网进行账号注册,创建应用获取应用密钥AppID和AppSecret。

7.3 使用

const ConstId = require('本地设备指纹js存放路径')
Page({
    onLoad: function () {
      new ConstId({
        appId: '【这里填写在顶象官网申请到的 AppID】', // 唯一标识,必填
        server: 'https://host/udid/w1' // 服务接口地址,请注意私有化客户填写自有域名
      }, (e, id) => {
        if (e) {
          console.log(e)
          return
        }
        console.log('constId:', id)
      })
    }
})

三、后端接入

接口详细描述: 根据token,appId,sign三个参数获得设备信息

1.SDK接入方法说明

1.1 Java SDK接入

  1. 包的引入
<dependency>
    <groupId>com.dingxiang-inc</groupId>
    <artifactId>ctu-client-sdk</artifactId>
    <version>2.6</version>
</dependency>
  1. Java使用示例
public class ConstantIdDemo {
    //顶象控制台,设备指纹菜单应用管理里面获取
    private static String appId = "0091a3xxxxxxxxxx557fac67b2f5afb";
    private static String appSecret = "e38dxxxxxxxxx6807c9e1edebaa2836";

    public static void main(String[] args) throws IOException {
        // 填写设备指纹域名或者url如:http://127.0.0.1:8080
        CtuConstidClient client = new CtuConstidClient("https://constid.dingxiang-inc.com", appId, appSecret);
        //设备指纹
        String result = client.getDeviceInfo("62c5013cel9o4xxxxxxxxxtTtKW5BwWtQq9u1f1");
         System.out.println(JSON.toJSON(result));
    }
}   

1.2 PHP SDK接入

点击下载SDK

使用示例

class Demo {

    // 根据实际情况填写
    const appKey = "你的AppID";

    // 根据实际情况填写
    const appSecret = "你的AppSecret";

    // 根据实际情况填写
    const token = "SDK里面获取到的token";
}

// 根据token获取设备详细信息工具类
$requestHandle = new DeviceFingerprintHandle();
// 设置请求超时时间。因为存在设备指纹降级和网络抖动的情况,默认2秒。可以根据实际情况调整
// $requestHandle->setTimeout(2);

// 填写设备指纹域名或者url入:http://127.0.0.1:9090
$responseData = $requestHandle->getDeviceInfo("https://constid.dingxiang-inc.com/udid/api/getDeviceInfo",
    Demo::appKey, Demo::appSecret, Demo::token);
$result = json_decode($responseData, true);

// 请求状态码。非 200 表示没有获取到设备明细信息
if ($result['stateCode'] == 200) 
    echo "设备明细信息如下: : " . json_encode($result['data'], true);
else 
    echo $result['message'];

1.3 NodeJS SDK接入

npm i dx-const-id-sdk --save

const SDK = require('dx-const-id-sdk')

const sdk = new SDK({
  appId: '您的appId',
  appSecret: '您的appSecret'
})

sdk.getDeviceInfo(token).then((data) => {
  console.log(data)
}).catch(err => {
  console.log('获取设备信息失败')
})

2.HTTP接口接入方法

2.1 请求参数

字段类型描述
appIdString当前应用的标识
signStringsign = MD5(appSecret + token + appSecret),AppSecret为appId对应的密钥
tokenString用户前端获取的token

2.2 成功响应

字段类型描述
stateCodeint状态码
messageString状态描述
dataJson返回设备信息及设备风险检测数据
{
    "stateCode": 200,
    "message": "请求响应成功",
    "data": {
        "hardId": "22e38229a7eda501c58bf3ddee1a340a",
        ......
    }
}

2.3 错误响应

字段类型描述
stateCodeint状态码
messageString状态描述
dataJson异常时数据为空
{
    "stateCode": -10002,
    "message": "签名为空或验证失败",
    "data": null
}
错误码描述
-10001appId不存在或已经过期
-10002签名为空或验证失败
-10003token为空或没有对应的设备信息
-10004token已经过期
-10005服务器内部异常
-10006证书已经失效
-10007服务器限流

3. HTTP接口返回参数明细说明

3.1 免费用户

字段名字段描述说明
token设备token默认返回
hardId设备指纹默认返回
3.1.1 web端返回结果
字段名字段描述说明
token设备token默认返回
hardId设备指纹默认返回

3.2 收费用户

3.2.1 移动端返回结果(部分示例,更多返回字段请联系售后支持获取)
字段名字段描述说明
token设备token默认返回
deviceType设备类型默认返回
hardId设备指纹默认返回
producter生产厂商默认返回
macAddressmac地址默认返回
isEmulator模拟器运行默认返回
isRoot是否root默认返回
isMultirun是否多开默认返回
isInject是否存在注入风险默认返回
isMemdump是否存在内存dump风险默认返回
isDebug是否存在调试风险默认返回
isHook是否存在hook风险默认返回
isJailBreak是否越狱默认返回
isVpn是否使用vpn默认返回
isProxy是否使用代理默认返回
isSimulateGPS是否篡改GPS默认返回
isCloudPhone是否云真机默认返回
......更多字段请联系售后
3.2.2 web端返回结果(部分示例,更多返回字段请联系售后支持获取)
字段名字段描述说明
token设备token默认返回
deviceType设备类型默认返回
hardId设备指纹默认返回
canvasIdcanvas指纹默认返回
webGlWebGl指纹默认返回
resolution设备分辨率默认返回
isLiedBrowser是否伪造浏览器默认返回
isCookieDisabled是否禁用cookie默认返回
isTamperUa是否篡改浏览器ua默认返回
isTamperRes是否篡改分辨率默认返回
isTamperCd是否篡改浏览器颜色深度默认返回
isEmulator是否模拟器默认返回
......更多字段请联系售后

四、 附:隐私政策示例

建议在集成了SDK的app中增加《隐私政策声明》,来规避风险。并在客户同意隐私政策后,进行sdk的调用,示例如下:

隐私政策(拟,可根据实际情况进行修改)

根据《工业和信息化部 337号令》的规定,重点对以下四个方面开展规范整治工作。


(一)违规收集用户个人信息方面
(二)违规使用用户个人信息方面
(三)不合理索取用户权限方面
(四)为用户账号注销设置障碍方面

其中SDK涉及到第一条:收集个人信息(包括唯一设备识别码、网络设备硬件地址等信息)。

法规规定,所采集的数据项目需在隐私政策中明确声明,在客户不同意隐私政策的情况下,不允许进行采集。且申请授权需与场景相关,请根据实际情况做出合理调整。

顶象隐私服务条款

https://www.dingxiang-inc.com/about/privacy

解决方式

需要客户在集成了SDK的app中增加《隐私政策声明》,来规避风险。并在客户同意隐私政策后,进行sdk的调用。

隐私政策(拟,可根据实际情况进行修改)

一、我们如何收集和使用个人信息
为了识别设备/账号异常状态,我们将会接受并记录您所使用的设备相关信息(包括设备型号、操作系统、设备设置、唯一设备标识符(IMEI码)、网络设备硬件地址(MAC)、设备环境等软硬件特征信息,设备所在位置相关信息(包括您授权的GPS位置以及WLAN接入点、蓝牙和基站等信息)。
其中IP地址、设备版本、系统版本、生成ID、手机样式、手机名、APP应用包名、APP应用名、APP应用版本为必要信息,其他为可选信息。

序号信息收集目的个人信息范围适用系统版本信息收集方式
1标识设备,用于验证码安全判断设备版本、系统版本、生成ID、手机样式、手机名、iccid、bssid、MAC地址、IMSI、IMEI、IP地址、AndroidID、蓝牙信息、GPS信息、APP应用包名、APP应用名、APP应用版本Android自动收集,在启动APP、初始化SDK时进行收集
2标识设备,用于验证码安全判断设备版本、系统版本、生成ID、手机样式、手机名、IP地址、WIFI参数、蓝牙信息、GPS信息、APP应用包名、APP应用名、APP应用版本iOS自动收集,在启动APP、初始化SDK时进行收集

二、我们如何保护您的个人信息
(一)我们已使用符合业界标准的安全防护措施保护您提供的个人信息,防止数据遭到未经授权访问、公开披露、使用、修改、损坏或丢失。我们会采取一切合理可行的措施,保护您的个人信息。例如,在您的浏览器与“服务”之间交换数据时受 SSL 加密保护;我们同时对我们网站提供 https 安全浏览方式;我们会使用加密技术确保数据的保密性;我们会使用受信赖的保护机制防止数据遭到恶意攻击;我们会部署访问控制机制,确保只有授权人员才可访问个人信息;以及我们会举办安全和隐私保护培训课程,加强员工对于保护个人信息重要性的认识。
(二)我们会采取一切合理可行的措施,确保未收集无关的个人信息。我们只会在达成本政策所述目的所需的期限内保留您的个人信息,除非需要延长保留期或受到法律的允许。
(三)互联网并非绝对安全的环境,而且电子邮件、即时通讯、及与其他我们用户的交流方式并未加密,我们强烈建议您不要通过此类方式发送个人信息。请使用复杂密码,协助我们保证您的账号安全。
(四)互联网环境并非百分之百安全,我们将尽力确保或担保您发送给我们的任何信息的安全性。如果我们的物理、技术、或管理防护设施遭到破坏,导致信息被非授权访问、公开披露、篡改、或毁坏,导致您的合法权益受损,我们将承担相应的法律责任。
(五)在不幸发生个人信息安全事件后,我们将按照法律法规的要求,及时向您告知:安全事件的基本情况和可能的影响、我们已采取或将要采取的处置措施、您可自主防范和降低风险的建议、对您的补救措施等。我们将及时将事件相关情况以邮件、信函、电话、推送通知等方式告知您,难以逐一告知个人信息主体时,我们会采取合理、有效的方式发布公告。 同时,我们还将按照监管部门要求,主动上报个人信息安全事件的处置情况。


文档版本: 311c7f93

加入社群

扫码进群领
【业务安全】资料礼包

在线咨询
400-878-6123