调用Coinbase Send Money API返回Cloudflare 400错误(Go实现)
Coinbase Send Money API请求返回Cloudflare 400错误求助
调用Coinbase的Send Money API端点时,请求返回HTML格式的Cloudflare 400错误,而非官方文档中说明的标准JSON错误响应。具体响应内容如下:
<html> <head><title>400 Bad Request</title></head> <body> <center><h1>400 Bad Request</h1></center> <hr><center>cloudflare</center> </body> </html>
已完成以下排查操作:
- 切换不同地区VPN无效,未发现请求头存在异常信息;
- 移除API密钥/秘钥请求头后,可正常返回未认证的JSON格式错误;
- 其他GET类型的API端点能够正常调用;
- 确认API密钥已包含
wallet:transactions:send权限; - 使用主账户和指定账户ID发起请求,均出现相同错误;
- 修改POST请求payload字段顺序(匹配文档或按字母排序),问题依旧存在。
相关Go语言请求代码如下:
var ( cbAPIKey = os.Getenv("CB_API_KEY") cbAPISecret = os.Getenv("CB_API_SECRET") ethAccountID = os.Getenv("CB_ETH_ACCOUNT_ID") version = "2023-04-01" // https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/versioning ) func TestSendEth(t *testing.T) { destination := "..." transaction, err := SendEth(destination, "0.1") assert.Nil(t, err) assert.Equal(t, destination, transaction.To.Address) } type sendPayload struct { Type string `json:"type"` // must be "send" To string `json:"to"` Amount string `json:"amount"` Currency string `json:"currency"` Description *string `json:"description,omitempty"` Idem *string `json:"idem,omitempty"` // For select currencies, destination_tag or memo indicates the beneficiary or destination of a // payment for select currencies. Example: // { "type" : "send", "to": "address", "destination_tag" : "memo", "amount": "", "currency": "" } DestinationTag *string `json:"destination_tag,omitempty"` } func SendEth(to, amount string) (transaction Transaction, err error) { payload := sendPayload{ Type: "send", To: to, Amount: amount, Currency: "ETH", } // serialize payload b, _ := json.Marshal(payload) reader := bytes.NewReader(b) url := fmt.Sprintf(transactionsURL, ethAccountID) req, _ := http.NewRequest("POST", url, reader) req.Header.Set("Content-Type", "application/json") // sign request err = signRequest(req) if err != nil { return } // send request c := http.Client{} response, err := c.Do(req) if err != nil { return } var cbResponse Response[Transaction] responseBytes, _ := ioutil.ReadAll(response.Body) err = json.Unmarshal(responseBytes, &cbResponse) if err != nil { log.Warn(string(responseBytes)) log.WithError(err).Error("Failed to unmarshal response") return } transaction = cbResponse.Data return } // signRequest modifies a http.Request to include the Coinbase-Auth-Signature // headers. You can find more information about these headers here: // https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-key-authentication func signRequest(req *http.Request) (err error) { reqTime := time.Now().Unix() /* The CB-ACCESS-SIGN header is generated by creating a sha256 HMAC using the secret key on the prehash string timestamp + method + requestPath + body (where + represents string concatenation). timestamp is the same as the X-CB-ACCESS-TIMESTAMP header. method should be UPPER CASE. requestPath is the full path and query parameters of the URL, e.g.: /v2/exchange-rates?currency=USD. */ body := "" if req.Body != nil { var bytes []byte bytes, err = ioutil.ReadAll(req.Body) if err != nil { return } body = string(bytes) } message := fmt.Sprintf("%d%s%s%s", reqTime, req.Method, req.URL.Path, body) // generate a sha256 HMAC using the secret key on the prehash string signature := generateHMAC(message, cbAPISecret) req.Header.Set("CB-ACCESS-KEY", cbAPIKey) req.Header.Set("CB-ACCESS-SIGN", signature) req.Header.Set("CB-ACCESS-TIMESTAMP", fmt.Sprintf("%d", reqTime)) req.Header.Set("CB-VERSION", version) return }
原本预期操作有误时能收到明确的错误提示,但现在仅得到模糊的Cloudflare错误,实在找不到问题所在,恳请帮忙排查!
内容的提问来源于stack exchange,提问作者adk992
相关产品推荐
相关产品推荐

