指南
回呼
安全地接收並驗證任務回呼的傳遞。
使用回呼在公開的 HTTPS 端點接收 Task 生命週期事件。在處理 JSON 主體之前,請驗證每個回呼,確保只有已針對您帳戶簽署的傳遞才能變更應用程式狀態。
設定回呼 URL
建立任務時,請加入公開的 HTTPS callback_url。事件主體與生命週期狀態取決於端點;請參閱該端點的 API 參考以取得其回呼內容。
JSON
{
"model": "flux-2-pro-text-to-image",
"prompt": "A product photograph on a clean studio background",
"callback_url": "https://your-domain.com/webhooks/runapi"
}
建立回呼密鑰
請遵循身分驗證指南登入, 然後開啟 API 金鑰並為建立 Task 的帳戶建立回呼密鑰。 將值存放於密鑰管理器中,並僅讓您的回呼接收器存取。 它不是 API 金鑰,絕不可在 Task 請求中傳送。
此密鑰用於為該帳戶的回呼簽章。輪換密鑰會變更後續傳送的簽章,因此請立即更新所有回呼接收端,並僅在處理傳輸中的傳送所需的最短時間內,同時保留兩個值。
驗證回呼簽章
每個回呼均為 HTTP POST,Content-Type: application/json。
RunAPI 不會在此請求中新增 Authorization 標頭。在反序列化主體之前,請先驗證這些標頭:
標頭
含義
X-Callback-Id
此次投遞嘗試的唯一識別碼。
X-Callback-Timestamp
投遞簽署時的 Unix 時間戳記(以秒為單位)。
X-Callback-Signature
Base64 編碼的 HMAC-SHA-256 簽章。
請按照以下方式精確建構簽章值,使用未經修改的請求本文位元組:
TEXT
X-Callback-Id + "." + X-Callback-Timestamp + "." + raw request body
對回呼密鑰進行 Base64 解碼,對該值計算 HMAC-SHA-256,將結果進行 Base64 編碼,並使用時序安全比較將其與 X-Callback-Signature 對照。驗證前請勿解析並重新序列化 JSON。
JavaScript
JAVASCRIPT
import { createHmac, timingSafeEqual } from "node:crypto";
export function verifyCallback({headers, rawBody, callbackSecret}) {
const callbackId = headers["x-callback-id"];
const timestamp = Number(headers["x-callback-timestamp"]);
const signature = headers["x-callback-signature"];
if (!callbackId || !signature || !Number.isSafeInteger(timestamp)) return false;
if (Math.abs(Date.now() / 1000 - timestamp) > 300) return false;
const signedContent = `${callbackId}.${timestamp}.${rawBody}`;
const expected = createHmac("sha256", Buffer.from(callbackSecret, "base64"))
.update(signedContent, "utf8")
.digest();
const received = Buffer.from(signature, "base64");
return expected.length === received.length && timingSafeEqual(expected, received);
}
將框架的原始請求主體字串傳入 rawBody;請勿對已解析的資料呼叫 JSON.stringify。
Python
PYTHON
import base64
import hashlib
import hmac
import time
def verify_callback(headers, raw_body, callback_secret):
callback_id = headers.get("X-Callback-Id")
timestamp = headers.get("X-Callback-Timestamp")
signature = headers.get("X-Callback-Signature")
if not callback_id or not timestamp or not signature:
return False
try:
timestamp = int(timestamp)
secret = base64.b64decode(callback_secret, validate=True)
received = base64.b64decode(signature, validate=True)
except (ValueError, TypeError):
return False
if abs(time.time() - timestamp) > 300:
return False
signed_content = f"{callback_id}.{timestamp}.{raw_body}".encode("utf-8")
expected = hmac.new(secret, signed_content, hashlib.sha256).digest()
return hmac.compare_digest(expected, received)
將 HTTP 框架接收到的原始請求主體字串,以 raw_body 的形式傳入。
安全處理傳遞
- 僅在回呼已被接受處理後才回傳
2xx回應。若回應非2xx或發生傳輸失敗,系統最多會重試傳送 10 次。 - 請在 15 秒內回應。較耗時的工作應在驗證後排入佇列,而非阻塞 HTTP 回應。
- 拒絕缺少簽章標頭、簽章無效,或時間戳超出接收端所定義容許範圍的回呼。
疑難排解驗證
- 簽章不符: 請確認回呼 Secret 與該 Task 屬於同一個帳號,以 Base64 解碼後,針對原始 body 而非解析後的 JSON 進行簽署。
- 缺少簽章標頭: 請在依賴回呼進行狀態變更之前,先建立回呼 Secret。
- 時間戳記被拒絕: 請同步接收端的時鐘,並根據您的部署環境設定適當的容許誤差。
如需設定與生命週期指引,請返回 Task API 快速入門。