# 签名算法 ## 计算步骤 1. 准备最终要发送的 UTF-8 JSON 文本 `rawBody`。序列化**一次**,后面签名和发送使用同一份字节。 2. 计算 `bodyHash = lowercaseHex(SHA256(rawBody))`。 3. 按下方顺序用换行符 `\n` 拼接六行,**末尾不加换行**。 4. 以 Secret 的 UTF-8 字节为密钥计算 HMAC-SHA256,并编码为 64 位小写 hex,填入 `X-Signature`。 ```text API Key POST 完整 Path(不含域名) X-Timestamp X-Nonce bodyHash ``` 公式: ```text canonical = apiKey + "\n" + "POST" + "\n" + path + "\n" + timestamp + "\n" + nonce + "\n" + lowercaseHex(SHA256(rawBody)) signature = lowercaseHex(HMAC_SHA256(UTF8(secret), UTF8(canonical))) ``` Secret 作为原始文本使用,**不先做 hex/Base64 解码**。示例代码见各接口的「调用示例」,可直接复制完整脚本。 ## 固定校验向量 此例只验证计算算法;时间戳已过期,不能用来调用线上 API。 | 输入 | 值 | |---|---| | API Key | `key` | | Secret | `secret` | | Method | `POST` | | Path | `/api/v1/open/viewers/upsert` | | Timestamp | `1700000000` | | Nonce | `0123456789abcdef` | | 原始 Body | `{}`(两个字符,无空格和换行) | | bodyHash | `44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a` | | Signature | `b04fca374e3428b338b6bcc0597f81762d99b21235971184293b9252d304ee65` | ## 常见失败原因 - **签名后重新序列化 JSON**:空格、字段顺序、换行和中文转义的变化都会改变哈希。 - 使用毫秒时间戳或服务器时钟偏差过大。 - 将完整 URL 放进签名,或签名 Path 与发送 Path 不一致。 - HMAC 结果使用 Base64 或大写 hex。 - 请求经过重定向或中间代理重新编码、压缩请求体。 - 重用同一 nonce。nonce 防重放不是业务幂等键,即使上次业务校验失败,也应为新请求生成新 nonce。 不要打印 Secret、完整签名串和包含观众资料的原始 Body。排查时使用本页固定向量,再携带 `requestId` 联系部署方。