黑名单检测接口对接文档
服务名称:黑名单检测
接口版本: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 Base64timestamp/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,常见原因:
- 客户端时间未与标准时间同步,超出 ±180 秒窗口。
- canonical 拼接顺序错误或缺少空行(无 query 时第 3 行为空)。
- JSON body 未做 JCS 规范化。
secret被误做 Base64 解码(应直接用 UTF-8 字节)。signature使用了 URL-safe Base64(应使用标准 Base64)。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_REQUEST(idType is invalid):
DriverLicense、NATIONALID、HealthID、PostalID、Passport、VotersCard、TINID、SSS、PRC、GSIS、UMID
说明:平台不强制校验
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 校验规则
以下为请求参数的校验规则:
args不可为 null;且至少包含一个非空字段:idNumber或phoneNumber。- 当
idNumber存在时,idType必传且必须属于 4.2 枚举。 idNumber仅支持明文传输。phoneNumber默认明文;明文须符合 4.4 格式。平台会对手机号做菲律宾号码归一(去非数字字符,剥离63国家码或前导0,归一为9开头的 10 位本体)。- 请求未携带有效
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 位纯数字)后再计算哈希值。若哈希无效或无法通过校验,请求将被拒绝。
手机号相关校验失败发生在网关层,响应结构为网关错误响应(code 为 GATEWAY_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 |