如何实现当每个wordpress用户使用期限到期时,用户无法使用,必须续费才能继续使用

以下是详细的实现方案概览,你可以根据它来构建你的系统:

实现环节核心任务关键方法/技术点
「 数据库与模型」扩展租户模型,记录订阅信息。tenants 表中添加 trial_ends_atsubscribed_at 等字段,并在 Tenant 模型中创建状态检查方法(如 isOnTrial)。
「 状态检查与更新」自动检查并更新到期租户的状态。使用 Laravel 任务调度器(Schedule)创建每日执行的命令,查询并暂停过期租户。
「 访问控制」拦截到期租户的访问请求。创建中间件(Middleware)验证当前租户订阅状态,对过期租户重定向至续费页面。
「 续费与恢复」提供续费通道并恢复租户访问。集成 Laravel Cashier 处理支付,续费成功后更新租户状态(如 subscribed_at)。

下面我们详细拆解每个步骤。

数据库与模型设计

首先,需要为租户(Tenant)添加与订阅相关的字段,以跟踪其订阅状态。

  1. 「创建迁移文件」:新建一个迁移文件,为 tenants 表添加必要的字段。 php artisan make:migration add_subscription_fields_to_tenants_table
    在迁移文件中添加字段: // database/migrations/xxxx_xx_xx_xxxxxx_add_subscription_fields_to_tenants_table.php
    public function up()
    {
        Schema::table('tenants', function (Blueprint $table) {
            // 试用期结束时间
            $table->timestamp('trial_ends_at')->nullable();
            // 订阅开始时间
            $table->timestamp('subscribed_at')->nullable();
            // 订阅结束时间
            $table->timestamp('subscription_ends_at')->nullable();
            // 标记订阅是否已暂停
            $table->boolean('is_suspended')->default(false);
        });
    }
    运行迁移:php artisan migrate
  2. 「扩展租户模型」:在 App\Models\Tenant 模型中添加用于检查订阅状态的方法。 // app/Models/Tenant.php
    public function isOnTrial()
    {
        return $this->trial_ends_at && $this->trial_ends_at->isFuture();
    }
    public function isSubscribed()
    {
        // 检查是否在订阅期内,例如订阅后一年内有效
        return $this->subscribed_at && $this->subscription_ends_at && $this->subscription_ends_at->isFuture();
    }
    public function isActive()
    {
        // 综合判断:在试用期内或有效订阅期内,都视为活跃状态
        return $this->isOnTrial() || $this->isSubscribed();
    }
    public function suspend()
    {
        $this->update(['is_suspended' => true]);
        // 这里可以添加其他暂停逻辑,例如记录日志
    }
    public function activate()
    {
        $this->update(['is_suspended' => false]);
        // 激活租户
    }

自动化状态检查与更新

使用 Laravel 的任务调度(Task Scheduler)定期检查租户订阅状态,并自动暂停过期的租户。

  1. 「创建 Artisan 命令」php artisan make:command CheckTenantSubscriptions
  2. 「编写命令逻辑」:在生成的命令类中,实现检查并更新过期租户状态的逻辑。// app/Console/Commands/CheckTenantSubscriptions.php
    protected $signature = 'tenants:check-subscriptions';
    protected $description = '检查租户订阅状态并暂停过期租户';
    public function handle()
    {
        $now = now();
        // 查找订阅已过期且未被暂停的租户
        $expiredTenants = Tenant::where('subscription_ends_at', '<=', $now)
                                ->where('is_suspended', false)
                                ->get();
        foreach ($expiredTenants as $tenant) {
            $tenant->suspend();
            $this->info("已暂停租户: {$tenant->id}");
            // 这里可以触发邮件通知,告知租户已过期
        }
        $this->info('订阅状态检查完成。');
    }
  3. 「注册定时任务」:在 app/Console/Kernel.phpschedule 方法中注册该命令,例如每天凌晨执行。// app/Console/Kernel.php
    protected function schedule(Schedule $schedule)
    {
        $schedule->command('tenants:check-subscriptions')->daily();
    }
    确保服务器上设置了 Cron 任务来触发 Laravel 调度器:* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1

