Laravel 8集成Stripe与spatie webhook客户端后数据库无法接收支付数据求助
问题原因定位及解决办法
核心错误原因
Webhook是Stripe服务端主动向应用发起的异步回调请求,和用户前端登录的会话完全独立,不存在登录态,所以auth()->user()永远返回null,if ($user)的判断永远不成立,Payment::create代码根本不会执行,这是数据库没有写入数据的最主要原因。
其他可能的原因
- 队列未启动/未正常消费:你的Job实现了
ShouldQueue接口属于异步任务,如果没有启动队列消费进程(php artisan queue:work),任务会一直堆积在队列中不会执行,自然不会写入数据。 - 字段不允许批量赋值:检查
Payment模型的$fillable属性是否包含了user_id、stripe_id、amount、product_id这几个字段,如果没有配置的话,create方法会静默丢弃这些字段导致写入失败。 - 字段映射错误:你当前代码把
$charge['currency']赋值给了product_id,属于明显的逻辑错误,你需要从Charge对象里取关联的产品ID,或者从Charge的metadata里取下单时存入的产品ID参数,不能把货币值赋值给产品ID字段。 - 没有提前存储用户标识到Stripe对象中:你创建支付Intent/Checkout Session的时候,需要把当前用户ID存到Stripe对象的
metadata参数里,回调的时候从$charge['metadata']['user_id']取用户ID,不能依赖登录态获取用户信息。
修正后代码参考
<?php namespace App\Jobs\StripeWebhooks; use App\Models\Payment; use App\Models\User; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; use Spatie\WebhookClient\Models\WebhookCall; class ChargeSucceededJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; public $webhookCall; public function __construct(WebhookCall $webhookCall) { $this->webhookCall = $webhookCall; } public function handle() { $charge = $this->webhookCall->payload['data']['object']; // 从Stripe对象的metadata取创建支付时预先存入的用户ID、产品ID $userId = $charge['metadata']['user_id'] ?? null; $productId = $charge['metadata']['product_id'] ?? null; if ($userId && $productId) { $user = User::find($userId); if ($user) { Payment::create([ 'user_id' => $user->id, 'stripe_id' => $charge['id'], 'amount' => $charge['amount'], 'product_id' => $productId, ]); } } } }
额外排查建议
- 可以在Job的handle方法开头加日志
\Log::info('ChargeSucceededJob执行', ['payload' => $this->webhookCall->payload]),确认任务是否真的被执行,以及参数是否正确。 - 检查
storage/logs目录下的Laravel日志,看是否有任务执行报错信息。 - 测试环境可以先去掉Job的
ShouldQueue接口,改成同步执行,方便直接排查报错。
内容的提问来源于stack exchange,提问作者Swimo Omix
相关产品推荐
相关产品推荐

