Node.js 调用示例
Node.js 调用 CatFee.IO Rest API 示例
前提条件
使用 Node.js 18 及以上版本。
安装
axios:npm install axios
示例代码
const axios = require('axios');
const crypto = require('crypto');
const API_KEY = 'your_api_key'; // 请替换为您的 API Key
const API_SECRET = 'your_api_secret'; // 请替换为您的 API Secret
const BASE_URL = 'https://api.catfee.io';
const TIMEOUT_MS = 15000;
// 生成带毫秒的 ISO 8601 UTC 时间戳。
function generateTimestamp() {
return new Date().toISOString();
}
// 构建参与签名并实际发送的完整请求路径。
function buildRequestPath(path, queryParams = []) {
if (queryParams.length === 0) {
return path;
}
return `${path}?${new URLSearchParams(queryParams).toString()}`;
}
// 使用 HMAC-SHA256 生成 Base64 编码的请求签名。
function generateSignature(timestamp, method, requestPath) {
const signString = timestamp + method.toUpperCase() + requestPath;
return crypto
.createHmac('sha256', API_SECRET)
.update(signString, 'utf8')
.digest('base64');
}
// 签名并发送 CatFee API 请求。
async function sendRequest(method, path, queryParams = []) {
method = method.toUpperCase();
const requestPath = buildRequestPath(path, queryParams);
const timestamp = generateTimestamp();
const signature = generateSignature(timestamp, method, requestPath);
const headers = {
'Content-Type': 'application/json',
'CF-ACCESS-KEY': API_KEY,
'CF-ACCESS-SIGN': signature,
'CF-ACCESS-TIMESTAMP': timestamp,
};
// requestPath 必须同时用于签名和实际请求,避免参数编码或顺序不一致。
return axios.request({
method,
url: BASE_URL + requestPath,
headers,
timeout: TIMEOUT_MS,
validateStatus: () => true,
});
}
async function main() {
// 示例:创建一笔能量订单。
// 使用数组固定参数顺序;client_order_id 用于网络异常时安全重试。
const clientOrderId = crypto.randomUUID();
const queryParams = [
['quantity', '65000'],
['receiver', 'TRON_ADDRESS'],
['duration', '1h'],
['client_order_id', clientOrderId],
['activate', 'true'],
];
console.log('Client Order ID:', clientOrderId);
try {
const response = await sendRequest('POST', '/v1/order', queryParams);
console.log('HTTP Status:', response.status);
console.log('Response Body:', response.data);
// HTTP 层失败(例如 4xx、5xx)。
if (response.status < 200 || response.status >= 300) {
throw new Error(`HTTP request failed with status ${response.status}`);
}
const result = response.data;
if (!result || typeof result !== 'object') {
throw new Error('Response is not valid JSON');
}
// CatFee API 通常返回 HTTP 200,仍需检查响应体中的业务 code。
if (result.code !== 0) {
const message = result.msg || result.sub_msg || 'Unknown error';
throw new Error(
`API request failed: code=${result.code}, message=${message}`
);
}
console.log('Order ID:', result.data?.id || '');
} catch (error) {
if (error.code === 'ECONNABORTED') {
console.error('Request timed out.');
} else {
console.error('Request failed:', error.message);
}
console.error('如需重试,请复用 Client Order ID:', clientOrderId);
}
}
main();代码解析
generateTimestamp(): 使用toISOString()生成带毫秒的 ISO 8601 UTC 时间戳,用于CF-ACCESS-TIMESTAMP请求头。buildRequestPath(): 使用URLSearchParams编码查询参数并拼接请求路径。返回结果同时用于签名和实际请求,确保两者完全一致。generateSignature(): 按照timestamp + method + requestPath拼接签名原文,使用 API Secret 计算 HMAC-SHA256,并对结果进行 Base64 编码。sendRequest(): 构造三个 CatFee 鉴权请求头,通过 Axios 发送请求,并设置 15 秒超时。main(): 调用POST /v1/order创建能量订单,并同时检查 HTTP 状态码和响应体中的业务code。
注意事项
API Key 和 Secret: 请确保将
API_KEY和API_SECRET替换为您从 CatFee.IO 获取的实际值。签名路径必须与请求路径一致: 查询参数的内容、URL 编码和顺序都必须一致。不要在生成签名后使用 Axios 的
params选项重新构造查询字符串。订单参数:
quantity当前不得小于65000,duration当前仅支持1h;receiver必须是有效的 TRON 地址。幂等重试: 每笔新订单使用唯一且不超过 64 个字符的
client_order_id。发生超时或连接中断时,应保存并复用原值重试,不能重新生成。地址激活:
activate=true表示必要时允许激活接收地址;如果设为false且地址未激活,接口将返回错误。响应判断: HTTP
200不一定表示业务成功,还必须确认响应 JSON 中的code为0。
总结
此示例展示了如何使用 Node.js 调用 POST /v1/order 购买能量,并正确处理请求签名、幂等订单号、超时和 API 响应。其他接口也可以复用 sendRequest(),只需传入对应的 HTTP 方法、路径和查询参数。
Last updated
Was this helpful?