Binance测试网市价订单请求报错AxiosError: 400状态码求助
交易机器人Binance Testnet市价订单400错误排查求助
错误信息
AxiosError: Request failed with status code 400 at settle (C:\Users\mansu\OneDrive\Documentos\Node Projects\Binance\node_modules\axios\dist\node\axios.cjs:2026:12) at IncomingMessage.handleStreamEnd (C:\Users\mansu\OneDrive\Documentos\Node Projects\Binance\node_modules\axios\dist\node\axios.cjs:3142:11) at IncomingMessage.emit (node:events:530:35) at endReadableNT (node:internal/streams/readable:1698:12) at process.processTicksAndRejections (node:internal/process/task_queues:90:21)
核心代码
WebSocket行情监听
const WebSocket = require("ws"); const ws = new WebSocket(`${process.env.STREAM_URL}/${process.env.SYMBOL.toLowerCase()}@ticker`); const PROFITABILITY = parseFloat(process.env.PROFITABILITY); let sellPrice = 0; ws.onmessage = (event) => { const obj = JSON.parse(event.data); console.log("Symbol: "+ obj.s); console.log("Best Ask: "+ obj.a); const currentPrice = parseFloat(obj.a); if(sellPrice == 0 && currentPrice < 96100){ console.log("Bom para comprar"); newOrder("0.001", "BUY"); sellPrice = currentPrice * PROFITABILITY; } else if(sellPrice!== 0 && currentPrice > sellPrice){ console.log("Bom para vender"); newOrder("0.001", "SELL"); sellPrice =0; } else console.log("Esperando...Sell Price: "+ sellPrice); }
下单请求函数
const axios = require('axios'); const crypto = require('crypto'); async function newOrder(quantity, side){ const data = { symbol: process.env.SYMBOL, type: 'MARKET', side, quantity }; const timestamp = Date.now(); const recvWindow = 10000; const signature = crypto .createHmac('sha256', process.env.SECRET_KEY) .update(`${new URLSearchParams({...data, timestamp, recvWindow})}`) .digest('hex'); const newData = { ...data, timestamp, recvWindow, signature }; const qs = `?${new URLSearchParams(newData)}`; try{ const result = await axios({ method: 'POST', url: `${process.env.API_URL}/v3/order${qs}`, headers: {'X-MBX-APIKEY': process.env.API_KEY } }) console.log(result.data); } catch(err){ console.error(err); } }
环境变量配置
API_URL=https://testnet.binance.vision/api API_KEY=MY_API_KEY SECRET_KEY=MY_SECRET_KEY STREAM_URL=wss://stream.testnet.binance.vision/ws SYMBOL=BTCUSDT PROFITABILITY=1.1
已尝试的排查步骤
- 检查API密钥和密钥,确认正确且权限充足;
- 尝试将quantity转换为字符串,问题仍存在;
- 确认签名通过HMAC SHA256和密钥正确生成;
- 对照Binance API文档,参数结构符合要求;
- 清理.env文件值中的空格并重新加载环境变量。
可行排查/解决建议
获取详细错误信息:修改catch块代码,打印
err.response.data,Binance的400错误会返回具体错误码和描述(比如LOT_SIZE过滤失败、余额不足等),这是定位问题的关键:catch(err){ console.error(err.response?.data || err); }检查订单数量精度与账户余额:Binance对BTCUSDT的MARKET订单最小下单数量为0.0001 BTC,你当前使用的0.001符合要求,但需确认测试账户是否有足够的对应资产(买单需要USDT,卖单需要BTC)。
验证时间同步:Binance API要求请求的
timestamp与服务器时间差不能超过recvWindow(你设置的10秒),可先请求Binance服务器时间接口,对比本地时间是否偏差过大:async function checkServerTime() { const res = await axios.get(`${process.env.API_URL}/v3/time`); console.log("服务器时间:", res.data.serverTime); console.log("本地时间:", Date.now()); console.log("时间差:", Math.abs(res.data.serverTime - Date.now()) + "ms"); } checkServerTime();确认签名生成逻辑:手动拼接参数字符串对比:将
data、timestamp、recvWindow按ASCII键名排序后拼接成symbol=BTCUSDT&type=MARKET&side=BUY&quantity=0.001×tamp=xxx&recvWindow=10000,再用HMAC SHA256加密,对比代码生成的签名是否一致。调整请求参数传递方式:Binance的POST订单接口支持将参数放在请求体(
application/x-www-form-urlencoded格式),而非URL查询字符串,可尝试修改代码:async function newOrder(quantity, side){ const data = { symbol: process.env.SYMBOL, type: 'MARKET', side, quantity, timestamp: Date.now(), recvWindow: 10000 }; const signature = crypto .createHmac('sha256', process.env.SECRET_KEY) .update(new URLSearchParams(data).toString()) .digest('hex'); data.signature = signature; try{ const result = await axios({ method: 'POST', url: `${process.env.API_URL}/v3/order`, headers: { 'X-MBX-APIKEY': process.env.API_KEY, 'Content-Type': 'application/x-www-form-urlencoded' }, data: new URLSearchParams(data) }) console.log(result.data); } catch(err){ console.error(err.response?.data || err); } }
内容的提问来源于stack exchange,提问作者reimannsur
相关产品推荐
相关产品推荐

