You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 8中Stripe Webhook如何获取认证用户以更新账户?

解决Laravel中Stripe支付链接Webhook无法关联用户的问题

方案一:通过Stripe客户关联+元数据映射(推荐)

核心思路是提前为已登录用户创建Stripe Customer并绑定Laravel用户ID,再通过支付链接的URL参数关联该客户,最终从Webhook的客户信息中反向获取用户ID。

  1. 提前创建并绑定Stripe Customer
    在用户访问定价页(或首次支付前),检查用户是否已有Stripe客户ID,没有则创建并关联,同时将Laravel用户ID存入Stripe Customer的元数据:
// 可放在定价页控制器或User模型的方法中
$user = auth()->user();
if (!$user->stripe_customer_id) {
    $stripeCustomer = \Stripe\Customer::create([
        'email' => $user->email,
        'metadata' => [
            'laravel_user_id' => $user->id,
        ],
    ]);
    $user->update(['stripe_customer_id' => $stripeCustomer->id]);
}
  1. 在支付链接中指定客户ID
    前端渲染支付按钮时,将用户的Stripe客户ID作为URL参数拼到支付链接后:
{{-- 定价页blade模板 --}}
<a href="https://buy.stripe.com/your_payment_link_id?customer={{ $user->stripe_customer_id }}" 
   class="btn btn-primary">立即购买</a>
  1. Webhook中关联用户并更新账户
    在Spatie的Webhook处理任务中,从会话对象拿到客户ID,调用Stripe API获取客户元数据,进而找到对应Laravel用户:
public function handle(array $payload)
{
    $session = $payload['data']['object'];
    $stripeCustomerId = $session['customer'];
    
    // 拉取Stripe客户详情
    $stripeCustomer = \Stripe\Customer::retrieve($stripeCustomerId);
    $laravelUserId = $stripeCustomer->metadata['laravel_user_id'];
    
    $user = \App\Models\User::find($laravelUserId);
    if ($user) {
        // 更新用户账户信息(示例)
        $user->update([
            'stripe_customer_id' => $stripeCustomerId,
            'subscription_status' => 'active',
            'purchased_product' => $session['line_items']['data'][0]['description'],
        ]);
    }
    
    // 注意:添加幂等性校验,比如记录已处理的session_id避免重复更新
}

方案二:通过加密的返回URL传递用户标识(兜底方案)

利用Stripe支付链接支持的success_url参数,将加密后的用户ID拼到返回地址中,在回调页面验证支付状态并更新用户。

  1. 生成加密的返回URL
    在定价页控制器中生成包含加密用户ID的成功回调地址:
$encryptedUserId = Crypt::encryptString(auth()->user()->id);
$successUrl = route('payment.success', [
    'user_id' => $encryptedUserId,
]);
$cancelUrl = route('payment.cancel');

// 传递给前端的支付链接需编码参数
$paymentLink = 'https://buy.stripe.com/your_payment_link_id?' . http_build_query([
    'success_url' => $successUrl,
    'cancel_url' => $cancelUrl,
]);
  1. 处理成功回调
    创建路由和控制器,解密用户ID并验证支付状态后更新账户:
// routes/web.php
Route::get('/payment/success', [PaymentController::class, 'success'])->name('payment.success');

// PaymentController.php
public function success(Request $request)
{
    try {
        $userId = Crypt::decryptString($request->user_id);
        $user = \App\Models\User::findOrFail($userId);
        
        // 验证Stripe会话的支付状态
        $session = \Stripe\Checkout\Session::retrieve($request->session_id);
        if ($session->payment_status !== 'paid') {
            return redirect()->route('pricing')->with('error', '支付未完成');
        }
        
        // 更新用户账户
        $user->update([
            'stripe_customer_id' => $session->customer,
            'subscription_status' => 'active',
        ]);
        
        return view('payment.success');
    } catch (\Exception $e) {
        return redirect()->route('pricing')->with('error', '验证失败');
    }
}

关键注意事项

  • Webhook处理必须添加幂等性校验(比如记录已处理的session_id),避免重复更新。
  • 方案一优先级更高,因为Webhook是Stripe主动推送,不受用户是否跳转回站点的影响。
  • 确保.env中配置正确的Stripe密钥(STRIPE_SECRET),并在Stripe后台配置正确的Webhook端点。

内容的提问来源于stack exchange,提问作者Hondaman900

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 23:34:51