Tích hợp
Kiểm chữ ký và xử lý webhook bên nhận
Xác thực raw body, chống xử lý trùng và đưa sự kiện vào hàng đợi bền vững trước khi phản hồi.
Bên nhận cần xác minh yêu cầu trước khi dùng nội dung sự kiện. Bạn nên tách bước nhận HTTP khỏi công việc chậm như gọi CRM, trả lời khách hoặc cập nhật bảng tính.
Ai làm được
Người quản lý dịch vụ nhận webhook thực hiện phần này. Bạn cần truy cập cấu hình bí mật và kho dữ liệu chống trùng của dịch vụ đó, không cần cấp thêm quyền Telegram cho bên nhận chỉ để kiểm chữ ký.
Cần chuẩn bị
Lưu bí mật ký trong biến môi trường WEBHOOK_SECRET. Giá trị thực có dạng whsec_…; không ghi giá trị vào mã nguồn hay log.
Giữ nguyên raw body. Không parse JSON rồi stringify lại trước khi kiểm chữ ký: khoảng trắng và thứ tự byte là một phần dữ liệu đã ký.
Bắt đầu ở đâu
Mở Cài đặt → Tài liệu API → Nhận webhook để xem hướng dẫn bên nhận. Phần sự kiện cho biết cấu trúc dữ liệu; hướng dẫn nhận cung cấp ví dụ theo nền tảng.
Ứng dụng có 9 công thức: Node.js Express, Hono cho Node.js/Bun/Deno, Python FastAPI, Go, PHP, Cloudflare Worker, n8n, Make và Zapier.
Các bước
- Đọc raw body và các header dưới đây.
- Kiểm timestamp.
- Kiểm chữ ký.
- Ghi sự kiện vào hàng đợi bền vững có chống trùng.
- Trả phản hồi
2xx. - Xử lý nghiệp vụ ở tiến trình nền.
| Header | Ý nghĩa |
|---|---|
webhook-id |
ID lần giao; giữ nguyên khi thử lại hoặc gửi lại lần giao đó |
webhook-timestamp |
Thời điểm ký, tính bằng giây Unix |
webhook-signature |
Một hoặc nhiều chữ ký dạng v1,<base64> |
Bỏ tiền tố whsec_ rồi giải mã base64 phần bí mật. Tính:
base64(HMAC-SHA256(secret_bytes, webhook-id + "." + webhook-timestamp + "." + raw_body))Chấp nhận nếu một chữ ký hợp lệ khớp, bằng phép so sánh thời gian hằng. Dung sai mặc định là 300 giây, tức 5 phút, theo cả hai chiều. Khi xoay khoá, bên nhận có thể chấp nhận chữ ký của một trong các khoá đang còn hiệu lực.
Node.js
Ví dụ dùng Express và thư viện standardwebhooks. inbox là adapter bạn tự cung cấp, ghi bền vững và có ràng buộc duy nhất trên ID lần giao.
import express from "express";
import { Webhook } from "standardwebhooks";
const app = express();
const verifier = new Webhook(process.env.WEBHOOK_SECRET);
app.post("/telegram-events", express.raw({ type: "*/*" }), async (req, res) => {
let event;
try {
event = verifier.verify(req.body.toString("utf8"), req.headers);
} catch {
return res.sendStatus(401);
}
try {
await inbox.acceptOnce({
deliveryId: req.get("webhook-id"),
eventId: event.id,
event,
});
return res.sendStatus(204);
} catch {
return res.sendStatus(503);
}
});Python
Ví dụ dùng FastAPI và thư viện standardwebhooks. Adapter inbox có cùng trách nhiệm như ví dụ trên.
import os
from fastapi import FastAPI, Request, Response
from standardwebhooks.webhooks import Webhook
app = FastAPI()
verifier = Webhook(os.environ["WEBHOOK_SECRET"])
@app.post("/telegram-events")
async def receive(request: Request):
body = await request.body()
try:
event = verifier.verify(body, dict(request.headers))
except Exception:
return Response(status_code=401)
try:
await inbox.accept_once(
delivery_id=request.headers["webhook-id"],
event_id=event["id"],
event=event,
)
except Exception:
return Response(status_code=503)
return Response(status_code=204)Kết quả
Yêu cầu sai chữ ký không vào hàng đợi. Yêu cầu hợp lệ được lưu trước khi xác nhận nhận thành công.
Kiểm tra
Chống trùng theo webhook-id cho việc thử lại cùng lần giao. Đồng thời chống tác dụng phụ trùng theo event.id: phát lại tạo lần giao mới nhưng giữ ID sự kiện.
Trả 2xx nhanh, trong giới hạn 10 giây của bên gửi. Đừng xác nhận thành công trước khi ghi bền vững.
Khi có lỗi
Kiểm tra raw body, đồng hồ máy, bí mật và proxy có làm thay đổi body không. Không hứa xử lý đúng thứ tự đến; khi nghiệp vụ cần thứ tự, đối chiếu dữ liệu sự kiện và trạng thái hiện tại.
Làm bằng API hoặc MCP
Đọc webhooks.receiver_guide qua tools_run, rồi dùng webhooks.test hoặc webhooks_test để kiểm tra đường nhận.
Xem thêm lỗi webhook.