关于风险控制:Part-1连续更新实时风控决策系统的对接之前端接入

53次阅读

共计 12065 个字符,预计需要花费 31 分钟才能阅读完成。

最近在整顿对于 实时风控决策零碎 的内容,明天抽空写了一篇如何疾速部署的简略攻略吧。

接入只需 4 步

具体步骤

Step 1:获取 AppId、AppSecret;

返回顶象治理后盾,在实时危险决策的二级菜单“利用治理”中获取;
PS:未开明服务的,须要先申请开明服务。

Step 2:前端接入,即设施指纹埋点;

反对 Web 接入,反对 IE8+、Chrome、Firefox、360 浏览器、QQ 浏览器等支流浏览器及 Android、iOS 上的内嵌 Webview。

PS: 提醒:设施指纹 token 具备时效性,超过肯定工夫会过期,请勿自行缓存
重要:因终端用户的设施网络环境和设施版本等因素,设施指纹采集率并不能肯定达到 100%,可能会存在极少局部未能失常采集到的状况。所以在集成指纹服务的时候,请尽量避免对指纹信息强依赖。
1. web 接入

1.1 环境要求
兼容 IE8+,Chrome,Firefox,360 浏览器,QQ 浏览器等支流浏览器。

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

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

1.3 生成 token
页面加载后,初始应用,须要在 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 拜访这个值。也能够持续调用下面的初始化办法,同一个浏览器屡次初始化返回的值雷同。

options 字段阐明

字段 类型 是否必填 阐明
AppId String 以后利用的标识, 须要分割工作人员获取
server String 服务接口,可选,如不填,则默认会用云服务接口
scene String 场景标识,例如 login、survey 等
userId String 业务方的用户惟一标识,例如用户名、用户 ID、手机号、Email 等
2. Android 接入

2.1 环境要求

条目 阐明
开发指标 Android 4.0+
开发环境 Android Studio 3.0.1 或者 Eclipse + ADT
CPU 架构 ARM 或者 x86
SDK 三方依赖

2.2 集成 SDK

2.2.1 下载 SDK

点击下载 SDK

点击下载 demo(仅做代码配置演示应用,其中 appId 请在顶象后盾申请,SDK 须要替换为链接中下载的 SDK)

2.2.2 Android Studio

集成 SDK 包集成内容:

  • libs 文件夹下的 jar 和 so
  • assets 文件夹下的配置文件

把 libs 下 jar 和 so 库放到相应模块的 libs 目录下,assets 下的文件搁置到我的项目 assets 下

在该 Module 的 build.gradle 中如下配置:

android{
    sourceSets {
        main {jniLibs.srcDirs = ['libs']
            assets.srcDirs = ['assets']
        }
    }

    packagingOptions {doNotStrip "**/libDX*.so"}
}

repositories{
    flatDir{dirs 'libs'}
}

dependencies {implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation files('libs/dx-risk-x.x.x.jar')
}

2.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"/>

<!-- 可选 -6.0 或以上需动静申请 -->
<uses-permission android:name="android.permission.BLUETOOTH"/>
<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" />

2.2.4

Proguard 混同配置 -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.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);

   // 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.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();}

2.3 接口应用阐明

2.3.1 办法和参数阐明

性能形容

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

办法阐明

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

初始化

setupSDK 应用前必须调用先 setup,setup 次要用于数据 / 环境初始化,个别在 Application 的 onCreate 下调用:

/**
* 初始化参数,环境
* @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

2.3.2 应用示例

(1) 初始化 setup

倡议 Application.onCreate 下调用

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

(2) 获取 token

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

new Thread(){

    @Override
    public void run() {
      /* 私有化配置 */
      HashMap<String, String> params = new HashMap<String, String>();
      // 私有化部署服务端 url
      params.put(DXRisk.KEY_URL, "https://constid.dingxiang-inc.com");
      // 开启线上数据备份
      params.put(DXRisk.KEY_BACKUP, DXRisk.VALUE_ENABLE_BACKUP);
      // 设置申请 token 超时时长 ms,不设置默认为 500ms
      parsms.put(DXRisk.KEY_DELAY_MS_TIME, "2000");

      // 开明服务后可在实时危险决策的菜单获取
      String appId = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
       // 获取设施指纹 token
      final String token = DXRisk.getToken(appId, params);

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

2.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 接入

