1. 让风控数据"可视化"
在信贷审核系统的后台或 H5 报告页中,风控专员往往需要一眼看穿用户的借贷趋势。是平稳借贷,还是最近两个月突然爆发?
天远数据 的借贷行为验证API (JRZQ8203)提供了极其宝贵的 T0(当前)至 T11(过去11个月) 的时间序列数据 。这些数据包含借贷次数、机构数和还款压力等级。
然而,API 返回的是扁平化的 Key-Value 结构(如 tl_id_t0_nbank_num, tl_id_t1_nbank_num...)。直接把这些数据丢给前端不仅增加了前端的处理负担,还暴露了加密细节。
Node.js 作为天然的 BFF (Backend for Frontend) 首选语言,凭借其对 JSON 的原生支持和高效的 IO 能力,非常适合充当这个"转换器":对接天远 API,清洗数据,最终输出给前端标准的图表数据。
2. API 调用示例:Node.js Crypto 实战
Node.js 的原生 crypto 模块完美支持天远 API 要求的 AES-128-CBC 算法,且默认支持 PKCS7 填充,因此代码实现比 Go 或 Python 更为简洁。
2.1 接口配置
- 接口地址 :
https://api.tianyuanapi.com/api/v1/JRZQ8203 - 加密规范:AES-128-CBC,IV 随机生成,Base64 输出 。
2.2 完整 Service 代码 (封装为 Class)
JavaScript
jsx
const crypto = require('crypto');
const axios = require('axios');
class RiskService {
constructor(accessId, accessKey) {
this.accessId = accessId;
// 确保密钥是 Buffer 类型
this.accessKey = Buffer.from(accessKey, 'utf8');
this.apiUrl = 'https://api.tianyuanapi.com/api/v1/JRZQ8203';
}
/**
* AES-128-CBC 加密
* Node.js createCipheriv 默认使用 PKCS7 填充,无需手动处理
*/
encrypt(data) {
const iv = crypto.randomBytes(16); // 随机生成 16 字节 IV
const cipher = crypto.createCipheriv('aes-128-cbc', this.accessKey, iv);
const jsonStr = JSON.stringify(data);
let encrypted = cipher.update(jsonStr, 'utf8');
encrypted = Buffer.concat([encrypted, cipher.final()]);
// 拼接 IV + 密文 -> Base64
return Buffer.concat([iv, encrypted]).toString('base64');
}
/**
* AES-128-CBC 解密
*/
decrypt(base64Str) {
const buffer = Buffer.from(base64Str, 'base64');
const iv = buffer.slice(0, 16); // 提取前 16 字节 IV
const content = buffer.slice(16); // 提取密文
const decipher = crypto.createDecipheriv('aes-128-cbc', this.accessKey, iv);
let decrypted = decipher.update(content);
decrypted = Buffer.concat([decrypted, decipher.final()]);
return JSON.parse(decrypted.toString('utf8'));
}
/**
* 执行查询
*/
async query(name, idCard, mobile) {
const payload = {
name: name,
id_card: idCard,
mobile_no: mobile
};
const encryptedData = this.encrypt(payload);
try {
// 添加时间戳防止缓存
const res = await axios.post(`${this.apiUrl}?t=${Date.now()}`, {
data: encryptedData
}, {
headers: {
'Access-Id': this.accessId,
'Content-Type': 'application/json'
}
});
if (res.data.code === 0) {
// 解密响应数据
return this.decrypt(res.data.data);
} else {
throw new Error(`API Error: ${res.data.message}`);
}
} catch (error) {
console.error('Risk Check Failed:', error.message);
return null;
}
}
}
// --- 使用示例 ---
(async () => {
const service = new RiskService("您的AccessId", "您的16位AccessKey");
const result = await service.query("测试用户", "110101199001011234", "13800138000");
if (result && result.flag_totalloan === '1') {
console.log("当前还款压力等级:", result.tl_id_t0_nbank_reamt);
}
})();
3. 核心数据结构解析:JS 动态映射
天远 API 返回的字段虽然多(例如 tl_id_t0_... 到 tl_id_t11_...),但非常有规律 。利用 JavaScript 的动态对象属性访问特性,我们可以轻松通过循环来处理这些数据,而不需要像 Java 那样定义庞大的 DTO。
3.1 数据清洗:扁平转数组
为了方便前端 ECharts 绘图,我们需要把 T0-T11 的数据转换成数组。
JavaScript
jsx
/**
* 将扁平的 API 响应转换为前端图表所需的数组
* @param {Object} rawData 解密后的 API 原始数据
*/
function formatForChart(rawData) {
const timeSeries = [];
const pressureSeries = [];
const orgCountSeries = [];
// 遍历 T0 到 T11 (API 提供近12个月的切片数据)
for (let i = 0; i < 12; i++) {
// 动态构建 Key
const pressureKey = `tl_id_t${i}_nbank_reamt`; // 还款压力
const orgKey = `tl_id_t${i}_nbank_org`; // 机构数
// 提取数据,注意 API 返回的是字符串,需转数字
// 倒序插入:因为 T0 是当前,图表通常希望 T11(过去) -> T0(现在)
timeSeries.unshift(`T${i}`);
pressureSeries.unshift(parseInt(rawData[pressureKey] || 0));
orgCountSeries.unshift(parseInt(rawData[orgKey] || 0));
}
return {
categories: timeSeries, // x轴
series: [
{ name: '还款压力', data: pressureSeries },
{ name: '借贷机构数', data: orgCountSeries }
],
// 提取一些关键汇总指标
summary: {
flag: rawData.flag_totalloan,
lastLoanTime: rawData.tl_id_eletail_lasttime,
loanType: rawData.tl_id_eletail_lasttype // a-h 类型
}
};
}
3.2 关键字段解读
flag_totalloan: 借贷行为输出标识。1: 成功。0: 未匹配上(可能为白户)。98: 输入信息不足。- BFF 层逻辑 :如果为
0,前端应显示"无借贷记录"状态页 。
tl_id_t0_nbank_reamt(1-101) : 预测当前时间近一年在非银机构的应还款等级 。- 业务含义:数值越高,代表用户本月需要偿还的金额压力越大。如果曲线在 T2-T0 期间陡峭上升,说明近期负债急剧增加 。
4. 应用价值分析:BFF 层的灵活性
场景一:借贷压力可视化
前端直接调用 Node.js 接口,获取 formatForChart 处理后的数据。
- 可视化效果:使用双轴折线图。左轴显示"机构数"(0-20),右轴显示"压力指数"(0-100)。
- 价值:信贷审核员无需阅读枯燥的表格,一眼就能看出曲线是否"抬头"。
场景二:基于规则的 API 聚合
在 BFF 层,我们可以将借贷行为验证 (JRZQ8203) 与其他业务逻辑聚合。
- 逻辑流 :
- 调用天远 API。
- 检查
tl_id_eletail_lasttype。如果是c(持牌网络小贷),标记为普通风险;如果是h(其他),标记为高危 。 - 检查
tl_id_m3_nbank_passnum。如果 > 10,标记为多头借贷 。 - 最终输出 :向前端仅返回
{ riskLevel: "HIGH", reason: "近期多头借贷且渠道下沉" },屏蔽原始数据的复杂性。
场景三:Serverless 降本增效
将上述 Node.js 代码部署为 AWS Lambda 或 阿里云 FC 函数。
- 优势:风控查询通常是偶发的(有用户申请时才触发)。Serverless 架构按调用次数计费,且自动扩缩容,完美匹配天远 API 按量计费的模式,将运维成本降至最低。
5. 总结
在 Node.js 环境下对接 天远借贷行为验证API 具有得天独厚的优势:
- 开发快:原生 Crypto 库直接搞定 AES 加密,无需折腾 Padding。
- 处理快:JavaScript 处理 API 返回的大型 JSON 对象(130+ 字段)非常灵活,无需定义繁琐的 Struct 或 Class。
- 体验好:通过 BFF 层的数据清洗,可以直接为前端提供可视化的图表数据,极大提升风控系统的用户体验。
通过这套方案,您不仅是在调用一个数据接口,更是在搭建一个智能化的风控数据中台。