顶象实时风险决策是一款基于设备指纹、规则引擎、指标策略、风险数据、机器学习等多项技术的业务风险防控产品, 支持快速私有化部署,帮助客户快速建立自有的业务安全体系,解决仿冒、盗用、欺诈、作弊、垃圾、爬虫等各类风险。
实时决策,利用策略和实时计算,同步识别风险,直接阻断恶意风险
近线分析,t+分钟级的近线计算,计算各种特征,为实时决策提供指标参数
离线挖掘,通过各种离线的挖掘和模型技术的应用,为实时决策和离线处置提供依据和能力,如:特征挖掘、模型平台训练、用户风险画像、设备风险画像等
快速私有化部署,支持平滑扩容和在线升级
盗号防控示例

垃圾注册防控示例

根据《工业和信息化部 337号令》的规定,重点对以下四个方面开展规范整治工作。 (一)违规收集用户个人信息方面 (二)违规使用用户个人信息方面 (三)不合理索取用户权限方面 (四)为用户账号注销设置障碍方面 其中SDK涉及到第一条:收集个人信息(包括唯一设备识别码、网络设备硬件地址等信息)。 法规规定,所采集的数据项目需在隐私政策中明确声明,在客户不同意隐私政策的情况下,不允许进行采集。且申请授权需与场景相关,请根据实际情况做出合理调整。
需要客户在集成了SDK的app中增加《隐私政策声明》,来规避风险。并在客户同意隐私政策后,进行sdk的调用,示例如下。
一、我们如何收集和使用个人信息 个人信息是指以电子或者其他方式记录的能够单独或者与其他信息结合识别特定自然人身份或者反映特定自然人活动情况的各种信息。我们深知个人信息对您的重要性,您的信赖对我们非常重要,我们将严格遵守法律法规要求采取相应的安全保护措施,致力于保护您的个人信息安全可控。我们仅会出于本政策所述的以下目的,收集和使用您的个人信息: 1、当您使用XXX产品及相关服务时,为了保障软件与服务的正常运行,我们会收集您的硬件型号、操作系统版本号、国际移动设备识别码(IMEI)、网络设备硬件地址(MAC)、IP 地址、软件版本号、网络接入方式及类型、操作日志等信息。请您了解,这些信息是我们提供服务和保障产品正常运行所必须收集的基本信息。
| 所属系统 | 第三方 | 第三方收集个人信息目的 | 第三方收集个人信息范围 | 第三方收集个人信息方式 | 
|---|---|---|---|---|
| iOS | 顶象设备指纹SDK | 标识设备,保障账号及交易安全 | 设备版本、系统版本、生成ID、手机样式、手机名 | 自动收集,在启动APP、初始化SDK时进行收集 | 
| Android | 顶象设备指纹SDK | 标识设备,保障账号及交易安全 | 设备版本、系统版本、生成ID、手机样式、手机名、iccid、bssid、MAC地址、IMSI、IMEI | 自动收集,在启动APP、初始化SDK时进行收集 | 
2、Cookie和同类技术的服务 Cookie和同类设备信息标识技术是互联网中普遍使用的技术。当您使用我们的服务时,我们可能会使用相关技术向您的设备发送一个或多个 Cookie 或匿名标识符(以下简称“Cookie”),以收集、标识和存储您访问、使用本产品时的信息。我们承诺,不会将Cookie 用于本隐私政策所述目的之外的任何其他用途。我们使用 Cookie 主要为了保障产品与服务的安全、高效运转,排查崩溃、延迟的相关异常情况,帮助您省去重复您填写表单、输入搜索内容的步骤和流程。 同时,我们可能会利用 Cookie 向您展示您可能感兴趣的信息或功能,并优化您对广告的选择。大多数浏览器均为用户提供了清除浏览器缓存数据的功能,您可以进行相应的数据清除操作,或可修改对Cookie的接受程度或拒绝我们的Cookie。您可能因为这些修改,无法使用依赖于Cookie的服务或相应功能。
附:相关定义
个人信息:以电子或者其他方式记录的与已识别或者可识别的自然人有关的各种信息,不包括匿名化处理后的信息。 设备信息:包括设备标识符(IMEI、IDFA、Android ID、MAC、OAID、IMSI及其他设备相关信息)、设备参数及系统信息(设备类型、设备型号、操作系统及硬件相关信息),设备网络环境信息(IP地址,WiFi信息,基站信息及其他网络相关信息)。以产品实际采集情况为准。
二、我们如何保护您的个人信息
1、我们已使用符合业界标准的安全防护措施保护您提供的个人信息,防止数据遭到未经授权访问、公开披露、使用、修改、损坏或丢失。我们会采取一切合理可行的措施,保护您的个人信息。例如,在您的浏览器与“服务”之间交换数据时受 SSL 加密保护;我们同时对我们网站提供 https 安全浏览方式;我们会使用加密技术确保数据的保密性;我们会使用受信赖的保护机制防止数据遭到恶意攻击;我们会部署访问控制机制,确保只有授权人员才可访问个人信息;以及我们会举办安全和隐私保护培训课程,加强员工对于保护个人信息重要性的认识。
2、我们会采取一切合理可行的措施,确保未收集无关的个人信息。我们只会在达成本政策所述目的所需的期限内保留您的个人信息,除非需要延长保留期或受到法律的允许。
3、互联网并非绝对安全的环境,而且电子邮件、即时通讯、及与其他我们用户的交流方式并未加密,我们强烈建议您不要通过此类方式发送个人信息。请使用复杂密码,协助我们保证您的账号安全。
4、互联网环境并非百分之百安全,我们将尽力确保或担保您发送给我们的任何信息的安全性。如果我们的物理、技术、或管理防护设施遭到破坏,导致信息被非授权访问、公开披露、篡改、或毁坏,导致您的合法权益受损,我们将承担相应的法律责任。
5、在不幸发生个人信息安全事件后,我们将按照法律法规的要求,及时向您告知:安全事件的基本情况和可能的影响、我们已采取或将要采取的处置措施、您可自主防范和降低风险的建议、对您的补救措施等。我们将及时将事件相关情况以邮件、信函、电话、推送通知等方式告知您,难以逐一告知个人信息主体时,我们会采取合理、有效的方式发布公告。 同时,我们还将按照监管部门要求,主动上报个人信息安全事件的处置情况。

