Hành vi gửi
Lấy từ tài liệu của chính hãng, kiểm tra lần cuối 2026-08-06. Hãng không nêu con số nào thì bảng này cũng không ghi.
| Thời hạn phản hồi | 3 giây Endpoint nhận interaction phải gửi phản hồi đầu tiên trong vòng 3 giây |
|---|---|
| Thử lại | hãng không công bố |
| Ngừng gửi | hãng không công bố |
| Nguồn | https://docs.discord.com/developers/interactions/receiving-and-responding |
Chữ ký
Kiểm chứng bằng một bộ xác minh chạy thật, có bộ test chứng minh, chứ không đọc từ tài liệu. Kiểm chứng lần cuối 2026-08-20.
| Thuật toán | Ed25519 |
|---|---|
| Payload được ký | {timestamp}{body} |
| Encoding | hex |
| Header | x-signature-ed25519 + x-signature-timestamp |
| Dung sai | không quy định |
Xác minh
Dùng raw body của request, đúng từng byte, trước mọi bước parse JSON. Mọi cơ chế trên trang này đều hỏng ngay khi framework serialize lại payload.
// Ed25519, not HMAC: verify with the application's public key (hex).
const hex = (s) => Uint8Array.from(s.match(/../g), (b) => parseInt(b, 16));
const key = await crypto.subtle.importKey(
"raw",
hex(publicKey), // Developer Portal → Application → Public Key
{ name: "Ed25519" },
false,
["verify"],
);
const valid = await crypto.subtle.verify(
"Ed25519",
key,
hex(req.headers["x-signature-ed25519"]),
new TextEncoder().encode(req.headers["x-signature-timestamp"] + rawBody),
);Discord chủ động thăm dò endpoint bằng chữ ký không hợp lệ và từ chối URL nếu chúng lọt qua, nên một bộ xác minh viết tạm sẽ trượt ngay ở bước thiết lập, chứ không chỉ khi review bảo mật.
Những chỗ dễ vấp
Thời hạn 3 giây áp dụng cho phản hồi interaction đầu tiên. Lối thoát là type 5 (deferred): xác nhận trong thời hạn đó, rồi gửi follow-up khi xử lý xong việc thật.
Đọc thêm
AnyHook đứng trước các endpoint nhận webhook từ Discord: trả lời sau khoảng 1 giây, tự thử lại theo lịch riêng khi server của bạn ngừng hoạt động, và giữ mọi sự kiện để bạn phát lại được. Đổi một URL, giữ nguyên code.