add
This commit is contained in:
324
docs/查询白名单公开接口-下游对接说明.md
Normal file
324
docs/查询白名单公开接口-下游对接说明.md
Normal file
@@ -0,0 +1,324 @@
|
|||||||
|
# 查询白名单接口 — 下游对接说明
|
||||||
|
|
||||||
|
> 本文档供**已开通权限的 API 用户 / 合作方**对接使用。
|
||||||
|
> 用于配置「查询为空」屏蔽规则:命中后,指定人员在指定接口上的查询将返回 `1000 查询为空`。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 服务地址
|
||||||
|
|
||||||
|
| 环境 | 基础地址 |
|
||||||
|
|------|----------|
|
||||||
|
| 生产 | `https://api.tianyuanapi.com` |
|
||||||
|
|
||||||
|
完整路径 = 基础地址 + 下表路径,例如:
|
||||||
|
|
||||||
|
`https://api.tianyuanapi.com/api/v1/query-whitelist/entries`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 接口一览
|
||||||
|
|
||||||
|
| 接口 | 方法 | 路径 | 说明 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| 创建规则 | POST | `/api/v1/query-whitelist/entries` | 首次为某身份证建立屏蔽规则 |
|
||||||
|
| 追加接口 | POST | `/api/v1/query-whitelist/entries/append` | 向已有规则追加产品编码(去重合并) |
|
||||||
|
|
||||||
|
**说明:**
|
||||||
|
|
||||||
|
- 规则仅对**当前 `Access-Id` 对应账号**生效。
|
||||||
|
- 本接口为**配置类接口**,不产生业务查询、**不扣费**,也不会出现在常规 API 调用记录中。
|
||||||
|
- 规则生效后,该账号调用对应产品接口时,若命中屏蔽条件,将返回 `1000 查询为空`。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 鉴权
|
||||||
|
|
||||||
|
每次请求需同时满足以下三项。
|
||||||
|
|
||||||
|
### 3.1 请求头
|
||||||
|
|
||||||
|
| 字段 | 类型 | 必填 | 说明 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| `Access-Id` | string | 是 | 您的 API 账号 Access-Id |
|
||||||
|
| `Whitelist-Mgmt-Key` | string | 是 | 平台单独下发的**白名单管理密钥**(与 Access Key 不同,请向商务/技术支持索取) |
|
||||||
|
| `Content-Type` | string | 是 | 固定为 `application/json` |
|
||||||
|
|
||||||
|
### 3.2 请求体加密
|
||||||
|
|
||||||
|
与业务 API 调用方式一致,外层仅传 `data`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"data": "<AES-128-CBC Base64 密文>"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| 字段 | 类型 | 必填 | 说明 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| `data` | string | 是 | 业务参数经 Access Key 加密后的 Base64 字符串 |
|
||||||
|
|
||||||
|
- 使用您账号的 **Access Key**(16 进制字符串)进行 AES 加密。
|
||||||
|
- Access Key **仅用于本地加密**,不要写入明文 JSON。
|
||||||
|
- 服务端根据请求头 `Access-Id` 查找密钥并解密;**解密成功即完成身份校验**。
|
||||||
|
|
||||||
|
### 3.3 IP 白名单
|
||||||
|
|
||||||
|
调用方出口 IP 须已加入该账号在控制台配置的 IP 白名单(与业务 API 要求一致)。未在白名单内的 IP 将返回 `1004`。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 业务参数(加密前明文 JSON)
|
||||||
|
|
||||||
|
创建与追加接口的明文字段相同:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "*",
|
||||||
|
"id_card": "350681198611130611",
|
||||||
|
"api_codes": ["FLXG0V4B", "JRZQ8A2D"],
|
||||||
|
"remark": "可选备注"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| 字段 | 类型 | 必填 | 说明 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| `name` | string | 是 | 姓名;填 `*` 表示只按身份证匹配,不校验姓名 |
|
||||||
|
| `id_card` | string | 是 | 18 位中国大陆身份证号 |
|
||||||
|
| `api_codes` | string[] | 是 | 生效的产品编码列表,见下表约束 |
|
||||||
|
| `remark` | string | 否 | 备注,最长 500 字符;追加接口传入非空时会覆盖原备注 |
|
||||||
|
|
||||||
|
### 4.1 `api_codes` 约束
|
||||||
|
|
||||||
|
| 传参方式 | 是否允许 | 示例 |
|
||||||
|
|----------|----------|------|
|
||||||
|
| 字符串数组 | 允许 | `["FLXG0V4B", "JRZQ8A2D"]` |
|
||||||
|
| 单个字符串 | 不允许 | `"FLXG0V4B"` |
|
||||||
|
| 通配 `*` | 不允许 | `["*"]` |
|
||||||
|
| 空数组 | 不允许 | `[]` |
|
||||||
|
| 非字符串元素 | 不允许 | `[123]` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 创建与追加的区别
|
||||||
|
|
||||||
|
同一账号下,**同一身份证号 + 同一 `name`** 仅对应**一条**规则;多个生效接口配置在该规则的 `api_codes` 数组中。
|
||||||
|
|
||||||
|
### 5.1 创建 `POST /entries`
|
||||||
|
|
||||||
|
| 情况 | 结果 |
|
||||||
|
|------|------|
|
||||||
|
| 尚无该身份证+姓名的规则 | 创建成功 |
|
||||||
|
| 规则已存在 | 失败,`1013 规则已存在`(不会自动合并) |
|
||||||
|
|
||||||
|
### 5.2 追加 `POST /entries/append`
|
||||||
|
|
||||||
|
| 情况 | 结果 |
|
||||||
|
|------|------|
|
||||||
|
| 规则已存在 | 成功;将本次 `api_codes` 与已有列表**去重合并**(保留原顺序,新编码追加在后) |
|
||||||
|
| 本次编码均已存在 | 仍返回成功(幂等),列表不变 |
|
||||||
|
| 规则不存在 | 失败,`1014 规则不存在,请先调用创建接口` |
|
||||||
|
|
||||||
|
**示例:**
|
||||||
|
|
||||||
|
```
|
||||||
|
创建:api_codes = ["FLXG0V4B"]
|
||||||
|
追加:api_codes = ["JRZQ8A2D"]
|
||||||
|
→ 合并后为 ["FLXG0V4B", "JRZQ8A2D"](同一条规则,非新建)
|
||||||
|
|
||||||
|
再次追加:api_codes = ["JRZQ8A2D", "FLXG2E8F"]
|
||||||
|
→ ["FLXG0V4B", "JRZQ8A2D", "FLXG2E8F"](JRZQ8A2D 已存在则跳过)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.3 推荐流程
|
||||||
|
|
||||||
|
1. 首次配置 → 调用**创建接口**(可一次传齐全部 `api_codes`)
|
||||||
|
2. 后续增补产品 → 调用**追加接口**(只传新增编码)
|
||||||
|
3. 创建返回 `1013` → 改调**追加接口**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 加密算法
|
||||||
|
|
||||||
|
与业务 API 完全一致:
|
||||||
|
|
||||||
|
1. Access Key 为 16 进制字符串,解码为 16 字节 AES 密钥
|
||||||
|
2. 采用 **AES-128-CBC**,**PKCS7** 填充
|
||||||
|
3. 每次加密随机生成 16 字节 IV,置于密文前
|
||||||
|
4. IV + 密文整体做 **Base64** 编码,放入 `data`
|
||||||
|
|
||||||
|
**加密步骤:**
|
||||||
|
|
||||||
|
```
|
||||||
|
明文 JSON → AES-128-CBC 加密 → [IV(16字节) + 密文] → Base64 → 填入 data 字段
|
||||||
|
```
|
||||||
|
|
||||||
|
**解密响应 `data` 时:** 取 Base64 解码后前 16 字节为 IV,余下为密文,用同一 Access Key 解密。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 响应格式
|
||||||
|
|
||||||
|
HTTP 状态码均为 `200`。以响应体 `code` 判断业务是否成功。
|
||||||
|
|
||||||
|
### 7.1 外层结构
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 0,
|
||||||
|
"message": "业务成功",
|
||||||
|
"transaction_id": "550e8400-e29b-41d4-a716-446655440000",
|
||||||
|
"data": "<AES 加密字符串>"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `code` | int | `0` 表示成功,非 `0` 见错误码表 |
|
||||||
|
| `message` | string | 结果描述 |
|
||||||
|
| `transaction_id` | string | 本次请求流水号 |
|
||||||
|
| `data` | string | 成功时返回,为规则详情的 AES 密文,需用 Access Key 解密 |
|
||||||
|
|
||||||
|
### 7.2 `data` 解密后结构
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
||||||
|
"name": "*",
|
||||||
|
"id_card_masked": "350681********0611",
|
||||||
|
"api_codes": ["FLXG0V4B", "JRZQ8A2D"],
|
||||||
|
"status": "enabled",
|
||||||
|
"remark": "",
|
||||||
|
"created_at": "2026-06-18T10:00:00+08:00",
|
||||||
|
"updated_at": "2026-06-18T10:00:00+08:00"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `id` | string | 规则唯一标识 |
|
||||||
|
| `name` | string | 姓名规则 |
|
||||||
|
| `id_card_masked` | string | 脱敏身份证号 |
|
||||||
|
| `api_codes` | string[] | 当前生效的产品编码列表 |
|
||||||
|
| `status` | string | `enabled` 启用 / `disabled` 禁用 |
|
||||||
|
| `remark` | string | 备注 |
|
||||||
|
| `created_at` | string | 创建时间(ISO 8601) |
|
||||||
|
| `updated_at` | string | 最近更新时间(ISO 8601) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. 错误码
|
||||||
|
|
||||||
|
| code | message | 说明 |
|
||||||
|
|------|---------|------|
|
||||||
|
| 0 | 业务成功 | 创建或追加成功 |
|
||||||
|
| 1001 | 接口异常 | 系统内部错误 |
|
||||||
|
| 1002 | 解密失败 | `data` 无法解密 |
|
||||||
|
| 1003 | 请求参数结构不正确 | 参数缺失、格式错误或 `api_codes` 不合法 |
|
||||||
|
| 1004 | 未经授权的IP | 调用 IP 不在账号白名单 |
|
||||||
|
| 1005 | 缺少Access-Id | 未传 `Access-Id` 请求头 |
|
||||||
|
| 1006 | 未经授权的AccessId | Access-Id 无效或账号已冻结 |
|
||||||
|
| 1010 | 缺少管理密钥 | 未传 `Whitelist-Mgmt-Key` |
|
||||||
|
| 1011 | 管理密钥无效 | 管理密钥错误 |
|
||||||
|
| 1012 | 接口未开放 | 功能未对该账号/环境开放 |
|
||||||
|
| 1013 | 规则已存在 | 创建时:该身份证+姓名规则已存在 |
|
||||||
|
| 1014 | 规则不存在 | 追加时:须先调用创建接口 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. 调用示例(Node.js)
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const crypto = require('crypto');
|
||||||
|
|
||||||
|
const BASE_URL = 'https://api.tianyuanapi.com';
|
||||||
|
const ACCESS_ID = '您的Access-Id';
|
||||||
|
const ACCESS_KEY = '您的AccessKey'; // 16 进制,用于加解密
|
||||||
|
const MGMT_KEY = '平台下发的Whitelist-Mgmt-Key';
|
||||||
|
|
||||||
|
function encrypt(plainText, keyHex) {
|
||||||
|
const key = Buffer.from(keyHex, 'hex');
|
||||||
|
const iv = crypto.randomBytes(16);
|
||||||
|
const cipher = crypto.createCipheriv('aes-128-cbc', key, iv);
|
||||||
|
cipher.setAutoPadding(true);
|
||||||
|
let enc = cipher.update(plainText, 'utf8');
|
||||||
|
enc = Buffer.concat([iv, enc, cipher.final()]);
|
||||||
|
return enc.toString('base64');
|
||||||
|
}
|
||||||
|
|
||||||
|
function decrypt(cipherBase64, keyHex) {
|
||||||
|
const key = Buffer.from(keyHex, 'hex');
|
||||||
|
const buf = Buffer.from(cipherBase64, 'base64');
|
||||||
|
const iv = buf.slice(0, 16);
|
||||||
|
const decipher = crypto.createDecipheriv('aes-128-cbc', key, iv);
|
||||||
|
decipher.setAutoPadding(true);
|
||||||
|
let dec = decipher.update(buf.slice(16));
|
||||||
|
dec = Buffer.concat([dec, decipher.final()]);
|
||||||
|
return dec.toString('utf8');
|
||||||
|
}
|
||||||
|
|
||||||
|
async function callWhitelistApi(path, payload) {
|
||||||
|
const res = await fetch(`${BASE_URL}${path}`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Access-Id': ACCESS_ID,
|
||||||
|
'Whitelist-Mgmt-Key': MGMT_KEY,
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
data: encrypt(JSON.stringify(payload), ACCESS_KEY),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
const json = await res.json();
|
||||||
|
if (json.code === 0 && json.data) {
|
||||||
|
json.decrypted = JSON.parse(decrypt(json.data, ACCESS_KEY));
|
||||||
|
}
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建
|
||||||
|
callWhitelistApi('/api/v1/query-whitelist/entries', {
|
||||||
|
name: '*',
|
||||||
|
id_card: '350681198611130611',
|
||||||
|
api_codes: ['FLXG0V4B'],
|
||||||
|
remark: '',
|
||||||
|
}).then(console.log);
|
||||||
|
|
||||||
|
// 追加
|
||||||
|
callWhitelistApi('/api/v1/query-whitelist/entries/append', {
|
||||||
|
name: '*',
|
||||||
|
id_card: '350681198611130611',
|
||||||
|
api_codes: ['JRZQ8A2D'],
|
||||||
|
}).then(console.log);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. 常见问题
|
||||||
|
|
||||||
|
### `name` 填 `*` 是什么意思?
|
||||||
|
|
||||||
|
只按**身份证号**匹配。只要业务请求中的身份证与该规则一致,无论传入什么姓名,均会返回「查询为空」。
|
||||||
|
|
||||||
|
### 与业务 API 的 Access Key 是什么关系?
|
||||||
|
|
||||||
|
- **Access Key**:加密请求/响应,证明账号身份(与业务 API 相同)。
|
||||||
|
- **Whitelist-Mgmt-Key**:平台另行下发的管理授权密钥,证明有权调用白名单配置接口。
|
||||||
|
|
||||||
|
两者缺一不可。
|
||||||
|
|
||||||
|
### 调用成功后,常规 API 调用记录里能看到吗?
|
||||||
|
|
||||||
|
不能。本接口为配置类操作,不计入业务 API 调用次数,也不扣费。
|
||||||
|
|
||||||
|
### 屏蔽何时生效?
|
||||||
|
|
||||||
|
接口返回 `code = 0` 后即生效(通常数秒内)。之后该账号调用 `api_codes` 中包含的产品且入参命中身份证(及姓名规则)时,将返回 `1000 查询为空`。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. 联系方式
|
||||||
|
|
||||||
|
- **Access-Id / Access Key**:登录控制台 → API 密钥
|
||||||
|
- **Whitelist-Mgmt-Key**:向平台商务或技术支持申请
|
||||||
|
- **IP 白名单**:登录控制台 → API 设置中配置
|
||||||
Reference in New Issue
Block a user