Published under Laravel.
This guide assumes you have a Stripe dev account setup and access to your Stripe Key and Secret. You should also have your products and pricing configure in Stripe. You will need at least one Price ID.
First, you need to figure out which entity in your application will be considered the billable entity. For example, if you have an application with teams where each team signs up and pays for a number of seats, then your
Team model will be your billable entity. However, if your application has users which sign up and pay for themselves, then your
User model will be your billable entity.
We need to setup some environment variables for Laravel Cashier to pass along to stripe. You only need to set
CASHIER_MODEL if your billable model is not
As of the time of this post (Jan 2021), the released version of Cashier does not support the Stripe Customer Portal feature. So instead, we need to install a development branch of the Cashier package:
On the frontend, we will be using the Stripe JS SDK, so make sure to include that on your page somewhere:
I recommend publishing Cashier's migrations into your local migrations directory, so that you have full control over them:
If your billable model is not
User, make sure to change the table in the
CreateCustomerColumns migration we just published to the table that corresponds to your billable model.
I also had to change the
CreateSubscriptionsTable migration to reference my billable entity's table:
Since we published Cashier's migrations, we should also tell Cashier not to run its default migrations. Add this to your
Next, we need to configure our billable model. In my case, the billable model is
Team. Add the
Billable trait to your model:
If your user is logged in but doesn't have an active subscription, we need to redirect them to a page asking them to subscribe. The following examples will be specific to Inertia, but the concepts can be used on any Laravel stack.
We're going to add a middleware which we will use to confirm the user has an active subscription. You can pass the name of the subscription into
We then need to add the new middleware to our HTTP Kernel:
Create the controller which will start a new Stripe Checkout session, and then return the Checkout Session ID to the UI.
You'll notice in the above example that I am referencing
config('stripe.price_id'). This comes from the Stripe Dashboard where you configure your products and pricing. I'll leave it up to you to figure out how you want to determine this value. Most people store their plans/pricing in a Laravel config file and then pull them from there based on what the user selected from your UI.
Don't forget to add the route for the above controller:
Note that the name of the route above matches the name of the route we are redirecting to in the
Here's my full Inertia (Vue) component to render the subscription page. This probably won't be copy/pastable, but hopefully it can guide you in the right direction.
The key to the above component is the
checkout method which we call via a button (user input). The
checkout method is called with our public Stripe Key (passed from the backend), and the
sessionId which is the Stripe Checkout Session ID (also passed from the backend).
From here, Laravel Cashier will take care of updating your database tables with the accurate subscription info, all via webhooks. You will need to make sure you've configured webhooks on the Stripe Dashboard though. The endpoint that Laravel Cashier automatically registers is:
The Billing Portal is the easiest part of this whole process. All you need to do is register a new endpoint which redirects to the billing portal.
And then define the route:
And then link to that new route from wherever you want in your application. In my Jetstream application, I've added it to the dropdown menu:
There are a bunch of steps involved, but mostly its following the Laravel Cashier documentation. You can check out the Laravel docs repo on GitHub to see the documentation changes made for the Billing Portal: https://github.com/laravel/docs/compare/stripe-checkout...master
Subscribe to my newsletter to know when I publish more content in the future.