跳到主要内容

基本信息

API 基本信息

HTTP 返回代码

  • HTTP 4XX 错误码用于指示错误的请求内容、行为、格式。问题在于请求者。
  • HTTP 403 错误码表示违反WAF限制(Web应用程序防火墙)。
  • HTTP 409 错误码表示重新下单(cancelReplace)的请求部分成功。(比如取消订单失败,但是下单成功了)
  • HTTP 429 错误码表示警告访问频次超限,即将被封IP。
  • HTTP 418 表示收到429后继续访问,于是被封了。
  • HTTP 5XX 错误码用于指示Binance服务侧的问题。

接口错误代码

  • 使用接口 /api/v3, 以及 /sapi/v1/margin时, 每个接口都有可能抛出异常;

API 与 SAPI 的错误代码返回形式如下:

{
"code": -1121,
"msg": "Invalid symbol."
}

接口的基本信息

  • GET 方法的接口, 参数必须在 query string中发送。
  • POST, PUT, 和 DELETE 方法的接口,参数可以在内容形式为application/x-www-form-urlencodedquery string 中发送,也可以在 request body 中发送。 如果你喜欢,也可以混合这两种方式发送参数。
  • 对参数的顺序不做要求。
  • 但如果同一个参数名在query string和request body中都有,query string中的会被优先采用。

访问限制

访问限制基本信息

  • 以下 是intervalLetter 作为头部值:

    • SECOND => S
    • MINUTE => M
    • HOUR => H
    • DAY => D
  • /api/v3/exchangeInfo rateLimits 数组中包含与交易的有关RAW_REQUESTS,REQUEST_WEIGHT和ORDERS速率限制相关的对象。这些在 限制种类 (rateLimitType) 下的 枚举定义 部分中进一步定义。

  • 违反任何一个速率限制时(访问频次限制或下单速率限制),将返回429。

IP 访问限制

  • 每个请求将包含一个X-MBX-USED-WEIGHT-(intervalNum)(intervalLetter)的头,其中包含当前IP所有请求的已使用权重。
  • 每一个接口均有一个相应的权重(weight),有的接口根据参数不同可能拥有不同的权重。越消耗资源的接口权重就会越大。
  • 收到429时,您有责任停止发送请求,不得滥用API。
  • 收到429后仍然继续违反访问限制,会被封禁IP,并收到418错误码
  • 频繁违反限制,封禁时间会逐渐延长,从最短2分钟到最长3天
  • Retry-After的头会与带有418或429的响应发送,并且会给出以秒为单位的等待时长(如果是429)以防止禁令,或者如果是418,直到禁令结束。
  • 访问限制是基于IP的,而不是API Key

###下单频率限制

  • 每个成功的下单回报将包含一个X-MBX-ORDER-COUNT-(intervalNum)(intervalLetter)的头,其中包含当前账户已用的下单限制数量。
  • 当下单数超过限制时,会收到带有429但不含Retry-After头的响应。请检查 GET api/v3/exchangeInfo 的下单频率限制 (rateLimitType = ORDERS) 并等待封禁时间结束。
  • 被拒绝或不成功的下单并不保证回报中包含以上头内容。
  • 下单频率限制是基于每个账户计数的。
  • 用户可以通过接口 GET api/v3/rateLimit/order 来查询当前的下单量.

WEB SOCKET 连接限制

  • Websocket服务器每秒最多接受5个消息。消息包括:
    • PING帧
    • PONG帧
    • JSON格式的消息, 比如订阅, 断开订阅.
  • 如果用户发送的消息超过限制,连接会被断开连接。反复被断开连接的IP有可能被服务器屏蔽。
  • 单个连接最多可以订阅 1024 个Streams。
  • 每IP地址、每5分钟最多可以发送300次连接请求。

/api/ 与 /sapi/ 接口限频说明