| 名称 | 释义 | 
|---|---|
| AppId | 应用公钥,唯一标识。开通服务后可在实时风险决策的二级菜单“应用管理”中获取 | 
| AppSecret | 应用私钥,开通服务后可在实时风险决策的二级菜单“应用管理”中获取,请妥善保管,勿泄漏给他人 | 
| ConstID | 设备指纹ID,通过采集设备的硬件信息生成的设备唯一标识。结合顶象风控系统,能够在各个业务环节进行风险过滤和实时决策,为企业提供提供强力业务安全保障 | 
| 用户前端 | Web端或集成SDK的Android端、iOS端、微信小程序 | 
| 用户后端 | 指企业的后台服务器 | 
| 风控后台 | 指部署在公有云或者私有云顶象的风控系统 | 
接入实时风险决策,只需四步:
     第一步:获取AppId、AppSecret,开通服务后可在实时风险决策的二级菜单“应用管理”中获取,
            在接入前请与顶象技术人员沟通,以根据您的业务特点配置不同的风险策略;
     第二步:前端接入,即设备指纹埋点,支持Web、Android、iOS、微信小程序接入,
            接入方法及相关SDK下载,请见前端接入章节;
     第三步:后端集成SDK,接入方法及SDK下载,请见后端接入章节;
     第四步:调试完毕,部署上线,可在实时风险决策的二级菜单“风险监控”中查看风险数据详情。
