Laravel生产环境laravel-stripe-webhooks签名无效,本地正常
Laravel 6 + Spatie Stripe Webhooks 生产环境(Forge)签名无效错误
我在Laravel 6应用中成功实现了laravel-stripe-webhooks,本地开发环境可正常处理Stripe Checkout返回的payload。但部署到Forge生产服务器后,出现签名无效错误,应用向Stripe返回500状态码。
已反复核对Stripe生产环境的webhook密钥(非Stripe CLI密钥),确认一致;查阅资料得知JSON解析修改接收的payload可能导致签名验证失败,但本地环境正常,因此可排除该原因。
完整错误信息
[2023-01-27 14:49:26] production.ERROR: The signature is invalid. {"exception":"[object] (Spatie\\WebhookClient\\Exceptions\\WebhookFailed(code: 0): The signature is invalid. at /home/forge/divorcesplit.com/vendor/spatie/laravel-webhook-client/src/Exceptions/WebhookFailed.php:11) [stacktrace] #0 /home/forge/mywebsite.com/vendor/spatie/laravel-webhook-client/src/WebhookProcessor.php(44): Spatie\\WebhookClient\\Exceptions\\WebhookFailed::invalidSignature() #1 /home/forge/mywebsite.com/vendor/spatie/laravel-webhook-client/src/WebhookProcessor.php(28): Spatie\\WebhookClient\\WebhookProcessor->ensureValidSignature() #2 /home/forge/mywebsite.com/vendor/spatie/laravel-stripe-webhooks/src/StripeWebhooksController.php(27): Spatie\\WebhookClient\\WebhookProcessor->process() #3 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(48): Spatie\\StripeWebhooks\\StripeWebhooksController->__invoke(Object(Illuminate\\Http\\Request), NULL) #4 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Routing/Route.php(219): Illuminate\\Routing\\ControllerDispatcher->dispatch(Object(Illuminate\\Routing\\Route), Object(Spatie\\StripeWebhooks\\StripeWebhooksController), '__invoke') #5 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Routing/Route.php(176): Illuminate\\Routing\\Route->runController() #6 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Routing/Router.php(681): Illuminate\\Routing\\Route->run() #7 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(130): Illuminate\\Routing\\Router->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request)) #8 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php(41): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request)) #9 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(171): Illuminate\\Routing\\Middleware\\SubstituteBindings->handle(Object(Illuminate\\Http\\Request), Object(Closure)) #10 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(78): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request)) #11 /home/forge/mywebsite.com/app/Http/Middleware/VerifyCsrfToken.php(32): Illuminate\\Foundation\\Http\\Middleware\\VerifyCsrfToken->handle(Object(Illuminate\\Http\\Request), Object(Closure)) #12 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(171): App\\Http\\Middleware\\VerifyCsrfToken->handle(Object(Illuminate\\Http\\Request), Object(Closure)) #13 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Session/Middleware/AuthenticateSession.php(39): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request)) #14 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(171): Illuminate\\Session\\Middleware\\AuthenticateSession->handle(Object(Illuminate\\Http\\Request), Object(Closure)) #15 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(49): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request)) #16 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(171): Illuminate\\View\\Middleware\\ShareErrorsFromSession->handle(Object(Illuminate\\Http\\Request), Object(Closure)) #17 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(56): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request)) #18 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(171): Illuminate\\Session\\Middleware\\StartSession->handle(Object(Illuminate\\Http\\Request), Object(Closure)) #19 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(37): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request)) #20 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(171): Illuminate\\Cookie\\Middleware\\AddQueuedCookiesToResponse->handle(Object(Illuminate\\Http\\Request), Object(Closure)) #21 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(67): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request)) #22 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(171): Illuminate\\Cookie\\Middleware\\EncryptCookies->handle(Object(Illuminate\\Http\\Request), Object(Closure)) #23 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(105): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request)) #24 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Routing/Router.php(683): Illuminate\\Pipeline\\Pipeline->then(Object(Closure)) #25 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Routing/Router.php(658): Illuminate\\Routing\\Router->runRouteWithinStack(Object(Illuminate\\Routing\\Route), Object(Illuminate\\Http\\Request)) #26 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Routing/Router.php(624): Illuminate\\Routing\\Router->runRoute(Object(Illuminate\\Http\\Request), Object(Illuminate\\Routing\\Route)) #27 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Routing/Router.php(613): Illuminate\\Routing\\Router->dispatchToRoute(Object(Illuminate\\Http\\Request)) #28 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(170): Illuminate\\Routing\\Router->dispatch(Object(Illuminate\\Http\\Request)) #29 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(130): Illuminate\\Foundation\\Http\\Kernel->Illuminate\\Foundation\\Http\\{closure}(Object(Illuminate\\Http\\Request)) #30 /home/forge/mywebsite.com/vendor/fideloper/proxy/src/TrustProxies.php(57): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request)) #31 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(171): Fideloper\\Proxy\\TrustProxies->handle(Object(Illuminate\\Http\\Request), Object(Closure)) #32 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request)) #33 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(171): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle(Object(Illuminate\\Http\\Request), Object(Closure)) #34 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request)) #35 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(171): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle(Object(Illuminate\\Http\\Request), Object(Closure)) #36 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php(27): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request)) #37 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(171): Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize->handle(Object(Illuminate\\Http\\Request), Object(Closure)) #38 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/CheckForMaintenanceMode.php(63): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request)) #39 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(171): Illuminate\\Foundation\\Http\\Middleware\\CheckForMaintenanceMode->handle(Object(Illuminate\\Http\\Request), Object(Closure)) #40 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(105): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request)) #41 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(145): Illuminate\\Pipeline\\Pipeline->then(Object(Closure)) #42 /home/forge/mywebsite.com/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(110): Illuminate\\Foundation\\Http\\Kernel->sendRequestThroughRouter(Object(Illuminate\\Http\\Request)) #43 /home/forge/mywebsite.com/public/index.php(55): Illuminate\\Foundation\\Http\\Kernel->handle(Object(Illuminate\\Http\\Request)) #44 {main} "}
解决建议
- 排除CSRF验证:确认
App\Http\Middleware\VerifyCsrfToken的$except数组已添加webhook路由(比如'stripe/webhooks'),避免CSRF中间件干扰请求处理。 - 验证环境变量加载:在生产服务器执行
php artisan tinker,运行echo config('stripe-webhooks.signing_secret'),确认输出的是Stripe生产环境的webhook密钥,而非本地开发密钥。若不一致,重新配置环境变量并执行php artisan config:cache刷新配置缓存。 - 检查服务器时间同步:Stripe签名验证依赖时间戳,若服务器与Stripe时间差超过5分钟会导致验证失败。执行
date命令查看服务器时间,对比标准时间,若不同步,手动同步NTP服务。 - 确认Nginx配置未修改请求体:Forge默认的Nginx配置可能开启gzip压缩或修改请求体,需确保webhook路由的Nginx配置中未对请求体进行修改,可添加
proxy_pass_request_body on;并关闭请求压缩相关配置。 - 检查TrustProxies中间件:Laravel 6的
TrustProxies中间件需正确配置代理IP,在App\Http\Middleware\TrustProxies中设置$proxies = '*';(或具体的Forge代理IP),避免请求头被代理篡改。 - 测试原始请求体读取:临时在webhook控制器中添加代码,输出原始请求体和
Stripe-Signature头,确认与Stripe发送的内容一致,排除中间件修改请求体的可能。
内容的提问来源于stack exchange,提问作者Hondaman900
相关产品推荐
相关产品推荐