实现访问控制中间件

创建一个中间件,在租户尝试访问其 WordPress 应用时进行拦截。

  1. 「创建中间件」php artisan make:middleware CheckTenantSubscription
  2. 「编写中间件逻辑」:在中间件中判断当前租户的订阅状态。// app/Http/Middleware/CheckTenantSubscription.php
    public function handle(Request $request, Closure $next)
    {
        // 获取当前请求对应的租户,这取决于你的多租户包如何识别租户
        $tenant = tenancy()->getCurrentTenant(); // 请根据你使用的多租户包调整此行
        if ($tenant && $tenant->is_suspended) {
            // 如果租户已被暂停,重定向到续费页面
            return redirect()->route('subscription.renewal', $tenant->id);
        }
        // 如果租户活跃,继续访问请求
        return $next($request);
    }
  3. 「注册并使用中间件」:将中间件注册到 app/Http/Kernel.php$routeMiddleware 数组中。// app/Http/Kernel.php
    protected $routeMiddleware = [
        // ... 其他中间件
        'check.tenant.subscription' => \App\Http\Middleware\CheckTenantSubscription::class,
    ];
    然后,在租户应用的路由组中应用此中间件。// routes/tenant.php 或类似的路由文件
    Route::middleware(['web', 'check.tenant.subscription'])->group(function () {
        // 所有租户的 WordPress 应用路由都应包含在此路由组内
        // 例如,通配路由,将请求转发给 WordPress 索引文件
        Route::get('/{any}', function () {
            // 这里引入你的租户专属 WordPress 应用的 index.php
            require public_path("tenants/{$tenant->id}/wordpress/index.php");
        })->where('any', '.*');
    });

集成支付与续费流程

当租户被暂停后,需要提供续费通道以恢复访问。

  1. 「创建续费页面路由和控制器」:展示续费信息并处理支付。
  2. 「集成支付系统」:使用如 「Laravel Cashier」 可以极大简化与 Stripe 或 Paddle 的集成,处理订阅支付。// 在续费控制器中
    public function processRenewal(Request $request, Tenant $tenant)
    {
        // 假设使用 Cashier,并已关联用户模型
        try {
            $paymentMethod = $request->payment_method; // 从前端获取的支付令牌
            // 创建或交换订阅
            $tenant->user->newSubscription('default', 'your_plan_id')->create($paymentMethod);
            // 更新租户状态
            $tenant->update([
                'subscribed_at' => now(),
                'subscription_ends_at' => now()->addYear(), // 假设年付
                'is_suspended' => false,
            ]);
            return redirect()->back()->with('success', '续费成功!您的站点已恢复访问。');
        } catch (\Exception $e) {
            return redirect()->back()->with('error', '支付失败: ' . $e->getMessage());
        }
    }
  3. 「处理 Webhooks」:配置 Stripe 等支付平台的 Webhook,以便在用户取消订阅或支付失败时,能及时更新你数据库中的租户状态,确保状态同步。

最佳实践与优化建议

  • 「状态缓存」:频繁检查租户状态可能影响性能。可以考虑使用 Laravel 的缓存来存储租户的活跃状态,并只在状态变更时更新缓存。
  • 「通知提醒」:在租户订阅到期前,通过邮件或站内通知发送提醒,提升用户体验并减少非故意过期。
  • 「数据备份与保留策略」:明确制定策略,规定过期租户的数据保留期限以及最终清理流程。
  • 「测试」:务必对各种场景(新租户试用、正常续费、过期暂停、续费恢复等)进行充分测试。

通过以上步骤,你就可以在 Laravel 多租户系统中建立起一套完整的 WordPress 用户订阅到期控制逻辑。这套系统能自动管理租户的生命周期,确保只有付费租户才能正常使用服务。

Comments

No comments yet. Why don’t you start the discussion?

发表回复