# Go 调用示例

### **前提条件**

1. [您需要一个有效的 API Key 和 API Secret](/getting-started/buy-energy-via-api-on-catfee/api-overview.md#apply-api-info)。
2. 请确保您的 Go 环境已经安装了 `net/http` 和 `crypto/hmac` 等标准库。

### **示例代码**

```go
package main

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/base64"
	"fmt"
	"net/http"
	"net/url"
	"time"
	"io/ioutil"
	"log"
)

const (
	APIKey    = "your_api_key"       // 请替换为您的API Key
	APISecret = "your_api_secret"    // 请替换为您的API Secret
	BaseURL   = "https://api.catfee.io"
)

// 生成当前的时间戳（ISO 8601格式）
func generateTimestamp() string {
	return time.Now().UTC().Format("2006-01-02T15:04:05.000Z")
}

// 构建请求路径，包括查询参数
func buildRequestPath(path string, queryParams map[string]string) string {
	if len(queryParams) == 0 {
		return path
	}

	queryString := "?"
	for key, value := range queryParams {
		queryString += fmt.Sprintf("%s=%s&", key, value)
	}

	// 去掉最后的"&"符号
	queryString = queryString[:len(queryString)-1]

	return path + queryString
}

// 使用 HMAC-SHA256 算法生成签名
func generateSignature(timestamp, method, requestPath string) string {
	signString := timestamp + method + requestPath
	mac := hmac.New(sha256.New, []byte(APISecret))
	mac.Write([]byte(signString))
	signature := mac.Sum(nil)
	return base64.StdEncoding.EncodeToString(signature)
}

// 创建 HTTP 请求
func createRequest(url, method, timestamp, signature string) (*http.Response, error) {
	client := &http.Client{}
	req, err := http.NewRequest(method, url, nil)
	if err != nil {
		return nil, err
	}

	// 设置请求头
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("CF-ACCESS-KEY", APIKey)
	req.Header.Add("CF-ACCESS-SIGN", signature)
	req.Header.Add("CF-ACCESS-TIMESTAMP", timestamp)

	return client.Do(req)
}

func main() {
	method := "POST" // 可以修改为 "GET", "PUT", "DELETE"
	path := "/v1/order"

	// 示例：创建订单
	queryParams := map[string]string{
		"quantity": "65000",
		"receiver": "TRON_ADDRESS",
		"duration": "1h",
	}

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

	// 创建请求 URL
	url := BaseURL + requestPath

	// 发送请求
	resp, err := createRequest(url, method, timestamp, signature)
	if err != nil {
		log.Fatal("Error making request:", err)
	}

	// 读取并输出响应
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatal("Error reading response:", err)
	}

	// 打印响应数据
	fmt.Println("Response Status:", resp.Status)
	fmt.Println("Response Body:", string(body))
}
```

### **代码解析**

1. **`generateTimestamp()`**：\
   使用 `time.Now().UTC().Format("2006-01-02T15:04:05.000Z")` 获取当前 UTC 时间，并格式化为 ISO 8601 时间戳。
2. **`buildRequestPath()`**：\
   该函数将传入的查询参数（`queryParams`）构建成 URL 查询字符串。每个查询参数用 `&` 连接，最后返回完整的请求路径。
3. **`generateSignature()`**：\
   通过 `timestamp`、`method` 和 `requestPath` 拼接生成签名字符串，然后使用 HMAC-SHA256 算法进行签名，并将结果进行 Base64 编码。最终返回签名。
4. **`createRequest()`**：\
   创建一个 HTTP 请求，使用 `http.NewRequest()` 创建请求对象，并通过 `req.Header.Add()` 添加必要的请求头，包括 `CF-ACCESS-KEY`、`CF-ACCESS-SIGN` 和 `CF-ACCESS-TIMESTAMP`。然后，发送请求并返回响应。
5. **`main()`**：\
   在 `main()` 函数中，设置请求方法为 `POST`，并传入需要的查询参数。调用 `generateTimestamp()`、`buildRequestPath()` 和 `generateSignature()` 来生成请求头信息。最后，使用 `createRequest()` 发送请求并打印响应内容。

### **注意事项**

* **API Key 和 Secret**：\
  请确保将 `APIKey` 和 `APISecret` 替换为您从 CatFee.IO 获取的实际值。
* **查询参数的顺序**：\
  本示例中，我们直接将查询参数拼接到请求路径中，并没有排序查询参数。如果需要对查询参数排序，请使用适当的排序方法。
* **响应处理**：\
  响应通过 `ioutil.ReadAll()` 读取并打印。如果响应体为 JSON 格式，您可以使用 `encoding/json` 库来解析 JSON 数据。
* **请求方法**：\
  当前示例支持 `POST`、`GET`、`PUT` 和 `DELETE` 方法，您可以根据实际需求修改请求方法。

### **总结**

这个示例展示了如何在 Go 中使用 CatFee.IO Rest API，通过 HMAC-SHA256 签名验证来确保请求的安全性。您可以根据实际需求修改代码，支持不同的 HTTP 方法（`GET`、`POST`、`PUT`、`DELETE`），并处理不同的 API 响应。


---

# 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/go.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.
