【问题标题】:How to authenticate Bitstamp HTTP API v2 request?如何验证 Bitstamp HTTP API v2 请求?
【发布时间】:2017-11-03 16:25:10
【问题描述】:

我正在尝试下订单:https://www.bitstamp.net/api/v2/sell/btceur/?key=xxxxxxxx&signature=BA3CBF267C54965441207FAD25AD7C1C4B9110CE49BA7F2752F7DA79828BF5A1&nonce=1509725707&amount=0.002&price=6267.0

我收到了 403 Forbidden 代码和这条 JSON 消息:

{
    "status": "error", 
    "reason": "Missing key, signature and nonce parameters.", 
    "code"  : "API0000"
}

我正在使用 C# 进行开发,但也使用 Postman 手动尝试并得到了相同的结果。

对于签名计算,我使用了类似帖子中的代码:

#region Methods

private string GetSignature(string customerId, string publicApiKey, string privateApiKey, Int32 nonce)
{
    string msg = string.Format("{0}{1}{2}", nonce,
        customerId,
        publicApiKey);

    return ByteArrayToString(SignHMACSHA256(privateApiKey, StringToByteArray(msg))).ToUpper();
}

private static byte[] SignHMACSHA256(String key, byte[] data)
{
    HMACSHA256 hashMaker = new HMACSHA256(Encoding.ASCII.GetBytes(key));
    return hashMaker.ComputeHash(data);
}

private static byte[] StringToByteArray(string str)
{
    return System.Text.Encoding.ASCII.GetBytes(str);
}

private static string ByteArrayToString(byte[] hash)
{
    return BitConverter.ToString(hash).Replace("-", "").ToLower();
}

#endregion

如何成功验证请求?

更新: 我对 python 代码的签名生成进行了交叉检查,没关系。还能是什么?

【问题讨论】:

  • 您插入了真正的密钥吗? URL中的key是:xxxxxxxx
  • 是的,我确实插入了一个真实的,我只是在这里掩盖了它
  • 网站经常给出虚假的错误信息,以防止黑客从错误信息中学习。 403 通常是一般错误消息,仅表示出现问题。您可能没有使用 V2。见简介:bitstamp.net/api

标签: c# api authentication httprequest


【解决方案1】:

我目前正在处理同样的问题,尝试在 Qt5 中实现 Bitstamp 客户端。 截至目前,我无法获得与您所写的 403-Error 不同的 JSON-Response,但我假设尝试将参数放在 JSON-Body 中,例如

{
  "key":"<your-key>,
  "signature: "<the-hmac>",
  "nonce": "<your-nonce>"
}

值得一试。

如果您弄清楚导致响应的原因以及解决问题的方法 - 或者至少知道如何进一步调查,我将很高兴获悉。

[编辑:]
我想通了,您需要将 POST-Body 中的参数作为 URL 编码字符串发送,所以通过插入来工作

nonce=nonce&signature=signature&keyapi_key

在正文中。您还需要确保提供正确的Content-Type-Header,在本例中为application/x-www-form-urlencoded

在 QT5 中,我设法做到了:

QNetworkAccessManager *manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply*)),
        this, SLOT(onFinished(QNetworkReply*)));

QNetworkRequest request;
request.setUrl(QUrl("https://www.bitstamp.net/api/v2/balance/"));
request.setRawHeader("User-Agent", "Kassiopeia 0.0.0");
request.setRawHeader("Accept", "application/json");
request.setRawHeader("Content-Type", "application/x-www-form-urlencoded");

uint nonce = QDateTime::currentMSecsSinceEpoch();
QByteArray signature = this->hmacSha256(m_customer_id, m_api_key, m_api_secret, nonce);
QByteArray body = "nonce="+QString::number(nonce).toUtf8()+"&signature="+signature+"&key="+m_api_key.toUtf8();

qDebug() << "Request Nonce: " << nonce;
qDebug() << "Request Body:  " << body;

reply = manager->post(request, body);
connect(reply, SIGNAL(readyRead()),
        this, SLOT(onReadReady()));
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
        this, SLOT(onError(QNetworkReply::NetworkError)));
connect(reply, SIGNAL(sslErrors(QList<QSslError>)),
        this, SLOT(onSslErrors(QList<QSslError>)));

如果有人需要它们,这些是插槽:

void Exchange::onError(QNetworkReply::NetworkError error)
{
    qDebug() << "Network Error: " << error;
}

void Exchange::onSslErrors(const QList<QSslError> &errors)
{
    QString errorString;
    foreach (const QSslError &error, errors) {
        if (!errorString.isEmpty())
            errorString += '\n';
        errorString += error.errorString();
    }

    qDebug() << "SSL Error: " << errorString;
}

void Exchange::onFinished(QNetworkReply *reply)
{
    qDebug() << "Finished Request.";
}

void Exchange::onReadReady()
{
    QString strReply = (QString) reply->readAll();
    QJsonDocument jsonReply = QJsonDocument::fromJson(strReply.toUtf8());
    qDebug() << "Read: " << jsonReply.object();
}

【讨论】:

    猜你喜欢
    • 2018-03-12
    • 1970-01-01
    • 2020-04-30
    • 1970-01-01
    • 2014-09-29
    • 2021-09-14
    • 1970-01-01
    • 2022-10-18
    • 1970-01-01
    相关资源
    最近更新 更多