如何在Laravel 9中监听Stripe支付链接的支付成功状态?
解决方案:通过Stripe Webhook与返回URL处理支付完成逻辑
一、配置Stripe Webhook(核心通知渠道)
- 登录Stripe后台,进入「开发者」→「Webhooks」,添加端点:
你的域名/stripe/webhook - 勾选监听事件:
checkout.session.completed(支付链接完成支付后会触发该事件) - 复制签名密钥,在Laravel的
.env中添加:STRIPE_WEBHOOK_SECRET=你的签名密钥
二、修改Enroll方法生成带跳转参数的支付链接
在你的控制器enroll方法中,生成支付链接时指定成功/取消跳转地址,并通过metadata存储用户、课程标识,方便后续关联处理:
public function enroll(Request $request) { $courseId = $request->course_id; $userEmail = $request->email; // 未注册用户可先收集邮箱 // 创建Stripe Checkout Session(支付链接本质是该Session的跳转地址) $session = \Stripe\Checkout\Session::create([ 'payment_method_types' => ['card'], 'line_items' => [[ 'price' => '你的课程Stripe价格ID', // 替换为你在Stripe后台创建的价格ID 'quantity' => 1, ]], 'mode' => 'payment', 'success_url' => route('payment.success', ['course_id' => $courseId]) . '?session_id={CHECKOUT_SESSION_ID}', 'cancel_url' => route('payment.cancel'), 'metadata' => [ 'course_id' => $courseId, 'user_email' => $userEmail, ], ]); // 重定向至Stripe支付页面 return redirect()->away($session->url); }
三、创建Webhook控制器处理支付完成事件
生成控制器并编写事件处理逻辑:
php artisan make:controller StripeWebhookController
控制器代码:
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Stripe\Webhook; use Stripe\Stripe; use App\Models\User; use App\Models\CourseEnrollment; use Illuminate\Support\Str; class StripeWebhookController extends Controller { public function handle(Request $request) { Stripe::setApiKey(env('STRIPE_SECRET')); $payload = $request->getContent(); $sigHeader = $request->header('Stripe-Signature'); $webhookSecret = env('STRIPE_WEBHOOK_SECRET'); // 验证Stripe签名,防止伪造请求 try { $event = Webhook::constructEvent($payload, $sigHeader, $webhookSecret); } catch (\Exception $e) { return response('', 400); } // 处理支付完成事件 if ($event->type === 'checkout.session.completed') { $session = $event->data->object; $courseId = $session->metadata->course_id; $userEmail = $session->metadata->user_email; // 1. 创建/获取用户(未注册用户自动创建账号) $user = User::firstOrCreate( ['email' => $userEmail], ['name' => explode('@', $userEmail)[0], 'password' => bcrypt(Str::random(10))] // 可后续引导用户重置密码 ); // 2. 记录选课信息并激活课程权限 CourseEnrollment::firstOrCreate( ['stripe_session_id' => $session->id], [ 'user_id' => $user->id, 'course_id' => $courseId, 'status' => 'active' ] ); // 可选:发送课程访问通知邮件 // Mail::to($user)->send(new CourseAccessGranted($user, $courseId)); } return response('', 200); } }
四、配置Webhook路由(排除CSRF验证)
在routes/web.php中添加路由:
use App\Http\Controllers\StripeWebhookController; // Stripe Webhook路由,排除CSRF验证 Route::post('/stripe/webhook', [StripeWebhookController::class, 'handle'])->withoutMiddleware(['csrf']);
五、支付成功/取消页面处理
添加跳转路由与视图逻辑:
// 支付成功页面 Route::get('/payment/success', function(Request $request) { $sessionId = $request->session_id; $courseId = $request->course_id; // 可选:二次验证支付状态 $session = \Stripe\Checkout\Session::retrieve($sessionId); if ($session->payment_status !== 'paid') { return redirect()->route('payment.cancel'); } return view('payment.success', compact('courseId')); })->name('payment.success'); // 支付取消页面 Route::get('/payment/cancel', function() { return view('payment.cancel'); })->name('payment.cancel');
关键注意事项
- Webhook必须公网可访问,本地开发可使用
ngrok暴露端口(如ngrok http 8000) - 必须验证Webhook签名,避免恶意请求
- 处理事件时要保证幂等性(比如通过
stripe_session_id判断是否已处理),防止重复创建用户或选课记录
内容的提问来源于stack exchange,提问作者BMM
相关产品推荐
相关产品推荐

