跳转至

API Key 与 HMAC 签名

证据:ptrader-api-gateway/docs/API-Authentication-Mechanism.en.md、filter/AuthFilter.java、Postman 集合预请求脚本。

Header 是否必需 说明
x-ptrader-apikey 是(签名与仅 Key) API Key
true-client-ip / x-real-ip 经 ingress 时常必需 客户端 IP;Postman 设置 true-client-ip

签名请求

适用于带 @SignAuth 且非 validKeyOnly 的接口(下单、账户、钱包等)。

参数

参数 是否必需 说明
timestamp 当 checkRecvWindow=true 时必需 Unix 毫秒
recvWindow 否 默认 5000 ms,最大 60000 ms
signature 是 HMAC-SHA256 十六进制(query 或 header)

时间窗规则

当且仅当:

timestamp ≤ serverTime + 1000 且 serverTime - timestamp ≤ recvWindow

签名原文(originStr)

originStr = queryStringWithoutSignature + requestBody

规则:

  1. Query:除 signature 外全部参数,按发送顺序以 key=value 用 & 连接。
  2. Body:
  3. application/json → 紧凑 JSON 字符串(网关经 Jackson JsonNode.toString())。
  4. application/x-www-form-urlencoded → 未出现在 query 中的表单字段(排除 signature)。
  5. Query 与 Body 之间无额外分隔符直接拼接。
signature = Hex(HMAC-SHA256(apiSecret, originStr))

可运行示例(LIMIT 下单,无 body)

示意凭证(来自 api-gateway 鉴权文档 — 非生产密钥):

  • API Key: vmPUZE6mv9SD5VNHk4HlWFsOr6aKE2zvsw0MuIgwCIPy6utIco14y7Ju91duEh8A
  • API Secret: NhqPtmdSJYdKjVHjA7PZj4Mge3R5YNiP1e3UZjInClVN65XAbvqqM6A7H5fATj0j
API_KEY="vmPUZE6mv9SD5VNHk4HlWFsOr6aKE2zvsw0MuIgwCIPy6utIco14y7Ju91duEh8A"
API_SECRET="NhqPtmdSJYdKjVHjA7PZj4Mge3R5YNiP1e3UZjInClVN65XAbvqqM6A7H5fATj0j"
BASE_URL="https://api-gateway-scb.dev.pcrypto.com"
TIMESTAMP=$(python3 -c 'import time; print(int(time.time()*1000))')

QUERY="symbol=BTCUSDT&side=BUY&type=LIMIT&timeInForce=GTC&quantity=0.001&price=50000&timestamp=${TIMESTAMP}&recvWindow=5000"
SIGNATURE=$(printf '%s' "${QUERY}" | openssl dgst -sha256 -hmac "${API_SECRET}" | awk '{print $2}')

curl -sS -X POST "${BASE_URL}/openapi/v1/order?${QUERY}&signature=${SIGNATURE}" \
  -H "x-ptrader-apikey: ${API_KEY}" \
  -H "true-client-ip: 1.2.3.4" \
  -H "Content-Type: application/x-www-form-urlencoded"

若有 JSON body,将紧凑 JSON 字符串追加到 query 字符串之后构成 originStr(Postman:JSON.stringify(JSON.parse(raw)))。

仅 Key 接口(listenKey)

POST|PUT|DELETE /openapi/v1/userDataStream 使用 @SignAuth(validKeyOnly = true, accountOnly = true)。

证据:UserDataApiController;AuthFilter 在 validKeyOnly() 分支仅经 broker-security 校验 Key,不校验签名。

只需发送 x-ptrader-apikey(Postman 的 X-Skip-Sign 仅为客户端提示,网关不识别)。

机构解析

BrokerInterceptor 由 Host → broker apiDomain 得到 x-org-id。失败 → INVALID_PARAMETER(host)。