You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无mod rewrite的Yii应用SendGrid事件Webhook无法携带GET参数问题

问题解决:SendGrid Event Webhook 适配无mod rewrite的Yii应用

核心结论

SendGrid的Event Webhook不会保留URL中的GET查询参数,它只会将事件数据以POST请求方式发送,原URL里的?r=...这类参数会被忽略——这就是你配置https://example.com/?r=sendgrid/action后没收到请求的核心原因(SendGrid实际请求的是不带查询参数的地址,Yii无法识别路由)。

解决方案

方法1:新增独立的Webhook接收脚本

在网站根目录创建单独的PHP文件(比如sendgrid-webhook.php),直接在脚本里初始化Yii并调用目标控制器动作:

<?php
// 引入Yii配置和入口逻辑(路径根据你的项目结构调整)
require_once(__DIR__ . '/protected/config/main.php');
// 直接调用指定控制器的动作
Yii::createWebApplication($config)->runController('sendgrid/action');

随后把SendGrid的Webhook配置为https://example.com/sendgrid-webhook.php即可,SendGrid发送的POST请求会触发这个脚本,进而调用你的Yii控制器处理事件。

方法2:修改Yii入口文件适配路由

如果不想新增脚本,可以修改根目录的index.php,判断是否为SendGrid的请求,强制指定路由参数:

<?php
$config = __DIR__ . '/protected/config/main.php';

// 通过请求头识别SendGrid的Webhook请求
$isSendGridHook = isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'SendGrid') !== false;
if ($isSendGridHook) {
    // 强制设置Yii路由参数
    $_GET['r'] = 'sendgrid/action';
}

Yii::createWebApplication($config)->run();

之后把SendGrid的Webhook配置为https://example.com/index.php即可,请求会被Yii正确路由到目标控制器。

额外建议:验证请求合法性

为避免恶意请求,建议在控制器的处理动作里添加SendGrid请求签名验证:

public function actionAction() {
    $signature = $_SERVER['HTTP_X_TWILIO_EMAIL_EVENT_WEBHOOK_SIGNATURE'] ?? '';
    $timestamp = $_SERVER['HTTP_X_TWILIO_EMAIL_EVENT_WEBHOOK_TIMESTAMP'] ?? '';
    $payload = file_get_contents('php://input');
    $secret = '你的SendGrid签名密钥'; // 从SendGrid后台获取

    // 验证签名
    $expectedSignature = hash_hmac('sha256', $timestamp . $payload, $secret);
    if (!hash_equals($expectedSignature, $signature)) {
        http_response_code(403);
        exit('Invalid request');
    }

    // 处理事件数据
    $events = json_decode($payload, true);
    // 你的业务逻辑代码
}

内容的提问来源于stack exchange,提问作者Denis Chenu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 05:36:11