WebSocket API基本信息
- 接口需要用户的 API Key,如何创建API-KEY请参考这里
- Base url为:wss://api.binance.com/sapi/wss
- 每个到 base URL 的链接有效期不超过24小时,请妥善处理断线重连。
- WebSocket 客户端建议每30秒主动发送 PING 消息。
- 如果 WebSocket 服务器没有在一分钟之内收到 PING 消息,连接会被断开。
- 对于这些 PING 消息,建议payload为空。
- 必须通过获取除签名之外的所有请求参数并按字母顺序按名称排序来生成签名payload
- 除非另有说明,否则所有时间戳均以 UTC 中的毫秒为单位。
- 除非另有说明,否则所有字段名称和值均区分大小写。
WEB SOCKET 连接限制
- Websocket服务器每秒最多接受5个消息。消息包括:
- PING帧
- PONG帧
- JSON格式的消息, 比如订阅, 断开订阅.
- 如果用户发送的消息超过限制,连接会被断开连接。反复被断开连接的IP有可能被服务器屏蔽。
WebSocket API 请求方式
接入地址: wss://api.binance.com/sapi/wss?random={{random}}&topic={{topic}}&recvWindow={{recvWindow}}×tamp={{timestamp}}&signature={{signature}}
其中变量{{xxx}}请替换成相应的值。
- 格式示例:
wss://api.binance.com/sapi/wss?random=56724ac693184379ae23ffe5e910063c&topic=topic1&recvWindow=30000×tamp=1753244327210&signature=341098eff29e3ef395ed4ea85035bd7fe9e9356d2b0d4f1f97655c74516a2d65
- 参数说明:
random
:随机数或字符串,建议长度不超过32,用于保证签名的随机性和有效性。- 例如:
random=56724ac693184379ae23ffe5e910063
- 例如:
topic
:支持订阅一个或多个主题,多个主题用竖线 | 分隔。- 例如:
topic=topic1|topic2
- 例如:
recvWindow
:允许的时间延迟,单位为毫秒,最大不能超过60000。- 例如:
recvWindow=30000
- 例如:
timestamp
:当 前时间戳,单位为毫秒。- 例如:
timestamp=1753244327210
- 例如:
signature
: 当前请求的签名。
WebSocket API 身份验证
建立链接时需要用到用户的 API Key进行身份验证, 需要在wss请求头中以 X-MBX-APIKEY
字段传递。
时间同步安全
- 签名接口均需要传递
timestamp
参数,其值应当是请求发送时刻的unix时间戳(毫秒)。 - 服务器收到请求时会判断请求中的时间戳,如果是5000毫秒之前发出的,则请求会被认为无效。这个时间空窗值可以通过发送可选参数
recvWindow
来定义。
签名
以下是在 linux bash 环境下使用 echo openssl 和 curl 工具实现的一个生成签名的示例
apikey、secret仅供示范
Key | Value |
---|---|
apiKey | vmPUZE6mv9SD5VNHk4HlWFsOr6aKE2zvsw0MuIgwCIPy6utIco14y7Ju91duEh8A |
secretKey | NhqPtmdSJYdKjVHjA7PZj4Mge3R5YNiP1e3UZjInClVN65XAbvqqM6A7H5fATj0j |
需要对接入地址的所有参数计算签名: random={{random}}&topic={{topic}}&recvWindow={{recvWindow}}×tamp={{timestamp}}
示例
HMAC SHA256 signature:
$ echo -n "random=56724ac693184379ae23ffe5e910063c&topic=topic1&recvWindow=30000×tamp=1753244327210" | openssl dgst -sha256 -hmac "Avqz4IQjoZSJOowMFSo3QZEd4ovfwLH7Kie8ZliTtP8ktDnqcX8bpCP7WluFtrfn"
SHA2-256(stdin)= 8346d214e0da7165a0093043395f67e08c63f61b5d6e25779d513c11450e691b
实时订阅/取消订阅
在连接之后, 可以继续通过websocket发送以实现订阅或取消订阅频道(支持同时操作多个频道, 以|分隔)。示例如下。
订阅
请求
{
"command": "SUBSCRIBE",
"value": "topic1"
}
响应
{
"type": "COMMAND",
"data": "SUCCESS",
"subType": "SUBSCRIBE",
"code": "00000000"
}
取消订阅
请求
{
"command": "UNSUBSCRIBE",
"value": "topic1"
}
响应
{
"type": "COMMAND",
"data": "SUCCESS",
"subType": "UNSUBSCRIBE",
"code": "00000000"
}
接入代码示例
JS 脚本
const WebSocket = require('ws');
const CryptoJS = require('crypto-js');
const uri = 'wss://api.binance.com/sapi/wss?random=56724ac693184379ae23ffe5e910063c&topic=topic1&recvWindow=30000×tamp=${timestamp}&signature=${signature}';
const binance_api_key = "替换成您的 API Key";
const binance_api_secret = "加载您的 Secret Key"; // 加载 private key。private key 建议使用强密码以提高安全性。
const ts = Date.now();
let paramsObject = {};
const queryString = uri.substring(uri.indexOf('?') + 1);
const parameters = queryString.split('&')
.filter(param => param.includes('='))
.map(param => {
const [key, value] = param.split('=');
return {key, value};
});
parameters.map((param) => {
if (param.key !== 'signature' &&
param.key !== 'timestamp') {
paramsObject[param.key] = param.value;
}
})
Object.assign(paramsObject, {'timestamp': ts});
const tmp = Object.keys(paramsObject).map((key) => {
return `${key}=${paramsObject[key]}`;
}).join('&');
const signature = CryptoJS.HmacSHA256(tmp, binance_api_secret).toString();
Object.assign(paramsObject, {'signature': signature});
const result = Object.keys(paramsObject).map((key) => {
return `${key}=${paramsObject[key]}`;
}).join('&');
const baseUri = uri.substring(0, uri.indexOf("?"))
console.log("final uri: " + baseUri + '?' + result)
const ws = new WebSocket(baseUri + '?' + result, [], {
headers: {
"X-MBX-APIKEY": binance_api_key
}
});
ws.on('open', function open() {
console.log('Connected to the server');
});
ws.on('message', function incoming(data) {
console.log(`Data from server: ${data}`);
});
ws.on('close', function close() {
console.log('Disconnected from server');
});
ws.on('error', function error(err) {
console.error(`Error: ${err.message}`);
});
// TODO setup your ping and reconnect logic