黑名单检测接口对接文档

服务名称:黑名单检测
接口版本:v1.0


1. 接口概述

1.1 接口能力

黑名单检测接口提供基于证件号和/或手机号的黑名单实时查询能力,聚合多种数据源,按生效 source 判定是否命中,并返回:

  • 整体是否命中(data.hit
  • 系统订单号(data.orderId
  • 是否计费(data.billable
  • 分数据源命中详情(data.hitSources,按租户配置决定是否返回)

1.2 业务场景

本接口为信贷业务提供黑名单风险筛查能力,主要面向现金贷场景下的申请人风险识别。命中黑名单建议拒绝该申请人的业务请求。


2. 接口基本信息

内容
接口名称 黑名单检测接口
请求方法 POST
请求路径 /api/v1/blacklist_check
Content-Type application/json
认证方式 API Key + 请求签名(HMAC-SHA256)
技术对接 ke@mocasa.com

2.1 环境地址

环境 Base URL
TEST https://data-gateway-test.creditkernel.ai
DEV https://data-gateway-dev.creditkernel.ai
PROD https://data-gateway.creditkernel.ai

完整请求地址 = Base URL + 请求路径,例如测试环境:

https://data-gateway-test.creditkernel.ai/api/v1/blacklist_check

3. 鉴权与签名

当前接入模式仅支持 API Key + 请求签名。标准接入方式为通过数据服务网关接入,请求依次经过网关的认证、限流、配额、权限校验后,转发至黑名单检测服务。

3.1 接入凭据

签名认证开始前,请确认已收到以下两项凭据:

  • X-API-Key(明文身份标识):通过请求头发送给网关,可视为接入方身份。
  • 签名密钥 secret:与 X-API-Key 唯一对应,仅用于在你的服务端计算签名,严禁出现在前端代码、客户端、URL、日志、git 提交中。

两项凭据由我方生成并通过安全渠道一次性下发,请妥善保管;如怀疑泄漏请立即联系我方更换。

3.2 请求头参数

每次请求须携带以下请求头:

参数 类型 必填 说明
Content-Type string 固定为 application/json
X-API-Key string 平台分配给租户的调用密钥
X-Timestamp string 秒级时间戳(Unix Epoch Seconds,UTC)
X-Nonce string 请求唯一随机串,用于防重放
X-Signature string HMAC-SHA256 后 Base64 编码的签名值

请求未携带有效 X-API-Key 或签名头时,将被直接拒绝。

3.3 签名计算规范

canonical = METHOD + "\n" + RAW_PATH + "\n" + sortedQuery + "\n" + bodySha256 + "\n" + timestamp + "\n" + nonce
signature = Base64( HMAC_SHA256(secret, canonical) )

完整计算逻辑见 3.5 签名示例代码。以下为代码中未体现的关键要点:

  • RAW_PATH:保留 percent-encoding,不做 URL 解码
  • JSON body 须先做 JCS 规范化(RFC 8785),Java 推荐 io.github.erdtman:java-json-canonicalization:1.1
  • secret 按 UTF-8 字节直接作为 HMAC 密钥,不要做 Base64 解码
  • signature 使用标准 Base64(含 +/=),不是 URL-safe Base64
  • timestamp / nonce:见 3.4

3.4 timestamp 与 nonce

  • X-Timestamp:Unix 秒级时间戳(UTC)。必须使用秒(13 位毫秒时间戳会被拒)。服务端允许时钟偏差 ±180 秒,超出将被拒绝(返回 401)。客户端机器时间应与标准时间保持同步(建议启用 NTP)。
  • X-Nonce:每次请求唯一的随机串,用于防重放。每次请求都生成新的 nonce,绝不复用;建议使用 UUIDv4 等高强度随机来源。重试场景必须重新生成 nonce 并重新签名。

3.5 签名示例

以下 Java 代码展示签名计算的核心逻辑:

// 1. JSON body 做 JCS 规范化
String canonicalBody = new JsonCanonicalizer(body).getEncodedString();

// 2. 计算 bodySha256(小写 hex)
String bodySha256 = sha256Hex(canonicalBody.getBytes(StandardCharsets.UTF_8));

// 3. 拼接 canonical(无 query 时 sortedQuery 为空字符串,\n 不可省)
String canonical = method + "\n"
        + rawPath + "\n"
        + sortedQuery + "\n"
        + bodySha256 + "\n"
        + timestamp + "\n"
        + nonce;

// 4. HMAC-SHA256 + 标准 Base64
String signature = Base64.getEncoder().encodeToString(
        hmacSha256(secret.getBytes(StandardCharsets.UTF_8),
                   canonical.getBytes(StandardCharsets.UTF_8)));

自验对照值(使用固定输入计算,你的实现应得到相同结果):

输入
body {"requestId":"8055ba71-fe16-4311-b9a3-17b1fdd18f3a","args":{"idType":"UMID","idNumber":"011145131134","phoneNumber":"9674315469"}}
timestamp 1779340359
nonce n-550e8400-e29b-41d4-a716-446655440000
secret demo_secret_please_replace_me
中间值 结果
JCS(body) {"args":{"idNumber":"011145131134","idType":"UMID","phoneNumber":"9674315469"},"requestId":"8055ba71-fe16-4311-b9a3-17b1fdd18f3a"}
bodySha256 2a3afc39ddc0f44fe7fb0f119e87e32f2da21ce970b5aabb1088f7ff7c27e00b
signature T7k4ytsf0rHYG6Y5/PQkgTqZKORdhDAmF55ksZxs0rw=

3.6 签名校验失败排查

签名校验失败时,网关返回 HTTP 401,常见原因:

  1. 客户端时间未与标准时间同步,超出 ±180 秒窗口。
  2. canonical 拼接顺序错误或缺少空行(无 query 时第 3 行为空)。
  3. JSON body 未做 JCS 规范化。
  4. secret 被误做 Base64 解码(应直接用 UTF-8 字节)。
  5. signature 使用了 URL-safe Base64(应使用标准 Base64)。
  6. nonce 在重试时复用了旧值。

4. 请求参数

4.1 请求体(Request Body)

请求体为 JSON 对象,字段如下:

字段 类型 必填 说明
requestId string 客户端请求号,建议传入,便于贵司侧对账。响应中的 requestId 始终由系统重新生成 UUID,与客户端传入值不同
args object 查询参数对象,不可为 null
args.idType string 条件必填 证件类型;当传 args.idNumber 时必传。合法枚举见 4.2
args.idNumber string 条件必填 证件号;与 args.phoneNumber 至少传一个(仅支持明文)
args.phoneNumber string 条件必填 手机号;与 args.idNumber 至少传一个。默认明文传输,加密传输方式见 4.4
args.phoneNumberEncryptType string 手机号加密类型,不传默认 PLAIN(明文)。可选 PLAIN / MD5 / SHA256,详见 4.4

4.2 证件类型与格式要求

idType 必须为以下枚举之一(大小写敏感),非法值返回业务 BAD_REQUESTidType is invalid):

DriverLicenseNATIONALIDHealthIDPostalIDPassportVotersCardTINIDSSSPRCGSISUMID

说明:平台不强制校验 idNumber 的字符格式;但为提高命中率与数据一致性,建议按下列格式准备证件号:

idType 建议格式
DriverLicense 首字母大写,其余为纯数字
NATIONALID 纯数字
HealthID 纯数字;首位为 0 时不可去除
PostalID 开头不含 PRN,仅含字母和数字,字母须大写
Passport 仅含字母和数字,字母须大写
VotersCard 不含 VIN,仅含字母和数字,字母须大写;首位为 0 时不可去除
TINID 至少 12 位数字;不足 12 位时在末尾补 0 至 12 位;已满则保持不变;首位为 0 时不可去除
SSS 纯数字;首位为 0 时不可去除
PRC 纯数字;首位为 0 时不可去除
GSIS 纯数字;首位为 0 时不可去除
UMID 须为 12 位数字,不足时在前面补 0

4.3 校验规则

以下为请求参数的校验规则:

  1. args 不可为 null;且至少包含一个非空字段:idNumberphoneNumber
  2. idNumber 存在时,idType 必传且必须属于 4.2 枚举。
  3. idNumber 仅支持明文传输。
  4. phoneNumber 默认明文;明文须符合 4.4 格式。平台会对手机号做菲律宾号码归一(去非数字字符,剥离 63 国家码或前导 0,归一为 9 开头的 10 位本体)。
  5. 请求未携带有效 X-API-Key 或签名头时,网关将直接拒绝请求。

4.4 可选:手机号加密传输

本接口默认采用明文传输手机号,推荐接入方使用明文方式调用。

如需加密传输,仅手机号phoneNumber)支持加密,证件号(idNumber)始终为明文。通过 args.phoneNumberEncryptType 指定加密方式。

phoneNumberEncryptType 说明
PLAIN(默认) 明文传输,须匹配:9xxxxxxxxx(10 位)/ 09xxxxxxxxx(11 位)/ 639xxxxxxxxx(12 位)
MD5 手机号标准化为 9xxxxxxxxx(10 位纯数字)后计算 MD5,输出 32 位小写十六进制字符串
SHA256 手机号标准化为 9xxxxxxxxx(10 位纯数字)后计算 SHA256,输出 64 位小写十六进制字符串

使用 MD5 或 SHA256 时,须先将手机号标准化为 9xxxxxxxxx(10 位纯数字)后再计算哈希值。若哈希无效或无法通过校验,请求将被拒绝。

手机号相关校验失败发生在网关层,响应结构为网关错误响应codeGATEWAY_BAD_REQUEST),不是业务层 BAD_REQUEST。见 6.5.4


