网易易盾手游智能反外挂支付安全(服务端)接入文档

2022.03.09 14:05:09


    一、接入说明

    购买支付安全服务后,客户端开始数据上报,服务端通过调用支付安全查询接口获取结果并进行分析。目前仅支持iOS手游。


    二、接入步骤


    2.1 获取安全凭证

    在调用支付安全服务前,需要从【易盾官网-服务管理-已开通业务】获取AppId和AppKey,用于计算接口请求认证签名,见认证参数token生成说明


    2.2 测试联调

    接入易盾支付安全SDK,上报数据并调用查询接口获取结果,查看结果是否符合预期响应。


    三、接口清单


    3.1 支付安全结果查询接口


    3.1.1 接口用途

    支付安全接口提供查询服务,服务端可通过调用该接口获取支付安全结果,建议支付前和支付后分别调用。


    3.1.2 接入须知

    • 注意事项:建议设置HTTP请求的超时时间,且建议http超时的情况下,认为检测结果为 “正常”。


    3.1.3 使用形式

    • 接口地址:http://open-yb.dun.163.com/api/v1/ps/check

    • 请求方法:POST

    • 请求头:Content-Type:application/json


    3.1.4 请求参数

    请求参数包括公共鉴权参数,和API私有业务参数,发起请求时都需要填写

    • (1) 公共参数
    鉴权参数名称 类型 是否必填 最大长度 描述
    appId String 10 appId
    timestamp long 13 调用接口当前时间,单位毫秒,防重放
    nonce String 16 随机码,防重放
    token String 32 使用appKey签名的数据,检验权限
    • (2) 业务参数
    参数名称 类型 必须 最大长度 描述
    acToken String 256 支付安全校验结果查询凭证,由业务前端提交给业务后端
    account String 256 用户唯一标识,如果是手机号or邮箱,支持传入hash值,hash算法:md5(account)
    email String 64 用户的邮箱,如果需要加密,支持传入hash值,hash算法:md5(email)
    phone String 64 默认国内手机号。如有海外手机,需包含国家地区代码,格式为“+447410xxx186(+44即为国家码)”。如果需要加密,支持传入hash值,hash算法:md5(phone)
    ip String 20 用户参加活动时的ip
    registerTime Number 13 用户的注册时间,单位:毫秒
    registerIp String 20 用户的注册IP
    nickname String 256 用户的昵称
    userLevel String 32 用户的等级
    activityId String 256 活动的唯一标识
    target String 256 活动操作的目标,比如:A给B点赞,则target为B。如果target是手机号或邮箱,请提供hash值,hash算法:md5(target)
    orderTime Number 13 订单时间,单位:毫秒
    orderReceipt String 订单收据,已经解析,json字符串


    3.1.5 请求参数示例

    支付前:

    {
    "acToken": "9ca17ae2e6fbcda170e2e6ee95ce79f7bff7cccd43ab928bb6d55e968f8b84f53ca8eff984ee4be9b683a2f42af0feaec3b92aa9ec8da6ed4bb4b7a6bad54e978a9ab6d44b8ff5a5abfb7b9aec9d8ced5cb598ee9e",
    "appId": "A001374634",
    "timestamp":${currentTime},
    "nonce":111,
    "token": "${sign}",
    "account": "test@163.com",
    "email": "test@163.com",
    "phone": "18955566611",
    "ip": "183.136.182.141"
    }
    

    支付后:(其中orderReceipt字段需要传入的内容为标准JSON字符串,示例中省略了部分字段)

    {
    "acToken": "9ca17ae2e6fbcda170e2e6ee95ce79f7bff7cccd43ab928bb6d55e968f8b84f53ca8eff984ee4be9b683a2f42af0feaec3b92aa9ec8da6ed4bb4b7a6bad54e978a9ab6d44b8ff5a5abfb7b9aec9d8ced5cb598ee9e",
    "appId": "A001374634",
    "timestamp":${currentTime},
    "nonce":111,
    "token": "${sign}",
    "account": "test@163.com",
    "email": "test@163.com",
    "phone": "18955566611",
    "ip": "183.136.182.141",
    "orderTime": 1632809505530,
    "orderReceipt": "{
    					'environment': 'Sandbox',
    					'receipt': {
    						'adam_id': 0,
    						'app_item_id': 0,
    						'application_version': 2013,
    						'bundle_id': 'com.netease.UUIDDemo16',
    						'download_id': 0,
    						'in_app':[
                                          {
                                          	'original_purchase_date': '2015-05-20 03:51:24 Etc/GMT',
                                            'original_purchase_date_ms': 1632809505530,
                                            'original_transaction_id': 1000000644961768,
                                            ...
                                          },
                                          ...
                                     ]
                                   },
                         'status': 0
    				  }"
    
    }
    


    3.1.6 响应结果

    • 响应数据格式:json如下所示
    参数名称 类型 描述
    code int 接口调用状态,取值参见:响应返回码
    msg String 结果说明,如果调用出错,返回错误描述
    result Object 接口返回结果,具体参见各接口说明。
    • result说明 响应的result结果字段如下
    参数名 类型 描述
    action int 检测结果:0 正常(放行),10 正常(观察),20 致命(拦截)
    taskId String 任务id,与检测请求一一对应,建议保存此值方便以后数据查询
    hitInfos List 命中信息,例如:[{"hitType":5,"hitMsg":"无SDK数据"}],
    其中hitType类型为int,含义是命中类型,详见下方“hitType返回码及含义”表,
    hitMsg类型为String,含义是命中详情,开通正式定制版后支持返回,可定制返回值.
    如果同时命中多个类型,则会返回所有风险信息
    • hitType返回码及含义
    hitType值 含义描述
    0 正常
    1 数据异常,主要表现有数据完整性校验不通过或数据伪造等
    2 行为异常,主要表现有用户的操作行为(鼠标点击/移动等)无法通过行为验证模型等
    3 设备模型,主要表现有设备指纹等信息无法通过设备验证模型等
    4 业务模型,主要表现有撞库、批量操作、违反业务规则等
    5 校验异常,主要表现有数据强校验结果异常或数据伪造等
    6 模拟器,主要表现有安卓端使用手机模拟器的行为
    7 越狱或ROOT,主要表现有iOS系统已越狱或Android系统已root
    8 浏览器异常,主要表现有浏览器分辨率等参数异常或遭篡改等
    9 IP异常,主要表现有终端IP画像结果为风险IP或高危IP等
    10 黑名单,易盾自有及客户自定义黑名单数据
    11 白名单,易盾自有及客户自定义白名单数据
    12 高危账号,主要表现有团伙账号或异常共享账号等风险账号类型
    13 多开小号,主要表现有批量多开
    14 篡改硬件信息,主要表现为篡改硬件设备参数信息
    15 篡改系统信息,主要表现为篡改系统参数信息
    16 高危设备,主要表现为高危设备画像风险评分,黑产特征设备等类型
    17 群控或云控,主要表现为群控工作室设备或云机
    18 安装修改工具,主要表现有安装Hook修改、Xposed修改,Magisk修改等
    19 虚拟环境,非真实设备访问环境,区别于安卓模拟器,如编辑后台等
    20 脚本工具,黑灰产用于作弊行为的脚本工具


    3.1.7 响应结果示例

    支付安全识别为正常的响应结果:

    {
        "code":200,
        "msg":"ok",
        "result":{
            "action":0,
            "taskId":"698256a52215495ab3c61f14e8e6e844",
            "hitInfos":[
                {
                    "hitType":0,
                    "hitMsg":"正式定制版在这个字段会返回命中详情"
                }]
        }
    }
    

    支付安全识别为异常的响应结果:

    {
        "code":200,
        "msg":"ok",
        "result":{
            "action":20,
            "taskId":"5aecbc658f2e4cfab24b6f4171e5839e",
            "hitInfos":[
                {
                    "hitType":5,
                    "hitMsg":"正式定制版在这个字段会返回命中详情"
                },
                {
                    "hitType":6,
                    "hitMsg":"正式定制版在这个字段会返回命中详情"
                }
            ]
        }
    }
    


    附录


    响应码定义

    状态码 说明
    200 正常
    400 请求参数不合法
    401 未授权或者授权已过期
    404 服务不存在
    405 参数错误
    410 签名验证失败
    420 请求时间戳不正确
    430 重放请求
    440 参数解密失败
    503 服务器内部出现异常
    4401 Token验证失败
    5503 API未开放,不可使用
    5509 API QPS超出限制
    5709 API 最小请求频率超出限制,需要降低请求频率


    认证参数token生成说明

    接口使用签名方式进行认证,每一次请求都必须包含签名信息(即参数token),以验证用户身份,防止信息被恶意篡改。具体使用步骤如下。

    (1) 申请安全凭证

    使用 API 之前,需申请安全凭证,Appkey,请妥善保管,避免泄漏。

    (2) 生成签名参数token

    • 步骤一:将公共参数,按照参数名ASCII码表升序顺序排序。如参数:foo=1, bar=2,foo_bar=3, baz=4 。排序后的顺序是 bar=2, baz=4, foo=1, foobar=3。

    • 步骤二:将排序好的参数名参数值对,拼装成字符串,格式为:key1value1key2value2…。根据上面示例结果为:bar2baz4foo1foobar3 。

    • 步骤三:将申请的Appkey,加到上一步拼装的参数字符串之后。

    • 步骤四:把步骤三的字符串,采用UTF-8编码,使用 MD5算法(128位长度)对字符串进行摘要计算,得到token参数值(32位十六进制字符串)。

    • 代码示例

    String token= SignatureUtils.genSignature(appKey, appId, timestamp, nonce);
    其中:SignatureUtils.java 如下:
    
    package com.netease.is.clientapi.utils;
    import com.google.common.collect.Maps;
    import org.apache.commons.codec.digest.DigestUtils;
    import java.io.UnsupportedEncodingException;
    import java.util.Arrays;
    import java.util.Map;
    /**
    * Created by yubaohong on 19-5-22.
      */
      public class SignatureUtils {
         /**
         * 暴露获取token的方法
         * @param appKey
         * @param appId
         * @param timestamp
         * @param nonce
         * @return
         * @throws UnsupportedEncodingException
            */
    
          public static String genSignature(String appKey, String appId, String timestamp, String nonce) throws UnsupportedEncodingException {
            Map<String, String>userParams = getTokenParams(appId, timestamp, nonce);
            return SignatureUtils.genSignature(appKey, userParams);
          }
    
         /**
         * 生成签名信息
         * @param appKey产品私钥
         * @param params 接口请求参数名和参数值map,不包括signature参数名
         * @return
            */
    
          private static String genSignature(String appKey, Map<String, String> params) throws UnsupportedEncodingException {
            // 1. 参数名按照ASCII码表升序排序
            String[] keys = params.keySet().toArray(new String[0]);
            Arrays.sort(keys);
            // 2. 按照排序拼接参数名与参数值
            StringBuilder sb = new StringBuilder();
            for (String key : keys) {
                sb.append(key).append(params.get(key));
            }
            // 3. 将appKey拼接到最后
            sb.append(appKey);
            // 4. MD5是128位长度的摘要算法,转换为十六进制之后长度为32字符
            return DigestUtils.md5Hex(sb.toString().getBytes("UTF-8"));
          }
    
        /**
         * 拼接参数
         * @param appId
         * @param timestamp
         * @param nonce
         * @return
            */
    
          private static Map<String, String> getTokenParams(String appId, String timestamp, String nonce) {
            <String, String> userParams = Maps.newHashMap();
            userParams.put("appId", appId);// 固定
            userParams.put("timestamp", timestamp);
            userParams.put("nonce", nonce);
            return userParams;
          }
      }
    
    
    Online Chat Tel:95163223 Free trial