/api/*接口和 /sapi/*接口采用两套不同的访问限频规则, 两者互相独立。

  • /api/*的接口相关:

    • 按IP和按UID(account)两种模式分别统计, 两者互相独立。
    • /api/*开头的接口按IP限频,且所有接口共用每分钟6,000限制
    • 每个请求将包含一个 X-MBX-USED-WEIGHT-(intervalNum)(intervalLetter)的头,包含当前IP所有请求的已使用权重。
    • 每个成功的下单回报将包含一个X-MBX-ORDER-COUNT-(intervalNum)(intervalLetter)的头,其中包含当前账户已用的下单限制数量。
  • /sapi/*的接口相关:

    • 按IP和按UID(account)两种模式分别统计, 两者互相独立。
    • /sapi/*开头的接口采用单接口限频模式。按IP统计的权重单接口权重总额为每分钟12000;按照UID统计的单接口权重总额是每分钟180000。
    • 每个接口会标明是按照IP或者按照UID统计, 以及相应请求一次的权重值。
    • 按照IP统计的接口, 请求返回头里面会包含X-SAPI-USED-IP-WEIGHT-1M=<value>X-SAPI-USED-IP-WEIGHT-1S=<value>, 包含当前IP所有请求已使用权重。
    • 按照UID统计的接口, 请求返回头里面会包含X-SAPI-USED-UID-WEIGHT-1M=<value>X-SAPI-USED-UID-WEIGHT-1S=<value>, 包含当前账户所有已用的UID权重。

数据来源

  • 因为API系统是异步的, 所以返回的数据有延时很正常, 也在预期之中。
  • 在每个接口中,都列出了其数据的来源,可以用于理解数据的时效性。

系统一共有3个数据来源,按照更新速度的先后排序。排在前面的数据最新,在后面就有可能存在延迟。

  • 撮合引擎 - 表示数据来源于撮合引擎
  • 缓存 - 表示数据来源于内部或者外部的缓存
  • 数据库 - 表示数据直接来源于数据库

请求鉴权类型

  • 每个接口都有一个鉴权类型,指示所需的 API 密钥权限,显示在接口名称旁边(例如,下新订单 (TRADE))。
  • 如果未指定,则鉴权类型为 NONE
  • 除了为 NONE 外,所有具有鉴权类型的接口均视为 SIGNED 请求(即包含 signature),listenKey 管理 除外。
  • 具有鉴权类型的接口需要提供有效的 API 密钥并验证通过。
    • API 密钥可在您的 Binance 账户的 API 管理 页面创建。
    • API 密钥和密钥对均为敏感信息,切勿与他人分享。 如果发现账户有异常活动,请立即撤销所有密钥并联系 Binance 支持。
  • API 密钥可配置为仅允许访问某些鉴权接口。
    • 例如,您可以拥有具有 TRADE 权限的 API 密钥用于交易, 同时使用具有 USER_DATA 权限的另一个 API 密钥来监控订单状态。
    • 默认情况下,API 密钥无法进行 TRADE,您需要先在 API 管理中启用交易权限。
鉴权类型描述
NONE不需要鉴权的接口
TRADE需要有效的 API-Key 和签名
MARGIN需要有效的 API-Key 和签名
USER_DATA需要有效的 API-Key 和签名
USER_STREAM需要有效的 API-Key
MARKET_DATA需要有效的 API-Key

需要签名的接口

  • 调用SIGNED 接口时,除了接口本身所需的参数外,还需要在 query stringrequest body 中传递 signature, 即签名参数。

签名是否是大小写敏感的

  • HMAC: 使用 HMAC 生成的签名不区分大小写。这意味着无论字母大小写如何,签名字符串都可以被验证。
  • RSA: 使用 RSA 生成的签名是大小写敏感的
  • Ed25519: 使用 Ed25519 生成的签名也是大小写敏感的

请参阅已签名请求示例 (HMAC)已签名请求示例 (RSA)已签名请求示例 (Ed25519),了解如何根据您使用的 API 密钥类型计算签名。

时间同步安全

  • SIGNED 请求还需要一个 timestamp 参数,该参数应为当前时间戳,单位为毫秒或微秒。(参见 通用 API 信息
  • 另一个可选参数 recvWindow,用以指定请求的有效期,只能以毫秒为单位。
    • recvWindow 扩展为三位小数(例如 6000.346),以便可以指定微秒。
    • 如果未发送 recvWindow,则 默认值为 5000 毫秒
    • recvWindow 的最大值为 60000 毫秒。
  • 请求处理逻辑如下:
serverTime = getCurrentTime()
if (timestamp < (serverTime + 1 second) && (serverTime - timestamp) <= recvWindow) {
// 开始处理请求
serverTime = getCurrentTime()
if (serverTime - timestamp) <= recvWindow {
// 将请求转发到撮合引擎
} else {
// 拒绝请求
}
// 结束处理请求
} else {
// 拒绝请求
}

关于交易时效性 互联网状况并不100%可靠,不可完全依赖,因此你的程序本地到币安服务器的时延会有抖动. 这是我们设置recvWindow的目的所在,如果你从事高频交易,对交易时效性有较高的要求,可以灵活设置recvWindow以达到你的要求。 不推荐使用5秒以上的recvWindow。最大值不能超过60秒!

POST /api/v3/order 的签名示例

HMAC Keys

不使用分隔符,把查询字符串与 HTTP body 连接在一起将生成请求的签名 payload。任何非 ASCII 字符在签名前都必须进行百分比编码(percent-encoded)。

以下示例分步演示如何使用 echoopensslcurl 从 Linux 命令行发送有效的签名 payload。其中一个例子中的交易对名称完全由 ASCII 字符组成,另一个例子中的交易对名称则包含非 ASCII 字符。

API 密钥和密钥示例:

KeyValue
apiKeyvmPUZE6mv9SD5VNHk4HlWFsOr6aKE2zvsw0MuIgwCIPy6utIco14y7Ju91duEh8A
secretKeyNhqPtmdSJYdKjVHjA7PZj4Mge3R5YNiP1e3UZjInClVN65XAbvqqM6A7H5fATj0j

警告:请勿与任何人分享您的 API 密钥和秘钥。

此处提供的示例密钥仅用于示范说明目的。

交易对名称完全由 ASCII 字符组成的请求示例:

参数取值
symbolLTCBTC
sideBUY
typeLIMIT
timeInForceGTC
quantity1
price0.1
recvWindow5000
timestamp1499827319559

交易对名称包含非 ASCII 字符的请求示例:

参数取值
symbol123456
sideBUY
typeLIMIT
timeInForceGTC
quantity1
price0.1
recvWindow5000
timestamp1499827319559

第一步: 构建签名 payload。

  1. 将参数格式化为 参数=取值 对并用 & 分隔每个参数对。
  2. 对字符串进行百分比编码(percent-encoded)。

对于第一组示例参数(仅限 ASCII 字符), parameter=value 字符串将如下所示:

symbol=LTCBTC&side=BUY&type=LIMIT&timeInForce=GTC&quantity=1&price=0.1&recvWindow=5000&timestamp=1499827319559

对字符串进行百分比编码(percent-encoded)后,签名 payload 如下所示:

symbol=LTCBTC&side=BUY&type=LIMIT&timeInForce=GTC&quantity=1&price=0.1&recvWindow=5000&timestamp=1499827319559

对于第二组示例参数(包含一些 Unicode 字符),parameter=value 字符串将如下所示:

symbol=123456&side=BUY&type=LIMIT&timeInForce=GTC&quantity=1&price=0.1&recvWindow=5000&timestamp=1499827319559

对字符串进行百分比编码(percent-encoded)后,签名 payload 如下所示:

symbol=%EF%BC%91%EF%BC%92%EF%BC%93%EF%BC%94%EF%BC%95%EF%BC%96&side=BUY&type=LIMIT&timeInForce=GTC&quantity=1&price=0.1&recvWindow=5000&timestamp=1499827319559

第二步: 计算签名。

  1. 使用 API 密钥中的 secretKey 作为 HMAC-SHA-256 算法的签名密钥。
  2. 对步骤 1 中构建的签名 payload 进行签名。
  3. 将 HMAC-SHA-256 的输出编码为十六进制字符串。

请注意,secretKey 和 payload 是大小写敏感的,而生成的签名值是不区分大小写的。

示例命令

对于第一组示例参数(仅限 ASCII 字符):

$ echo -n "symbol=LTCBTC&side=BUY&type=LIMIT&timeInForce=GTC&quantity=1&price=0.1&recvWindow=5000&timestamp=1499827319559" | openssl dgst -sha256 -hmac "NhqPtmdSJYdKjVHjA7PZj4Mge3R5YNiP1e3UZjInClVN65XAbvqqM6A7H5fATj0j"

c8db56825ae71d6d79447849e617115f4a920fa2acdcab2b053c4b2838bd6b71

对于第二组示例参数(包含一些 Unicode 字符):

$ echo -n "symbol=%EF%BC%91%EF%BC%92%EF%BC%93%EF%BC%94%EF%BC%95%EF%BC%96&side=BUY&type=LIMIT&timeInForce=GTC&quantity=1&price=0.1&recvWindow=5000&timestamp=1499827319559" | openssl dgst -sha256 -hmac "NhqPtmdSJYdKjVHjA7PZj4Mge3R5YNiP1e3UZjInClVN65XAbvqqM6A7H5fATj0j"

e1353ec6b14d888f1164ae9af8228a3dbd508bc82eb867db8ab6046442f33ef3

第三步: 为请求添加签名

通过在查询字符串中添加 signature 参数来完成请求。

对于第一组示例参数(仅限 ASCII 字符):

curl -s -v -H "X-MBX-APIKEY: $apiKey" -X POST "https://api.binance.com/api/v3/order?symbol=LTCBTC&side=BUY&type=LIMIT&timeInForce=GTC&quantity=1&price=0.1&recvWindow=5000&timestamp=1499827319559&signature=c8db56825ae71d6d79447849e617115f4a920fa2acdcab2b053c4b2838bd6b71"

对于第二组示例参数(包含一些 Unicode 字符):

curl -s -v -H "X-MBX-APIKEY: $apiKey" -X POST "https://api.binance.com/api/v3/order?symbol=%EF%BC%91%EF%BC%92%EF%BC%93%EF%BC%94%EF%BC%95%EF%BC%96&side=BUY&type=LIMIT&timeInForce=GTC&quantity=1&price=0.1&recvWindow=5000&timestamp=1499827319559&signature=e1353ec6b14d888f1164ae9af8228a3dbd508bc82eb867db8ab6046442f33ef3"

以下是一个执行上述所有步骤的 Bash 脚本示例:

apiKey="vmPUZE6mv9SD5VNHk4HlWFsOr6aKE2zvsw0MuIgwCIPy6utIco14y7Ju91duEh8A"
secretKey="NhqPtmdSJYdKjVHjA7PZj4Mge3R5YNiP1e3UZjInClVN65XAbvqqM6A7H5fATj0j"

payload="symbol=LTCBTC&side=BUY&type=LIMIT&timeInForce=GTC&quantity=1&price=0.1&recvWindow=5000&timestamp=1499827319559"

# 对请求进行签名

signature=$(echo -n "$payload" | openssl dgst -sha256 -hmac "$secretKey")
signature=${signature#*= } # Keep only the part after the "= "

# 发送请求

curl -H "X-MBX-APIKEY: $apiKey" -X POST "https://api.binance.com/api/v3/order?$payload&signature=$signature"

RSA Keys

不使用分隔符,把查询字符串与 HTTP body 连接在一起将生成请求的签名 payload。任何非 ASCII 字符在签名前都必须进行百分比编码(percent-encoded)。

要获取 API 密钥,您需要将 RSA 公钥上传到您的帐户中,系统将为您提供相应的 API 密钥。

仅支持 PKCS#8 密钥。

在以下示例中,其中一个例子中的交易对名称完全由 ASCII 字符组成,另一个例子中的交易对名称则包含非 ASCII 字符。

这些示例假设私钥存储在文件 ./test-prv-key.pem 中。

KeyValue
apiKeyCAvIjXy3F44yW6Pou5k8Dy1swsYDWJZLeoK2r8G4cFDnE9nosRppc2eKc1T8TRTQ

交易对名称完全由 ASCII 字符组成的请求示例:

参数取值
symbolBTCUSDT
sideSELL
typeLIMIT
timeInForceGTC
quantity1
price0.2
timestamp1668481559918
recvWindow5000

交易对名称包含非 ASCII 字符的请求示例:

参数取值
symbol123456
sideSELL
typeLIMIT
timeInForceGTC
quantity1
price0.2
timestamp1668481559918
recvWindow5000

第一步: 构建签名 payload。

  1. 将参数格式化为 参数=取值 对并用 & 分隔每个参数对。
  2. 对字符串进行百分比编码(percent-encoded)。

对于第一组示例参数(仅限 ASCII 字符), parameter=value 字符串将如下所示:

symbol=BTCUSDT&side=SELL&type=LIMIT&timeInForce=GTC&quantity=1&price=0.2&timestamp=1668481559918&recvWindow=5000

对字符串进行百分比编码(percent-encoded)后,签名 payload 如下所示:

symbol=BTCUSDT&side=SELL&type=LIMIT&timeInForce=GTC&quantity=1&price=0.2&timestamp=1668481559918&recvWindow=5000

对于第二组示例参数(包含一些 Unicode 字符),parameter=value 字符串将如下所示:

symbol=123456=SELL&type=LIMIT&timeInForce=GTC&quantity=1&price=0.2&timestamp=1668481559918&recvWindow=5000

对字符串进行百分比编码(percent-encoded)后,签名 payload 如下所示:

symbol=%EF%BC%91%EF%BC%92%EF%BC%93%EF%BC%94%EF%BC%95%EF%BC%96&side=SELL&type=LIMIT&timeInForce=GTC&quantity=1&price=0.2&timestamp=1668481559918&recvWindow=5000

第二步: 计算签名。

  1. 使用 RSASSA-PKCS1-v1_5 算法和 SHA-256 哈希函数对步骤 1 中构建的签名 payload 进行签名。
  2. 将输出结果编码为 base64 格式。

请注意,payload 和生成的签名值大小写敏感的

对于第一组示例参数(仅限 ASCII 字符):

$  echo -n 'symbol=BTCUSDT&side=SELL&type=LIMIT&timeInForce=GTC&quantity=1&price=0.2&timestamp=1668481559918&recvWindow=5000' | openssl dgst -sha256 -sign ./test-prv-key.pem | openssl enc -base64 -A | tr -d '\n'
HZ8HOjiJ1s/igS9JA+n7+7Ti/ihtkRF5BIWcPIEluJP6tlbFM/Bf44LfZka/iemtahZAZzcO9TnI5uaXh3++lrqtNonCwp6/245UFWkiW1elpgtVAmJPbogcAv6rSlokztAfWk296ZJXzRDYAtzGH0gq7CgSJKfH+XxaCmR0WcvlKjNQnp12/eKXJYO4tDap8UCBLuyxDnR7oJKLHQHJLP0r0EAVOOSIbrFang/1WOq+Jaq4Efc4XpnTgnwlBbWTmhWDR1pvS9iVEzcSYLHT/fNnMRxFc7u+j3qI//5yuGuu14KR0MuQKKCSpViieD+fIti46sxPTsjSemoUKp0oXA==

对于第二组示例参数(包含一些 Unicode 字符):

$  echo -n 'symbol=%EF%BC%91%EF%BC%92%EF%BC%93%EF%BC%94%EF%BC%95%EF%BC%96&side=SELL&type=LIMIT&timeInForce=GTC&quantity=1&price=0.2&timestamp=1668481559918&recvWindow=5000' | openssl dgst -sha256 -sign ./test-prv-key.pem | openssl enc -base64 -A | tr -d '\n'

qJtv66wyp/1mZE+mIFAAMUoTe8xkmLN7/eAZjuC9x1ocxovItHLl/sNK7Wq8QjgiHqGn0bb8P7yVvGBEd1gFe71NQ8aM0M+JNIMz5UFxfeA53rXjFlvsyH1Sig+OuO9Nz5nhCaJ6bEfj2iuv7w27pB3L8MVqmoCi6D9C/QMiLxtPaR70CxtnvoOlIgPmpv2bQy029A31NEK19ieVLkoyp1EUkXRaX3v0mohx8yMnUG1dhX9nUg3Oy8TYZ03DQy7kHDGkMKisNX7rt/GuGx1HIgjFclDGLsbAFIodvSLjm9FbseasMELoxlAJDlwRnW8zo5sQmL0Fz7ao935QBynrng==
  1. 对 base64 格式的字符串进行百分比编码(percent-encoded)。

对于第一组示例参数(仅限 ASCII 字符):

HZ8HOjiJ1s%2FigS9JA%2Bn7%2B7Ti%2FihtkRF5BIWcPIEluJP6tlbFM%2FBf44LfZka%2FiemtahZAZzcO9TnI5uaXh3%2B%2BlrqtNonCwp6%2F245UFWkiW1elpgtVAmJPbogcAv6rSlokztAfWk296ZJXzRDYAtzGH0gq7CgSJKfH%2BXxaCmR0WcvlKjNQnp12%2FeKXJYO4tDap8UCBLuyxDnR7oJKLHQHJLP0r0EAVOOSIbrFang%2F1WOq%2BJaq4Efc4XpnTgnwlBbWTmhWDR1pvS9iVEzcSYLHT%2FfNnMRxFc7u%2Bj3qI%2F%2F5yuGuu14KR0MuQKKCSpViieD%2BfIti46sxPTsjSemoUKp0oXA%3D%3D

对于第二组示例参数(包含一些 Unicode 字符):

qJtv66wyp%2F1mZE%2BmIFAAMUoTe8xkmLN7%2FeAZjuC9x1ocxovItHLl%2FsNK7Wq8QjgiHqGn0bb8P7yVvGBEd1gFe71NQ8aM0M%2BJNIMz5UFxfeA53rXjFlvsyH1Sig%2BOuO9Nz5nhCaJ6bEfj2iuv7w27pB3L8MVqmoCi6D9C%2FQMiLxtPaR70CxtnvoOlIgPmpv2bQy029A31NEK19ieVLkoyp1EUkXRaX3v0mohx8yMnUG1dhX9nUg3Oy8TYZ03DQy7kHDGkMKisNX7rt%2FGuGx1HIgjFclDGLsbAFIodvSLjm9FbseasMELoxlAJDlwRnW8zo5sQmL0Fz7ao935QBynrng%3D%3D

第三步: 为请求添加签名

通过在查询字符串中添加 signature 参数来完成请求。

对于第一组示例参数(仅限 ASCII 字符):

curl -H "X-MBX-APIKEY: CAvIjXy3F44yW6Pou5k8Dy1swsYDWJZLeoK2r8G4cFDnE9nosRppc2eKc1T8TRTQ" -X POST 'https://api.binance.com/api/v3/order?symbol=BTCUSDT&side=SELL&type=LIMIT&timeInForce=GTC&quantity=1&price=0.2&timestamp=1668481559918&recvWindow=5000&signature=HZ8HOjiJ1s%2FigS9JA%2Bn7%2B7Ti%2FihtkRF5BIWcPIEluJP6tlbFM%2FBf44LfZka%2FiemtahZAZzcO9TnI5uaXh3%2B%2BlrqtNonCwp6%2F245UFWkiW1elpgtVAmJPbogcAv6rSlokztAfWk296ZJXzRDYAtzGH0gq7CgSJKfH%2BXxaCmR0WcvlKjNQnp12%2FeKXJYO4tDap8UCBLuyxDnR7oJKLHQHJLP0r0EAVOOSIbrFang%2F1WOq%2BJaq4Efc4XpnTgnwlBbWTmhWDR1pvS9iVEzcSYLHT%2FfNnMRxFc7u%2Bj3qI%2F%2F5yuGuu14KR0MuQKKCSpViieD%2BfIti46sxPTsjSemoUKp0oXA%3D%3D'

对于第二组示例参数(包含一些 Unicode 字符):

curl -H "X-MBX-APIKEY: CAvIjXy3F44yW6Pou5k8Dy1swsYDWJZLeoK2r8G4cFDnE9nosRppc2eKc1T8TRTQ" -X POST 'https://api.binance.com/api/v3/order?symbol=%EF%BC%91%EF%BC%92%EF%BC%93%EF%BC%94%EF%BC%95%EF%BC%96&side=SELL&type=LIMIT&timeInForce=GTC&quantity=1&price=0.2&timestamp=1668481559918&recvWindow=5000&signature=qJtv66wyp%2F1mZE%2BmIFAAMUoTe8xkmLN7%2FeAZjuC9x1ocxovItHLl%2FsNK7Wq8QjgiHqGn0bb8P7yVvGBEd1gFe71NQ8aM0M%2BJNIMz5UFxfeA53rXjFlvsyH1Sig%2BOuO9Nz5nhCaJ6bEfj2iuv7w27pB3L8MVqmoCi6D9C%2FQMiLxtPaR70CxtnvoOlIgPmpv2bQy029A31NEK19ieVLkoyp1EUkXRaX3v0mohx8yMnUG1dhX9nUg3Oy8TYZ03DQy7kHDGkMKisNX7rt%2FGuGx1HIgjFclDGLsbAFIodvSLjm9FbseasMELoxlAJDlwRnW8zo5sQmL0Fz7ao935QBynrng%3D%3D'

以下是一个执行上述所有步骤的 Bash 脚本示例:

function rawurlencode {
local string="${1}"
local strlen=${#string}
local encoded=""
local pos c o

for (( pos=0 ; pos<strlen ; pos++ )); do
c=${string:$pos:1}
case "$c" in
[-_.~a-zA-Z0-9] ) o="${c}" ;;
* ) printf -v o '%%%02x' "'$c"
esac
encoded+="${o}"
done
echo "${encoded}"
}

# 设置身份验证:
API_KEY="替换成您的 API Key"
PRIVATE_KEY_PATH="test-prv-key.pem"
# 设置您的请求:
API_METHOD="POST"
API_CALL="api/v3/order"
API_PARAMS="symbol=BTCUSDT&side=SELL&type=LIMIT&timeInForce=GTC&quantity=1&price=0.2"
# 计算签名:
timestamp=$(date +%s000)
api_params_with_timestamp="$API_PARAMS&timestamp=$timestamp"

rawSignature=$(echo -n $api_params_with_timestamp | openssl dgst -keyform PEM -sha256 -sign $PRIVATE_KEY_PATH | openssl enc -base64 | tr -d '\n')

# 对签名编码进行百分号编码(percent-encoding)
signature=$(rawurlencode "$rawSignature")

# 发送请求:
curl -H "X-MBX-APIKEY: $API_KEY" -X "$API_METHOD" \
"https://api.binance.com/$API_CALL?$api_params_with_timestamp" \
--data-urlencode "signature=$signature"

Ed25519 Keys

我们强烈建议使用 Ed25519 API keys,因为它在所有受支持的 API key 类型中提供最佳性能和安全性。

不使用分隔符,把查询字符串与 HTTP body 连接在一起将生成请求的签名 payload。任何非 ASCII 字符在签名前都必须进行百分比编码(percent-encoded)。

在以下示例中,其中一个例子中的交易对名称完全由 ASCII 字符组成,另一个例子中的交易对名称则包含非 ASCII 字符。

这些示例假设私钥存储在文件 ./test-prv-key.pem 中。

KeyValue
apiKey4yNzx3yWC5bS6YTwEkSRaC0nRmSQIIStAUOh1b6kqaBrTLIhjCpI5lJH8q8R8WNO

交易对名称完全由 ASCII 字符组成的请求示例:

参数取值
symbolBTCUSDT
sideSELL
typeLIMIT
timeInForceGTC
quantity1
price0.2
timestamp1668481559918
recvWindow5000

交易对名称包含非 ASCII 字符的请求示例:

参数取值
symbol123456
sideSELL
typeLIMIT
timeInForceGTC
quantity1
price0.2
timestamp1668481559918
recvWindow5000

第一步: 构建签名 payload。

  1. 将参数格式化为 参数=取值 对并用 & 分隔每个参数对。
  2. 对字符串进行百分比编码(percent-encoded)。

对于第一组示例参数(仅限 ASCII 字符), parameter=value 字符串将如下所示:

symbol=BTCUSDT&side=SELL&type=LIMIT&timeInForce=GTC&quantity=1&price=0.2&timestamp=1668481559918&recvWindow=5000

对字符串进行百分比编码(percent-encoded)后,签名 payload 如下所示:

symbol=BTCUSDT&side=SELL&type=LIMIT&timeInForce=GTC&quantity=1&price=0.2&timestamp=1668481559918&recvWindow=5000

对于第二组示例参数(包含一些 Unicode 字符),parameter=value 字符串将如下所示:

symbol=123456&side=SELL&type=LIMIT&timeInForce=GTC&quantity=1&price=0.2&timestamp=1668481559918&recvWindow=5000

对字符串进行百分比编码(percent-encoded)后,签名 payload 如下所示:

symbol=%EF%BC%91%EF%BC%92%EF%BC%93%EF%BC%94%EF%BC%95%EF%BC%96&side=SELL&type=LIMIT&timeInForce=GTC&quantity=1&price=0.2&timestamp=1668481559918&recvWindow=5000

第二步: 计算签名。

  1. 对 payload 进行签名。
  2. 将输出结果编码为 base64 格式。

请注意,payload 和生成的签名值大小写敏感的

对于第一组示例参数(仅限 ASCII 字符):

echo -n "symbol=BTCUSDT&side=SELL&type=LIMIT&timeInForce=GTC&quantity=1&price=0.2&timestamp=1668481559918&recvWindow=5000" | openssl dgst -keyform PEM -sha256 -sign ./test-prv-key.pem | openssl enc -base64 | tr -d '\n'

HaZnek7KOGa/k5+f6Q1nw8lzMUpo36mRVvvLHCMUCXxlmdQQGZge1luAUKnleD/DYeD19YrqzeHbb6xU3MkSIXKhAO1MaYq48uGVYb3vJScEZVOutgMInrZzUcCWNulNkfcbmExSiymCZ5xQBw5QDuzpuDFqRZ1Xt+BZxEHBN9OYQKpoe0+ovjnXyVOaH8VUKhE/ghUWnThrXJr+hmSc5t7ggjiVPQc7pGn3qSNGCQwdpkQC9GHMr/r+8n6qeEKMYB5j/1wC4d8Jae8FQiU8xcXR0NlUgV2LAw61/ZJv5BTJpa+z5Lv1W9v6jHQWRX2O8uaG3KU/lR3spR7+oGlWOw=

对于第二组示例参数(包含一些 Unicode 字符):

echo -n "symbol=%EF%BC%91%EF%BC%92%EF%BC%93%EF%BC%94%EF%BC%95%EF%BC%96&side=SELL&type=LIMIT&timeInForce=GTC&quantity=1&price=0.2&timestamp=1668481559918&recvWindow=5000" | openssl dgst -keyform PEM -sha256 -sign ./test-prv-key.pem | openssl enc -base64 | tr -d '\n'

qJtv66wyp/1mZE+mIFAAMUoTe8xkmLN7/eAZjuC9x1ocxovItHLl/sNK7Wq8QjgiHqGn0bb8P7yVvGBEd1gFe71NQ8aM0M+JNIMz5UFxfeA53rXjFlvsyH1Sig+OuO9Nz5nhCaJ6bEfj2iuv7w27pB3L8MVqmoCi6D9C/QMiLxtPaR70CxtnvoOlIgPmpv2bQy029A31NEK19ieVLkoyp1EUkXRaX3v0mohx8yMnUG1dhX9nUg3Oy8TYZ03DQy7kHDGkMKisNX7rt/GuGx1HIgjFclDGLsbAFIodvSLjm9FbseasMELoxlAJDlwRnW8zo5sQmL0Fz7ao935QBynrng==
  1. 对 base64 格式的字符串进行百分比编码(percent-encoded)。

对于第一组示例参数(仅限 ASCII 字符):

HaZnek7KOGa%2Fk5%2Bf6Q1nw8lzMUpo36mRVvvLHCMUCXxlmdQQGZge1luAUKnleD%2FDYeD19YrqzeHbb6xU3MkSIXKhAO1MaYq48uGVYb3vJScEZVOutgMInrZzUcCWNulNkfcbmExSiymCZ5xQBw5QDuzpuDFqRZ1Xt%2BBZxEHBN9OYQKpoe0%2BovjnXyVOaH8VUKhE%2FghUWnThrXJr%2BhmSc5t7ggjiVPQc7pGn3qSNGCQwdpkQC9GHMr%2Fr%2B8n6qeEKMYB5j%2F1wC4d8Jae8FQiU8xcXR0NlUgV2LAw61%2FZJv5BTJpa%2Bz5Lv1W9v6jHQWRX2O8uaG3KU%2FlR3spR7%2BoGlWOw%3D

对于第二组示例参数(包含一些 Unicode 字符):

qJtv66wyp%2F1mZE%2BmIFAAMUoTe8xkmLN7%2FeAZjuC9x1ocxovItHLl%2FsNK7Wq8QjgiHqGn0bb8P7yVvGBEd1gFe71NQ8aM0M%2BJNIMz5UFxfeA53rXjFlvsyH1Sig%2BOuO9Nz5nhCaJ6bEfj2iuv7w27pB3L8MVqmoCi6D9C%2FQMiLxtPaR70CxtnvoOlIgPmpv2bQy029A31NEK19ieVLkoyp1EUkXRaX3v0mohx8yMnUG1dhX9nUg3Oy8TYZ03DQy7kHDGkMKisNX7rt%2FGuGx1HIgjFclDGLsbAFIodvSLjm9FbseasMELoxlAJDlwRnW8zo5sQmL0Fz7ao935QBynrng%3D%3D

第三步: 为请求添加签名

通过在查询字符串中添加 signature 参数来完成请求。

对于第一组示例参数(仅限 ASCII 字符):

curl -H "X-MBX-APIKEY: 4yNzx3yWC5bS6YTwEkSRaC0nRmSQIIStAUOh1b6kqaBrTLIhjCpI5lJH8q8R8WNO" -X POST 'hhttps://api.binance.com/api/v3/order?symbol=BTCUSDT&side=SELL&type=LIMIT&timeInForce=GTC&quantity=1&price=0.2&timestamp=1668481559918&recvWindow=5000&signature=HaZnek7KOGa%2Fk5%2Bf6Q1nw8lzMUpo36mRVvvLHCMUCXxlmdQQGZge1luAUKnleD%2FDYeD19YrqzeHbb6xU3MkSIXKhAO1MaYq48uGVYb3vJScEZVOutgMInrZzUcCWNulNkfcbmExSiymCZ5xQBw5QDuzpuDFqRZ1Xt%2BBZxEHBN9OYQKpoe0%2BovjnXyVOaH8VUKhE%2FghUWnThrXJr%2BhmSc5t7ggjiVPQc7pGn3qSNGCQwdpkQC9GHMr%2Fr%2B8n6qeEKMYB5j%2F1wC4d8Jae8FQiU8xcXR0NlUgV2LAw61%2FZJv5BTJpa%2Bz5Lv1W9v6jHQWRX2O8uaG3KU%2FlR3spR7%2BoGlWOw%3D'

对于第二组示例参数(包含一些 Unicode 字符):

curl -H "X-MBX-APIKEY: 4yNzx3yWC5bS6YTwEkSRaC0nRmSQIIStAUOh1b6kqaBrTLIhjCpI5lJH8q8R8WNO" -X POST 'https://api.binance.com/api/v3/order?symbol=%EF%BC%91%EF%BC%92%EF%BC%93%EF%BC%94%EF%BC%95%EF%BC%96&&side=SELL&type=LIMIT&timeInForce=GTC&quantity=1&price=0.2&timestamp=1668481559918&recvWindow=5000&signature=qJtv66wyp%2F1mZE%2BmIFAAMUoTe8xkmLN7%2FeAZjuC9x1ocxovItHLl%2FsNK7Wq8QjgiHqGn0bb8P7yVvGBEd1gFe71NQ8aM0M%2BJNIMz5UFxfeA53rXjFlvsyH1Sig%2BOuO9Nz5nhCaJ6bEfj2iuv7w27pB3L8MVqmoCi6D9C%2FQMiLxtPaR70CxtnvoOlIgPmpv2bQy029A31NEK19ieVLkoyp1EUkXRaX3v0mohx8yMnUG1dhX9nUg3Oy8TYZ03DQy7kHDGkMKisNX7rt%2FGuGx1HIgjFclDGLsbAFIodvSLjm9FbseasMELoxlAJDlwRnW8zo5sQmL0Fz7ao935QBynrng%3D%3D'

以下是一个执行上述所有步骤的 Bash 脚本示例:

#!/usr/bin/env python3

import base64
import requests
import time
import urllib.parse
from cryptography.hazmat.primitives.serialization import load_pem_private_key

# 设置身份验证:
API_KEY='替换成您的 API Key'
PRIVATE_KEY_PATH='test-prv-key.pem'

# 加载 private key。
# 在这个例子中,private key 没有加密,但我们建议使用强密码以提高安全性。
with open(PRIVATE_KEY_PATH, 'rb') as f:
private_key = load_pem_private_key(data=f.read(), password=None)

# 设置请求参数:
params = {
'symbol': 'BTCUSDT',
'side': 'SELL',
'type': 'LIMIT',
'timeInForce': 'GTC',
'quantity': '1.0000000',
'price': '0.20',
}

# 参数中加时间戳:
timestamp = int(time.time() * 1000) # 以毫秒为单位的 UNIX 时间戳
params['timestamp'] = timestamp

# 参数中加签名:
payload = urllib.parse.urlencode(params, encoding='UTF-8')
signature = base64.b64encode(private_key.sign(payload.encode('ASCII')))
params['signature'] = signature

# 发送请求:
headers = {
'X-MBX-APIKEY': API_KEY,
}
response = requests.post(
'https://api.binance.com/api/v3/order',
headers=headers,
data=params,
)
print(response.json())