鑑權與簽名
接入方呼叫開放介面使用 AppKey / AppSecret,採用 HMAC-SHA256 簽名。不依賴控制檯登入態或瀏覽器 Cookie。
請求頭
| 請求頭 | 說明 |
|---|---|
OC-App-Key | 當前工作空間的 AppKey |
OC-Timestamp | Unix 毫秒時間戳,與平臺時間相差不超過 5 分鐘 |
OC-Nonce | 每次請求生成新的隨機串,16~64 位,允許字母、數字、-、_ |
OC-Signature | v1= 加 HMAC-SHA256 的小寫十六進位制結果 |
X-Request-ID | 可選,請求排查標識,最長 64 位 |
AppSecret 只放在接入方服務端,不進入網頁、移動端安裝包或模型上下文。
簽名內容
使用換行符連線以下七行,末尾不加換行:
text
OC-HMAC-SHA256
{大寫 HTTP 方法}
{原始請求路徑}
{原始查詢串,不含問號}
{OC-Timestamp}
{OC-Nonce}
{請求體 SHA-256,小寫十六進位制}沒有查詢串時,第四行保留為空。路徑和查詢串按實際傳送內容計算,不額外排序或解碼。沒有請求體時,對空位元組序列求摘要。
簽名自檢
當前已有 GET /api/open/v1/auth/check 和 POST /api/open/v1/auth/check,可用於確認簽名鏈路。開放介面域名由平臺在聯調時提供。
下面的 Node.js 示例只呼叫自檢介面,不推送業務訊息:
js
import { createHash, createHmac, randomBytes } from 'node:crypto'
const { OMNICHAT_BASE_URL, OMNICHAT_APP_KEY, OMNICHAT_APP_SECRET } = process.env
if (!OMNICHAT_BASE_URL || !OMNICHAT_APP_KEY || !OMNICHAT_APP_SECRET) {
throw new Error('請在服務端配置域名、AppKey 與 AppSecret')
}
const url = new URL('/api/open/v1/auth/check', OMNICHAT_BASE_URL)
if (url.protocol !== 'https:') throw new Error('開放介面須使用 HTTPS')
const body = JSON.stringify({ ping: 'hello' })
const timestamp = String(Date.now())
const nonce = randomBytes(16).toString('hex')
const digest = createHash('sha256').update(body, 'utf8').digest('hex')
const canonical = ['OC-HMAC-SHA256', 'POST', url.pathname,
url.search.slice(1), timestamp, nonce, digest].join('\n')
const signature = createHmac('sha256', OMNICHAT_APP_SECRET)
.update(canonical, 'utf8').digest('hex')
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'OC-App-Key': OMNICHAT_APP_KEY,
'OC-Timestamp': timestamp,
'OC-Nonce': nonce,
'OC-Signature': `v1=${signature}`,
},
body,
signal: AbortSignal.timeout(10000),
})
console.log(response.status, await response.text())常見排查方向
- 簽名不匹配:檢查傳送位元組是否和計算摘要的請求體相同。
- 請求過期:確認伺服器時鐘和毫秒時間戳。
- 隨機數重複:每次重試更換 nonce,並重新簽名。
- 空間不正確:確認使用的憑證屬於目標空間,不透過請求體切換空間。
訊息回撥使用獨立金鑰,簽名格式見訊息回撥。
錯誤與限流
業務接口均為 POST JSON;簽章自檢另支援 GET。請求體最大 1 MB,預設每個 AppKey 每個自然分鐘 600 次請求,部署可調。成功響應為 {"code":"OK","message":"success","data":{}};錯誤如下:
json
{"code":"CONFLICT","message":"請檢查目前資源狀態","data":null}| HTTP | code | 處理方式 |
|---|---|---|
| 400 | INVALID_ARGUMENT | 修正欄位或配置 |
| 401 | AUTH_REQUIRED / INVALID_CREDENTIALS | 檢查憑證及簽章 |
| 401 | REQUEST_EXPIRED | 校時並重新簽章;OC-Server-Time 返回平台毫秒時間 |
| 401 | REQUEST_REPLAYED | 更換 nonce,重新簽章;保留業務 eventId |
| 403 | CREDENTIAL_DISABLED / FORBIDDEN | 檢查空間、憑證狀態及 IP 白名單 |
| 404 | NOT_FOUND | 先同步使用者或核對角色識別 |
| 409 | CONFLICT / VERSION_CONFLICT | 查詢目前資料,再決定修改或重試 |
| 413 | PAYLOAD_TOO_LARGE | 縮小請求體 |
| 429 | RATE_LIMITED | 退避後重新簽章重試 |
| 503 | SERVICE_UNAVAILABLE | 暫時不可用,稍後重試 |
網路超時不代表請求未執行。聊天事件重試保持 eventId;角色建立/發布先查詢確認結果,不要盲目重試。X-Request-ID 用於追蹤,不提供業務去重。
可下載 Node.js 請求簽章與回呼驗簽範例,用法見快速開始。