5. 请求示例

5.1 明文手机号(含可选 sourceCodes)

curl -X POST \
  -H "Content-Type: application/json" \
  -H "X-API-Key: <Your API Key>" \
  -H "X-Timestamp: <epoch_seconds>" \
  -H "X-Nonce: <random_nonce>" \
  -H "X-Signature: <Your Signature>" \
  -d '{
    "requestId": "14db1297-651a-4af7-b80c-33c5d59cb2c4",
    "args": {
      "idType": "UMID",
      "idNumber": "011188130034",
      "phoneNumber": "9674885469"
    }
  }' \
  "https://data-gateway-test.creditkernel.ai/api/v1/blacklist_check"

5.2 MD5 手机号(可选,见 4.4

curl -X POST \
  -H "Content-Type: application/json" \
  -H "X-API-Key: <Your API Key>" \
  -H "X-Timestamp: <epoch_seconds>" \
  -H "X-Nonce: <random_nonce>" \
  -H "X-Signature: <Your Signature>" \
  -d '{
    "requestId": "14db1297-651a-4af7-b80c-33c5d59cb2c4",
    "args": {
      "idType": "UMID",
      "idNumber": "011188130034",
      "phoneNumber": "e10adc3949ba59abbe56e057f20f883e",
      "phoneNumberEncryptType": "MD5"
    }
  }' \
  "https://data-gateway-test.creditkernel.ai/api/v1/blacklist_check"

