python-telegram-bot在Heroku部署时设置Webhook遇端口错误求助
我完全理解你被这个问题困扰一周的焦急心情,其实这个错误的核心原因是你的代码没有适配Heroku的WSGI运行环境——虽然你指定了端口,但Telegram无法正确和Heroku的反向代理以及你的Bot内置服务器建立连接。下面是具体的解决方案:
问题分析
Heroku采用反向代理机制:外部的HTTPS请求(默认走合规的443端口)会被转发到它为你的应用分配的动态端口上。但你的代码使用Updater.start_webhook启动了内置的web服务器,这种方式和Heroku的运行模型不兼容,导致Telegram端误判你的Webhook端口不符合要求。
解决方案:改用Flask处理Webhook请求
我们需要调整代码,用Flask作为Web服务入口接收Telegram的Webhook请求,再把请求转交给Dispatcher处理,同时配置Heroku的Procfile来正确启动应用。
1. 修改Bot代码
替换你现有的代码为以下版本(记得根据需求添加自己的处理器逻辑):
from configparser import ConfigParser import logging import os import telegram from flask import Flask, request from telegram.ext import Dispatcher, MessageHandler, Filters, CommandHandler # 配置日志,方便排查问题 logging.basicConfig( format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO ) logger = logging.getLogger(__name__) # 加载配置(建议后续改用Heroku环境变量存储TOKEN,更安全) env = ConfigParser() env.read('config.ini') TOKEN = env['TELEGRAM']['ACCESS_TOKEN'] # 读取Heroku分配的动态端口,本地测试默认用5000 PORT = int(os.environ.get('PORT', 5000)) # 初始化Flask应用 app = Flask(__name__) # 初始化Telegram Bot和Dispatcher bot = telegram.Bot(token=TOKEN) dispatcher = Dispatcher(bot, None, use_context=True) # --- 这里添加你的Bot处理器逻辑 --- def start_command(update, context): update.message.reply_text('🎉 欢迎使用我的Bot!') def echo_message(update, context): update.message.reply_text(f'你说:{update.message.text}') # 注册处理器 dispatcher.add_handler(CommandHandler('start', start_command)) dispatcher.add_handler(MessageHandler(Filters.text & ~Filters.command, echo_message)) # --- Webhook路由配置 --- @app.route(f'/{TOKEN}', methods=['POST']) def webhook(): if request.method == 'POST': # 解析Telegram发送的更新数据 update = telegram.Update.de_json(request.get_json(force=True), bot) dispatcher.process_update(update) return 'ok', 200 return 'Method Not Allowed', 405 # 用于手动触发设置Webhook的路由(可选) @app.route('/') def set_webhook_route(): webhook_url = f'https://tgbot00.herokuapp.com/{TOKEN}' success = bot.set_webhook(url=webhook_url) if success: return '✅ Webhook设置成功!' return '❌ Webhook设置失败,请检查配置' if __name__ == '__main__': app.run(host='0.0.0.0', port=PORT)
2. 创建Procfile
在项目根目录创建一个名为Procfile的文件(无后缀名),内容如下:
web: gunicorn your_bot_script_name:app
把your_bot_script_name替换成你的Python脚本文件名(比如脚本叫telegram_bot.py,就写成telegram_bot:app)。这个文件告诉Heroku用gunicorn(WSGI服务器)来运行你的Flask应用。
3. 额外优化建议
- 用Heroku环境变量存储TOKEN:避免把敏感的TOKEN提交到版本控制,你可以在Heroku控制台的「Settings」→「Config Vars」里添加
TELEGRAM_ACCESS_TOKEN,然后代码里改成TOKEN = os.environ.get('TELEGRAM_ACCESS_TOKEN'),删除config.ini相关代码会更安全。 - 确认域名可访问:部署后先访问
https://tgbot00.herokuapp.com,如果能看到Webhook设置的提示,说明应用启动正常。
为什么这样能解决问题?
通过Flask作为WSGI应用,我们能完美适配Heroku的反向代理机制:Telegram向https://tgbot00.herokuapp.com/{TOKEN}(443端口)发送请求,Heroku会把请求转发到你的应用监听的动态端口上,Flask接收后转交给Dispatcher处理,这样Telegram端看到的Webhook端口是合规的443,自然不会再报错。
内容的提问来源于stack exchange,提问作者codinLover

