Webhook Telegram bot: cài setWebhook, bảo mật bằng secret_token và dùng với n8n
Webhook Telegram bot là cơ chế để Telegram tự gửi (HTTPS POST) từng update tới server của bạn ngay khi có tin nhắn mới, thay vì bot phải liên tục gọi getUpdates. Bạn cần một URL HTTPS công khai và một lệnh setWebhook. Bài này hướng dẫn cài đặt, bảo mật bằng secret_token, kiểm tra trạng thái và sửa lỗi thường gặp, kể cả khi dùng webhook Telegram với n8n.
Webhook hay getUpdates?
- getUpdates (long polling): bot chủ động hỏi Telegram. Không cần domain hay HTTPS, chạy được trên laptop — hợp khi học và phát triển.
- Webhook: Telegram chủ động đẩy update tới bạn. Cần server có HTTPS — hợp khi chạy production hoặc serverless.
Hai cách loại trừ nhau: khi webhook đang bật, getUpdates trả về 409 Conflict. Dù chọn cách nào, update chưa nhận cũng chỉ được giữ tối đa 24 giờ.
Yêu cầu đối với URL webhook
- URL phải là
https://; HTTP thường không được chấp nhận. - Chỉ dùng các cổng 443, 80, 88, 8443.
- Chứng chỉ hợp lệ (ví dụ Let's Encrypt) với CN hoặc SAN khớp domain và đủ chuỗi chứng chỉ trung gian; hỗ trợ TLS 1.2 trở lên.
- Dùng chứng chỉ tự ký thì upload file PEM qua tham số
certificate(multipart/form-data). - Server nhận kết nối qua IPv4; URL không được redirect.
Đặt webhook bằng setWebhook
Tạo một chuỗi bí mật (1–256 ký tự, chỉ gồm A-Z, a-z, 0-9, _ và -), rồi gọi setWebhook:
export TOKEN="123456789:AAEexampleTokenReplaceWithYours"
export WEBHOOK_SECRET="$(openssl rand -hex 32)"
curl -X POST "https://api.telegram.org/bot$TOKEN/setWebhook" \
-H "Content-Type: application/json" \
-d '{
"url": "https://bot.example.com/telegram/webhook",
"secret_token": "'"$WEBHOOK_SECRET"'",
"allowed_updates": ["message", "callback_query"],
"drop_pending_updates": true,
"max_connections": 40
}'
url— địa chỉ HTTPS nhận update; truyền chuỗi rỗng để gỡ webhook.secret_token— Telegram gửi kèm trong headerX-Telegram-Bot-Api-Secret-Token.allowed_updates— chỉ nhận các loại update cần thiết; không truyền tham số này thì Telegram giữ thiết lập trước đó.drop_pending_updates— xóa các update đang chờ, tránh bot xử lý lại tin cũ.max_connections— số kết nối đồng thời 1–100, mặc định 40.
Với chứng chỉ tự ký, gửi dạng multipart:
curl -F "url=https://203.0.113.10:8443/telegram/webhook" \
-F "certificate=@public.pem" \
"https://api.telegram.org/bot$TOKEN/setWebhook"
Thành công sẽ nhận {"ok":true,"result":true,"description":"Webhook was set"}. Muốn điền tham số qua form thay vì gõ JSON, hãy dùng setWebhook trong Bot API Tester.
Kiểm tra trạng thái bằng getWebhookInfo
curl "https://api.telegram.org/bot$TOKEN/getWebhookInfo"
{
"ok": true,
"result": {
"url": "https://bot.example.com/telegram/webhook",
"has_custom_certificate": false,
"pending_update_count": 12,
"last_error_date": 1793260800,
"last_error_message": "Wrong response from the webhook: 500 Internal Server Error",
"max_connections": 40,
"allowed_updates": ["message", "callback_query"]
}
}
pending_update_count tăng dần kèm last_error_message nghĩa là Telegram không giao được update: đọc thông báo lỗi, xem log server rồi sửa. Khi webhook chạy tốt, hai trường last_error_* sẽ không xuất hiện hoặc chỉ ghi nhận lỗi cũ. Có thể xem nhanh qua getWebhookInfo trong Bot API Tester.
Viết handler: kiểm tra secret và trả 2xx thật nhanh
Ví dụ Flask: so khớp header bí mật, trả lời tin nhắn và luôn trả về 200.
import hmac
import os
import requests
from flask import Flask, abort, request
API = f"https://api.telegram.org/bot{os.environ['TOKEN']}"
SECRET = os.environ["WEBHOOK_SECRET"]
app = Flask(__name__)
@app.post("/telegram/webhook")
def telegram_webhook():
got = request.headers.get("X-Telegram-Bot-Api-Secret-Token", "")
if not hmac.compare_digest(got, SECRET):
abort(403)
update = request.get_json(force=True)
msg = update.get("message")
if msg and "text" in msg:
requests.post(f"{API}/sendMessage", json={
"chat_id": msg["chat"]["id"],
"text": "Đã nhận: " + msg["text"],
}, timeout=10)
return "", 200
Nếu handler trả mã khác 2xx, Telegram sẽ gửi lại update đó. Việc nặng (gọi AI, xuất báo cáo) nên đẩy vào hàng đợi rồi trả 200 ngay; dùng update_id để bỏ qua update trùng. Các tùy chọn khi trả lời người dùng có trong bài API gửi tin nhắn Telegram.
Xóa webhook, quay lại getUpdates
curl "https://api.telegram.org/bot$TOKEN/deleteWebhook?drop_pending_updates=true"
Bỏ drop_pending_updates nếu muốn giữ lại các update đang chờ để đọc bằng getUpdates.
Webhook Telegram với n8n
Node Telegram Trigger của n8n cũng đăng ký webhook bằng setWebhook, nên mọi yêu cầu ở trên vẫn áp dụng:
- n8n chạy ở
http://localhost:5678sẽ gặp lỗiBad Request: bad webhook: An HTTPS URL must be provided for webhook. Telegram cần một URL HTTPS công khai: đưa n8n lên server có domain và chứng chỉ (qua reverse proxy) hoặc dùng tunnel có HTTPS, và cấu hình để n8n dùng địa chỉ công khai đó. - URL có cổng không hỗ trợ như
:5678sẽ bị từ chối:Webhook can be set up only on ports 80, 88, 443 or 8443. - Mỗi bot chỉ có một webhook. Hai workflow hoặc một dịch vụ khác dùng chung token sẽ ghi đè webhook của nhau — mỗi tích hợp nên dùng một bot riêng.
- Dùng
getWebhookInfođể xem n8n đã đăng ký URL nào và lỗi gần nhất là gì.
Lỗi webhook thường gặp
| Lỗi | Cách xử lý |
|---|---|
Bad Request: bad webhook: An HTTPS URL must be provided for webhook | Đổi sang URL https:// với chứng chỉ hợp lệ. |
409 Conflict: can't use getUpdates method while webhook is active | Bot đang có webhook. Gọi deleteWebhook hoặc đọc update ở handler. |
Wrong response from the webhook: 404 Not Found | Sai đường dẫn: URL trong setWebhook không khớp route của server. |
Lỗi SSL trong last_error_message | Thiếu chứng chỉ trung gian, CN không khớp domain hoặc chưa upload chứng chỉ tự ký. |
Lỗi 409 khi cần lấy chat id được giải thích thêm trong bài chat id Telegram lấy ở đâu. Mới bắt đầu và chưa có bot? Đọc bài cách tạo bot Telegram, hoặc tham khảo hướng dẫn webhook chính thức.
Câu hỏi thường gặp
Webhook Telegram có bắt buộc HTTPS không?
Có. Bot API chỉ nhận URL https:// trên các cổng 443, 80, 88 hoặc 8443. Chứng chỉ có thể do CA cấp hoặc tự ký, khi đó bạn upload file PEM qua tham số certificate.
Có thể dùng webhook và getUpdates cùng lúc không?
Không. Hai cách nhận update loại trừ nhau: khi webhook đang bật, getUpdates trả về lỗi 409 Conflict. Gọi deleteWebhook để quay lại long polling.
Làm sao biết request webhook thật sự đến từ Telegram?
Đặt secret_token khi gọi setWebhook. Telegram gửi giá trị này trong header X-Telegram-Bot-Api-Secret-Token ở mọi request; handler từ chối request nào có header sai.
Vì sao bot nhận cùng một update nhiều lần?
Handler trả mã khác 2xx hoặc xử lý quá lâu nên Telegram gửi lại. Hãy trả 200 ngay, đẩy việc nặng ra hàng đợi và bỏ qua các update_id đã xử lý.
Một bot có thể đặt nhiều webhook không?
Không. Mỗi bot chỉ có một URL webhook; lần gọi setWebhook sau sẽ ghi đè lần trước. Nếu nhiều hệ thống cần nhận update, hãy dùng các bot riêng.
Bài viết liên quan
Cách tạo bot Telegram từ A đến Z: BotFather, token và tin nhắn đầu tiên
Tạo bot Telegram miễn phí với @BotFather: chọn username, lấy token, kiểm tra bằng getMe, tìm chat id và gửi tin nhắn đầu tiên bằng curl, Python.
API gửi tin nhắn Telegram: hướng dẫn sendMessage với curl, Python và JavaScript
Dùng API gửi tin nhắn Telegram qua sendMessage: ví dụ curl, Python requests, JavaScript fetch, định dạng HTML, MarkdownV2, nút inline và lỗi 400, 403, 429.
Cách lấy token bot Telegram: tìm lại, kiểm tra bằng getMe và thu hồi khi bị lộ
Cách lấy token bot Telegram từ @BotFather, xem lại token của bot cũ, kiểm tra bằng getMe, sửa lỗi 401 Unauthorized và thu hồi token khi bị lộ.
Chat id Telegram lấy ở đâu? Cách lấy chat id cho người dùng, group, kênh và topic
Chat id Telegram lấy ở đâu: cách lấy chat id bot cho chat riêng, group, supergroup, kênh và topic bằng getUpdates, kèm cách sửa lỗi result rỗng, 409.