Initial commit: API Debug Tool

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
jason
2026-03-12 04:32:35 +08:00
commit 96bdc292bb
42 changed files with 8577 additions and 0 deletions

View File

@@ -0,0 +1,145 @@
/**
* 标品PP 真实接口调试脚本(从 DB 读取完整数据)
* 使用租户 id=5 (名称:895) + 接口 id=4 (标品部门数据)
*/
const crypto = require('crypto');
const axios = require('axios');
const db = require('../db');
// ─── 工具函数 ─────────────────────────────────────────────────────────────
/**
* 将私钥(多种格式)解析为 Node.js crypto 可用的 KeyObject
* 支持:
* - 裸 base64 PKCS8 DERJava 导出格式)
* - PEM 格式
*/
function loadPrivateKey(raw) {
if (raw.includes('-----BEGIN')) {
return crypto.createPrivateKey(raw);
}
const derBuf = Buffer.from(raw.trim(), 'base64');
return crypto.createPrivateKey({ key: derBuf, format: 'der', type: 'pkcs8' });
}
function generateNonce(length = 8) {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
return Array.from({ length }, () => chars[Math.floor(Math.random() * chars.length)]).join('');
}
function generateSign(params, privateKey) {
const sortedKeys = Object.keys(params).sort();
const signString = sortedKeys.map(k => `${k}=${params[k]}`).join('&');
console.log('[签名] 待签名字符串:', signString);
const signer = crypto.createSign('RSA-MD5');
signer.update(signString, 'utf8');
const signature = signer.sign(privateKey, 'base64');
console.log('[签名] Base64 (前30):', signature.substring(0, 30) + '...');
return signature;
}
// ─── 主流程 ────────────────────────────────────────────────────────────────
async function main() {
console.log('='.repeat(60));
console.log('标品PP 真实接口调试:标品部门数据');
console.log('='.repeat(60));
// 从 DB 读取完整数据
const [[tenant]] = await db.query('SELECT * FROM tenants WHERE id = ?', [5]);
const [[endpoint]] = await db.query('SELECT * FROM endpoints WHERE id = ?', [4]);
if (!tenant || !endpoint) {
console.error('❌ 租户或接口不存在');
process.exit(1);
}
console.log('\n[租户] 名称:', tenant.name, '| 类型:', tenant.type);
console.log('[接口] 名称:', endpoint.name, '| URL:', endpoint.url);
console.log('[私钥] 长度:', tenant.private_key?.length, '字符');
// 1. 加载私钥
let privateKey;
try {
privateKey = loadPrivateKey(tenant.private_key);
console.log('✅ 私钥加载成功(类型:', privateKey.asymmetricKeyType, '');
} catch (e) {
console.error('❌ 私钥加载失败:', e.message);
// 尝试输出私钥前后片段以诊断
console.log(' 私钥开头:', tenant.private_key.substring(0, 50));
console.log(' 私钥结尾:', tenant.private_key.slice(-50));
process.exit(1);
}
// 2. 构建 query 参数(不含 sign
const params = {
entCode: tenant.ent_code,
apiCode: endpoint.api_code,
timestamp: Date.now().toString(),
nonce: generateNonce(8),
};
console.log('\n[参数] 基础参数:', JSON.stringify(params));
// 3. 生成签名
let signature;
try {
signature = generateSign(params, privateKey);
params.sign = signature;
console.log('✅ 签名生成成功');
} catch (e) {
console.error('❌ 签名失败:', e.message);
process.exit(1);
}
// 4. 构建请求
const encodedKey = Buffer.from(`${tenant.api_key}:`).toString('base64');
const headers = {
'Authorization': `Basic ${encodedKey}`,
'Content-Type': 'application/json',
};
const body = JSON.parse(endpoint.body || '{}');
// 5. CURL 命令
const urlObj = new URL(endpoint.url);
Object.entries(params).forEach(([k, v]) => urlObj.searchParams.set(k, v));
let curlCmd = `curl -X ${endpoint.method} '${urlObj.toString()}'`;
Object.entries(headers).forEach(([k, v]) => {
curlCmd += ` \\\n -H '${k}: ${v}'`;
});
curlCmd += ` \\\n -d '${JSON.stringify(body)}'`;
console.log('\n[CURL]\n' + curlCmd);
// 6. 发送请求
console.log('\n[请求] 发送中...');
try {
const response = await axios({
method: endpoint.method.toLowerCase(),
url: endpoint.url,
headers,
params,
data: body,
timeout: 15000,
});
console.log('\n✅ 请求成功!');
console.log('[响应] 状态:', response.status);
console.log('[响应] 数据:');
console.log(JSON.stringify(response.data, null, 2).substring(0, 1000));
} catch (err) {
console.error('\n❌ 请求失败!');
if (err.response) {
console.error('[错误] HTTP 状态:', err.response.status);
console.error('[错误] 响应:', JSON.stringify(err.response.data, null, 2));
} else {
console.error('[错误]', err.message);
}
}
process.exit(0);
}
main().catch(e => { console.error(e); process.exit(1); });