5.3 SHA256 手机号(可选,见 4.4

curl -X POST \
  -H "Content-Type: application/json" \
  -H "X-API-Key: <Your API Key>" \
  -H "X-Timestamp: <epoch_seconds>" \
  -H "X-Nonce: <random_nonce>" \
  -H "X-Signature: <Your Signature>" \
  -d '{
    "requestId": "14db1297-651a-4af7-b80c-33c5d59cb2c4",
    "args": {
      "idType": "UMID",
      "idNumber": "011188130034",
      "phoneNumber": "01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b",
      "phoneNumberEncryptType": "SHA256"
    }
  }' \
  "https://data-gateway-test.creditkernel.ai/api/v1/blacklist_check"

6. 响应说明

标准接入(网关接入)模式下,本接口存在两种响应结构

  • 网关层错误响应:请求在网关侧(认证、限流、配额、权限、路由、手机号加密校验等)被拦截时返回,结构为 {timestamp, path, status, code, message, requestId},HTTP 状态码为非 2xx。
  • 业务层响应:请求通过网关校验后进入业务处理,返回结构为 {success, code, message, requestId, data}

6.1 业务层响应字段

字段 类型 说明
success boolean 业务处理结果,true / false
code string 业务状态码,见 6.4.1
message string 业务状态说明
requestId string 系统生成的请求追踪 ID(UUID),与请求体中可选的客户端 requestId 不同
data.hit boolean 是否命中黑名单:任一生效 source 命中即为 true
data.orderId string 系统订单号
data.billable boolean 是否计费;当前实现与 hit 一致
data.hitSources object 分数据源命中详情;是否返回由租户配置决定(默认返回)。见 6.1.1

