Laravel Cashier支付成功后代码未执行、页面未跳转问题排查
问题排查与解决方案
你的核心问题在于:当触发IncompletePayment异常跳转到支付页面后,支付完成的流程不会回到原控制器动作,导致后续创建Product的代码无法执行,同时跳转逻辑也未按预期触发。以下是具体排查点和修复方案:
1. 根源分析
原代码中,Product创建逻辑仅在订阅直接创建成功(用户无需额外支付验证)时才会执行。但当用户需要跳转支付页面完成验证时,支付流程结束后不会回到原控制器方法,因此后续代码完全不会运行,直接跳转到dashboard也没有处理订阅完成后的收尾逻辑。
2. 分步修复方案
步骤1:新增支付完成后的处理路由
不要直接跳转到dashboard,而是创建一个专门的路由来处理支付完成后的订阅确认与Product创建:
// 在routes/web.php中添加 Route::get('/payment-complete/{paymentId}', [ProductController::class, 'handlePaymentComplete'])->name('payment.complete');
步骤2:修改原控制器的异常重定向逻辑
将支付页面的redirect参数指向新路由,传递支付ID以便后续验证:
$user = Auth::user(); // 先把产品信息存入session(避免支付跳转后丢失) session([ 'product_title' => $this->title, 'product_icon_url' => $this->icon_url, ]); try { $subscription = $user->newSubscription('default', env('STRIPE_PRICE_ID'))->create(); // 若订阅直接创建成功,直接生成Product $prod = new Product([ 'title' => $this->title, 'icon_url' => $this->icon_url, ]); $prod->user()->associate($user); $prod->save(); return redirect()->route('dashboard')->with('success', '订阅完成,产品已创建'); } catch (IncompletePayment $exception) { return redirect()->route( 'cashier.payment', [ $exception->payment->id, 'redirect' => route('payment.complete', ['paymentId' => $exception->payment->id]) ] ); }
步骤3:实现支付完成后的处理方法
在ProductController中添加方法,验证支付状态、确认订阅后创建Product:
public function handlePaymentComplete($paymentId) { $user = Auth::user(); $payment = $user->findPayment($paymentId); // 验证支付是否完成,订阅是否激活 if ($payment && $payment->isCompleted()) { $subscription = $user->subscription('default'); if ($subscription && $subscription->active()) { // 从session中取出产品信息创建Product $prod = new Product([ 'title' => session('product_title'), 'icon_url' => session('product_icon_url'), ]); $prod->user()->associate($user); $prod->save(); // 清理session临时数据 session()->forget(['product_title', 'product_icon_url']); return redirect()->route('dashboard')->with('success', '支付完成,产品已创建'); } } return redirect()->route('dashboard')->with('error', '支付或订阅状态验证失败'); }
步骤4:检查Stripe Webhook配置(关键)
确保Stripe Webhook已正确配置,因为支付完成后Stripe会发送事件通知Cashier更新订阅状态:
- 在Stripe后台添加Webhook端点:
你的域名/stripe/webhook - 在
.env中设置STRIPE_WEBHOOK_SECRET,值取自Stripe后台的Webhook签名密钥 - 确保路由文件包含Cashier的Webhook路由:
Route::post('/stripe/webhook', '\Laravel\Cashier\Http\Controllers\WebhookController@handleWebhook');
内容的提问来源于stack exchange,提问作者sameer manek
相关产品推荐
相关产品推荐

