7

I'm currently integrating Laravel Cashier (using Stripe) into a small application that has the following three tiers of account;

  • Free
  • Basic (e.g. £1.99/month)
  • Premium (e.g. £4.99/month)

The current process is that, when a user confirms their email address post-registration, they are signed up to Stripe on a free plan (no card). They then have the choice to upgrade to a paid plan at any point.

The confusion I have is around managing changes in user subscription, the code for which looks like;

// Check if the user has a subscription
$activeSubscription = $user->subscriptions()->first();

if ($activeSubscription instanceof Subscription) {
    return $activeSubscription->swap($targetPlan);
}

// No active plan (new registration) - create a new one
return $user->newSubscription($targetPlan, $targetPlan)->create();

When using the swap method to change a user's plan from Free to Basic, the stripe_id column in the subscriptions table updates to reflect, which is fine because the user is essentially gaining more functionality. If however a user decides to downgrade from premium to basic there is no record in that table that the user should retain premium features until the end of that billing period because again it updates the single row in the above table.

What process should happen here? How can I manage this hierarchy and ensure that the correct plan is known as "active" until the end of its billing period?


Edit

After thinking about it, I assume that using swap should only be used for cases where straight swaps are applicable (e.g. from a Monthly plan to an equal Annual plan). What is the best way therefore to perform the above? My guess would be to cancel the existing one and subscribe to the new target, but how do you delay the start of the latter until the first period ends?


This is the full subscribe method in case it's helpful;

public function subscribe(User $user, string $targetPlan, string $token = null)
{
    $activeSubscription = $user->subscriptions()->first();

    if ($targetPlan !== self::FREE_PLAN) {
        if (null === $token && !$user->hasCardOnFile()) {
            throw new SubscriptionException('No card token provided for paid subscription');
        }

        $user->updateCard($token);
    }

    // If the current user is in the cancellation grace period of the selected plan, resume that subscription
    $existingSubscription = $user->subscription($targetPlan);

    if ($existingSubscription instanceof Subscription && $existingSubscription->onGracePeriod()) {
        return $existingSubscription->resume();
    }

    // If the user has an active subscription, and the target plan is different, swap to that plan    
    if ($activeSubscription instanceof Subscription) {
        $activeSubscription->name = $targetPlan;
        return $activeSubscription->swap($targetPlan);
    }

    return $user->newSubscription($targetPlan, $targetPlan)->create();
}
James Crinkley
  • 1,398
  • 1
  • 13
  • 33

0 Answers0