Yii2配置Telegram Webhook返回302错误的解决求助
解决Yii2中Telegram Webhook返回302错误的配置问题
问题概述
将Telegram Webhook配置到Yii2项目的site/webhook路由后,Telegram返回302 Found错误,无法正常接收消息数据;若将Webhook指向根目录独立文件可获取数据,但无法执行数据库操作,需调整Yii2项目配置解决该问题。
当前配置
根目录.htaccess
Options +FollowSymLinks IndexIgnore / RewriteEngine on RewriteCond %{REQUEST_URI} ^/admin RewriteRule ^admin\/?(.*) /backend/web/$1 RewriteCond %{REQUEST_URI} !^/(frontend/web|backend/web|admin|site/webhook) RewriteRule (.*) /frontend/web/$1 [L] RewriteCond %{REQUEST_URI} ^/frontend/web RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /frontend/web/index.php [L] RewriteCond %{REQUEST_URI} ^/backend/web RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /backend/web/index.php [L]
前端SiteController代码
public function actionSetWebhook() { Yii::$app->telegram->setWebhook([ 'url' => Yii::$app->urlManager->createAbsoluteUrl(['site/webhook']), ]); } public function actionWebhook() { $data = file_get_contents('php://input'); $data = json_decode($data, true); }
错误信息
Telegram返回结果
{"ok":true,"result":{"url":"https://домен/site/webhook","has_custom_certificate":false,"pending_update_count":35,"last_error_date":1680856667,"last_error_message":"Wrong response from the webhook: 302 Found","max_connections":40,"ip_address":"айпи"}}
Yii2应用日志
2023-04-07 11:37:47 [айпи][-][-][info][application] $_GET = [ 'r' => 'site/webhook' ] $_POST = [] $_FILES = [] $_COOKIE = [] $_SERVER = [ 'REDIRECT_HTTPS' => 'on' 'REDIRECT_downgrade-1_0' => '' 'REDIRECT_suppress-error-charset' => '' 'REDIRECT_STATUS' => '200' 'HTTPS' => 'on' 'downgrade-1_0' => '' 'suppress-error-charset' => '' 'HTTP_HOST' => 'домен' 'HTTP_X_REAL_IP' => 'айпи' 'HTTP_X_PROTOCOL' => 'HTTP/1.1' 'HTTP_X_SERVER_IP' => 'айпи' 'HTTP_X_FORWARDED_PROTOCOL' => 'https' 'HTTP_X_FORWARDED_PROTO' => 'https' 'HTTP_CONNECTION' => 'close' 'CONTENT_LENGTH' => '444' 'CONTENT_TYPE' => 'application/json' 'HTTP_ACCEPT_ENCODING' => 'gzip, deflate' 'PATH' => '/usr/bin:/bin:/usr/local/bin' 'SERVER_SIGNATURE' => '' 'SERVER_SOFTWARE' => 'Apache' 'SERVER_NAME' => 'домен' 'SERVER_ADDR' => 'айпи' 'SERVER_PORT' => '80' 'REMOTE_ADDR' => 'айпи' 'DOCUMENT_ROOT' => '/home/users/o/аккаунт/domains/домен' 'REQUEST_SCHEME' => 'http' 'CONTEXT_PREFIX' => '' 'CONTEXT_DOCUMENT_ROOT' => '/home/users/o/аккаунт/domains/домен' 'SERVER_ADMIN' => 'info@jino.ru' 'SCRIPT_FILENAME' => '/home/users/o/аккаунт/domains/домен/frontend/web/index.php' 'REMOTE_PORT' => '36426' 'REDIRECT_URL' => '/site/webhook' 'REDIRECT_QUERY_STRING' => 'r=site/webhook' 'GATEWAY_INTERFACE' => 'CGI/1.1' 'SERVER_PROTOCOL' => 'HTTP/1.0' 'REQUEST_METHOD' => 'POST' 'QUERY_STRING' => 'r=site/webhook' 'REQUEST_URI' => '/site/webhook' 'SCRIPT_NAME' => '/frontend/web/index.php' 'PHP_SELF' => '/frontend/web/index.php' 'REQUEST_TIME_FLOAT' => 1680856667.8266 'REQUEST_TIME' => 1680856667 ]
解决方案
1. 调整.htaccess重写规则
修改根目录.htaccess,确保/site/webhook请求直接转发到Yii2前端入口文件:
Options +FollowSymLinks IndexIgnore / RewriteEngine on # 处理admin路由到backend RewriteCond %{REQUEST_URI} ^/admin RewriteRule ^admin\/?(.*) /backend/web/$1 [L] # 专门处理webhook路由,直接转发到frontend入口 RewriteRule ^site/webhook(/.*)?$ /frontend/web/index.php [L] # 其他请求转发到frontend/web RewriteCond %{REQUEST_URI} !^/(frontend/web|backend/web|admin) RewriteRule (.*) /frontend/web/$1 [L] # frontend的URL重写 RewriteCond %{REQUEST_URI} ^/frontend/web RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /frontend/web/index.php [L] # backend的URL重写 RewriteCond %{REQUEST_URI} ^/backend/web RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /backend/web/index.php [L]
2. 关闭Webhook路由的CSRF验证
Telegram发送的是JSON格式POST请求,不携带CSRF Token,需在SiteController中针对webhook动作关闭CSRF验证:
public function beforeAction($action) { if ($action->id === 'webhook') { $this->enableCsrfValidation = false; } return parent::beforeAction($action); }
3. 确保Webhook动作返回200响应
Telegram要求Webhook必须返回200状态码,修改actionWebhook:
public function actionWebhook() { $data = file_get_contents('php://input'); $data = json_decode($data, true); // 在这里添加消息处理逻辑(如写入数据库等) // 返回符合要求的200响应 Yii::$app->response->format = \yii\web\Response::FORMAT_RAW; Yii::$app->response->headers->set('Content-Type', 'text/plain'); return 'ok'; }
4. 配置Yii2识别HTTPS请求
若服务器通过反向代理提供HTTPS,需在frontend/config/main.php的request组件中配置信任代理:
'components' => [ 'request' => [ 'trustedHosts' => ['домен'], 'trustedProxies' => [ '你的服务器反向代理IP', // 或Telegram的IP段 ], 'secureHeaders' => [ \yii\web\Request::HEADER_X_FORWARDED_PROTO => 'https', ], ], // 其他组件配置... ]
内容的提问来源于stack exchange,提问作者Максим Егоров
相关产品推荐
相关产品推荐

