Telegram Webhook重复请求问题求助(PHP应用场景)
解决Telegram Webhook重复发送POST请求的问题
我看到你遇到了Telegram Webhook重复发送请求的问题——虽然你的PHP应用返回了200 OK,用户也能收到Bot的回复,但Telegram还是不断重试请求。从你提供的getWebhookInfo响应来看,核心问题是Unsupported Media Type: unsupported content-encoding这个错误,这才是Telegram判定请求未被正确处理、进而重复发送的根本原因,而不是单纯的200响应。
下面是针对性的解决方案:
1. 确认PHP启用zlib扩展
Telegram会用gzip压缩Webhook请求的JSON数据,你的PHP应用需要zlib扩展来解压这些请求:
- 检查扩展状态:
- 创建
phpinfo.php文件并访问,查看zlib相关配置是否存在; - 或在命令行执行:
php -m | grep zlib,输出zlib则说明已启用。
- 创建
- 未启用的话:
- 打开
php.ini,找到extension=zlib.so(Linux)或extension=php_zlib.dll(Windows),去掉前面的注释符号;; - 确保
zlib.output_compression = On(可选,优化响应压缩); - 重启Web服务器(Apache/Nginx)和PHP-FPM(若使用)。
- 打开
2. 在应用中手动处理gzip压缩的请求体
即使启用了zlib扩展,PHP默认不会自动处理gzip压缩的POST数据,需要手动解压。在Webhook处理脚本最开头添加以下代码:
// 检查请求是否使用gzip压缩 if (isset($_SERVER['HTTP_CONTENT_ENCODING']) && strpos($_SERVER['HTTP_CONTENT_ENCODING'], 'gzip') !== false) { // 读取原始压缩请求体 $rawInput = file_get_contents('php://input'); // 解压内容 $decodedInput = gzdecode($rawInput); // 将解压后的JSON解析到$_POST(适配依赖$_POST的逻辑) if ($decodedInput) { $_POST = json_decode($decodedInput, true); } }
如果你使用Telegram Bot SDK,需要修改SDK内部的请求处理逻辑,确保它能读取并解压php://input的内容,而非直接依赖$_POST。
3. 确保响应符合Telegram的要求
除了200状态码,响应格式也会影响Telegram的判断:
- 响应的
Content-Type建议设为application/json或text/plain; - 处理成功时返回空响应或简单的
{"ok": true}即可,无需额外内容; - 示例响应代码:
http_response_code(200); header('Content-Type: application/json'); echo json_encode(['ok' => true]); // 或直接echo ''; exit; // 确保脚本立即终止,避免输出多余内容
4. 重置Webhook并验证修复效果
完成修改后,需要重置Webhook清除错误状态:
- 调用Telegram Bot API的
deleteWebhook方法(可用curl或SDK实现); - 重新设置Webhook,确保URL正确;
- 再次调用
getWebhookInfo,检查:last_error_message是否消失;pending_update_count是否逐渐减少(说明Telegram不再重复发送请求)。
额外排查点
- 若使用反向代理(如Nginx),确保代理未修改
Content-Encoding头,可在location配置中添加:proxy_set_header Accept-Encoding ""; proxy_pass_request_headers on; - 查看服务器错误日志,确认是否有解压失败的相关报错;
- 验证服务器响应时间不超过5秒(Telegram的超时阈值)。
内容的提问来源于stack exchange,提问作者Арсен Гоян




