---
title: "Kiểm chữ ký và xử lý webhook bên nhận"
locale: vi
url: https://tlg.builera.app/docs/integrations/webhook-receivers
verified: 2026-10-24
app_version: "2.0"
---

# 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

1. Đọc raw body và các header dưới đây.
2. Kiểm timestamp.
3. Kiểm chữ ký.
4. Ghi sự kiện vào hàng đợi bền vững có chống trùng.
5. Trả phản hồi `2xx`.
6. 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:

```text
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.

```javascript
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.

```python
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](https://tlg.builera.app/docs/reference/rest/webhooks.receiver_guide) qua `tools_run`, rồi dùng [webhooks.test](https://tlg.builera.app/docs/reference/rest/webhooks.test) hoặc `webhooks_test` để kiểm tra đường nhận.

Xem thêm [lỗi webhook](https://tlg.builera.app/docs/troubleshooting/webhook-failures).

