Laravel Cashier (Stripe) 自定义Webhook无法接收payload且报参数缺失错误
问题根因
你遇到的参数数量报错,核心是把具体事件的处理方法直接注册成了Webhook的路由入口,完全不符合Laravel Cashier的Webhook流转逻辑。
Laravel Cashier的Webhook控制器自带统一入口方法handleWebhook,所有Stripe的回调请求都会先走到这个方法,自动完成Stripe签名校验、请求体JSON解析、根据事件名自动分发到对应处理方法的全流程,最后才把解析好的payload数组传入匹配的事件处理方法。你直接把路由指向handleCheckoutSessionCompleted,相当于跳过了所有前置的参数传递逻辑,框架在调用这个方法时找不到任何可传入的参数,自然会报“需要1个参数但实际传入0个”的错误。
逐步排查解决
- 修正路由注册规则
删掉原来直接绑定事件处理方法的错误路由,改成指向自定义Webhook控制器的统一入口handleWebhook,正确写法参考:// routes/web.php 内 use App\Http\Controllers\StripeWebhookController; Route::post('/stripe/webhook', [StripeWebhookController::class, 'handleWebhook']); - 校验自定义控制器的方法定义
确保继承Cashier的核心Webhook控制器后,事件处理方法的命名、参数格式严格和Cashier约定保持一致,不要自行添加多余的依赖注入参数,正确的控制器结构参考:<?php namespace App\Http\Controllers; use Laravel\Cashier\Http\Controllers\WebhookController as CashierWebhookController; class StripeWebhookController extends CashierWebhookController { // 方法名严格按规则映射:事件checkout.session.completed 转大驼峰加handle前缀 public function handleCheckoutSessionCompleted(array $payload) { // 这里写你的业务逻辑,$payload是已经过校验、解析的完整事件数组 } } - 确认CSRF排除规则生效
你已经在VerifyCsrfToken的$except属性加了stripe/*,需要再确认匹配范围覆盖实际的路由路径:如果你的Webhook路由是/stripe/webhook,stripe/*可以正常匹配;如果存在路径偏移、域名前缀,需要调整匹配规则,也可以直接在路由定义时链式调用->withoutMiddleware(VerifyCsrfToken::class),确保跳过CSRF校验。 - 核对Webhook密钥配置
检查.env中配置的CASHIER_STRIPE_WEBHOOK_SECRET,和Stripe后台对应Webhook端点的签名密钥完全一致,不要混用其他端点的密钥,否则会在入口验签阶段直接返回403,根本进不到你的自定义事件处理逻辑。 - 对齐Stripe端的回调配置
登录Stripe后台确认两个配置:一是你填的Webhook公网回调地址,和本地/线上实际可访问的路由地址完全一致(不要多、少斜杠这类格式差异);二是这个Webhook端点确实勾选了checkout.session.completed事件,避免事件根本没推送到你的服务。
快速验证技巧
可以用Stripe CLI在本地模拟推送Webhook事件,不需要把本地服务暴露到公网,就能快速走通从请求接收到业务逻辑执行的全流程。排查时可以在handleCheckoutSessionCompleted方法开头写一行日志打印接收到的$payload,确认数据是否正常流入。
内容的提问来源于stack exchange,提问作者Yuami
相关产品推荐
相关产品推荐

