Introduction Laravel Cashier provides an expressive, fluent interface to Stripe's subscription billing services. It handles almost all of the boilerplate subscription billing code you are dreading writing. Now install the laravel cashier, open composer.json and add 'laravel/cashier': '7.0' in required block, run composer update to pull it. Next, register the Laravel Cashier CashierServiceProvider service provider in your config/app.php configuration file. Cashier Migrations.
- Configuration
- Subscriptions
- Subscription Trials
- Handling Stripe Webhooks
- Handling Braintree Webhooks
- Invoices
Introduction
Laravel Cashier provides an expressive, fluent interface to Stripe's and Braintree's subscription billing services. It handles almost all of the boilerplate subscription billing code you are dreading writing. In addition to basic subscription management, Cashier can handle coupons, swapping subscription, subscription 'quantities', cancellation grace periods, and even generate invoice PDFs.
{note} If you're only performing 'one-off' charges and do not offer subscriptions. You should not use Cashier. You should use the Stripe and Braintree SDKs directly.
Configuration
Stripe
Composer
First, add the Cashier package for Stripe to your composer.json
file and run the composer update
command:
Service Provider
Next, register the LaravelCashierCashierServiceProvider
service provider in your config/app.php
configuration file.
Database Migrations
Before using Cashier, we'll also need to prepare the database. We need to add several columns to your users
table and create a new subscriptions
table to hold all of our customer's subscriptions:
Once the migrations have been created, run the migrate
Artisan command.
Billable Model
Next, add the Billable
trait to your model definition. This trait provides various methods to allow you to perform common billing tasks, such as creating subscriptions, applying coupons, and updating credit card information:
API Keys
Finally, you should configure your Stripe key in your services.php
configuration file. You can retrieve your Stripe API keys from the Stripe control panel:
Braintree
Braintree Caveats
For many operations, the Stripe and Braintree implementations of Cashier function the same. Both services provide subscription billing with credit cards but Braintree also supports payments via PayPal. However, Braintree also lacks some features that are supported by Stripe. You should keep the following in mind when deciding to use Stripe or Braintree:
Composer
First, add the Cashier package for Braintree to your composer.json
file and run the composer update
command:
Service Provider
Next, register the LaravelCashierCashierServiceProvider
service provider in your config/app.php
configuration file.
Plan Credit Coupon
Before using Cashier with Braintree, you will need to define a plan-credit
discount in your Braintree control panel. This discount will be used to properly prorate subscriptions that change from yearly to monthly billing, or from monthly to yearly billing.
The discount amount configured in the Braintree control panel can be any value you wish, as Cashier will simply override the defined amount with our own custom amount each time we apply the coupon. This coupon is needed since Braintree does not natively support prorating subscriptions across subscription frequencies.
Database Migrations
Before using Cashier, we'll need to prepare the database. We need to add several columns to your users
table and create a new subscriptions
table to hold all of our customer's subscriptions:
Once the migrations have been created, simply run the migrate
Artisan command.
Billable Model
Next, add the Billable
trait to your model definition:
API Keys
Next, You should configure the following options in your services.php
file:
Then you should add the following Braintree SDK calls to your AppServiceProvider
service provider's boot
method:
Currency Configuration
The default Cashier currency is United States Dollars (USD). You can change the default currency by calling the Cashier::useCurrency
method from within the boot
method of one of your service providers. The useCurrency
method accepts two string parameters: the currency and the currency's symbol:
Subscriptions
Creating Subscriptions
To create a subscription, first retrieve an instance of your billable model, which typically will be an instance of AppUser
. Once you have retrieved the model instance, you may use the newSubscription
method to create the model's subscription:
The first argument passed to the newSubscription
method should be the name of the subscription. If your application only offers a single subscription, you might call this main
or primary
. The second argument is the specific Stripe / Braintree plan the user is subscribing to. This value should correspond to the plan's identifier in Stripe or Braintree.
The create
method will begin the subscription as well as update your database with the customer ID and other relevant billing information.
Additional User Details
If you would like to specify additional customer details, you may do so by passing them as the second argument to the create
method:
To learn more about the additional fields supported by Stripe or Braintree, check out Stripe's documentation on customer creation or the corresponding Braintree documentation.
Coupons
If you would like to apply a coupon when creating the subscription, you may use the withCoupon
method:
Checking Subscription Status
Once a user is subscribed to your application, you may easily check their subscription status using a variety of convenient methods. First, the subscribed
method returns true
if the user has an active subscription, even if the subscription is currently within its trial period:
The subscribed
method also makes a great candidate for a route middleware, allowing you to filter access to routes and controllers based on the user's subscription status:
If you would like to determine if a user is still within their trial period, you may use the onTrial
method. This method can be useful for displaying a warning to the user that they are still on their trial period:
The subscribedToPlan
method may be used to determine if the user is subscribed to a given plan based on a given Stripe / Braintree plan ID. In this example, we will determine if the user's main
subscription is actively subscribed to the monthly
plan:
Cancelled Subscription Status
To determine if the user was once an active subscriber, but has cancelled their subscription, you may use the cancelled
method:
You may also determine if a user has cancelled their subscription, but are still on their 'grace period' until the subscription fully expires. For example, if a user cancels a subscription on March 5th that was originally scheduled to expire on March 10th, the user is on their 'grace period' until March 10th. Note that the subscribed
method still returns true
during this time:
Changing Plans
After a user is subscribed to your application, they may occasionally want to change to a new subscription plan. To swap a user to a new subscription, pass the plan's identifier to the swap
method:
If the user is on trial, the trial period will be maintained. Also, if a 'quantity' exists for the subscription, that quantity will also be maintained.
If you would like to swap plans and cancel any trial period the user is currently on, you may use the skipTrial
method:
Subscription Quantity
{note} Subscription quantities are only supported by the Stripe edition of Cashier. Braintree does not have a feature that corresponds to Stripe's 'quantity'.
Sometimes subscriptions are affected by 'quantity'. For example, your application might charge $10 per month per user on an account. To easily increment or decrement your subscription quantity, use the incrementQuantity
and decrementQuantity
methods:
Alternatively, you may set a specific quantity using the updateQuantity
method:
For more information on subscription quantities, consult the Stripe documentation.
Subscription Taxes
To specify the tax percentage a user pays on a subscription, implement the taxPercentage
method on your billable model, and return a numeric value between 0 and 100, with no more than 2 decimal places.
The taxPercentage
method enables you to apply a tax rate on a model-by-model basis, which may be helpful for a user base that spans multiple countries and tax rates.
{note} The taxPercentage
method only applies to subscription charges. If you use Cashier to make 'one off' charges, you will need to manually specify the tax rate at that time.
Cancelling Subscriptions
To cancel a subscription, simply call the cancel
method on the user's subscription:
When a subscription is cancelled, Cashier will automatically set the ends_at
column in your database. This column is used to know when the subscribed
method should begin returning false
. For example, if a customer cancels a subscription on March 1st, but the subscription was not scheduled to end until March 5th, the subscribed
method will continue to return true
until March 5th.
You may determine if a user has cancelled their subscription but are still on their 'grace period' using the onGracePeriod
method:
If you wish to cancel a subscription immediately, call the cancelNow
method on the user's subscription:
Resuming Subscriptions
If a user has cancelled their subscription and you wish to resume it, use the resume
method. The user must still be on their grace period in order to resume a subscription:
If the user cancels a subscription and then resumes that subscription before the subscription has fully expired, they will not be billed immediately. Instead, their subscription will simply be re-activated, and they will be billed on the original billing cycle.
Updating Credit Cards
The updateCard
method may be used to update a customer's credit card information. This method accepts a Stripe token and will assign the new credit card as the default billing source:
Subscription Trials
With Credit Card Up Front
If you would like to offer trial periods to your customers while still collecting payment method information up front, You should use the trialDays
method when creating your subscriptions:
This method will set the trial period ending date on the subscription record within the database, as well as instruct Stripe / Braintree to not begin billing the customer until after this date.
{note} If the customer's subscription is not cancelled before the trial ending date they will be charged as soon as the trial expires, so you should be sure to notify your users of their trial ending date.
You may determine if the user is within their trial period using either the onTrial
method of the user instance, or the onTrial
method of the subscription instance. The two examples below are identical:
Without Credit Card Up Front
If you would like to offer trial periods without collecting the user's payment method information up front, you may simply set the trial_ends_at
column on the user record to your desired trial ending date. This is typically done during user registration:
{note} Be sure to add a date mutator for trial_ends_at
to your model definition.
Cashier refers to this type of trial as a 'generic trial', since it is not attached to any existing subscription. The onTrial
method on the User
instance will return true
if the current date is not past the value of trial_ends_at
:
You may also use the onGenericTrial
method if you wish to know specifically that the user is within their 'generic' trial period and has not created an actual subscription yet:
Once you are ready to create an actual subscription for the user, you may use the newSubscription
method as usual:
Handling Stripe Webhooks
Both Stripe and Braintree can notify your application of a variety of events via webhooks. To handle Stripe webhooks, define a route that points to Cashier's webhook controller. This controller will handle all incoming webhook requests and dispatch them to the proper controller method:
{note} Once you have registered your route, be sure to configure the webhook URL in your Stripe control panel settings.
By default, this controller will automatically handle cancelling subscriptions that have too many failed charges (as defined by your Stripe settings); however, as we'll soon discover, you can extend this controller to handle any webhook event you like.
Webhooks & CSRF Protection
Since Stripe webhooks need to bypass Laravel's CSRF protection, be sure to list the URI as an exception in your VerifyCsrfToken
middleware or list the route outside of the web
middleware group:
Defining Webhook Event Handlers
Cashier automatically handles subscription cancellation on failed charges, but if you have additional Stripe webhook events you would like to handle, simply extend the Webhook controller. Your method names should correspond to Cashier's expected convention, specifically, methods should be prefixed with handle
and the 'camel case' name of the Stripe webhook you wish to handle. For example, if you wish to handle the invoice.payment_succeeded
webhook, you should add a handleInvoicePaymentSucceeded
method to the controller:
Failed Subscriptions
What if a customer's credit card expires? No worries - Cashier includes a Webhook controller that can easily cancel the customer's subscription for you. As noted above, all you need to do is point a route to the controller:
That's it! Failed payments will be captured and handled by the controller. The controller will cancel the customer's subscription when Stripe determines the subscription has failed (normally after three failed payment attempts).
Handling Braintree Webhooks
Both Stripe and Braintree can notify your application of a variety of events via webhooks. To handle Braintree webhooks, define a route that points to Cashier's webhook controller. This controller will handle all incoming webhook requests and dispatch them to the proper controller method:
{note} Once you have registered your route, be sure to configure the webhook URL in your Braintree control panel settings.
By default, this controller will automatically handle cancelling subscriptions that have too many failed charges (as defined by your Braintree settings); however, as we'll soon discover, you can extend this controller to handle any webhook event you like.
Webhooks & CSRF Protection
Since Braintree webhooks need to bypass Laravel's CSRF protection, be sure to list the URI as an exception in your VerifyCsrfToken
middleware or list the route outside of the web
middleware group:
Defining Webhook Event Handlers
Cashier automatically handles subscription cancellation on failed charges, but if you have additional Braintree webhook events you would like to handle, simply extend the Webhook controller. Your method names should correspond to Cashier's expected convention, specifically, methods should be prefixed with handle
and the 'camel case' name of the Braintree webhook you wish to handle. For example, if you wish to handle the dispute_opened
webhook, you should add a handleDisputeOpened
method to the controller:
Failed Subscriptions
What if a customer's credit card expires? No worries - Cashier includes a Webhook controller that can easily cancel the customer's subscription for you. Just point a route to the controller:
That's it! Failed payments will be captured and handled by the controller. The controller will cancel the customer's subscription when Braintree determines the subscription has failed (normally after three failed payment attempts). Don't forget: you will need to configure the webhook URI in your Braintree control panel settings.
Single Charges
Simple Charge
{note} When using Stripe, the charge
method accepts the amount you would like to charge in the lowest denominator of the currency used by your application. However, when using Braintree, you should pass the full dollar amount to the charge
method:
If you would like to make a 'one off' charge against a subscribed customer's credit card, you may use the charge
method on a billable model instance.
The charge
method accepts an array as its second argument, allowing you to pass any options you wish to the underlying Stripe / Braintree charge creation. Consult the Stripe or Braintree documentation regarding the options available to you when creating charges:
The charge
method will throw an exception if the charge fails. If the charge is successful, the full Stripe / Braintree response will be returned from the method:
Charge With Invoice
Sometimes you may need to make a one-time charge but also generate an invoice for the charge so that you may offer a PDF receipt to your customer. The invoiceFor
method lets you do just that. For example, let's invoice the customer $5.00 for a 'One Time Fee':
The invoice will be charged immediately against the user's credit card. The invoiceFor
method also accepts an array as its third argument, allowing you to pass any options you wish to the underlying Stripe / Braintree charge creation:
{note} The invoiceFor
method will create a Stripe invoice which will retry failed billing attempts. If you do not want invoices to retry failed charges, you will need to close them using the Stripe API after the first failed charge.
Invoices
You may easily retrieve an array of a billable model's invoices using the invoices
method:
When listing the invoices for the customer, you may use the invoice's helper methods to display the relevant invoice information. For example, you may wish to list every invoice in a table, allowing the user to easily download any of them:
Generating Invoice PDFs
Before generating invoice PDFs, you need to install the dompdf
PHP library:
Then, from within a route or controller, use the downloadInvoice
method to generate a PDF download of the invoice. This method will automatically generate the proper HTTP response to send the download to the browser:
Swapnil Bhavsar • January 2, 2021
laravelI recently worked on a Laravel project which had the requirement of two authenticable models along with separate subscriptions. The project of course was using Laravel Cashier to manage user's subscriptions.
By default, Laravel Cashier assumes the AppModelUser
class as a Billable model. We can configure it to use a different model, but in our case, there were two different models. So, I had to follow a different approach.
PS: This is going to be a long tutorial! I am going to explain everything from creating models, updating migrations, configuring webhooks, etc.
But if you are in hurry, here is your solution, the trick is to set Cashier's billable model at the runtime using the config
helper function.
Initial Setup
Let's start by assuming that our application has two billable models, a User
, and Seller
. Both models will have subscriptions. There can be multiple ways to use Cashier with multiple models, but for simplicity, we are going to store the details of their subscription in separate tables.
Let's start by installing the Cashier package for Stripe first.
Crusader Kings III skidrow codex. CRUSADER KINGS III. Forza Horizon 4: 09 March 2021; Stronghold Warlords: 09 March 2021; Sapper Defuse The Bomb Simulator: 11 March 2021; Cyanide & Happiness Freakpocalypse: 11 March 2021. SKIDROW GAMES & IGG GAMES. Crusader kings 3 codex torrent. Crusader Kings III is the heir to a long legacy of historical grand strategy experiences and arrives with a host of new ways to ensure the success of your royal house. Choose a royal or noble house from a number of realms on a map that stretches from Iceland to India, from the Arctic Circle to Central Africa. Crusader Kings III torrent download. CRUSADER KINGS III. AnShi: 22 February 2021; Revolution The Spark: 22 February 2021; Rogue Heroes: Ruins of Tasos: 23 February 2021; Tiny Room Stories Town Mystery: 23 February 2021. SKIDROW GAMES & IGG GAMES. Your path to glory begins today in Crusader Kings III. A life of medieval drama and majesty awaits you in Crusader Kings III! Build history's greatest dynasty through war, diplomacy or intrigue.
The cashier will use subscriptions
and subscription_items
tables to store information about the user's subscriptions. Let's publish Cashier's default migrations so that we can take over a look at the table structure.
Now we should have the following files in our database/migrations
directory.
2019_05_03_000001_create_customer_columns.php
2019_05_03_000002_create_subscriptions_table.php
2019_05_03_000003_create_subscription_items_table.php
These files contain schema information about the subscriptions table. Don't worry about them, we will come to these files later.
The User
model setup
First, let's set up our first billable model, User
with Cashier. Add Billable
trait to our first billable model which at AppModelsUser
.
This user model is going to have its subscription information stored in the subscriptions
table.
Next, let's create our second billable model & add migrations for it.
The Seller
model setup
Our Seller
model is going to have subscriptions like the User
model. But, we need to set up a few more things than just adding a Billable
trait to our model. We will need to add migrations, configure auth guard, etc. for the Seller
model.
Along with the Seller
model, we will create two more models, SellerSubscription
& SellerSubscriptionItem
. The SellerSubscription
will hold the subscription information for the Seller
model and the SellerSubscriptionItem
model will be responsible for holding Multiplan Subscriptions.
In short, we are going to need the following models & tables for our Seller
model.
- The
Seller
model withsellers
table. - The
SellerSubscription
model withseller_subscriptions
table. - The
SellerSubscriptionItem
model withseller_subscription_items
table.
Let's start by generating our model using the following artisan command. Also, generate model & migrations files by adding the -m
flag to our command.
It should generate these two files at the following locations.
Seller.php
(In/app/models
directory) - The Seller model2021_XX_XX_XXXXXX_create_sellers_table.php
(In/database/migrations
directory) - The migration file
Now, let's set up our Seller
model. Just like the User
model we need to add the Billable
trait to our Seller
model sitting at AppModelsSeller
.
In the migration file (2021_XX_XX_XXXXXX_create_sellers_table.php
) for creating the sellers
table, add the following schema content. We will also bring columns we got from 2019_05_03_000001_create_customer_columns.php
after publishing Cashier's default migrations.
We are almost finished with our Seller
model. But we still need to add seller specific subscriptions model and migration.
The SellerSubscription
model setup
By default, subscription information for model AppModelsUser
will be stored in the subscriptions
table. By using the Billable
trait we are instructing Laravel, the User
model will have a hasMany
relation with the LaravelCashierSubscription
model. We can confirm that by the ManagesSubscriptions
trait.
Here in the LaravelCashierConcernsManagesSubscriptions
trait, we can see the subscriptions
method, which defines hasMany
relation with the LaravelCashierSubscription
model.
So, we are going to create a class called SellerSubscription
which extends the LaravelCashierSubscription
model & inherits its properties.
In your console run the following command to generate the SellerSubscription
model & migration.
Laravel Cashier
This will generate the following files.
SellerSubscription.php
(In/app/models
directory)2021_XX_XX_XXXXXX_create_seller_subscriptions_table.php
(In/database/migrations
directory)
The SellerSubscriptionItem
model setup
Our User
model has Multiplan Subscriptions stored in the subscription_items
table. Then why should we leave the Seller
model behind? Let's add multi-plan subscriptions functionality to the Seller
model by defining a new model called SellerSubscriptionItem
.
Let's generate the SellerSubscriptionItem
model along with migration by running the following command in the terminal.
This command should generate the following files.
SellerSubscriptionItem.php
(In/app/models
directory)2021_XX_XX_XXXXXX_create_seller_subscription_items_table.php
(In/database/migrations
directory)
Next, modify the SellerSubscription
class slightly to extend LaravelCashierSubscription
class. And also define belongsTo
relation with the Seller
class as well as hasMany
relation with the SellerSubscriptionItem
class.
Next, also modify SellerSubscriptionItem
class to extend LaravelCashierSubscriptionItem
class. And define belongsTo
relation with the SellerSubscription
class like this.
Now, it's time to take inspiration from Cashier's default migration, and update migrations for seller_subscriptions
and seller_subscription_items
accordingly.
Update migration 2021_XX_XX_XXXXXX_create_seller_subscriptions_table.php
for seller_subscriptions
table with the following schema structure. Pay attention to referencing key seller_id
& modify it according to your custom model.
Next, also update migration 2021_XX_XX_XXXXXX_create_seller_subscription_items_table.php
for seller_subscription_items
with the following schema structure. And also pay attention to referencing key seller_subscription_id
& modify it according to your custom subscription item model.
After defining the SellerSubscription
and SellerSubscriptionItem
models, define a hasMany
relation by adding the subscriptions
method on the Seller
class.
And finally, run the migration command to create/update tables in the database.
The Seller
model
Now, modify the Seller
model to override the subscriptions
relation coming from the Billable
trait. Instead of defining a relationship between the LaravelCashierSubscription
class, define it with AppModelsSellerSubscription
.
Your finished seller model should look like this.
Laravel Cashier Invoices
Next, let's set up Stripe webhooks for the Seller
model. By default, the cashier will use the /stripe/webhook
route to handle Stripe webhooks for the default configured model.
Webhooks for the Seller
model.
Stripe can notify your application in case the customer's payment method declined and many such events. We need to ensure that our application is handling it. The Cashier package makes it easy by using the /stripe/webhook
route to handle these events.
Next, add the Billable
trait to your model definition:
API Keys
Next, You should configure the following options in your services.php
file:
Then you should add the following Braintree SDK calls to your AppServiceProvider
service provider's boot
method:
Currency Configuration
The default Cashier currency is United States Dollars (USD). You can change the default currency by calling the Cashier::useCurrency
method from within the boot
method of one of your service providers. The useCurrency
method accepts two string parameters: the currency and the currency's symbol:
Subscriptions
Creating Subscriptions
To create a subscription, first retrieve an instance of your billable model, which typically will be an instance of AppUser
. Once you have retrieved the model instance, you may use the newSubscription
method to create the model's subscription:
The first argument passed to the newSubscription
method should be the name of the subscription. If your application only offers a single subscription, you might call this main
or primary
. The second argument is the specific Stripe / Braintree plan the user is subscribing to. This value should correspond to the plan's identifier in Stripe or Braintree.
The create
method will begin the subscription as well as update your database with the customer ID and other relevant billing information.
Additional User Details
If you would like to specify additional customer details, you may do so by passing them as the second argument to the create
method:
To learn more about the additional fields supported by Stripe or Braintree, check out Stripe's documentation on customer creation or the corresponding Braintree documentation.
Coupons
If you would like to apply a coupon when creating the subscription, you may use the withCoupon
method:
Checking Subscription Status
Once a user is subscribed to your application, you may easily check their subscription status using a variety of convenient methods. First, the subscribed
method returns true
if the user has an active subscription, even if the subscription is currently within its trial period:
The subscribed
method also makes a great candidate for a route middleware, allowing you to filter access to routes and controllers based on the user's subscription status:
If you would like to determine if a user is still within their trial period, you may use the onTrial
method. This method can be useful for displaying a warning to the user that they are still on their trial period:
The subscribedToPlan
method may be used to determine if the user is subscribed to a given plan based on a given Stripe / Braintree plan ID. In this example, we will determine if the user's main
subscription is actively subscribed to the monthly
plan:
Cancelled Subscription Status
To determine if the user was once an active subscriber, but has cancelled their subscription, you may use the cancelled
method:
You may also determine if a user has cancelled their subscription, but are still on their 'grace period' until the subscription fully expires. For example, if a user cancels a subscription on March 5th that was originally scheduled to expire on March 10th, the user is on their 'grace period' until March 10th. Note that the subscribed
method still returns true
during this time:
Changing Plans
After a user is subscribed to your application, they may occasionally want to change to a new subscription plan. To swap a user to a new subscription, pass the plan's identifier to the swap
method:
If the user is on trial, the trial period will be maintained. Also, if a 'quantity' exists for the subscription, that quantity will also be maintained.
If you would like to swap plans and cancel any trial period the user is currently on, you may use the skipTrial
method:
Subscription Quantity
{note} Subscription quantities are only supported by the Stripe edition of Cashier. Braintree does not have a feature that corresponds to Stripe's 'quantity'.
Sometimes subscriptions are affected by 'quantity'. For example, your application might charge $10 per month per user on an account. To easily increment or decrement your subscription quantity, use the incrementQuantity
and decrementQuantity
methods:
Alternatively, you may set a specific quantity using the updateQuantity
method:
For more information on subscription quantities, consult the Stripe documentation.
Subscription Taxes
To specify the tax percentage a user pays on a subscription, implement the taxPercentage
method on your billable model, and return a numeric value between 0 and 100, with no more than 2 decimal places.
The taxPercentage
method enables you to apply a tax rate on a model-by-model basis, which may be helpful for a user base that spans multiple countries and tax rates.
{note} The taxPercentage
method only applies to subscription charges. If you use Cashier to make 'one off' charges, you will need to manually specify the tax rate at that time.
Cancelling Subscriptions
To cancel a subscription, simply call the cancel
method on the user's subscription:
When a subscription is cancelled, Cashier will automatically set the ends_at
column in your database. This column is used to know when the subscribed
method should begin returning false
. For example, if a customer cancels a subscription on March 1st, but the subscription was not scheduled to end until March 5th, the subscribed
method will continue to return true
until March 5th.
You may determine if a user has cancelled their subscription but are still on their 'grace period' using the onGracePeriod
method:
If you wish to cancel a subscription immediately, call the cancelNow
method on the user's subscription:
Resuming Subscriptions
If a user has cancelled their subscription and you wish to resume it, use the resume
method. The user must still be on their grace period in order to resume a subscription:
If the user cancels a subscription and then resumes that subscription before the subscription has fully expired, they will not be billed immediately. Instead, their subscription will simply be re-activated, and they will be billed on the original billing cycle.
Updating Credit Cards
The updateCard
method may be used to update a customer's credit card information. This method accepts a Stripe token and will assign the new credit card as the default billing source:
Subscription Trials
With Credit Card Up Front
If you would like to offer trial periods to your customers while still collecting payment method information up front, You should use the trialDays
method when creating your subscriptions:
This method will set the trial period ending date on the subscription record within the database, as well as instruct Stripe / Braintree to not begin billing the customer until after this date.
{note} If the customer's subscription is not cancelled before the trial ending date they will be charged as soon as the trial expires, so you should be sure to notify your users of their trial ending date.
You may determine if the user is within their trial period using either the onTrial
method of the user instance, or the onTrial
method of the subscription instance. The two examples below are identical:
Without Credit Card Up Front
If you would like to offer trial periods without collecting the user's payment method information up front, you may simply set the trial_ends_at
column on the user record to your desired trial ending date. This is typically done during user registration:
{note} Be sure to add a date mutator for trial_ends_at
to your model definition.
Cashier refers to this type of trial as a 'generic trial', since it is not attached to any existing subscription. The onTrial
method on the User
instance will return true
if the current date is not past the value of trial_ends_at
:
You may also use the onGenericTrial
method if you wish to know specifically that the user is within their 'generic' trial period and has not created an actual subscription yet:
Once you are ready to create an actual subscription for the user, you may use the newSubscription
method as usual:
Handling Stripe Webhooks
Both Stripe and Braintree can notify your application of a variety of events via webhooks. To handle Stripe webhooks, define a route that points to Cashier's webhook controller. This controller will handle all incoming webhook requests and dispatch them to the proper controller method:
{note} Once you have registered your route, be sure to configure the webhook URL in your Stripe control panel settings.
By default, this controller will automatically handle cancelling subscriptions that have too many failed charges (as defined by your Stripe settings); however, as we'll soon discover, you can extend this controller to handle any webhook event you like.
Webhooks & CSRF Protection
Since Stripe webhooks need to bypass Laravel's CSRF protection, be sure to list the URI as an exception in your VerifyCsrfToken
middleware or list the route outside of the web
middleware group:
Defining Webhook Event Handlers
Cashier automatically handles subscription cancellation on failed charges, but if you have additional Stripe webhook events you would like to handle, simply extend the Webhook controller. Your method names should correspond to Cashier's expected convention, specifically, methods should be prefixed with handle
and the 'camel case' name of the Stripe webhook you wish to handle. For example, if you wish to handle the invoice.payment_succeeded
webhook, you should add a handleInvoicePaymentSucceeded
method to the controller:
Failed Subscriptions
What if a customer's credit card expires? No worries - Cashier includes a Webhook controller that can easily cancel the customer's subscription for you. As noted above, all you need to do is point a route to the controller:
That's it! Failed payments will be captured and handled by the controller. The controller will cancel the customer's subscription when Stripe determines the subscription has failed (normally after three failed payment attempts).
Handling Braintree Webhooks
Both Stripe and Braintree can notify your application of a variety of events via webhooks. To handle Braintree webhooks, define a route that points to Cashier's webhook controller. This controller will handle all incoming webhook requests and dispatch them to the proper controller method:
{note} Once you have registered your route, be sure to configure the webhook URL in your Braintree control panel settings.
By default, this controller will automatically handle cancelling subscriptions that have too many failed charges (as defined by your Braintree settings); however, as we'll soon discover, you can extend this controller to handle any webhook event you like.
Webhooks & CSRF Protection
Since Braintree webhooks need to bypass Laravel's CSRF protection, be sure to list the URI as an exception in your VerifyCsrfToken
middleware or list the route outside of the web
middleware group:
Defining Webhook Event Handlers
Cashier automatically handles subscription cancellation on failed charges, but if you have additional Braintree webhook events you would like to handle, simply extend the Webhook controller. Your method names should correspond to Cashier's expected convention, specifically, methods should be prefixed with handle
and the 'camel case' name of the Braintree webhook you wish to handle. For example, if you wish to handle the dispute_opened
webhook, you should add a handleDisputeOpened
method to the controller:
Failed Subscriptions
What if a customer's credit card expires? No worries - Cashier includes a Webhook controller that can easily cancel the customer's subscription for you. Just point a route to the controller:
That's it! Failed payments will be captured and handled by the controller. The controller will cancel the customer's subscription when Braintree determines the subscription has failed (normally after three failed payment attempts). Don't forget: you will need to configure the webhook URI in your Braintree control panel settings.
Single Charges
Simple Charge
{note} When using Stripe, the charge
method accepts the amount you would like to charge in the lowest denominator of the currency used by your application. However, when using Braintree, you should pass the full dollar amount to the charge
method:
If you would like to make a 'one off' charge against a subscribed customer's credit card, you may use the charge
method on a billable model instance.
The charge
method accepts an array as its second argument, allowing you to pass any options you wish to the underlying Stripe / Braintree charge creation. Consult the Stripe or Braintree documentation regarding the options available to you when creating charges:
The charge
method will throw an exception if the charge fails. If the charge is successful, the full Stripe / Braintree response will be returned from the method:
Charge With Invoice
Sometimes you may need to make a one-time charge but also generate an invoice for the charge so that you may offer a PDF receipt to your customer. The invoiceFor
method lets you do just that. For example, let's invoice the customer $5.00 for a 'One Time Fee':
The invoice will be charged immediately against the user's credit card. The invoiceFor
method also accepts an array as its third argument, allowing you to pass any options you wish to the underlying Stripe / Braintree charge creation:
{note} The invoiceFor
method will create a Stripe invoice which will retry failed billing attempts. If you do not want invoices to retry failed charges, you will need to close them using the Stripe API after the first failed charge.
Invoices
You may easily retrieve an array of a billable model's invoices using the invoices
method:
When listing the invoices for the customer, you may use the invoice's helper methods to display the relevant invoice information. For example, you may wish to list every invoice in a table, allowing the user to easily download any of them:
Generating Invoice PDFs
Before generating invoice PDFs, you need to install the dompdf
PHP library:
Then, from within a route or controller, use the downloadInvoice
method to generate a PDF download of the invoice. This method will automatically generate the proper HTTP response to send the download to the browser:
Swapnil Bhavsar • January 2, 2021
laravelI recently worked on a Laravel project which had the requirement of two authenticable models along with separate subscriptions. The project of course was using Laravel Cashier to manage user's subscriptions.
By default, Laravel Cashier assumes the AppModelUser
class as a Billable model. We can configure it to use a different model, but in our case, there were two different models. So, I had to follow a different approach.
PS: This is going to be a long tutorial! I am going to explain everything from creating models, updating migrations, configuring webhooks, etc.
But if you are in hurry, here is your solution, the trick is to set Cashier's billable model at the runtime using the config
helper function.
Initial Setup
Let's start by assuming that our application has two billable models, a User
, and Seller
. Both models will have subscriptions. There can be multiple ways to use Cashier with multiple models, but for simplicity, we are going to store the details of their subscription in separate tables.
Let's start by installing the Cashier package for Stripe first.
Crusader Kings III skidrow codex. CRUSADER KINGS III. Forza Horizon 4: 09 March 2021; Stronghold Warlords: 09 March 2021; Sapper Defuse The Bomb Simulator: 11 March 2021; Cyanide & Happiness Freakpocalypse: 11 March 2021. SKIDROW GAMES & IGG GAMES. Crusader kings 3 codex torrent. Crusader Kings III is the heir to a long legacy of historical grand strategy experiences and arrives with a host of new ways to ensure the success of your royal house. Choose a royal or noble house from a number of realms on a map that stretches from Iceland to India, from the Arctic Circle to Central Africa. Crusader Kings III torrent download. CRUSADER KINGS III. AnShi: 22 February 2021; Revolution The Spark: 22 February 2021; Rogue Heroes: Ruins of Tasos: 23 February 2021; Tiny Room Stories Town Mystery: 23 February 2021. SKIDROW GAMES & IGG GAMES. Your path to glory begins today in Crusader Kings III. A life of medieval drama and majesty awaits you in Crusader Kings III! Build history's greatest dynasty through war, diplomacy or intrigue.
The cashier will use subscriptions
and subscription_items
tables to store information about the user's subscriptions. Let's publish Cashier's default migrations so that we can take over a look at the table structure.
Now we should have the following files in our database/migrations
directory.
2019_05_03_000001_create_customer_columns.php
2019_05_03_000002_create_subscriptions_table.php
2019_05_03_000003_create_subscription_items_table.php
These files contain schema information about the subscriptions table. Don't worry about them, we will come to these files later.
The User
model setup
First, let's set up our first billable model, User
with Cashier. Add Billable
trait to our first billable model which at AppModelsUser
.
This user model is going to have its subscription information stored in the subscriptions
table.
Next, let's create our second billable model & add migrations for it.
The Seller
model setup
Our Seller
model is going to have subscriptions like the User
model. But, we need to set up a few more things than just adding a Billable
trait to our model. We will need to add migrations, configure auth guard, etc. for the Seller
model.
Along with the Seller
model, we will create two more models, SellerSubscription
& SellerSubscriptionItem
. The SellerSubscription
will hold the subscription information for the Seller
model and the SellerSubscriptionItem
model will be responsible for holding Multiplan Subscriptions.
In short, we are going to need the following models & tables for our Seller
model.
- The
Seller
model withsellers
table. - The
SellerSubscription
model withseller_subscriptions
table. - The
SellerSubscriptionItem
model withseller_subscription_items
table.
Let's start by generating our model using the following artisan command. Also, generate model & migrations files by adding the -m
flag to our command.
It should generate these two files at the following locations.
Seller.php
(In/app/models
directory) - The Seller model2021_XX_XX_XXXXXX_create_sellers_table.php
(In/database/migrations
directory) - The migration file
Now, let's set up our Seller
model. Just like the User
model we need to add the Billable
trait to our Seller
model sitting at AppModelsSeller
.
In the migration file (2021_XX_XX_XXXXXX_create_sellers_table.php
) for creating the sellers
table, add the following schema content. We will also bring columns we got from 2019_05_03_000001_create_customer_columns.php
after publishing Cashier's default migrations.
We are almost finished with our Seller
model. But we still need to add seller specific subscriptions model and migration.
The SellerSubscription
model setup
By default, subscription information for model AppModelsUser
will be stored in the subscriptions
table. By using the Billable
trait we are instructing Laravel, the User
model will have a hasMany
relation with the LaravelCashierSubscription
model. We can confirm that by the ManagesSubscriptions
trait.
Here in the LaravelCashierConcernsManagesSubscriptions
trait, we can see the subscriptions
method, which defines hasMany
relation with the LaravelCashierSubscription
model.
So, we are going to create a class called SellerSubscription
which extends the LaravelCashierSubscription
model & inherits its properties.
In your console run the following command to generate the SellerSubscription
model & migration.
Laravel Cashier
This will generate the following files.
SellerSubscription.php
(In/app/models
directory)2021_XX_XX_XXXXXX_create_seller_subscriptions_table.php
(In/database/migrations
directory)
The SellerSubscriptionItem
model setup
Our User
model has Multiplan Subscriptions stored in the subscription_items
table. Then why should we leave the Seller
model behind? Let's add multi-plan subscriptions functionality to the Seller
model by defining a new model called SellerSubscriptionItem
.
Let's generate the SellerSubscriptionItem
model along with migration by running the following command in the terminal.
This command should generate the following files.
SellerSubscriptionItem.php
(In/app/models
directory)2021_XX_XX_XXXXXX_create_seller_subscription_items_table.php
(In/database/migrations
directory)
Next, modify the SellerSubscription
class slightly to extend LaravelCashierSubscription
class. And also define belongsTo
relation with the Seller
class as well as hasMany
relation with the SellerSubscriptionItem
class.
Next, also modify SellerSubscriptionItem
class to extend LaravelCashierSubscriptionItem
class. And define belongsTo
relation with the SellerSubscription
class like this.
Now, it's time to take inspiration from Cashier's default migration, and update migrations for seller_subscriptions
and seller_subscription_items
accordingly.
Update migration 2021_XX_XX_XXXXXX_create_seller_subscriptions_table.php
for seller_subscriptions
table with the following schema structure. Pay attention to referencing key seller_id
& modify it according to your custom model.
Next, also update migration 2021_XX_XX_XXXXXX_create_seller_subscription_items_table.php
for seller_subscription_items
with the following schema structure. And also pay attention to referencing key seller_subscription_id
& modify it according to your custom subscription item model.
After defining the SellerSubscription
and SellerSubscriptionItem
models, define a hasMany
relation by adding the subscriptions
method on the Seller
class.
And finally, run the migration command to create/update tables in the database.
The Seller
model
Now, modify the Seller
model to override the subscriptions
relation coming from the Billable
trait. Instead of defining a relationship between the LaravelCashierSubscription
class, define it with AppModelsSellerSubscription
.
Your finished seller model should look like this.
Laravel Cashier Invoices
Next, let's set up Stripe webhooks for the Seller
model. By default, the cashier will use the /stripe/webhook
route to handle Stripe webhooks for the default configured model.
Webhooks for the Seller
model.
Stripe can notify your application in case the customer's payment method declined and many such events. We need to ensure that our application is handling it. The Cashier package makes it easy by using the /stripe/webhook
route to handle these events.
By default, it handles these events for the default configured model AppModelsUser
. In our case, we should register a different route the handle Stripe webhooks for our custom model.
First, generate a controller called SellerWebhookController
using artisan command.
Next, update SellerWebhookController
by extending LaravelCashierHttpControllersWebhookController
class. And, also modify the getUserByStripeId
method to use our custom model Seller
.
After controller, register a new route SellerWebhookController to handle webhook events coming from the Stripe.
Next, in your Stripe control panel, you should enable the following webhooks for URL https://{yourapplication.com}/stripe/seller/webhook
.
customer.subscription.updated
- When subscription is updatedcustomer.subscription.deleted
- When subscription is cancelled/deleted.customer.updated
- When customer's information updated.customer.deleted
- When a customer is deleted.invoice.payment_action_required
- When action is required for the payment method. Typically when the customer's card is declined.
That's it our application is now ready to handle Stripe webhooks for the custom billable model Seller
.
Configure auth guards & providers
In our application, sellers can authenticate themselves. So it makes sense to configure the Seller
model to take advantage of Laravel's authentication functionality.
Start by registering a new User provider in the providers
array in config/auth.php
for our billable model Seller
and also register a new guard in the guards
array in config/auth.php
file.
After this, we should able to retrieve our authenticated seller by using the $request->user('seller')
helper.
Uses
With all the setup, we are finally ready to use our Seller
model with the Cashier. Now we should be able to retrieve our authenticated seller using $request->user('seller')
and override Cashier's default model using config
helper.
Laravel Cashier Alternative
Let's see it, how we can use it in actual code.
Creating a new Subscription
When creating a new subscription for our custom model Seller
, retrieve it first by using the $request->user('seller')
helper. And then set the cashier billable model to Seller
at runtime using config
helper.
Retrieving Stripe Customer
When we need to retrieve a customer using Stripe ID, we should use Cashier::findBillable()
. But before that don't forget to set Cashier's billable model using config
helper.
Stripe Billing Portal
If you are using Stripe's billing portal in your application, you can redirect our custom Seller
model to his billing portal like this.
That's it! These are few ways to use multiple models with the Cashier package. You can find more information about the Cashier in the documentation.
Summary
Laravel Cashier is an awesome package for managing subscriptions in Laravel. Of course, there can be other ways to use Cashier with multiple models. This is one of the approaches you can use when you have more than two billable models.
Laravel Cashier Paypal
Anyway, this was one long article, and thank you for going through the article! If you have questions about the article, then hit me up on Twitter @swapnil_bhavsar.
Laravel Cashier Braintree
PS: Here is the source code for the project on Github - https://github.com/IamSwap/laravel-cashier-multiple-models