stable · guide · 0.1.0
接收 Domain Event Webhook
驗證並處理 webhook
- 在解析 JSON 前,先拒絕超過五分鐘的
X-MiniCenter-Timestamp,並以訂閱 secret 對timestamp.delivery_id.raw_body計算 HMAC-SHA256;使用 constant-time compare 核對X-MiniCenter-Signature的sha256=值。 - 驗證
X-MiniCenter-Event-ID與 body 的id相同,再用 Event Reference 的 canonical schema 驗證 envelope。 - 以
X-MiniCenter-Delivery-ID防止重播,並以事件id作為處理結果唯一鍵;已處理的事件直接回覆成功。 - 有
stream_id時,確認sequence緊接上一筆事件。 - 先持久化處理結果,再回覆成功;失敗時讓 MiniCenter 重試。
{
"id": "10000000-0000-4000-8000-000000000001",
"type": "files.object.available",
"schema_version": 1,
"occurred_at": "2026-07-30T09:00:00Z",
"published_at": "2026-07-30T09:00:01Z",
"stream_id": "file-object-42",
"sequence": 1,
"correlation_id": "20000000-0000-4000-8000-000000000002",
"data": {"object_id": "42"}
}
不要假設全域事件順序。若同一 stream 出現 sequence 缺口,先暫停該 stream 並修復快照。
執行簽章驗證範例
以下範例只需要 PHP。複製程式碼後執行,即會建立一組完整 headers、驗證五分鐘時效與 HMAC 簽章,最後輸出已驗證的事件 ID:
$secret = 'replace-with-subscription-secret';
$body = '{"id":"10000000-0000-4000-8000-000000000001","type":"files.object.available","schema_version":1}';
$timestamp = (string) time();
$deliveryId = 'delivery-example-1';
$headers = [
'X-MiniCenter-Delivery-ID' => $deliveryId,
'X-MiniCenter-Event-ID' => '10000000-0000-4000-8000-000000000001',
'X-MiniCenter-Timestamp' => $timestamp,
'X-MiniCenter-Signature' => 'sha256='.hash_hmac(
'sha256',
$timestamp.'.'.$deliveryId.'.'.$body,
$secret,
),
];
if (abs(time() - (int) $headers['X-MiniCenter-Timestamp']) > 300) {
throw new RuntimeException('Expired webhook.');
}
$expected = 'sha256='.hash_hmac(
'sha256',
$headers['X-MiniCenter-Timestamp'].'.'.$headers['X-MiniCenter-Delivery-ID'].'.'.$body,
$secret,
);
if (! hash_equals($expected, $headers['X-MiniCenter-Signature'])) {
throw new RuntimeException('Invalid signature.');
}
$event = json_decode($body, true, flags: JSON_THROW_ON_ERROR);
if ($headers['X-MiniCenter-Event-ID'] !== $event['id']) {
throw new RuntimeException('Event ID mismatch.');
}
echo "Verified {$event['id']}\n";