支持Web接入,支持IE8+、Chrome、Firefox、360浏览器、QQ浏览器等主流浏览器及Android、iOS上的内嵌Webview。引用JS参见Web接入章节
支持Android接入,获取SDK并接入,参见Android接入章节
支持iOS接入,获取SDK并接入,参见iOS接入章节
支持微信小程序接入,接入参见微信小程序接入章节
提示:设备指纹token具有时效性,超过一定时间会过期,请勿自行缓存
重要:因终端用户的设备网络环境和设备版本等因素,设备指纹采集率并不能一定达到100%,可能会存在极少部分未能正常采集到的情况。
所以在集成指纹服务的时候,请尽量避免对指纹信息强依赖。
兼容IE8+,Chrome,Firefox,360浏览器,QQ浏览器等主流浏览器。
在页面 HTML 中引入const-id.js,代码如下:
<script src="https://cdn.dingxiang-inc.com/ctu-group/constid-js/index.js"></script>
页面加载后,初始使用,需要在 JavaScript 中调用_dx.ConstID(options, callback)方法,生成token,代码形如:
var options = {
    appId: '【这里填写 AppId】', // 唯一标识,必填
    server: 'https://constid.dingxiang-inc.com/udid/c1', // ConstId 服务接口,可选
    userId: '【这里填写 userID】' // 用户标识,可选
};
_dx.ConstID(options, function (e, id) {
if (e) {
    // console.log('error: ' + e);
    return;
}
// console.log('token is ' + id);
// console.log(_dx.constID === id); // true
});
执行成功后,页面中将会有一个全局变量_dx,可以通过_dx.constID访问这个值。也可以继续调用上面的初始化方法,同一个浏览器多次初始化返回的值相同。
| 字段 | 类型 | 是否必填 | 说明 | 
|---|---|---|---|
| AppId | String | 是 | 当前应用的标识,请联系您在顶象的商务经理获取 | 
| server | String | 否 | 服务接口,可选,如不填,则默认会用云服务接口 | 
| scene | String | 否 | 场景标识,例如login、survey等 | 
| userId | String | 否 | 业务方的用户唯一标识,例如用户名、用户ID、手机号、Email等 | 
| 条目 | 说明 | 
|---|---|
| 开发目标 | 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.0、Tls1.1。
目前(2023-02-03), android 5.0及以上占比为99.3%。
早期Android版本无法支持全部CPU架构(e.g. Android 4.0只支持armeabi)。
点击下载demo(仅做代码配置演示使用,其中appId请在顶象后台申请,SDK需要替换为链接中下载的SDK)
SDK包集成内容:
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
android {
  packagingOptions {
      doNotStrip "**/lib*Risk*.so"
  }
}
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.aar'])
}
<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.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<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"/>
-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.**{*;}
需要动态申请权限如下:
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);
   // 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();
}
采集端的设备指纹信息,上传至风控后台,再由风控后台返回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则采集手机的应用安装列表,否则不采集 | 
SDK使用前必须调用先setup,setup主要用于数据/环境初始化,一般在Application的onCreate下调用:
/**
* 初始化参数,环境
* @param context
* @return
*/
public static boolean setup(Context context)
PS:下列两种方式获取token在网络通畅的情况下没有任何的不同。
/**
 * @return token 通常返回长度为40的字符串。在网络卡顿或不通的情况下,返回4-5k的字符串。
 * @throws DXRiskErrorException 如在主线程调用本API,或者appId为空等等,则会抛出该异常
 */
public static String getToken(String appId, HashMap<String, String> paramsMap) throws DXRiskErrorException
获取轻量级Token可获取的设备信息信息远少于getToken(),可能会造成在判断设备是否有风险时出现较大误差,请谨慎使用。
/**
 `* @return token 通常返回长度为40的字符串。在网络卡顿或不通的情况下,返回1k的字符串。
 `* @throws DXRiskErrorException 如在主线程调用本API,或者appId为空等等,则会抛出该异常
 */
