簡體   English   中英

如何使用 Vanilla Javascript 在 Binance API 生成有效簽名:“API 密鑰格式無效。”

[英]How to produce valid signature at Binance API using Vanilla Javascript: "API-key format invalid."

我在這個問題上花了幾個小時。 我嘗試了不同的方法來獲取該簽名,如文檔中所述: https://developers.binance.com/docs/binance-api/spot/index/#signed-trade-user_data-and-margin-endpoint-安全但似乎沒有任何效果。

我嘗試了幾種使用不同庫和函數生成有效簽名的方法,但它們不起作用(甚至Web Crypto API文檔)

撥打電話時出現此錯誤:

{"code":-2014,"msg":"API-key format invalid."}

這是電話:

https://testnet.binance.vision/api/v3/account?timestamp=my_timestamp&signature=my_signature

我猜這是 Fetch 的問題,但我的應用程序中的其他功能沒有引起問題。 只有這一張有簽名。

香草 JS 解決方案

盡管我使用了依賴項,但我認為這仍然是一個完整的有效解決方案。

https://www.npmjs.com/package/jhash.js功能相當簡單直接使用。

問題

問題出在我發送到 hash 函數的 queryString 中。

正如 Binance API 文檔解釋的那樣,雖然含糊不清:

  • 端點使用HMAC SHA256簽名。 HMAC SHA256簽名是鍵控HMAC SHA256操作。 使用您的secretKey作為密鑰,使用totalParams作為 HMAC 操作的值。
  • totalParams定義為與請求正文連接的查詢字符串。

最后一點真的讓我很困惑。

現在,解決方案是將正確的字符串 (queryString) 發送到 sha256 function。 API 需要的是:

https://testnet.binance.vision/api/v3/account?timestamp=my_timestamp&signature=my_signature

timestamp= substring 是我的問題的解決方案。 我不得不將那一小段代碼發送到hex_hmac_sha256 function,這是 Binance API 所需的格式。

完整的解決方案。

async function serverTimestamp() {
    const url = 'https://testnet.binance.vision/api/v3/time';
    const timeServer = await getJson(url);
    return timeServer.serverTime;
}

不是本地時間,但必須在簽名中發送時間服務器。

export async function getAccountInfo() {
    const apiSecret = pub.TESTNET_SECRETKEY; // Your secret key

    const timestamp = await serverTimestamp()
        .then(timestamp => {
            return timestamp;
        });

    const queried_timestamp = 'timestamp=' + timestamp;

    // https://www.npmjs.com/package/jhash.js
    let signature = JHash.hex_hmac_sha256(apiSecret, queried_timestamp);
    // let signature = await sha256(apiSecret, queried_timestamp); // This one is not library dependant.

    const testnet = 'https://testnet.binance.vision/api';

    // {{url}}/api/v3/account?timestamp={{timestamp}}&signature={{signature}}
    const fullUrl = testnet + '/v3/account?timestamp=' + timestamp + '&signature=' + signature; // + '&recvWindow=60000';
    retrieveInformation(fullUrl);
}

請注意,在以下代碼行中,我將 URL 中包含的字符串作為查詢字符串發送。

let signature = JHash.hex_hmac_sha256(apiSecret, queried_timestamp);

這是引導我走向正確方向的示例: https://developers.binance.com/docs/binance-api/spot/index/#example-1-as-a-request-body

如您所見,他們回顯了用於制作簽名的完整 queryString(s)。

現在,其他功能:

async function retrieveInformation(url = null) {
    const apiKey = pub.TESTNET_APIKEY; // Your ApiKey
    let httpHeaders = {
        'Content-Type': 'application/x-www-form-urlencoded',
        'X-MBX-APIKEY': apiKey
    }

    let myHeaders = new Headers(httpHeaders);
    var requestOptions = {
        headers: myHeaders
    };
    console.log(url);
    console.log(requestOptions);
    const data = await getJson(url, requestOptions);
    console.log(data);
    return data;
}

data顯示如下 JSON object:

{
  "makerCommission": 15,
  "takerCommission": 15,
  "buyerCommission": 0,
  "sellerCommission": 0,
  "canTrade": true,
  "canWithdraw": true,
  "canDeposit": true,
  "updateTime": 123456789,
  "accountType": "SPOT",
  "balances": [
    {
      "asset": "BTC",
      "free": "4723846.89208129",
      "locked": "0.00000000"
    },
    {
      "asset": "LTC",
      "free": "4763368.68006011",
      "locked": "0.00000000"
    }
  ],
  "permissions": [
    "SPOT"
  ]
}

您可以在 API Binance 文檔中看到相同的信息: https://developers.binance.com/docs/binance-api/spot/index/#account-information-user_data

使用的其他功能(獎勵哈哈)

最后,這是我使用的fetch function:

async function getJson(url = null, requestOptions = null) {
    return fetch(url, requestOptions)
        .then((response) => {
            if (!response.ok) {
                throw Error(response.statusText);
            } else {
                const jsoned = response.json();
                return jsoned;
                /* NOTE:
                    response.json().then(data => {
                        → do something with your data
                    });
                */
            }
        })
        .catch(function (error) {
            console.log(error);
        });
}

這是我能夠制作的 sha256 function。 它返回的結果與依賴項中的結果相同。

async function sha256_2(key, message) {
    // Step 1
    const msgUint8_key = new TextEncoder().encode(key); // encode as (utf-8) Uint8Array
    const msgUint8_message = new TextEncoder().encode(message); // encode as (utf-8) Uint8Array
    // Step 2
    const importedKey = await crypto.subtle.importKey('raw', msgUint8_key, {
        name: 'HMAC',
        hash: 'SHA-256'
    }, true, ['sign']);
    // Step 3
    const signedKey = await crypto.subtle.sign('HMAC', importedKey, msgUint8_message);
    const hashArray = Array.from(new Uint8Array(signedKey)); // convert buffer to byte array
    const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join(''); // convert bytes to hex string
    return hashHex;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM