[英]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 的問題,但我的應用程序中的其他功能沒有引起問題。 只有這一張有簽名。
盡管我使用了依賴項,但我認為這仍然是一個完整的有效解決方案。
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.