Apple Store 上架请特地留神(2.2.3 节)

3.1 环境需要阐明

条目 阐明
兼容平台 iOS 8.0+
开发环境 XCode 4.0 +
CPU 架构 armv7, arm64, i386, x86_64
SDK 依赖 libz, libresolv, libc++ , SystemConfiguration.framework , CoreLocation.framework , CoreTelephony.framework

3.2 集成 SDK

3.2.1 下载 SDK

点击下载 SDK,SDK 的目录构造如下:

点击下载集成 demo

  • 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

3.2.2 将 SDK 接入 XCode

(1) 导入 Framework

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

  • 如果 App 中蕴含广告相干的性能,则抉择 DXRiskWithIDFA.framework 或者 DXRiskStaticWithIDFA.framework,该版本能够提供更精准的 token
  • 如果没有广告,获取 idfa 可能导致回绝上架,此时请抉择 DXRisk.framework 或者 DXRiskStatic.framework

(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 如下图:

(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

3.3 接口应用阐明

3.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.3.2 应用示例

示例一:Native

// 整个过程因为是耗时操作,必须要在非主线程上执行,否则会阻塞 UI。如果自身曾经在非 UI 线程上执行,则不须要另开线程
    dispatch_queue_t dxrisk_queue = dispatch_queue_create("com.dingxiang.dxrisk", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(dxrisk_queue, ^{
        // 依据业务逻辑,填充自定义字段
        NSDictionary *dic = @{DXRiskManagerKeyUserId: @"123456"};
        // 如需自定义服务端 URL,填充 DXRiskManagerKeyURL 字段,如需备份私有化数据填充 DXRiskManagerKeyBackup 字段,如下正文
        // NSDictionary *dic = @{DXRiskManagerKeyUserId: @"123456",DXRiskManagerKeyURL:@"http://xxxxxxx",DXRiskManagerKeyBackup:DXRiskManagerKeyBackupEnable};
        // 如需统计设施降级率,填充 DXRiskManagerKeyDegradeNotify 字段,如下正文
        // NSDictionary *dic = @{DXRiskManagerKeyUserId: @"123456",DXRiskManagerKeyDegradeNotify:DXRiskManagerKeyDegradeNotifyEnable};
        // 获取 token
        // 留神:token 最好不要保留在某个局部变量或者字段,每次应用时,都通过 API 获取。// 初始化
        BOOL isSuccess = [DXRiskManager setup];
        NSLog(@"setup success: %@" , isSuccess ? @"YES":@"NO");
        // 获取 token
        // 留神:token 最好不要保留在某个局部变量或者字段,每次应用时,都通过 API 获取。NSString *constID = [DXRiskManager getToken:@"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" extendsParams:dic];                    NSLog(@"token: %@", token);
        // TODO 把 token 通过 Post 申请,传到业务后盾。// 上面是模仿频繁调用的过程
        while(TRUE) {NSLog(@"constID: %@", [DXRiskManager getToken:@"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" extendsParams:dic]);
            [NSThread sleepForTimeInterval:.5];
        }
    });

示例二:JavaScript

将相干变量导入 JSContext

JSContext *jsContext = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    jsContext[@"DXRiskManager"] = [DXRiskManager class];
    jsContext[@"DXRiskManagerKeyUserId"] = DXRiskManagerKeyUserId;
    jsContext[@"DXRiskManagerKeyBackup"] = DXRiskManagerKeyBackup;
    jsContext[@"DXRiskManagerKeyURL"] = DXRiskManagerKeyURL;
    jsContext.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue) {
        context.exception = exceptionValue;
        NSLog(@"异样信息:%@", exceptionValue);
    };
    // 依据业务逻辑,填充自定义字段(同 Native 应用示例)var isSuccess = DXRiskManager.setup()
  var token = DXRiskManager.getToken('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' , {[DXRiskManagerKeyUserId]: '123456'})

私有化部署的用户,应用 4.8.0 以上版本的 SDK, DXRiskManagerKeyURL 填写规定为 ip+port(http://ip:port)或者域名(http://domain.com),留神前面不要拼 ”/”

3.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 微信小程序接入

js 接入

一、下载设施指纹 js

私有化版本下载

SaaS 版本下载

二、获取密钥

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

三、应用

1. 代码接入

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

后续将继续更新后端接入示例代码,记得关注呀!

正文完
 0