Webhook
Nhận sự kiện tin cậy từ Voicebox về backend của bạn và kiểm chữ ký.
Sự kiện ở trình duyệt có thể bị giả mạo. Khi cần cập nhật hệ thống (ghi nhận đơn, mở ticket), hãy nhận webhook server-to-server.
Thiết lập
- Khai báo
webhook_url(bắt buộchttps) cho voicebox. - Xoay secret webhook — secret hiển thị một lần, lưu vào secret manager.
- Gửi thử để kiểm tra endpoint.
Kiểm chữ ký
Mỗi request có các header:
| Header | Ý nghĩa |
|---|---|
X-Voicebox-Event-Id | Mã sự kiện — dùng để xử lý idempotent |
X-Voicebox-Timestamp | Thời điểm gửi (giây) |
X-Voicebox-Signature | sha256= + hex(HMAC_SHA256(secret, timestamp + "." + body thô)) |
import { createHmac, timingSafeEqual } from 'node:crypto';
app.post('/webhooks/voicebox', express.raw({ type: '*/*' }), (req, res) => {
const ts = req.header('X-Voicebox-Timestamp');
const sig = req.header('X-Voicebox-Signature') ?? '';
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return res.sendStatus(400); // lệch giờ > 5 phút
const expected = 'sha256=' + createHmac('sha256', process.env.VOICEBOX_WEBHOOK_SECRET)
.update(`${ts}.${req.body}`).digest('hex');
if (sig.length !== expected.length || !timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) return res.sendStatus(401);
const eventId = req.header('X-Voicebox-Event-Id');
// đã xử lý eventId này rồi ⇒ trả 200 luôn
queue.push(JSON.parse(req.body)); // xử lý nặng đưa vào hàng đợi
res.sendStatus(200);
});Thử lại
Endpoint trả lỗi hoặc quá thời gian ⇒ Voicebox thử lại sau 1 giây, 5 giây, 30 giây. Trả 2xx càng nhanh càng tốt.