在Telegram机器人开发中,Webhook机制是实现服务器实时推送消息的关键。相比轮询(Polling),Webhook能让Telegram在机器人收到新消息时主动向你的服务器发送HTTPS请求,从而显著降低延迟和资源消耗。本教程将手把手教你如何从零配置Webhook,并提供可直接运行的代码示例,帮助你快速上手。
一、Webhook核心概念与工作原理
Webhook是一种反向API回调:Telegram服务器作为客户端,你的服务器作为服务端。当用户向机器人发送消息时,Telegram会向预先设定的URL地址发送一个包含消息数据的JSON对象。开发者只需在服务器上监听该URL并处理收到的数据即可。
与GetUpdates轮询相比,Webhook具有以下优势:
- 实时性高:消息即时推送,无需客户端轮询间隔。
- 资源占用低:服务器只需处理有消息时的请求。
- 支持双向推送:便于实现主动发送消息(如定时通知)。
但使用Webhook必须满足两个基本要求:
- 服务器必须拥有公网IP且能通过HTTPS访问;
- 需配置有效的SSL证书(Telegram不支持自签名证书,但支持通过Linux Foundation签发的免费证书)。
二、准备工作:创建机器人与获取令牌
所有Telegram机器人都需要先通过BotFather创建。步骤如下:
- 在Telegram中打开
@BotFather,发送/newbot命令。 - 按照提示设置机器人显示名称和用户名(用户名必须以
bot结尾,如MyRssBot)。 - 创建成功后,BotFather会返回一个HTTP API令牌(形如
123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11)。请立即保存并保持机密,该令牌是控制机器人的唯一凭证。
三、配置Webhook的三种方法
获取令牌后,可通过以下任一方式设置Webhook地址。
方法一:使用浏览器直接访问URL(最快速)
在浏览器中打开以下API地址(请替换自己的令牌和URL):
https://api.telegram.org/bot<你的令牌>/setWebhook?url=https://yourdomain.com/webhook
若设置成功,页面会返回 {"ok":true,"result":true,"description":"Webhook was set"}。
方法二:使用curl命令(服务器端推荐)
curl -F "url=https://yourdomain.com/webhook" "https://api.telegram.org/bot<你的令牌>/setWebhook"
方法三:编写代码脚本动态设置
在您的后端代码中调用API接口,以便在应用启动时自动注册。
// Node.js 示例
const token = '你的令牌';
const webhookUrl = 'https://yourdomain.com/webhook';
const res = await fetch(`https://api.telegram.org/bot$/setWebhook?url=$`);
const data = await res.json();
console.log(data);
四、Webhook服务器的实现(Node.js示例)
创建Webhook端点,接收Telegram推送的Update对象。以下为使用Express的完整示例:
const express = require('express');
const app = express();
app.use(express.json());
const BOT_TOKEN = '你的令牌';
const TELEGRAM_API = `https://api.telegram.org/bot$`;
app.post('/webhook', (req, res) => {
const update = req.body;
const { message } = update;
if (message && message.text) {
console.log('收到消息:', message.text);
// 这里可以调用API回复消息
// fetch(TELEGRAM_API + '/sendMessage', {
// method: 'POST',
// headers: { 'Content-Type': 'application/json' },
// body: JSON.stringify({ chat_id: message.chat.id, text: '你好!' })
// });
}
res.sendStatus(200); // 必须尽快响应200,否则Telegram会重试
});
app.listen(3000, () => console.log('Webhook server listening on port 3000'));
关键点:一定要返回200状态码,否则Telegram会按指数退避策略重试发送同一更新,导致重复处理。
五、Webhook服务器的Python实现(Flask)
from flask import Flask, request, jsonify
import requests
app = Flask(__name__)
BOT_TOKEN = '你的令牌'
TELEGRAM_API = f'https://api.telegram.org/bot'
@app.route('/webhook', methods=['POST'])
def webhook():
update = request.get_json()
if 'message' in update:
chat_id = update['message']['chat']['id']
text = update['message'].get('text','')
print(f'收到消息: ')
# 回复消息
requests.post(f'/sendMessage', json={'chat_id': chat_id, 'text': '收到!'})
return 'OK', 200
if __name__ == '__main__':
app.run(host='0.0.0.0', port=443, ssl_context=('cert.pem', 'key.pem')) # 本地测试时用,生产建议用Nginx反代
六、SSL证书与HTTPS部署要点
Telegram要求Webhook必须使用HTTPS。常见解决方案:
- 使用云服务器厂商提供的免费证书(如Let's Encrypt)。
- 将Nginx作为反向代理,配置好SSL后把请求转发到本地应用的HTTP端口。
- 如果使用Python/Node开发,也可直接配置证书,但更推荐Nginx统一处理。
示例Nginx配置:
server {
listen 443 ssl;
server_name yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
location /webhook {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
七、验证Webhook是否设置成功
使用 getWebhookInfo 方法检查状态:
https://api.telegram.org/bot<令牌>/getWebhookInfo
响应中会包含 url have_custom_certificate pending_update_count last_error_message 等字段,方便调试。
八、常见问题排查
1. 设置Webhook时报错“Bad Request: can't use getUpdates method while webhook is active”
原因是当前有正在运行的轮询程序。必须先删除或停用所有通过getUpdates获取更新的进程,再设置Webhook。可先调用 deleteWebhook 清空旧配置。
2. Webhook一直收不到消息
使用 getWebhookInfo 查看 last_error_message,常见错误为“Wrong URL”或“SSL certificate error”。检查URL是否公网可访问、证书是否有效。
3. 重复收到相同消息
可能是因为没有及时返回200或处理时间超过请求超时。确保你的处理逻辑尽量轻量,或先返回200再异步处理业务逻辑。
4. 如何关闭Webhook恢复轮询
调用 /deleteWebhook?drop_pending_updates=true,然后使用getUpdates即可。
总结
Webhook机制是开发Telegram机器人时必须掌握的核心技能。通过本指南,你已经学会了从创建Bot到配置SSL、编写服务器代码以及排查常见问题。实际项目中,还需结合数据库、消息队列等实现复杂逻辑。建议先使用本地内网穿透工具(如ngrok)做测试,再部署到生产环境。
如果你在配置过程中遇到其他问题,欢迎在评论区留言,我们会持续更新教程。