GitHub Webhook 在 XAMPP 本地收不到请求,是因为 GitHub 仅支持公网可访问的 http/https URL,而 localhost 不可达,需用 ngrok 等内网穿透工具暴露本地端口,并正确配置 Payload URL、Content type 为 application/json、PHP 接收逻辑及服务器参数。

为什么 GitHub Webhook 在 XAMPP 本地收不到请求?
因为 GitHub 默认只支持 http 或 https 协议的公开 URL,而 XAMPP 运行在 localhost(如 http://localhost:8080)时,GitHub 无法从外网访问你的机器——它不是“不可达”,而是根本不会发请求过去。你看到的“无响应”或 GitHub 后台显示 Connection refused,本质是网络层阻断,不是 PHP 或 Apache 配错了。
所以第一步必须绕过这个限制:用内网穿透工具把本地端口映射成公网可访问地址。推荐用 ngrok(轻量、免部署、有免费额度),不建议用 localtunnel 或自建反代——它们对 Webhook 的 POST body 解析兼容性更差。
如何用 ngrok 暴露 XAMPP 的 webhook.php?
确保 XAMPP 的 Apache 已启动,并且你的接收脚本放在 htdocs/webhook/ 下,比如 htdocs/webhook/receive.php。该文件至少要能响应 POST 并记录原始 payload:
file_put_contents('log.txt', print_r(file_get_contents('php://input'), true) . "\n", FILE_APPEND);
然后执行:
ngrok http 80(假设 XAMPP 用默认 80 端口;若改过,请替换为实际端口,如 ngrok http 8080)
命令返回类似 https://a1b2c3d4.ngrok-free.app 的地址,这就是你要填进 GitHub Webhook URL 的值。注意必须用 https 开头,GitHub 强制要求。
- 不要在 ngrok 命令后加路径(如
ngrok http 80/webhook),它只代理端口,路径由你自己的 PHP 路由处理 - ngrok 免费版每次重启会换域名,Webhook URL 需同步更新;可注册账号后绑定子域名避免频繁改配置
- 如果收到
400 Bad Request,大概率是 GitHub 发送了application/json数据,但你的 PHP 没正确读取——务必用file_get_contents('php://input'),别依赖$_POST
GitHub Webhook 配置里哪些字段不能错?
进入仓库 Settings → Webhooks → Add webhook,关键项如下:
-
Payload URL:填 ngrok 提供的完整地址,例如https://a1b2c3d4.ngrok-free.app/webhook/receive.php -
Content type必须选application/json(不是application/x-www-form-urlencoded) -
Which events would you like to trigger this webhook?:先勾选Just the push event,验证通了再扩展 -
Active:确保打钩
保存后,点右侧的 Test webhook。如果失败,点击触发记录旁的 Redeliver 查看详细错误——重点关注 Response 标签页里的状态码和响应体。常见问题是 PHP 脚本报错导致返回 500,或者没输出任何内容导致 GitHub 认为超时(默认 10 秒)。
PHP 接收端要防哪些坑?
XAMPP 默认关闭 display_errors,Webhook 请求失败时你看不到报错,只会得到空响应。调试前先在 receive.php 开头加:
error_reporting(E_ALL); ini_set('display_errors', 1);
同时注意:
- GitHub Webhook 请求带
X-Hub-Signature-256头,用于校验 payload 完整性。如果你没配 secret,就别校验;一旦配了 secret,PHP 必须用hash_hmac('sha256', $payload, $secret)对比,否则所有请求都会被拒绝 - Apache 的
post_max_size和max_execution_time默认值偏小,大仓库 push 可能含大量 commit 数据,建议在php.ini中调高:post_max_size = 20M,max_execution_time = 30 - 不要在脚本里直接
exit或die后续逻辑,GitHub 会等响应结束才认为送达成功;哪怕只是写日志,也要保证 HTTP 200 返回
本地测试最易忽略的是:ngrok 进程退出后链接立刻失效,而 GitHub 不会主动通知你。只要发现 webhook 突然不触发,第一反应应该是检查 ngrok 是否还在运行。

















