Stripe Checkout with Laravel Cashier

use Stripe\Checkout\Session as CheckoutSession;

public function checkout(User $user)
    return with($request->user(), function ($user) use ($request) {
        return with(CheckoutSession::create(array_merge($user->stripe_id ? ['customer' => $user->stripe_id] : ['customer_email' => $user->email], [
            'payment_method_types'        => ['card'],
            'subscription_data' => [
                'items'             => [['plan' => 'PLAN_ID_HERE']],
                'trial_period_days' => 7,
            'allow_promotion_codes' => true,
            'mode'                  => 'subscription',
            'client_reference_id'   => $user->id,
            'success_url'           => url('/home'),
            'cancel_url'            => URL::previous(url('/register')),
        ])), fn ($session) => $session->id);
use Illuminate\Support\Facades\DB;
use Laravel\Cashier\Http\Controllers\WebhookController as CashierController;

class StripeWebhookController extends CashierController
    public function handleCheckoutSessionCompleted(array $payload)
        $session = $payload['data']['object'];
        $user = User::findOrFail($session['client_reference_id']);

        DB::transaction(function () use ($session, $user) {
            $user->update(['stripe_id' => $session['customer']]);

                'name'          => 'default',
                'stripe_id'     => $session['subscription'],
                'stripe_status' => 'trialing' // Or use "active" if you don't provide a trial
                'stripe_plan'   => 'PLAN_ID_HERE',
                'quantity'      => 1,
                'trial_ends_at' => now()->addDays(7),
                'ends_at'       => null,

        return $this->successMethod();


While Laravel Cashier uses Stripe Elements by default, Stripe can now handle the checkout flow themselves. The following snippet allows you to implement this new flow into your Laravel application, while keeping the rest of Cashier working.


For this to work you'll need to create a route pointing to your StripeWebhookController and point your Stripe webhooks to that route instead of the default one provided by Cashier. You'll also need to add the checkout.session_completed event to your webhook from the Stripe Dashboard.

Enjoyed the article? Consider sharing it on Twitter so others can enjoy it too :)

Share on Twitter

Receive project updates, article drafts & thoughts on your inbox every saturday.

Subscribe →