Files
ycc-proxy-server/tyapi.md
2026-06-19 11:27:53 +08:00

10 KiB
Raw Blame History

查询白名单接口 — 下游对接说明

本文档供已开通权限的 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

{
  "data": "<AES-128-CBC Base64 密文>"
}
字段 类型 必填 说明
data string 业务参数经 Access Key 加密后的 Base64 字符串
  • 使用您账号的 Access Key16 进制字符串)进行 AES 加密。
  • Access Key 仅用于本地加密,不要写入明文 JSON。
  • 服务端根据请求头 Access-Id 查找密钥并解密;解密成功即完成身份校验

3.3 IP 白名单

调用方出口 IP 须已加入该账号在控制台配置的 IP 白名单(与业务 API 要求一致)。未在白名单内的 IP 将返回 1004


4. 业务参数(加密前明文 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-CBCPKCS7 填充
  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 外层结构

{
  "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 解密后结构

{
  "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

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 设置中配置