c++ Kraken API:400使用Boost.Beast发出AddOrder请求时请求错误

dgsult0t  于 2022-12-30  发布在  其他
关注(0)|答案(1)|浏览(138)

我正在尝试使用C++中的Boost.Beast向Kraken API的AddOrder端点发出请求。
这是我尝试访问的终结点:https://docs.kraken.com/rest/#tag/User-Trading/operation/addOrder
我正在对请求体进行编码并将其传递给req_.body()方法,但仍然收到400 Bad Request错误。
下面是我传递的请求正文和编码后的请求正文:
请求正文:

nonce=1419646086&ordertype=limit&pair=XBTUSD&price=25000.000000&type=buy&volume=1.000000

传递给req_.body()的编码请求正文:

nonce%3D1419646086%26ordertype%3Dlimit%26pair%3DXBTUSD%26price%3D25000.000000%26type%3Dbuy%26volume%3D1.000000

url.string()输出正确的端点:

https://api.kraken.com/0/private/AddOrder

下面是原始请求和响应:

raw request:
POST /0/private/AddOrder HTTP/1.1
API-Sign: vMP6JwOHe4nA+hnOfDSMEOUmMmZ2UK9RCk9gpRfYOONXhxZW2/QUrDslZCELJo9/cNJlVyBvC4texDk49fwE6g==
Host: api.kraken.com
User-Agent: Boost.Beast/330
API-Key: Skz2FPOvhvvYrOHi6qMEqmmz

回复:

raw response : HTTP/1.1 400 Bad Request
Server: cloudflare
Date: Tue, 27 Dec 2022 17:25:24 GMT
Content-Type: text/html
Content-Length: 155
Connection: close
CF-RAY: -

<html>
<head><title>400 Bad Request</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<hr><center>cloudflare</center>
</body>
</html>

正如您所看到的,我已经包含了所有必要的头,并正确地签署了邮件(我已经在 Postman 验证了它,它的工作)。
这是我使用boost.beast中提供的示例编写的代码:https://gist.github.com/Naseefabu/0f2315ec9727c3e0821ff941a5b370ce

6psbrbz9

6psbrbz91#

我只是在处理代码中的一些问题。你的nonce生成一个字符串,然后你将其转换为long,但是存储在一个int32变量中。然后再将其转换回字符串。我会通过使用

long generate_nonce() {
    return std::chrono::system_clock::now().time_since_epoch() / 1ms;
}

请注意这是多么简单和高效,也是多么正确,正如你所看到的int32致命地破坏了这个值:http://coliru.stacked-crooked.com/a/ce30cbd6ec5b089e
这只是我看到的第一件事,从这里开始它变得更加复杂。我不相信你生成的postdata签名正确:

  • 您使用的std::map会影响排序
  • 您没有使用编码数据-这可能是您应该做的,因为URL存在不同的有效编码,并且服务器可能会在尝试解释这些部分之前首先验证签名**(出于安全原因)。
  • 当建立url时,我更喜欢使用库而不是手工处理字符串
  • 在后数据中我没有看到nonce=部分(也许我在温和的意大利面中忽略了它),但我在这里看到了它

我可能会继续找一点,但这应该让你开始。

更新

我发现了另一个问题:

std::vector<char> sigdigest_b64(2 * sigdigest_len);
EVP_EncodeBlock((unsigned char*)sigdigest_b64.data(), sigdigest, sigdigest_len);

return std::string(sigdigest_b64.data(), sigdigest_b64.size());

长度近似值和忽略的返回值都不能激发信心。

std::string sigdigest_b64(1 + 4 * (1 + sigdigest_len / 3), '\0');
auto        sigdigest_b64_len = EVP_EncodeBlock(
    reinterpret_cast<unsigned char*>(sigdigest_b64.data()), sigdigest, sigdigest_len);
sigdigest_b64.resize(sigdigest_b64_len);

return sigdigest_b64;

或者更好,

// Encode the signature in base64.
return base64_encode({sigdigest, sigdigest_len});

使用一个您甚至不需要自己重新实现的合适的helper函数:

std::string base64_encode(std::basic_string_view<unsigned char> payload) {
    std::string result(1 + 4 * (1 + payload.size() / 3), '\0');
    auto        n = EVP_EncodeBlock(reinterpret_cast<unsigned char*>(result.data()),
                                    payload.data(), payload.size());
    result.resize(n);
    return result;
}

然后,对该实现进行单元测试:)

相关问题