Telegram getUpdates 与 setWebhook 冲突:安全切换 Runbook
Telegram Bot API 的接收规则很直接:同一个机器人不能同时用 getUpdates 轮询和 setWebhook 推送。若部署后收不到消息,先确认当前到底由谁接收,再决定是删除 webhook 后恢复轮询,还是停止轮询 worker 后设置 webhook。Telegram 官方文档也说明,待处理 updates 只会临时保存,因此跨境团队切换客服入口时不要凭感觉操作。
关键结论
getUpdates和setWebhook是两个官方 Bot API 接收模式,不应并行使用。- 先调用
getWebhookInfo,确认当前是否还设置了 webhook URL。 - 回到轮询前,调用
deleteWebhook,并明确drop_pending_updates是否可以丢弃历史更新。 - 如果你还在比较接收路径,先看 Telegram Bot API webhook vs unified inbound webhook。
- 如果问题出在凭证概念,先读 Telegram API ID/API hash 与 bot token 的区别。
官方边界是什么
Telegram 官方 Bot API 文档把接收 updates 分成两种:getUpdates 是你的服务长轮询 Telegram;webhook 是 Telegram 向你的 HTTPS 地址发送请求。官方文档同时说明,只要 outgoing webhook 仍然存在,就不能通过 getUpdates 接收 updates;如需切回轮询,要使用 deleteWebhook。
所以大多数“切换后没消息”的问题,先按状态排查:
| 现象 | 可能状态 | 先检查 |
|---|---|---|
| 轮询没有返回消息 | webhook URL 仍在 | getWebhookInfo |
| webhook 端点没有请求 | 旧轮询 worker 仍在运行,或 webhook 未正确设置 | 停 worker,再查 getWebhookInfo |
| 内部队列重复或漏处理 | 多个应用实例抢同一份业务处理 | 先确定唯一 owner |
| 切换后涌入测试消息 | 旧 pending updates 被保留 | 决定处理还是丢弃 |
步骤 1:查看当前接收端
在受控环境执行,BOT_TOKEN 放在环境变量中,不要写进日志:
curl "https://api.telegram.org/bot$BOT_TOKEN/getWebhookInfo"
如果返回中 url 非空,说明这个 bot 仍有 webhook。若 url 为空,Bot API webhook 未启用,getUpdates 可以作为接收路径。
步骤 2:从 webhook 切回 getUpdates
先删除 webhook:
curl -X POST "https://api.telegram.org/bot$BOT_TOKEN/deleteWebhook" \
-d "drop_pending_updates=false"
生产客服消息通常应保留 false,然后由一个轮询 worker 幂等消化。只有确认 backlog 都是测试流量,或业务明确选择干净切换时,才把它设为 true。
随后只启动一个轮询 worker,并在每次 getUpdates 返回后推进 offset:
curl "https://api.telegram.org/bot$BOT_TOKEN/getUpdates?timeout=30"
步骤 3:从 getUpdates 切到 setWebhook
先停掉轮询 worker,再设置生产 webhook:
curl -X POST "https://api.telegram.org/bot$BOT_TOKEN/setWebhook" \
-d "url=https://support.example.com/telegram/bot-webhook"
接收端应快速响应:先存下 update,再让 CRM、AI 分类或人工分派异步运行。这一点也适用于 webhook-first inbound integration checklist 里的入站架构,只是 Telegram Bot API update 与 UnifyPort 事件 schema 不同。
什么时候改用统一入站 webhook
这份 runbook 解决的是 Telegram bot 的接收模式切换。它不会把 bot 变成普通账号收件箱,也不会自动统一 WhatsApp、LINE、TikTok、Zalo 或 X 的消息格式。
如果你的客服系统需要共享事件层,可以创建 UnifyPort webhook。深度文档是 Create webhook endpoint:配置 HTTPS url、status: "active",订阅 message.received 或 ["*"],需要签名时设置 signing_secret。
UnifyPort 的 Telegram 入站事件使用跨平台统一结构:
{
"id": "evt_b1a7c3e5f8",
"type": "message.received",
"provider": "telegram",
"account_id": "acc_8c21d0",
"occurred_at": "2026-06-08T12:37:00Z",
"data": {
"conversation": { "id": "5005", "type": "user" },
"sender": { "id": "4004", "type": "user", "name": "Jordan Lee" },
"message": { "id": "3003", "direction": "inbound", "sent_at": "2026-06-08T12:37:00Z", "text": "Can you check my order?" },
"event": { "kind": "message_received" }
}
}
如果用户本来就应该与 bot 对话,继续使用官方 Bot API。若目标是把现有 Telegram 账号或多个渠道的入站消息放进同一个队列,使用 UnifyPort 的非官方接口更合适。
FAQ
getUpdates 和 setWebhook 能同时使用吗?
不能。Telegram 官方把二者定义为互斥的 bot update 接收方式。轮询前删除 webhook;设置 webhook 前停止轮询。
drop_pending_updates 应该设为 true 吗?
只有当待处理更新可以丢弃时才设为 true。生产客服消息通常应保留,并用幂等存储慢慢消化。
这等于连接 Telegram 普通账号吗?
不是。getUpdates 和 setWebhook 属于 Bot API,使用 bot token。UnifyPort 连接 Telegram 账号后,会发送标准化 message.received 事件。
Sources checked on 2026-09-09
- Telegram Bot API
getUpdates: https://core.telegram.org/bots/api#getupdates - Telegram Bot API
setWebhook: https://core.telegram.org/bots/api#setwebhook - Telegram Bot API
deleteWebhook: https://core.telegram.org/bots/api#deletewebhook - Telegram webhook guide: https://core.telegram.org/bots/webhooks
- UnifyPort Create webhook endpoint
让消息接入变成一条稳定的产品管线。
先用统一 API 跑通发送,再用标准事件把所有入站消息接回业务系统。