public static String getLightToken(String appId, HashMap<String, String> paramsMap) throws DXRiskErrorException
建议Application.onCreate下调用
@Override
public void onCreate() {
  super.onCreate();
  // 环境初始化
  DXRisk.setup(this);
}
整个过程由于是耗时操作,必须要在非主线程上执行,否则会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();
在获取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为空
如果出现上述错误信息,请联系顶象技术人员。
Apple Store上架请特别注意(2.2.3 节)
| 条目 | 说明 | 
|---|---|
| 兼容平台 | 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,SDK的目录结构如下:

DXRisk.xcframework,DXRiskWithIDFA.xcframework,DXRiskStatic.xcframework,DXRiskStaticWithIDFA.xcframework`其中之一直接拖入工程目录中,或者右击总文件夹添加文件。
DXRiskWithIDFA.xcframework 或者 DXRiskStaticWithIDFA.xcframework,该版本可以提供更精准的tokenDXRisk.xcframework 或者 DXRiskStatic.xcframework若在项目中添加DXRisk.xcframework或者DXRiskWithIDFA.xcframework其中之一,选择Target -> General,在Frameworks,Libraries,and Embedded Content中,将DXRisk.xcframework或者DXRiskWithIDFA.xcframework 对应的 Embed 切换到Embed & Sign。如下图:

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

在iOS 12的环境最好在Capabilities->Access WiFi Information 进行开启操作,这样方便设备指纹数据采集。 
// 风控组件: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
// 整个过程由于是耗时操作,必须要在非主线程上执行,否则会阻塞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];
        }
    });
在获取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为空
如果出现上述错误信息,请联系顶象技术人员。
请注意选择对应的版本,下载完成后放到本地项目中。
未注册用户可在顶象官网进行账号注册,创建应用获取应用密钥AppID和AppSecret。
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)
      })
    }
})
https://constid.dingxiang-inc.com,私有化用户配置本地部署域名,测试阶段可以开启微信开发者工具右上角详情->本地设置->“不校验域名”。请注意选择对应的版本,下载完成后放到本地项目中。
未注册用户可在顶象官网进行账号注册,创建应用获取应用密钥AppID和AppSecret。
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)
      })
    }
})
请注意选择对应的版本,下载完成后放到本地项目中。
未注册用户可在顶象官网进行账号注册,创建应用获取应用密钥AppID和AppSecret。
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)
      })
    }
})
请注意选择对应的版本,下载完成后放到本地项目中。
未注册用户可在顶象官网进行账号注册,创建应用获取应用密钥AppID和AppSecret。
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)
      })
    }
})
请注意选择对应的版本,下载完成后放到本地项目中。
未注册用户可在顶象官网进行账号注册,创建应用获取应用密钥AppID和AppSecret。
const ConstId = require('本地设备指纹js存放路径')
export default{
    onLoad: function () {
      new ConstId({
        appId: '【这里填写在顶象官网申请到的 AppID】', // 唯一标识,必填
        server: 'https://host/udid/w1' // 服务接口地址,请注意私有化客户填写自有域名
      }, (e, id) => {
        if (e) {
          console.log(e)
          return
        }
        console.log('constId:', id)
      })
    }
}
非maven项目
JAVA6版本SDK下载点击下载,
JAVA7、8版本SDK下载点击下载, 如需其他版本SDK请联系在线客服。
<dependency>
  <groupId>com.dingxiang-inc</groupId>
  <artifactId>ctu-client-sdk</artifactId>
  <version>2.2</version>
</dependency>
PHP版本SDK下载:点击下载
C#版本SDK下载 支持.net framework 4.0:点击下载
Python版本SDK下载: 点击下载
NodeJS版本SDK参考下方示例,直接从npm安装
接入事件的event_code和事件需要的参数,请咨询顶象技术人员或官网在线客服
| 字段名称 | 类型 | 是否必须 | 说明 | 
|---|---|---|---|
| eventCode | String | 是 | 事件的唯一编码,由顶象提供 | 
| flag | String | 否 | 请求标记,客户端可以标记该次请求 | 
| data | Map<String, object> | 是 | Map结构,包含该次请求的业务数据 | 
| 字段名称 | 类型 | 说明 | 
|---|---|---|
| uuid | String | 服务端返回的请求标识码,供服务端排查问题 | 
| status | String | 服务端返回的状态 | 
| result | CtuResult | 服务端返回的识别结果类 | 
| 状态code | 描述 | 出现的场景 | 
|---|---|---|
| SUCCESS | 成功 | 调用成功无误 | 
| INVALID_REQUEST_PARAMS | 请求不合法,缺少必须参数 | 1. 请求url中缺少sign参数 2. 缺少AppId 3. 缺少eventCode 4. 缺少执行策略过程中的某些字段指标, 在这种情况下会额外返回错误描述信息在CtuResult中extraInfo的_rule_eval_error和_error_policy, 标识发生在哪条策略, 哪条规则  | 
| INVALID_REQUEST_BODY | 请求不合法,请求body为空 | 请求中没有传CtuRequest对象 | 
| INVALID_REQUEST_NO_EVENT_DATA | 请求不合法,请求事件的数据为空 | 请求中没有传业务数据, ``CtuRequest.data` | 
| INVALID_REQUEST_SIGN | 请求签名错误 | 请求签名校验失败 | 
| INVALID_APP_KEY | 不合法的AppId | 找不到传入的AppId | 
| INVALID_EVENT_CODE | 不合法的事件 | 传入的事件Code有误 | 
| INVALID_APP_EVENT_RELATION | 应用和事件的绑定关系错误 | 传入的 AppId和事件Code没有关联关系 | 
| EVENT_GRAY_SCALE | 事件有灰度控制,非灰度请求 | 事件设置了灰度值, 本次请求非灰度请求 | 
| POLICY_HAS_ERROR | 防控策略配置有错误 | 执行策略过程中发生异常 | 
| NOT_SUPPORTED_POLICY_OPERATOR | 不支持防控策略里的操作符 | 某个策略中使用的操作符不存在 | 
| SERVICE_INTERNAL_ERROR | 服务器内部错误 | 执行过程中产生了异常, 在这种情况下会额外返回错误描述信息在CtuResult中extraInfo的_exception_msg | 
| QPS_EXCEEDING_MAXIMUM_THRESHOLD | 并发超过限制 | 流量过大时,服务端会进行限流,超出部分流量返回ACCEPT | 
| 字段名称 | 类型 | 说明 | 
|---|---|---|
| riskLevel | RiskLevel类 | 该次请求的风险级别,枚举类型,包括 ACCEPT(无风险,建议放过),REVIEW(不确定,需要进一步审核),REJECT(有风险,建议拒绝) | 
| riskType | String | 风险类型,例如 垃圾注册,账号盗用 | 
| hitPolicyCode | String | 命中的策略code | 
| handleFlag | String | 处置标识 | 
| hitPolicyName | String | 命中的策略标题 | 
| hitRules | List | 命中的规则列表,每个规则包括规则id和左变量 | 
| suggestPolicies | List | 建议的防控策略 | 
| suggestion | List | 命中策略处置建议 | 
| flag | String | 客户端请求带上来的标记 | 
| extraInfo | Map<String, Object> | 附加信息 | 
/**
 * 风控引擎url
 **/
