For the complete documentation index, see llms.txt. This page is also available as Markdown.

Node.js 调用示例

Node.js 调用 CatFee.IO Rest API 示例

前提条件

  1. 使用 Node.js 18 及以上版本。

  2. 安装 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();

代码解析

  1. generateTimestamp(): 使用 toISOString() 生成带毫秒的 ISO 8601 UTC 时间戳,用于 CF-ACCESS-TIMESTAMP 请求头。

  2. buildRequestPath(): 使用 URLSearchParams 编码查询参数并拼接请求路径。返回结果同时用于签名和实际请求,确保两者完全一致。

  3. generateSignature(): 按照 timestamp + method + requestPath 拼接签名原文,使用 API Secret 计算 HMAC-SHA256,并对结果进行 Base64 编码。

  4. sendRequest(): 构造三个 CatFee 鉴权请求头,通过 Axios 发送请求,并设置 15 秒超时。

  5. 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?