# Node.js 调用示例

### **前提条件**

1. [您需要一个有效的 API Key 和 API Secret](/getting-started/buy-energy-via-api-on-catfee/api-overview.md#apply-api-info)。
2. 请确保您的 Node.js 环境已安装 `axios` 库。可以通过 `npm install axios` 安装。

### **示例代码**

```javascript
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';

// 生成当前的时间戳（ISO 8601格式）
function generateTimestamp() {
    return new Date().toISOString();
}

// 构建请求路径，包括查询参数
function buildRequestPath(path, queryParams) {
    if (!queryParams || Object.keys(queryParams).length === 0) {
        return path;
    }
    const queryString = new URLSearchParams(queryParams).toString();
    return `${path}?${queryString}`;
}

// 使用 HMAC-SHA256 算法生成签名
function generateSignature(timestamp, method, requestPath) {
    const signString = timestamp + method + requestPath;
    return crypto.createHmac('sha256', API_SECRET)
                 .update(signString)
                 .digest('base64');
}

// 创建 HTTP 请求
async function createRequest(url, method, timestamp, signature) {
    const headers = {
        'Content-Type': 'application/json',
        'CF-ACCESS-KEY': API_KEY,
        'CF-ACCESS-SIGN': signature,
        'CF-ACCESS-TIMESTAMP': timestamp
    };

    try {
        const response = await axios({
            url,
            method,
            headers,
        });
        return response.data;
    } catch (error) {
        console.error('Error: ', error.response ? error.response.data : error.message);
        throw error;
    }
}

async function main() {
    const method = 'POST'; // 可以修改为 "GET", "PUT", "DELETE"
    const path = '/v1/order';

    // 示例：创建订单
    const queryParams = {
        quantity: '65000',
        receiver: 'TRON_ADDRESS',
        duration: '1h'
    };

    // 生成请求头
    const timestamp = generateTimestamp();
    const requestPath = buildRequestPath(path, queryParams);
    const signature = generateSignature(timestamp, method, requestPath);

    // 创建请求 URL
    const url = BASE_URL + requestPath;

    // 发送请求
    try {
        const response = await createRequest(url, method, timestamp, signature);
        console.log('Response Data: ', response);
    } catch (error) {
        console.error('Request failed', error);
    }
}

// 执行主函数
main();
```

### **代码解析**

1. **`generateTimestamp()`**：\
   返回当前 UTC 时间戳，使用 JavaScript 的 `toISOString()` 方法生成 ISO 8601 格式的时间戳。
2. **`buildRequestPath()`**：\
   该函数根据传入的查询参数（`queryParams`）构建完整的 URL 路径。`URLSearchParams` 类用于将查询参数转为 URL 编码的查询字符串。
3. **`generateSignature()`**：\
   该函数使用 `HMAC-SHA256` 算法对 `timestamp`、`method` 和 `requestPath` 拼接后的字符串进行签名，使用 API Secret 作为密钥。通过 `crypto` 模块生成签名，并返回 Base64 编码的签名。
4. **`createRequest()`**：\
   使用 `axios` 库发送 HTTP 请求。根据不同的请求方法（`GET`、`POST`、`PUT`、`DELETE`）构建请求，并设置请求头，包括 `CF-ACCESS-KEY`、`CF-ACCESS-SIGN` 和 `CF-ACCESS-TIMESTAMP`。
5. **`main()`**：\
   在 `main()` 函数中，设置请求方法为 `POST`，并构建查询参数。生成时间戳、签名和请求路径后，调用 `createRequest()` 函数发送请求并打印响应。

### **注意事项**

* **API Key 和 Secret**：\
  请确保将 `API_KEY` 和 `API_SECRET` 替换为您从 CatFee.IO 获取的实际值。
* **查询参数的顺序**：\
  在此示例中，我们直接通过 `URLSearchParams` 创建查询字符串，不对查询参数进行排序。
* **错误处理**：\
  使用 `try-catch` 捕获并打印可能出现的异常。通过 `error.response` 可以获取服务器的错误响应。
* **请求方法**：\
  当前示例支持 `POST`、`GET`、`PUT` 和 `DELETE` 方法，您可以根据实际需求修改请求方法。
* **响应处理**：\
  如果请求成功，`axios` 会返回 `response.data`，即响应体数据，您可以根据实际情况进一步解析响应数据（如 JSON 格式）。

### **总结**

此示例展示了如何在 Node.js 中使用 CatFee.IO Rest API，确保请求的安全性，并通过 HMAC-SHA256 签名验证请求。您可以根据需求调整代码，支持不同的 HTTP 方法（`GET`、`POST`、`PUT`、`DELETE`）。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.catfee.io/getting-started/buy-energy-via-api-on-catfee/nodejs.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
