适用版本：

- Android-SDK 5.8.0 开始以及以后，带 -pro 的版本，例如5.8.0-pro
- Android-SDK 5.8.0 之前的版本，不带-pro。例如 5.7.9.3

## 隐私说明

请参照[网易易盾隐私政策](https://dun.163.com/clause/privacy)，请将易盾隐私政策链接放到应用“用户协议”中。




## 接入说明

接入“智能风控” SDK，开发者需要完成以下步骤：

```
1. 根据应用/游戏开发平台，将SDK拷贝到指定的工程目录，并修改项目配置；
2. 接入风控SDK必接接口，根据业务需求接入建议接口；
3. 测试风控SDK接入是否正确；
4. 验证风控SDK功能效果；
5. 按业务常规发版流程进行测试与发版
```


**游戏必须接入：**

* 全局必须要接入的接口：[初始化接口](#4.1)
* 游戏类型应用反外挂场景业务必须要接入的接口：[设置用户信息接口](#4.2)
* 选择角色进入游戏后，接入该接口完成数据透传：[同步获取凭证](#4.4)/[异步获取凭证](#4.5)

**建议接入：**

* 获取风控基础信息：[交互接口](#4.8)
* 协议保护/防脱机:[安全通信协议接口](#4.11)
* 本地存档保护:[本地数据加解密接口](#4.12)

  



## 接入步骤
请登录[易盾官网后台](https://dun.163.com/dashboard?v=0116&locale=zh-CN#/m/risk-manage/service/)风控引擎-服务管理获取SDK，详情如图。![image title](https://nos.netease.com/yidun/e5adb07ec735e95205e83d48bb2a00aa.png)


SDK 涉及到以下文件：

```
nethtprotect.jar
libNetHTProtect.so
assets/motion/xxx.so
htp_agent.h
htp_sdk.cpp
htp_sdk.h
```


**注意：**

打包出来的 apk，必须包含 lib/xxx/libNetHTProtect.so 与 assets/motion/ 下的所有so文件。


### <a id="3.1">**引入jar**</a>


在工程内添加对``nethtprotect.jar``的依赖 


### <a id="3.2">**引入so**</a>

在 android 工程加载游戏 so 的地方，添加对``libNetHTProtect.so`` 的引用。

```java
public class Game {
    static {
        System.loadLibrary("NetHTProtect");
        System.loadLibrary("game");
    }
} 
```

> 注意：``libNetHTProtect.so``的加载顺序，需要在游戏自己的 so 之前。

### <a id="3.3">**引入htp_sdk**</a>

将 `htp_agent.h htp_sdk.h htp_sdk.cpp` 导入到项目中，在需要使用反外挂sdk函数的cpp中，引入 `htp_sdk.h` 头文件

### <a id="3.4">**链接so**</a>


在 jni/android.mk 中添加如下代码，用于链接``libNetHTProtect.so``  

```
include $(CLEAR_VARS)
LOCAL_MODULE := libNetHTProtect
LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libNetHTProtect.so
include $(PREBUILT_SHARED_LIBRARY)
```

在 jni/Android.mk 中，游戏所在的 so 节，添加如下代码，用于指示对 libNetHTProtect 的引用

```
LOCAL_SHARED_LIBRARIES += libNetHTProtect
```



### <a id="3.5">**添加权限信息**</a>

SDK 不会申请任何权限，但是为了提升风控的效果，建议在 AndroidMenifest.xml 文件中添加下列权限配置：

```java
    <!--网络通信-->
    <uses-permission android:name="android.permission.INTERNET"/>
    <!--获取设备信息-->
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <!--获取MAC地址-->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <!--获取网络状态-->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <!--若targetSdkVersion>=30，则需要增加以下权限，否则会影响SDK功能-->
    <queries>
        <intent>
            <action android:name="android.intent.action.MAIN"/>
        </intent>
    </queries>
```


### <a id="3.6">**添加 ProGuard 配置**</a>

若使用 ProGuard 进行混淆，需要将 SDK 使用的类排除掉。若使用 Android Studio 开发，则在 proguard-rules.pro 文件中添加如下信息：

```java
 -keep class com.netease.htprotect.**{*;}
 -keep class com.netease.mobsec.**{*;}
```



## SDK 接入调用说明
重要：如果是在子线程调用反外挂的接口，请务必在子线程开始处调用
AndroidJNI.AttachCurrentThread() ，并且在子线程结束前调用
AndroidJNI.DetachCurrentThread() ，否则会发生内存泄漏或崩溃。

部分产品相关参数请用账号登录易盾官网控制台获取参考![image title](https://nos.netease.com/yidun/e729ec778f5485d37473476c3e82f8a4.png)

### <a id = "4.1">**SDK 初始化接口（init）**</a>


#### **接口用途：**

用于初始化智能风控 SDK。


#### **接入须知：**

1. 使用其他接口之前，必须先调用初始化接口（init），建议在应用/游戏启动过后第一时间调用（初始化后，并不会获取任何个人隐私相关信息）；
2. 该接口为 **<font color='red'>必须调用接口</font>**。


#### **函数原型：**

```c++
void htp_init(const char *productid, const GameSetInfo &info, CallBack cb);
```


#### **参数说明：**

| 参数      | 说明                                      | 必要性                |
|-----------|-------------------------------------------|---------------------|
| productId | 易盾HTP分配的productId，可登录易盾后台获取 | 必填                |
| info | 与HTP相关的一些配置信息 | 可选，不需要可填null |
| cb  | 初始化是否成功的回调                    | 可选，不需要可填null |


##### GameSetInfo结构体

```c++
struct GameSetInfo {
    std::string game_key;            //由易盾分配
    int server_type;                 //服务端所属地区
    std::string channel;             //渠道信息
    std::map<std::string ,std::string> ext_data;            //额外数据
}
```



| 字段        | 说明                                                         |
| ----------- | ------------------------------------------------------------ |
| game_key    | 由易盾分配gameKey，可登录易盾后台获取。[数据校验](#7)，[存档加解密](#9)必须设置此值，如果不使用这三个功能，可不设置或置空，可以自定义32位长度字符串 |
| server_type | 服务器归属地，反外挂默认上报的服务器为中国大陆，若需要更改服务器归属地，可以调用该接口进行配置，支持的类型如下：1：中国大陆地区，默认即为该值，无须设置；2：中国台湾地区；3：海外地区 |
| channel     | 渠道信息                                                     |
| ext_data    | 额外数据，作弊监控接口需要，可设置一些额外信息，必须在init之前设置 |

示例

```c++
GameSetInfo info;
info.server_type = 1; // 服务器所在地址，1：中国大陆，2：中国台湾地区，3：其他地区，4：欧盟地区
info.channel = "testchannel"; // 渠道
info.game_key = "fed80c732b7b467ea2156c29f830eed24fc8"; // 易盾HTP分配的gameKey
std::map<std::string, std::string> ext_data;
ext_data["c"] = "1";
ext_data["e"] = "11Y=";
ext_data["i"] = "222";
info.ext_data = ext_data; // 额外信息，反作弊接口需要，可不设置
```



##### CallBack回调

CallBack为一个函数指针，定义如下

```c++
typedef int(*CallBack)(int, const char*);
```

在使用时，需自己实现一个相同参数的函数，比如

```c++
/**
 * 初始化的回调接口
 * @param code 回调接口返回的错误码
 * @param msg 回调接口返回的信息
 * @return
 */
int htp_init_callback(int code, const char* msg) {
    LOGD("code = %d msg = %s", code, msg);
    // 如果code == 200，说明反外挂一切正常
    // 如果code == 400，请将 msg发送到贵方服务端，由贵方服务端通过[getConfig接口](https://support.dun.163.com/documents/761315885761396736?docId=771983453572567040)转发给易盾服务端，由易盾服务端响应
    // 易盾服务端返回结果，再将结果通过 通用查询接口(Cmd_SetConfigData) 反馈给反外挂sdk
    // char *config_buf = nullptr;
    // size_t config_buf_size = 0;
    // htp_ioctl(Cmd_SetConfigData, configData, config_buf, &config_buf_size); configData为易盾服务端返回的数据
    // SAFEFREE(config_buf)
    return 0;
}
```



#### 示例代码

```c++
/**
 * htp防剥离线程，验证反外挂是否已经正常启动，建议在初始化完成之后，立马调用
 * 可简单判断反外挂是否正常启动，接入简单
 */
void *check_htp_alive_thread(void *arg) {
    sleep(60);
    if (!htp_check_alive()) {
        // 反外挂已被剥离
        LOGD("error htp is not alive");
    } else {
        // 反外挂正常
        LOGD("htp is alive");
    }
    return nullptr;
}

void my_htp_init() {
	GameSetInfo info;
    info.server_type = 1; // 服务器所在地址，1：中国大陆，2：中国台湾地区，3：其他地区，4：欧盟地区
    info.channel = "testchannel"; // 渠道
    info.game_key = "fed80c732b7b467ea2156c29f830eed24fc8"; // 易盾HTP分配gameKey，与手游加固的appKey对应，gameKey可登录易盾后台获取(如果没有调用数据校验(getDataSign)接口，此值可以为空或者不设置)
    std::map<std::string, std::string> ext_data;
    ext_data["c"] = "1";
    ext_data["e"] = "11Y=";
    ext_data["i"] = "222";
    info.ext_data = ext_data; // 额外信息，反作弊接口需要，可不设置
    htp_init(appid, info, htp_init_callback);
    // 初始化结束之后，立马启动htp防剥离线程
    pthread_t t;
    pthread_create(&t, nullptr, check_htp_alive_thread, nullptr);
}
```

如需要示例demo请联系易盾获取。


### <a id="4.2">**设置用户信息接口（setRoleInfo）**</a>




#### **接口用途：**

游戏类型应用，在进行数据采集的过程中，会将角色 ID，角色名称、用户/角色账号等设置在风控 SDK 采集的数据中一同上传，用于表示角色信息，以便对有恶意、风险行为的用户/角色进行相应的处置。


#### **接口须知：**

1. 须在 [SDK 初始化](#4.1)且 **用户同意隐私政策后才能调用该接口**；
2. 凡是涉及到用户登录、或者切换角色的地方，均需要调用该接口设置或者更新用户/玩家信息；


#### **函数原型：**

```c++
int htp_set_role_info(const char *business_id, const char *role_id, const char *role_name, const char *role_account,
                       const char *role_server, int server_id, const char *game_json);
```


#### **参数说明：**

| 参数        | 说明                                           | 必要性              |
|-------------|------------------------------------------------|---------------------|
| business_id | 当前业务 ID                             | 必填                |
| role_id | 用户/玩家的角色 ID                             | 必填                |
| role_name | 用户/玩家的角色名称                            | 可选，不需要可填null |
| role_account | 用户/玩家的账号必填 | 必填                 |
| role_server | 用户/玩家的角色的服务器名称                    | 可选，不需要可填null |
| server_id | 用户/玩家的角色所属服务器的 ID                 | 可选，不需要请传入-1 |
| game_json | 游戏类型应用需要上传的信息，对应一个 json 字符串 | 可选，不需要可填null |

game_json字段说明：

| key 名称     | key 类型 | key 值       | 必要性              | 说明                         |
|--------------|----------|--------------|:--------------------|:-----------------------------|
| 游戏版本号 | String | GameVersion | 可选，不需要可填null | 游戏版本号 |
| 资源文件版本 | String   | AssetVersion | 可选，不需要可填null | 游戏类型应用的资源文件版本号 |


#### **示例代码：**

```c++
htp_set_role_info(HTP_BUSINESS_ID, "123456","易小盾","yd@163.com", "游戏测试服",1,"");
```



### <a id="4.3">**登出接口（logOut）**</a>


#### **接口用途：**

为了更好地统计该用户/玩家角色在本次登录后的行为，精准标识和打击有恶意行为的用户/玩家。


#### **接入须知：**

1. 须在 [设置用户信息接口](#4.2)接口被调用后方可调用，在用户/玩家退出当前角色（包括切换角色）或者退出游戏时调用接口。
2. 此接口主要用于判断用户/玩家本次生命周期，不强制要求接入。
3. 如果未调用初始化，此接口默认为空，不会执行任何逻辑。


#### **函数原型：**

```c#
void htp_logout();
```


#### **示例代码：**

```c++
htp_logout();   
```




### <a id="4.4">**同步获取凭证（getToken）**</a>


#### **接口用途：**

用于关键业务节点风险防控场景中，比如注册、登录、领券、抽卡、兑换、点赞、评论等业务场景。业务方可通过此接口，获取检测唯一凭证 token。业务服务端通过此凭证实时获取当前用户/玩家风险检测结果，并根据结果进行处置。


```java
接口适用场景为:
1、游戏类应用，当 SDK 数据上报接口被屏蔽导致数据上报失败时，通过 getToken 接口获取 SDK 采集信息，并由客户服务端传递给易盾服务器；
2、全类型应用，在关键业务节点主动调用检测时，通过 getToken 接口获取检测凭证，由客户服务端通过 token 凭证从易盾服务器查询检测结果。
```


#### **接入须知：**

1. 须在 [SDK 初始化](#4.1)且用户同意隐私政策后才能调用该接口，[网易易盾隐私说明](https://dun.163.com/clause/privacy)。
2. 内部存在网络请求，**<font color='red'>只允许在子线程上调用</font>**。
3. 返回值token的使用方法请参考“后端接入-智能风控数据服务接口-[在线检测接口](https://support.dun.163.com/documents/761315885761396736?docId=834511620372037632)”。


#### **函数原型：**

```c++
int htp_get_anti_cheat_token(const char *businessId, char **out, size_t *out_len);
```


#### **参数说明：**

| 参数       | 说明         | 必要性                                        |
|------------|--------------|-----------------------------------------------|
| businessId | 业务 ID | 必填，由易盾后台分配，并在官网“服务管理”中查询 |
| out | token的值 | 出参，token |
| out_len | token的长度 | 出参，token的长度 |

#### **返回值：**

| 值   | 说明                                    |
| ---- | --------------------------------------- |
| 200  | 成功，当out不再使用时，需手动释放内存   |
| -201 | 未初始化                                |
| -203 | businessId不合法                        |
| -204 | 生成token出错                           |
| -205 | 参数错误，比如 out 或 out_len指针为NULL |

#### 示例代码

```c++
/*
 * 反作弊getToken线程
 */
void *anti_cheat_token_thread(void *arg) {
    char *token = nullptr;
    size_t token_len = 0;
    int ret = get_anti_cheat_token(appid, &token, &token_len);
    LOGD("ret = %d", ret);
    LOGD("token = %s", token);
    return nullptr;
}

void start_get_token() {
    pthread_t t;
    pthread_create(&t, nullptr, anti_cheat_token_thread, nullptr);
}
```




### <a id="4.8">**交互接口（ioctl）**</a>



#### **接口用途：**

1. 用于在客户端查询 SDK 采集的基础数据、设置需要传递给 SDK 数据（比如初始化配置内容、check 结果信息等）、及其他可能的定制功能服务。
2. 如果未调用初始化，此接口默认返回 `-201`。


#### **接入须知：**

接口调用前置条件是：调用了[设置用户信息接口](#4.2)，并且设置了roleId等信息。


#### **函数原型：**

```c++
int htp_ioctl(int request, const char *data, /*[out]*/char **buf, /*[out]*/size_t *buf_size);
```


#### **参数说明：**

| 参数    | 说明                     |
|---------|--------------------------|
| request | 对应向风控系统请求的命令 |
| data    | 设置信息的附加数据       |
| buf | 返回数据buffer |
| buf_size | 实际使用的buffuer大小 |

request值说明：

```c++
enum RequestCmdID
{
    //初始化配置内容，防止初始化失败情况下，客户可以通过服务端请求初始化配置并传递给SDK
    Cmd_SetConfigData = 16,
    
    //客户服务端将check结果传递给SDK，便于执行后续动作
    Cmd_SetResponseData = 17
};
```


#### **返回值：**

错误的情况下，返回：unsupported request（不支持的命令）；正确的情况下，返回对应命令的结果。

注意：<font color="red">该接口的返回值类型均为String，对返回值做判断的时候需要注意该值的类型。</font>



#### **不同命令设置方法：**



##### **(1) 设置配置信息**

向风控 SDK 配置传递从易盾服务器获取到的产品的**配置信息**（主要适用于风控 SDK 因被黑灰产屏蔽或其他原因导致无法正常获取配置信息的情况）。

**配置信息**：

初始化接口需设置callback

如果callback的code返回400，将msg发送到服务端，再发送到易盾服务端

易盾服务端的返回结果即为配置信息

**示例代码：**
```c++
char *config_buf = nullptr;
size_t config_buf_size = 0;
htp_ioctl(Cmd_SetConfigData, responseData, config_buf, &config_buf_size); responseData为易盾服务端返回的数据
SAFEFREE(config_buf);
//如果入参为null或空，则表示查询当前内存中配置版本；如果参数不为空，则表示更新初始化配置
```


**返回值：**
返回值为一个json：
```java
{"s":0,"v":33554433}//s：状态，int类型，只有为0，v 字段的值才有意义;
                   // v：版本，long类型(8字节)，配置的版本
```




| 返回值 | 说明                |
|--------|---------------------| 
| s     | 0:成功  -1:内存配置加载失败     |
| v    | 配置的版本号   | 



##### **(2) 设置响应信息**

向风控 SDK 配置传递从易盾服务端获取到的命中及**响应结果信息**，以便 SDK 执行相关处置动作（主要适用于风控 SDK 因被黑灰产屏蔽或其他原因导致无法正常获取响应结果的情况）。

**响应结果信息**：

调用获取凭证(`getToken`)接口，获取`token`

将`token`发送到服务端，在服务端调用`check`接口，获取结果，其中的 `sdkRespData` 即为 响应结果信息。

**示例代码：**

```c#
char *data1 = nullptr;
size_t data1_size = 0;
htp_ioctl(Cmd_SetResponseData, response, &data, &data1_size);
SAFEFREE(data)
SAFEFREE(data1)
```

**返回值：**
返回值为字符串格式：

| 返回值 | 说明                |
|--------|---------------------|
| 0或者-1     | 输入数据格式有误     |
| 1      | 解析成功   |




### <a id="4.11">**安全通信协议接口**</a>



#### **接口用途：**

该接口用于对通信数据进行白盒加密和白盒 HMAC 签名，加密和签名的密钥均会被隐藏，攻击者无法获取，从而保障应用/游戏的通信安全。

最新版本接口（V2.1）更新内容如下：
* 自定义二进制格式，增大分析难度；
* 多重加密，防明文传输；
* 数据将进行校验，防止篡改；
* 支持多算法，一旦加密算法被破解，可及时更新为另一种算法；
* 一次一密，每次加密的密钥都不相同；
* 自定义安全随机数发生器，防止系统随机数接口被篡改，始终生成一样的密钥；
* 防重放攻击；
* 防模拟执行(脱离Android/iOS环境运行)。


#### **接口须知：**

如需使用该接口，请联系易盾获取详细说明文档。



### <a id="4.12">**本地数据加解密接口**</a>



#### **接口用途：**

该接口用于对应用/游戏本地存储的数据进行加解密，保护本地数据安全<font color="red">（游戏类型应用可用于本地游戏存档保护）</font>。


#### **接口须知：**

1. 加密后的数据，需要接入方自行存储，风控 SDK 只提供加密和解密功能。
2. 初始化接口的配置类必须设置gameKey
3. 只有返回`1`，才表示调用成功

#### **函数原型：**
```c#
int htp_enc_local(const char* buf, size_t size, /*[out]*/char* enc_buf, size_t enc_buf_size, /*[out]*/size_t *used_buf_size,int alg_type);
int htp_dec_local(const char* buf, size_t size, /*[out]*/char* dec_buf, size_t dec_buf_size, /*[out]*/size_t *used_buf_size,int alg_type);
```
#### **参数说明：**

| 参数                      | 说明                                           |
| ------------------------- | ---------------------------------------------- |
| buf                       | 需要加密或者解密的数据                         |
| size                      | buf的大小                                      |
| enc_buf/dec_buf           | 返回数据buffer                                 |
| enc_buf_size/dec_buf_size | 返回数据buffer大小                             |
| used_buf_size             | 实际使用的buffuer大小                          |
| alg_type                  | 参数为0：跟app安装绑定；参数为1：跟app签名绑定 |


#### **返回值：**

* 若是加密接口，返回的数据即为原始数据的密文；
* 若是解密接口，返回的数据即为密文对应的原始数据。


### <a id="4.13">**模拟点击AI识别**</a>

##### **接口用途：**

批量的模拟点击极大的影响到游戏的正常，特别是工作室的参与，不仅影响到游戏的平台，还影响到游戏方的收入。易盾智能反外挂SDK提供相关的行为检测方案，使用模拟点击行为检测接口时，需要在游戏登录后，并且调用[设置用户信息接口](#4.2)，设置role_id等信息后调用。

##### **接入须知：**

**SDK5.3.5以之后版本支持该接口**

请在作弊情况较严重的玩法和场景下调用registerTouchEvent和unregisterTouchEvent，开启和关闭点击数据的采集，初次接入建议设置一个玩法和场景id，并同步给易盾，如需接入多个玩法和场景需提前与易盾沟通。
开启registerTouchEvent后，在该场景结束后必须调用unregisterTouchEvent关闭检测逻辑。
**（1）开启采集数据**

##### **函数原型：**


```java
void htp_register_touchevent(int gameplayId, int sceneId)
```

##### **函数说明：**

调用该接口后，开始采集点击事件的相关数据。

##### **参数说明：**

| 参数       | 说明   |
| ---------- | ------ |
| gameplayId | 玩法id |
| sceneId    | 场景id |

**（2）关闭数据采集**

##### **函数原型：**

```java
void htp_unregister_touchevent()
```

##### **函数说明：**

取消点击事件数据采集。
