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

Laravel Cashier(Paddle)未存储交易与订阅问题修复咨询

适配 Laravel 12 + Inertia + React + Cashier(Paddle) 的订阅实现方案

你的核心问题是结账流程未正确关联 Laravel 用户与 Paddle 交易,导致 Webhook 无法同步订阅数据到数据库。以下是针对性的修复步骤:

1. 重构服务器端结账会话生成

替换手动调用 createAsCustomer() 的方式,使用 Cashier 内置的 checkout() 方法生成绑定用户的结账会话,确保 Paddle 能识别交易归属的 Laravel 用户。

修改 SubscriptionController.php:

class SubscriptionController extends Controller
{
    public function store(Request $request)
    {
        try {
            $user = $request->user();
            $priceId = config('subscription.paddle_price_id');
            
            // 自动创建Paddle客户(如果不存在)并生成关联用户的结账会话
            $checkout = $user->checkout([
                $priceId => 1,
            ], [
                'redirect_url' => route('dashboard'),
                'customer' => [
                    'name' => $user->name,
                    'email' => $user->email,
                ],
            ]);

            // 返回会话ID给前端,而非直接返回价格ID
            return response()->json([
                'sessionId' => $checkout->id,
                'redirectUrl' => route('dashboard'),
            ]);

        } catch (\Exception $e) {
            Log::error('CHECKOUT - Subscription error: ' . $e->getMessage());
            Log::error($e->getTraceAsString());
            return response()->json(['error' => $e->getMessage()], 500);
        }
    }
}

2. 更新前端结账逻辑

使用服务器返回的会话 ID 打开 Paddle 结账弹窗,确保交易与用户绑定。

修改 useHandleCheckoutOpen.tsx:

import axios from 'axios';
import { type User } from '@/types';

export function useHandleCheckoutOpen(user: User) {
    return async () => {
        try {
            const response = await axios.post('/subscribe');

            if (response.data.error) {
                console.error('Server returned an error:', response.data.error);
                return;
            }

            const { sessionId } = response.data;

            if (window.Paddle && window.Paddle.Checkout) {
                window.Paddle.Checkout.open({
                    sessionId, // 使用绑定用户的会话ID
                    settings: {
                        displayMode: 'overlay',
                        allowLogout: false,
                    },
                });
            } else {
                console.error('Paddle script not loaded or window.Paddle not defined.');
            }
        } catch (error: any) {
            console.error('Error starting subscription:', error);
            if (error.response) {
                console.error('Server response:', error.response.data);
            }
        }
    };
}

3. 确保 Webhook 正确同步订阅数据

验证 Webhook 控制器是否继承 Cashier 的内置处理逻辑,自动同步 Paddle 交易到 Laravel 数据库。

修改 WebhookController.php:

use Laravel\Cashier\WebhookController as CashierWebhookController;

class WebhookController extends CashierWebhookController
{
    // 可自定义扩展事件处理逻辑,比如发送订阅通知
    protected function handleSubscriptionCreated($payload)
    {
        // 调用父类方法自动创建订阅记录
        parent::handleSubscriptionCreated($payload);
        
        // 自定义逻辑示例:$user = User::where('paddle_id', $payload['data']['customer_id'])->first();
    }
}

配套配置检查

  • 在 .env 中配置正确的 Paddle Webhook 密钥:
    PADDLE_WEBHOOK_SECRET=你的Paddle后台Webhook密钥
    
  • 在 Paddle 后台的 Webhook 设置中,将 URL 指向 https://你的域名/paddle/webhook,并勾选以下事件:
    • subscription.created
    • subscription.updated
    • payment.succeeded

4. 验证订阅状态

完成上述修改后,即可使用 Cashier 内置方法检查用户订阅:

// 检查用户是否有活跃订阅
if ($request->user()->subscribed()) {
    // 订阅生效逻辑
}

// 获取用户订阅详情
$subscription = $request->user()->subscription();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 01:50:12