6.1.1 hitSources 结构

hitSources 为以 source 编码为 key 的对象,例如:

{
  "source1": { "hit": false, "blacklistTime": null },
  "source2": { "hit": true, "blacklistTime": "2025-10-20" }
}
字段 类型 说明
hit boolean 该 source 是否命中
blacklistTime string null

若租户被配置为不返回 hitSources,成功响应中将不包含该字段;data.hit / data.billable / data.orderId 仍会返回。

测试环境默认返回所有source的命中情况详情; 经过测试结果分析,上生产前租户告知服务方使用哪些源

6.2 网关层错误响应字段

字段 类型 说明
timestamp string 错误发生时间(UTC)
path string 请求路径
status integer HTTP 状态码
code string 网关错误码,见 6.4.2
message string 错误说明
requestId string 网关请求 ID
subCode string 可选;部分鉴权失败场景会附带子码

6.3 计费规则

场景 code data.hit data.billable 是否计费
命中黑名单 SUCCESS true true
未命中黑名单 SUCCESS false false
参数错误 BAD_REQUEST / GATEWAY_BAD_REQUEST
API Key 未授权 / source 越权 FORBIDDEN
服务内部异常 INTERNAL_ERROR
网关层错误 网关错误码

计费原则:仅命中黑名单时计费,未命中及各类错误均不计费。

6.4 状态码说明

6.4.1 业务状态码

Status Code HTTP Charge Message / 场景
SUCCESS 200 pay OK;命中时计费
BAD_REQUEST 400 free 请求参数错误或缺失(如缺 idType、非法 idType、非法 sourceCodes、缺证件/手机号等)
FORBIDDEN 403 free API Key 未授权,或不在白名单;请求 sourceCodes 超出租户允许范围
INTERNAL_ERROR 500 free 服务内部异常

Charge 列含义:pay = 命中时计费,free = 不计费。详见 6.3 计费规则

6.4.2 网关状态码(常见)

Status Code HTTP Status Message
GATEWAY_UNAUTHORIZED 401 API Key 或签名无效
SIGNATURE_INVALID_CONTENT_TYPE 400 Content-Type 与请求体类型不一致
GATEWAY_FORBIDDEN 403 路由无访问权限
GATEWAY_BAD_REQUEST 400 请求格式或参数错误(含手机号加密校验失败)
GATEWAY_RATE_LIMITED 429 请求频率超限
GATEWAY_QUOTA_EXHAUSTED 429 请求额度超限
GATEWAY_ROUTE_NOT_FOUND 404 路由未配置
GATEWAY_SERVICE_INSTANCE_UNAVAILABLE 503 下游服务不可用
GATEWAY_INTERNAL_ERROR 500 网关内部异常

429(限流/配额超限)与 503(下游不可用)为可重试错误,接入方可根据自身业务实现重试逻辑。

6.5 响应示例

6.5.1 成功响应(命中)

{
  "success": true,
  "code": "SUCCESS",
  "message": "",
  "requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "data": {
    "hit": true,
    "orderId": "BL20260611143303916be007480370d4d2784c2dcf625a2fc04",
    "billable": true,
    "hitSources": {
      "source1": { "hit": false, "blacklistTime": null },
      "source2": { "hit": true, "blacklistTime": "2025-10-20" }
    }
  }
}

6.5.2 成功响应(未命中)

{
  "success": true,
  "code": "SUCCESS",
  "message": "",
  "requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "data": {
    "hit": false,
    "orderId": "BL20260611143303916be007480370d4d2784c2dcf625a2fc04",
    "billable": false,
    "hitSources": {
      "source1": { "hit": false, "blacklistTime": null },
      "source2": { "hit": false, "blacklistTime": null }
    }
  }
}

