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

# Java调用Mefree.NET API

本指南详细介绍如何使用 **Java** 实现对 Mefree.NET API 的调用，包括生成签名的方法、构建 HTTP 请求以及完整的调用流程。

***

#### **1. 签名规则概述**

Mefree.NET API 使用签名机制对请求进行身份验证。以下是签名的详细规则：

**1.1 签名字符串规则**

签名生成的格式如下：

```
sign = timestamp + method + requestPath
```

* **timestamp**：UTC 时间，格式为 ISO 8601，例如：`2024-11-26T12:34:56.789Z`。
* **method**：HTTP 方法，例如 `GET` 或 `POST`。
* **requestPath**：API 请求路径（包括查询参数），例如：
  * `/api/config`
  * `/api/order?quantity=65000&target_address=TRON_ADDRESS&period=1`

**1.2 签名生成流程**

1. 拼接签名字符串，格式为 `timestamp + method + requestPath`。
2. 使用 **HMAC-SHA256** 算法，用 API 的 **Secret Key** 对拼接的字符串进行加密。
3. 对加密结果进行 **Base64** 编码，生成最终的签名。

**1.3 请求头参数**

每次请求需要包含以下 HTTP 头：

* `Content-Type: application/json`
* `MF-ACCESS-KEY`: 您的 API Key。
* `MF-ACCESS-SIGN`: 生成的签名值。
* `MF-ACCESS-TIMESTAMP`: 当前的 UTC 时间戳。

***

#### **2. Java实现签名方法**

**2.1 签名生成函数**

以下代码展示了如何用 Java 生成 API 的签名：

```java
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class MefreeApiUtils {
    /**
     * 生成 Mefree API 的签名
     * @param timestamp UTC 时间戳 (ISO 8601 格式)
     * @param method HTTP 方法 (GET/POST)
     * @param requestPath API 请求路径（含参数）
     * @param secretKey API 的 Secret Key
     * @return 签名字符串 (Base64 编码)
     * @throws Exception
     */
    public static String generateSignature(String timestamp, String method, String requestPath, String secretKey) throws Exception {
        // 拼接待签名字符串
        String stringToSign = timestamp + method + requestPath;

        // 使用 HMAC-SHA256 生成签名
        Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
        SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes("UTF-8"), "HmacSHA256");
        sha256_HMAC.init(secretKeySpec);

        // 加密并进行 Base64 编码
        byte[] hash = sha256_HMAC.doFinal(stringToSign.getBytes("UTF-8"));
        return Base64.getEncoder().encodeToString(hash);
    }
}
```

***

#### **3. API 请求构建**

**3.1 基础配置**

在 Java 项目中，定义以下常量用于配置 API 的基础信息：

```java
// Mefree API 配置信息
public class Config {
    public static final String BASE_URL = "https://api.mefree.net"; // Mefree API 基础地址
    public static final String API_KEY = "your_api_key";       // 替换为实际的 API Key
    public static final String SECRET_KEY = "your_secret_key"; // 替换为实际的 Secret Key
}
```

**3.2 通用请求方法**

使用 **HttpURLConnection** 构建通用的 HTTP 请求方法：

```java
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class HttpRequestUtil {
    /**
     * 发起 API 请求
     * @param method HTTP 方法 (GET/POST)
     * @param requestPath API 请求路径（含参数）
     * @param apiKey API Key
     * @param secretKey Secret Key
     * @return 响应内容
     * @throws Exception
     */
    public static String sendRequest(String method, String requestPath, String apiKey, String secretKey) throws Exception {
        // 当前 UTC 时间戳
        String timestamp = java.time.Instant.now().toString();

        // 生成签名
        String signature = MefreeApiUtils.generateSignature(timestamp, method, requestPath, secretKey);

        // 构造 URL
        URL url = new URL(Config.BASE_URL + requestPath);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();

        // 设置请求方法和头信息
        conn.setRequestMethod(method);
        conn.setRequestProperty("Content-Type", "application/json");
        conn.setRequestProperty("MF-ACCESS-KEY", apiKey);
        conn.setRequestProperty("MF-ACCESS-SIGN", signature);
        conn.setRequestProperty("MF-ACCESS-TIMESTAMP", timestamp);


        // 读取响应
        int responseCode = conn.getResponseCode();
        BufferedReader br = new BufferedReader(new InputStreamReader(
                (responseCode < 400) ? conn.getInputStream() : conn.getErrorStream()
        ));

        StringBuilder response = new StringBuilder();
        String line;
        while ((line = br.readLine()) != null) {
            response.append(line);
        }
        br.close();

        return response.toString();
    }
}
```

***

#### **4. 示例接口调用**

**4.1 获取账户信息**

**接口描述**：

* 请求路径：`/api/config`
* HTTP 方法：`GET`

**调用代码**：

```java
public class Main {
    public static void main(String[] args) {
        try {
            String response = HttpRequestUtil.sendRequest("GET", "/api/config", Config.API_KEY, Config.SECRET_KEY);
            System.out.println("账户信息: " + response);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
```

***

**4.2 创建订单**

**接口描述**：

* 请求路径：`/api/order?quantity=65000&target_address=TRON_ADDRESS&period=1`
* HTTP 方法：`POST`

**调用代码**：

```java
public class Main {
    public static void main(String[] args) {
        try {
            String requestPath = "/api/order?quantity=65000&target_address=TRON_ADDRESS&period=1";
            String response = HttpRequestUtil.sendRequest("POST", requestPath, Config.API_KEY, Config.SECRET_KEY);
            System.out.println("订单已创建: " + response);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
```

***

**4.3 查询订单状态**

**接口描述**：

* 请求路径：`/api/order/{pay_hash}`
* HTTP 方法：`GET`

**调用代码**：

```java
public class Main {
    public static void main(String[] args) {
        try {
            String payHash = "abcd1234"; // 替换为实际的 pay_hash
            String requestPath = "/api/order/" + payHash;
            String response = HttpRequestUtil.sendRequest("GET", requestPath, Config.API_KEY, Config.SECRET_KEY);
            System.out.println("订单状态: " + response);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
```

***

#### **5. 常见问题**

**5.1 签名无效 (401 Unauthorized)**

* 确认 `MF-ACCESS-KEY` 是否正确。
* 确保签名按照规则生成：
  * 拼接顺序为：`timestamp + method + requestPath`。
  * 时间戳格式是否为 UTC。
  * 使用正确的 `SECRET_KEY`。

**5.2 请求参数错误 (400 Bad Request)**

* 检查请求路径是否正确，尤其是查询参数是否完整。
* 确认 `Content-Type` 是否为 `application/json`。

**5.3 请求频率限制 (429 Too Many Requests)**

* 添加合理的请求间隔（例如每秒最多 2 次请求）。

***

#### **6. 总结**

通过本指南，您可以使用 Java 实现对 Mefree.NET API 的调用，包括生成签名、发送请求和解析响应数据。对重要的操作（如订单创建）建议添加重试机制，确保请求可靠性。如遇问题，请联系 Mefree 官方支持团队。
