Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

tenantcloud's avatar

Laravel cashier 6 renew subscription after cancellation

I've just updated Laravel cashier package from 5 version to the latest 6 version. It supports multiple subscriptions and it's really cool. But I've got one problem with renewing subscription after subscription cancellation. I'm removing subscription manually from stripe dashboard and customer.subscription.deleted event is firing.

Cashier method is catching this event: \Laravel\Cashier\Http\Controllers\WebhookController@handleWebhook

And $subscription->markAsCancelled(); is firing.

From that moment subscription cannot be renewed. I've tried to use resume() function, but subscription can be resumed only(!) on grace period.

In previous version of cashier I was using swap() method to resume subscription. Now it returns:

Stripe\Error\InvalidRequest: Customer cus_*** does not have a subscription with ID sub_***** in /**/vendor/stripe/stripe-php/lib/ApiRequestor.php:103 from API request 'req_****'

Creating new customer and subscription is not very efficient way. What your thoughts about this issue?

0 likes
6 replies
Francismori7's avatar

You should not delete the subscription but rather cancel it from your stripe dashboard. If you delete it, it's impossible to resume it. Cancel it instead.

1 like
tenantcloud's avatar

Thank you @Francismori7 for your response! I was imitating card payment failure using Stripe special card number 4000000000000341. It works as cancellation, but result is the same .

tenantcloud's avatar

@Francismori7 Also, there is handleCustomerSubscriptionDeleted method in \Laravel\Cashier\Http\Controllers\WebhookController@handleWebhook which is fired when subscription is deleted or cancelled. So, it should be some way of resuming subscription after this webhook was handled.

tenantcloud's avatar

My solution at this moment:

public function resume()
    {
        $user = Auth::user();
        $subscription = $user->subscription(ServicePackageRepository::SUBSCRIPTION_NAME);

        if ($subscription->cancelled() && $subscription->onGracePeriod()) { 
            //if it was cancelled by user in grace period
            $subscription->resume();

            return $this->respondWithSaved([]);
        } else { //if cancelled by payment failure or smth else...
            if($user->subscription(ServicePackageRepository::SUBSCRIPTION_NAME)) {
                $user->newSubscription(ServicePackageRepository::SUBSCRIPTION_NAME,
                        $user->subscription(ServicePackageRepository::SUBSCRIPTION_NAME)->stripe_plan)
                    ->create();

                return $this->respondWithSaved([]);
            } else {
                return $this->respondWithError([]);
            }
        }
    }

Francismori7's avatar

@ukietech The problem resides in Stripe's API. When you cancel the subscription, it still exists on your stripe account. When you delete it, it is completely removed.

Laravel Cashier cannot see the difference between those two events (customer.subscription.deleted) because they are the same. Cashier keeps the subscription ID associated with the user to allow resuming it. However, if the subscription was DELETED entirely, it cannot be resumed since it doesn't exist anymore.

1 like
tenantcloud's avatar

@Francismori7 Agree with that. The main difference was in swap() method. In 5th version it was creating new subscription if it does not exists, and in 6 version it just throws an exception - not very convenient.

Please or to participate in this conversation.