6.5.3 业务参数错误响应

{
  "success": false,
  "code": "BAD_REQUEST",
  "message": "idType is required when idNumber is provided",
  "requestId": "eef65760-12bd-4414-a8eb-25483de36012",
  "data": null
}

常见业务参数错误提示(code 均为 BAD_REQUEST,以 message 区分):

message
args must not be null
args must contain a non-blank idNumber or phoneNumber
idType is required when idNumber is provided
idType is invalid

以上多种参数错误共用同一业务状态码 BAD_REQUEST,仅靠 message 文本区分。对接方如需程序化区分具体错误类型,需对 message 做字符串匹配。

6.5.4 网关手机号参数错误响应

手机号明文/哈希格式错误、加密类型非法、哈希校验失败等,由网关拦截,示例:

{
  "timestamp": "2026-06-14T04:53:10.972Z",
  "path": "/api/v1/blacklist_check",
  "status": 400,
  "code": "GATEWAY_BAD_REQUEST",
  "message": "phoneNumber format invalid for PLAIN",
  "requestId": "1d13ad16-9988"
}

常见网关手机号相关 message

message
phoneNumberEncryptType must be PLAIN, MD5 or SHA256
phoneNumber format invalid for PLAIN
phoneNumber format invalid for MD5, expected 32-char lowercase hex
phoneNumber format invalid for SHA256, expected 64-char lowercase hex
phoneNumber invalid for MD5
phoneNumber invalid for SHA256

6.5.5 API Key / source 权限错误响应

{
  "success": false,
  "code": "FORBIDDEN",
  "message": "header X-API-KEY is not allowed",
  "requestId": "eef65760-12bd-4414-a8eb-25483de36012",
  "data": null
}

sourceCodes 越权示例 message

requested sourceCodes are out of tenant allowed scope: [source9]

6.5.6 网关鉴权错误响应(401)

{
  "timestamp": "2026-05-13T10:37:05.612Z",
  "path": "/api/v1/blacklist_check",
  "status": 401,
  "code": "GATEWAY_UNAUTHORIZED",
  "message": "签名校验失败",
  "requestId": "60afbeb9-8"
}

6.5.7 网关配额超限响应(429)

{
  "timestamp": "2026-06-14T03:59:43.869Z",
  "path": "/api/v1/blacklist_check",
  "status": 429,
  "code": "GATEWAY_QUOTA_EXHAUSTED",
  "message": "租户调用总配额已用尽",
  "requestId": "..."
}

6.5.8 网关限流响应(429)

{
  "timestamp": "2026-06-14T04:53:10.972Z",
  "path": "/api/v1/blacklist_check",
  "status": 429,
  "code": "GATEWAY_RATE_LIMITED",
  "message": "请求过于频繁",
  "requestId": "1d13ad16-9988"
}

7. 限流与配额

网关提供两层流量控制:

  • QPS 限流:基于令牌桶算法,按租户+客户端+路由维度限制每秒请求数。超限返回 GATEWAY_RATE_LIMITED(429)。
  • 总配额:按租户维度控制累计调用总量,跨实例共享。耗尽返回 GATEWAY_QUOTA_EXHAUSTED(429)。

具体 QPS 上限与配额总量由租户签约约定,如有调整需求请联系我方。


8. 术语表(Glossary)

术语 说明
API Key 租户调用身份凭证,放在请求头 X-API-Key
secret 与 API Key 唯一对应的签名密钥,仅用于服务端计算签名,不可外泄
Timestamp 签名时间戳,单位秒(UTC)
Nonce 签名随机串,用于防重放,每次请求唯一
requestId 响应中的系统追踪 ID(UUID);请求体可选的 requestId 仅为客户端请求号,便于对账
source / sourceCodes 对外数据源编码,格式 sourceN;可指定查询范围
hitSources 分 source 命中详情,元素为 { hit, blacklistTime }
blacklistTime 入黑时间;无证据时为 null
billable 计费标识,位于 data.billable;当前与 hit 一致
JCS RFC 8785 定义的 JSON 规范化算法,用于消除等价 JSON 的字节差异
hit 是否命中黑名单,位于 data.hit;任一生效 source 命中即为 true