public static final String url = "https://sec.dingxiang-inc.com/ctu/event.do";
/**
 * 应用AppId,公钥
 **/
public static final String appId = "你的AppId";
/**
 * 应用AppSecret,私钥
 **/
public static final String appSecret = "你的AppSecret";
public static void checkRisk() throws Exception {
    /**业务请求数据,仅供参考,具体传参依据风控场景而定**/
    Map<String, Object> data = new HashMap<>();
    data.put("const_id", "exxxxxxwbZsF1PqoflWOyhKLIhAzw9X1");
    // 设备指纹token,端上获取 传入后台
    data.put("user_id", 456799324); // 用户ID
    data.put("phone_number", "13800138000"); // 手机号
    data.put("source", 2); // 登录来源
    data.put("ip", "127.0.0.1"); // 终端用户的ip地址
    data.put("register_date", "注册时间,时间格式2017-09-27 10:09:20");
    //涉及时间参数,请勿传date类型,需要转为标准时间格式yyyy-MM-dd HH:mm:ss后以String类型传入
    data.put("ext_amount", "123.456"); // 涉及浮点类型,请转为String类型传入
    /**创建一个请求数据实例**/
    CtuRequest request = new CtuRequest();
    /**设置事件编码**/
    request.setEventCode("event_code");
    request.setData(data);
    request.setFlag("请求唯一标识符,可自定义,可选");
    /**创建一个客户端实例**/
    CtuClient client = new CtuClient(url, appId, appSecret);
   /** CtuClient client = new CtuClient(url,appKey,appSecret, connectTimeout, connectionRequestTimeout,socketTimeout)
     用户可以自定义超时设置
     connectTimeout,connectionRequestTimeout,socketTimeout 单位:毫秒
     默认超时设置均为2000毫秒
     **/
    /**向风控引擎发送请求,获取引擎返回的结果**/
    CtuResponse response = client.checkRisk(request);
    if (RiskLevel.ACCEPT.equals(response.getResult().getRiskLevel())) {
        System.out.printf(JSON.toJSONString(response));
        //... 业务代码,当前请求没有风险
    } else if (RiskLevel.REVIEW.equals(response.getResult().getRiskLevel())) {
        System.out.printf(JSON.toJSONString(response));
        //... 业务代码,当前请求有一定风险,建议复审
    } else if (RiskLevel.REJECT.equals(response.getResult().getRiskLevel())) {
        System.out.printf(JSON.toJSONString(response));
        //... 业务代码,当前请求有风险,建议拒绝
    }
}
include "./CtuClient.php";
$url = "https://sec.dingxiang-inc.com/ctu/event.do";
$appId = "你的AppId";
$appSecret = "你的AppSecret";
// 时区
ini_set('date.timezone','Asia/Shanghai');
// 构造请求参数
$request = new CtuClient($url, $appId, $appSecret);
$reqJsonString =  json_encode($request, JSON_UNESCAPED_UNICODE);
$ctuRequest = new CtuRequest();
// $data 具体的业务参数,根据业务实际情况传入
$data = array (
  "const_id" => "exxxxxxKgiPKBMmcwbZsF1PqoflWOyhKLIhAzw9X1",  // 设备指纹token,端上获取 传入后台
  "user_id" => "438888824",
  "phone_number" => "13800138000",
  "source" => 2,
  "activity_id" => 1,
  "register_date" => date('Y-m-d H:i:s'),
  "ext_user_level" => 5,
  "ext_open_id" => "58888888174dde1f",
  "ip" => "127.0.0.1"
);
// $eventCode 事件code
$ctuRequest -> eventCode = "event_code";
$ctuRequest -> flag = "activity_" . time();
$ctuRequest -> data = $data;
// 请求超时时间,单位秒
$timeout = 1;
//调用风控引擎
$responseData = $request -> checkRisk($ctuRequest, $timeout);
echo "风险引擎返回结果:" . $responseData. "\n";
$jsonResult = json_decode($responseData, true);
$result = $jsonResult['result']["riskLevel"];
// ... 根据不同风险做出相关处理
if ($result == "ACCEPT") {
    // 无风险,建议放过
    echo "风险结果:无风险,建议放过" . "\n";
} else if ($result == "REVIEW") {
    // 不确定,需要进一步审核
    echo "风险结果:不确定,需要进一步审核" . "\n";
} else if ($result == "REJECT") {
    // 有风险,建议拒绝
    echo "风险结果:有风险,建议拒绝" . "\n";
}
String appId = "560074aad5xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
 /**应用AppId,公钥**/
