> For the complete documentation index, see [llms.txt](https://docs.catfee.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.catfee.io/getting-started/buy-energy-via-api-on-catfee/java.md).

# Java调用示例

### **前提条件**

1. [您需要一个有效的 API Key 和 API Secret](/getting-started/buy-energy-via-api-on-catfee/api-overview.md#apply-api-info)。
2. 确保您的环境已安装 Java 8 及以上版本，并导入以下依赖：
   * `java.net.http.HttpClient`
   * `java.security.MessageDigest`
   * `javax.crypto.Mac`
   * `javax.crypto.spec.SecretKeySpec`

### **示例代码**

```java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

public class CatFeeAPIExample {

    private static final String API_KEY = "your_api_key"; // 请替换为您的API Key
    private static final String API_SECRET = "your_api_secret"; // 请替换为您的API Secret
    private static final String BASE_URL = "https://api.catfee.io";

    public static void main(String[] args) throws Exception {
        // 请求方法
        String method = "POST"; // 可以根据需要修改为 "GET", "PUT", "DELETE" 等

        // 示例：创建订单
        String path = "/v1/order";
        Map<String, String> queryParams = new HashMap<>();
        queryParams.put("quantity", "65000");
        queryParams.put("receiver", "TRON_ADDRESS");
        queryParams.put("duration", "1h");

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

        // 创建HTTP请求
        String url = BASE_URL + requestPath;
        HttpRequest request = createRequest(url, method, timestamp, signature);

        // 发送请求并获取响应
        HttpClient client = HttpClient.newHttpClient();
        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

        // 打印响应
        System.out.println("Response Code: " + response.statusCode());
        System.out.println("Response Body: " + response.body());

        // 处理可能的错误信息
        if (response.statusCode() != 200) {
            System.out.println("Error: " + response.body());
        }
    }

    // 生成当前 UTC 时间戳（ISO 8601格式）
    public static String generateTimestamp() {
        return Instant.now().toString();
    }

    // 构建请求路径，包括查询参数
    public static String buildRequestPath(String path, Map<String, String> queryParams) {
        if (queryParams == null || queryParams.isEmpty()) {
            return path;
        }
        String queryString = queryParams.entrySet().stream()
                .map(entry -> entry.getKey() + "=" + entry.getValue())
                .collect(Collectors.joining("&", "?", ""));
        return path + queryString;
    }

    // 生成签名
    public static String generateSignature(String timestamp, String method, String requestPath) throws Exception {
        String signString = timestamp + method + requestPath;
        return hmacSHA256(signString, API_SECRET);
    }

    // 使用 HMAC-SHA256 算法生成签名
    public static String hmacSHA256(String data, String secret) throws Exception {
        Mac sha256Hmac = Mac.getInstance("HmacSHA256");
        SecretKeySpec secretKey = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
        sha256Hmac.init(secretKey);
        byte[] hash = sha256Hmac.doFinal(data.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(hash);
    }

    // 创建 HTTP 请求，支持 GET, POST, PUT, DELETE
    public static HttpRequest createRequest(String url, String method, String timestamp, String signature) {
        HttpRequest.Builder requestBuilder = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .header("Content-Type", "application/json")
                .header("CF-ACCESS-KEY", API_KEY)
                .header("CF-ACCESS-SIGN", signature)
                .header("CF-ACCESS-TIMESTAMP", timestamp);

        switch (method.toUpperCase()) {
            case "POST":
                requestBuilder.POST(HttpRequest.BodyPublishers.noBody());
                break;
            case "PUT":
                requestBuilder.PUT(HttpRequest.BodyPublishers.noBody());
                break;
            case "DELETE":
                requestBuilder.DELETE();
                break;
            case "GET":
                requestBuilder.GET();
                break;
            default:
                throw new UnsupportedOperationException("Unsupported HTTP method: " + method);
        }

        return requestBuilder.build();
    }
}
```

### **代码解析**

1. **`method` 变量**：\
   在 `main` 函数中，使用 `String method = "POST";` 来定义请求方法。这可以根据需要修改为 `"GET"`、`"PUT"` 或 `"DELETE"` 等。
2. **生成当前时间戳**：\
   `generateTimestamp()` 函数使用 `Instant.now().toString()` 获取当前 UTC 时间，并以 ISO 8601 格式返回时间戳。
3. **构建请求路径**：\
   `buildRequestPath()` 函数根据传入的查询参数（`queryParams`）构建完整的 URL 路径，并将查询参数拼接到请求路径后。该函数返回一个带有查询参数的完整路径。
4. **生成签名**：\
   `generateSignature()` 函数将 `timestamp`、`method` 和 `requestPath` 拼接成签名字符串，并通过 `hmacSHA256()` 方法进行加密，使用 API Secret 作为密钥，生成签名。
5. **HMAC-SHA256 加密**：\
   `hmacSHA256()` 函数实现了 HMAC-SHA256 签名算法，用于生成请求的签名。
6. **创建请求**：\
   `createRequest()` 函数根据不同的 HTTP 方法（`GET`、`POST`、`PUT`、`DELETE`）动态构建 HTTP 请求。如果是 `POST` 或 `PUT` 请求，使用 `HttpRequest.BodyPublishers.noBody()`，如果是 `DELETE` 或 `GET` 请求，则使用对应的 `DELETE()` 和 `GET()` 方法。
7. **发送请求并获取响应**：\
   使用 `HttpClient` 发送 HTTP 请求，并通过 `HttpResponse.BodyHandlers.ofString()` 获取响应内容。
8. **错误处理**：\
   示例代码中通过 `if (response.statusCode() != 200)` 判断响应状态码，如果响应失败，打印错误信息。

### **注意事项**

* **API Key 和 Secret**：\
  请确保将 `API_KEY` 和 `API_SECRET` 替换为您从 CatFee.IO 获取的实际值。
* **签名的作用**：\
  签名用于验证请求的合法性，确保请求未被篡改。签名是通过将 `timestamp`、`HTTP 方法`、`请求路径` 和 `查询字符串` 拼接在一起计算得到的。
* **查询参数的顺序**：\
  查询参数应按照原始顺序传递，不需要特别排序。
* **请求的 HTTP 方法**：\
  当前示例支持 `POST`、`PUT`、`GET` 和 `DELETE` 方法，查询参数仍然通过 URL 中传递。
* **响应处理**：\
  示例中直接打印响应内容。如果需要进一步处理响应数据，可以将其解析为 JSON 或其他格式。

### **总结**

此示例展示了如何在 Java 中使用 CatFee.IO Rest API 进行安全的 API 调用。通过使用 HMAC-SHA256 签名和正确的查询参数处理，确保请求的有效性和安全性。您可以根据需要调整代码，进行不同的操作，支持 `GET`、`POST`、`PUT` 和 `DELETE` 方法。

如有任何问题或需要进一步的帮助，欢迎联系 CatFee.IO 支持团队！