String appSecret = "ea2662cxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
/**应用AppSecret,私钥**/
String url = "https://sec.dingxiang-inc.com/ctu/event.do";
/** 风控引擎url**/
CtuClient ctuClient = new CtuClient(url, appId, appSecret);
Dictionary<string, string> data = new Dictionary<string, string>();
/**业务请求数据,根据实际情况传入**/
data.Add("const_id", "exxxxxxKgiPKBMmcwbZsF1PqoflWOyhKLIhAzw9X1");// 设备指纹token,端上获取 传入后台
data.Add("user_id", "438888824");
data.Add("ext_referer", "ext_refererext_referer");
data.Add("phone_number", "1801002000");
data.Add("ip", "123.21.21.12");
data.Add("time", "2016-10-15 20:12:12"); //时间格式
CtuRequest ctuRequest = new CtuRequest();
ctuRequest.data = data;
ctuRequest.eventCode = "your event code";
ctuRequest.flag = "自定义标记,可以用uuid";
CtuResponse response = ctuClient.CheckRisk(ctuRequest);
/**向风控引擎发送请求,获取引擎返回的结果**/
if (String.Equals(response.result.RiskLevel, "ACCEPT"))
{
     //... 业务代码,当前请求没有风险
}
else if (String.Equals(response.result.RiskLevel, "REVIEW"))
{
    //... 业务代码,当前请求有一定风险,建议复审
}
else if (String.Equals(response.result.RiskLevel, "REJECT"))
{
    //... 业务代码,当前请求有风险,建议拒绝
}
# coding=utf-8
import json
from CtuRequest import CtuRequest
from CtuClient import CtuClient
from RiskLevel import RiskLevel
class Demo:
    URL = "https://sec.dingxiang-inc.com/ctu/event.do"
    #风控引擎url
    APP_ID = 'appId'
    #应用AppId,公钥
    APP_SECERT = 'appSecret'
    #应用AppSecret,私钥
    if __name__ == '__main__':
        event_code = 'event_code'
        flag = 'test1'
        data = { #业务请求数据,根据实际情况传入
            'const_id': 'constId', #设备指纹token,端上获取 传入后台
            'user_id': '123',
            'phone_number': '15700000000',
            'ip': '127.0.0.1'
        }
        ctuRequest = CtuRequest(event_code, flag, data)
        client = CtuClient(URL, APP_ID, APP_SECERT)
        #client.timeout = 2
        #设置超时时间 默认两秒
        ctuResponse = client.checkRisk(ctuRequest)
        #向风控引擎发送请求,获取引擎返回的结果
        print ctuResponse
        if ctuResponse["result"]["riskLevel"] == RiskLevel.ACCEPT:
            print "当前请求没有风险"
            pass
        elif ctuResponse["result"]["riskLevel"] == RiskLevel.REVIEW:
            print "当前请求有一定风险,建议复审"
            pass
        elif ctuResponse["result"]["riskLevel"] == RiskLevel.REJECT:
            print "当前请求有风险,建议拒绝"
            pass
npm install dx-ctu-client-sdk --save
const ClientSDK = require('dx-ctu-client-sdk')
const sdk = new ClientSDK('服务url', '您的appId', '您的appSecret')
sdk.checkRisk({
  "data": {
    "phone_number": "17800000000",
    "user_id": "12345326232",
    "ip": "125.121.232.219",
    "const_id": "N4RG6TtsY6ILK5ePY6HVtjj12pu5Yi5wnjnbaUI41" // 设备指纹token,端上获取 传入后台
  },
  "eventCode": "test_event_1",
  "flag": "test1"
}).then((resp) => {
  const level = resp.result.riskLevel
  if (level === 'ACCEPT') {
    // 业务代码,当前请求没有风险
  } else if (level === 'REVIEW') {
    // 业务代码,当前请求有一定风险,建议复审
  } else if (level === 'REJECT') {
    // 业务代码,当前请求有风险,建议拒绝
  }
})
// 设置超时时间
// checkRisk第二个参数为超时时间,默认为2000(2秒)
文档版本: 5c1900b4