In this tutorial we’re going to see how easy it is to create a basic paid membership website using the Laravel Cashier package. You can see a demo of the app here and download the source code here.
Key Takeaways
- Laravel Cashier simplifies the creation of a basic paid membership website by managing subscription billing, handling coupons, swapping subscriptions, cancellation grace periods, and generating invoice PDFs.
- To integrate Laravel Cashier into an existing Laravel project, install the package via Composer, run a migration to add necessary columns to the users table, set up API keys, and add the Billable trait to the model.
- Laravel Cashier can handle failed payments by retrying the payment automatically. If the payment continues to fail, the subscription will be cancelled.
- Laravel Cashier currently supports only Stripe and Braintree but can be extended to work with other payment gateways with a good understanding of Laravel and the payment gateway’s API.
Setting up a working environment
We need to create a boilreplate project to get started, and we can do that in two different ways:
- we can clone the Github repo to our project folder.
- Assuming that you have composer installed, ( check installation guide for more details).
we run composer create-project laravel/laravel laravel_membership --prefer-dist, this will create a laravel boilerplate project in our laravel_membership folder.
Now we need to require the Laravel Cashier package to the project by adding "laravel/cashier": "~1.0" to our composer.json on the require section and run composer update to update our dependencies.
After that we need to tell our app to load the Cashier service provider class. We can do that by adding "LaravelCashierCashierServiceProvider" to the providers array on the config/app.php file.
Note: You must run composer dump-autoload to update the classMap package.
Creating the database using migrations
If you are new to Laravel Migrations be sure to check the documentation.
We are going to use two tables:
posts table:
– INT id
– STRING title
– LONG_TEXT content
– BOOL is_premium
users table:
– INT id
– VARCHAR(60) email
– VARCHAR(60) password
The Laravel artisan command line tool makes it easy to create and manage migration classes.
<span>php artisan migrate:make create_posts_table --create="posts" </span><span> </span><span>php artisan migrate:make create_users_table --create="users"</span>
and then we fill the Schema::create callback function argument with the necessary code that looks like this
<span>Schema::create('posts', function(Blueprint $table) </span><span>{ </span><span> $table->increments('id'); </span><span> $table->string('title'); </span><span> $table->longText('content'); </span><span> $table->boolean("is_premium"); </span><span> $table->timestamps(); </span><span>}); </span><span> </span><span>Schema::create('users', function(Blueprint $table) </span><span>{ </span><span> $table->increments('id'); </span><span> $table->string('email', 100)->unique(); </span><span> $table->string('password', 60); </span><span> $table->timestamps(); </span><span>});</span>
To let Laravel Cashier know about our billable table we need to create a specific migration for that. Laravel Cashier has a built in command for that purpose.
<span>php artisan cashier:table users</span>
Now we are ready to migrate our database
<span>php artisan migrate:make create_posts_table --create="posts" </span><span> </span><span>php artisan migrate:make create_users_table --create="users"</span>
if you open your users table you will see a bunch of fields added when the package migration is executed.
– stripe_active if you have an active subscription.
– stripe_id user id on Stripe server.
– stripe_plan Stripe subscription plan.
– last_four credit card last four digits.
– trial_ends_at an end date is stored if you specify a trial period.
– subscription_ends_at subscription end date.
Now we will seed the database with some dummy data to get started; check the final result on GitHub.
Stripe billing process
Dealing with payment can be a pain in the neck, and Stripe can help you with that, they use tokens instead of card numbers etc.., and that’s how you can make sure that your customers stay secure while paying for your service.
NOTE: Check if Stripe is supported in your country, but you can still use it for testing if not.
To get started we need to get an account first. Stripe doesn’t have a monthly fee for the subscription, you only pay when you get paid.
Now, after getting an account you need to create Plans for your application (Monthly, Yearly, Silver, Gold…).
Every field is self explanatory, so lets create a Gold membership that will cost $40 and a Basic membership for $10. They will be billed every month.
We have already added the necessary columns to our users table, now we need to let Laravel Cashier know that we will use the User class as our billing class.
<span>Schema::create('posts', function(Blueprint $table) </span><span>{ </span><span> $table->increments('id'); </span><span> $table->string('title'); </span><span> $table->longText('content'); </span><span> $table->boolean("is_premium"); </span><span> $table->timestamps(); </span><span>}); </span><span> </span><span>Schema::create('users', function(Blueprint $table) </span><span>{ </span><span> $table->increments('id'); </span><span> $table->string('email', 100)->unique(); </span><span> $table->string('password', 60); </span><span> $table->timestamps(); </span><span>});</span>
Note: we’re using BillableTrait and traits require PHP 5.4 or greater.
Now we have to set our Stripe API access key, which you can get from Your account > Account settings > API Keys and copy your Test Secret Key.
By using the BillableTrait we get access to the User::setStripeKey(key) method which can be called anywhere in our code, but the preferred way is to create a services.php file under your config directory and return an array like this:
<span>php artisan cashier:table users</span>
When getStripeKey tries to load your key it will look for a property called stripeKey. If not found, it will automatically load your services file.
Creating our pages
To keep things simple we will create only a few pages:
– Signup: where user can signup with a membership plan ( Basic, Gold ).
– Login: members login page.
– Upgrade: upgrade from basic to gold membership.
– Post: display a single post page.
To speed up the process we will use bootsnipp. You can get the final code from the GitHub repo.
Login page:
The login page has a basic email and password field, with a LoginController page that looks like this:
<span>php artisan migrate:make create_posts_table --create="posts" </span><span> </span><span>php artisan migrate:make create_users_table --create="users"</span>
Signup page:
The signup page has a Subscription plan field used to assign a user to plan.
We have also a Credit card number, Expiration date, CVC.
As we said earlier, we will never have to deal with any payment or verification process, we pass those values to the Stripe server to take care of the charging and verification process.
The return value is a token in case of success otherwise we get an error message that we can show to the user.
Let’s see what the front-end code looks like:
<span>Schema::create('posts', function(Blueprint $table) </span><span>{ </span><span> $table->increments('id'); </span><span> $table->string('title'); </span><span> $table->longText('content'); </span><span> $table->boolean("is_premium"); </span><span> $table->timestamps(); </span><span>}); </span><span> </span><span>Schema::create('users', function(Blueprint $table) </span><span>{ </span><span> $table->increments('id'); </span><span> $table->string('email', 100)->unique(); </span><span> $table->string('password', 60); </span><span> $table->timestamps(); </span><span>});</span>
First we include the JavaScript API file, then we set our public key that we grabbed from our Stripe dashboard settings.
Next we attach a callback function to our submit form (be sure that your form ID matches the one used on the event handler), to prevent a double submission we disable our submit button.
The Stripe.card.createToken accepts two arguments, the first one is a JSON object that has some required and optional values.
Required values:
- number: card number as a string without any separators.
- exp_month: two digit number representing the card’s expiration month.
- exp_year: two or four digit number representing the card’s expiration year.
Optional values:
- cvc: card security code as a string, the cvc number is optional but recommended to help prevent fraud.
- name: cardholder name.
- address_line1: billing address line 1.
- address_line2: billing address line 2.
- address_city: billing address city.
- address_state: billing address state.
- address_zip: billing zip as a string.
- address_country: billing address country.
You can notice that we’re passing a form object instead of a JSON object, you can choose to grab the values manually or use the data-stripe html5 attribute on your inputs and Stripe will use some helper methods to grab those values automatically for you. Ex:
<span>php artisan cashier:table users</span>
The second argument passed to Stripe.card.createToken method is a callback function to handle the response.
In case of failure the stripeResponseHandler will try to find an element with a class of payment_errors to display some descriptive errors to the user.
In case of success a stripeToken hidden input will be appended to the form and it will be available on submit.
Additional options
- Trial periods: as we stated before, when you create a new plan you have a choice to specify a trial period for users to test your product, and they won’t be charged until the specified period has elapsed.
- Coupons: you create coupons via your dashboard menu where you can specify a fixed amount or by percentage,with some other useful options.
Now let’s move to our SignupController to see how we will handle this.
<span>php artisan migrate:make create_posts_table --create="posts" </span><span> </span><span>php artisan migrate:make create_users_table --create="users"</span>
We will skip the validation process to keep things simple.
After creating a new User and saving it, we now have the option to subscribe the user to a new membership plan. The subscription method accepts an already registered plan as an argument, that can be either a PlanInterface or a String and return a StripeGateway.
The create method accepts a token as a parameter; we pass the new hidden input value with the name stripeToken.
Upgrade page:
The upgrade page will submit to the UpgradeController that looks like this:
<span>Schema::create('posts', function(Blueprint $table) </span><span>{ </span><span> $table->increments('id'); </span><span> $table->string('title'); </span><span> $table->longText('content'); </span><span> $table->boolean("is_premium"); </span><span> $table->timestamps(); </span><span>}); </span><span> </span><span>Schema::create('users', function(Blueprint $table) </span><span>{ </span><span> $table->increments('id'); </span><span> $table->string('email', 100)->unique(); </span><span> $table->string('password', 60); </span><span> $table->timestamps(); </span><span>});</span>
We check if the user is logged in first, then we create a new subscription with the new plan and we call the swap method, obviously in a real project you will have some fees adjustments and a downgrade option, but it should work the same way.
Post page:
The PostController checks if the post is_premium, and if so, we test if the user is a gold member who can see the post, else we return a simple error message.
<span>php artisan cashier:table users</span>
Of course in our routes.php file we need to add an auth filter to prevent unauthenticated users from accessing the page.
Our routes file will look like this:
<span>php artisan migrate</span>
Other useful methods
- withCoupon: we said before that we have the possibility to create discount coupons, in our example we can do that like so:
<span>use Laravel\Cashier\BillableInterface; </span><span>use Laravel\Cashier\BillableTrait; </span><span> </span><span>class User extends Eloquent implements BillableInterface { </span><span> </span><span> use BillableTrait; </span><span> protected $dates = ['trial_ends_at', 'subscription_ends_at'];</span>
- cancel: you can easily cancel a subscription using this method, but you have to check whether the user is onGracePeriod to be sure you don’t block them immediately:
<span>return [ </span><span> 'stripe' => [ </span><span> 'secret' => 'Your key' </span><span> ] </span><span>];</span>
- onPlan: see if a user is on a certain plan.
- onTrial: see if a user still on trial period.
- canceled: if the user has canceled their subscription.
- getLastFourCardDigits: get the user card last four digits.
- getSubscriptionEndDate: get the subscription end date.
- getTrialEndDate: get the trial end date.
- invoices: get the list of user invoices.
- findInvoice: find an invoice by id.
- downloadInvoice: generate a downloadable invoice by id.
Conclusion
In this tutorial we explored how Laravel Cashier can ease the billing process and help manage your customers more easily.
We certainly didn’t cover everything here, but it’s a start for you to dig into the source code to explore what else you can do. If you’d like to see a Nitrous-hosted demo of this app, see here.
Frequently Asked Questions (FAQs) about Laravel Cashier Memberships
How does Laravel Cashier handle subscription billing?
Laravel Cashier is a powerful tool that simplifies the process of managing subscription billing. It 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. Laravel Cashier can handle coupons, swapping subscription, subscription “quantities”, cancellation grace periods, and even generate invoice PDFs.
What are the prerequisites for using Laravel Cashier?
Before using Cashier, you’ll need to create a Stripe account and install the Cashier package via Composer. You’ll also need to 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 card information.
How can I integrate Laravel Cashier into my existing Laravel project?
Integrating Laravel Cashier into your existing Laravel project is straightforward. First, you need to install the package via Composer. Then, you need to prepare the database by running a migration that adds several columns to your users table. After that, you need to set up the API keys and add the Billable trait to your model. Finally, you can use the various methods provided by the Billable trait to manage your subscriptions.
How does Laravel Cashier handle failed payments?
Laravel Cashier has built-in functionality to handle failed payments. If a payment fails, Cashier will automatically retry the payment. If the payment continues to fail, the subscription will be cancelled. However, you can also handle these events manually by listening for the relevant events and taking appropriate action.
Can I use Laravel Cashier with other payment gateways?
Currently, Laravel Cashier only supports Stripe and Braintree. However, you can extend Cashier to work with other payment gateways if you wish. This would require a good understanding of both Laravel and the payment gateway’s API.
How can I cancel a subscription using Laravel Cashier?
You can cancel a subscription using the cancel method on a user’s subscription. When a subscription is cancelled, Cashier will automatically set the end date of the subscription to the end of the current billing cycle.
Can I offer trial periods with Laravel Cashier?
Yes, Laravel Cashier supports trial periods. You can set the trial period when creating the subscription. The user will not be billed until the trial period is over.
How can I generate invoices using Laravel Cashier?
Laravel Cashier can automatically generate invoice PDFs. You can access the downloadable PDF version of the invoice by calling the download method on an invoice instance, which will write the PDF to disk or stream it to the browser.
Can I apply coupons to subscriptions using Laravel Cashier?
Yes, Laravel Cashier supports applying coupons to subscriptions. You can do this by using the withCoupon method when creating a new subscription.
How can I handle subscription quantities with Laravel Cashier?
Laravel Cashier allows you to handle subscription quantities, which can be useful for “per seat” type subscriptions. You can update the quantity of a subscription using the updateQuantity method on a subscription instance.
The above is the detailed content of Memberships with Laravel Cashier. For more information, please follow other related articles on the PHP Chinese website!

PHPsessionstrackuserdataacrossmultiplepagerequestsusingauniqueIDstoredinacookie.Here'showtomanagethemeffectively:1)Startasessionwithsession_start()andstoredatain$_SESSION.2)RegeneratethesessionIDafterloginwithsession_regenerate_id(true)topreventsessi

In PHP, iterating through session data can be achieved through the following steps: 1. Start the session using session_start(). 2. Iterate through foreach loop through all key-value pairs in the $_SESSION array. 3. When processing complex data structures, use is_array() or is_object() functions and use print_r() to output detailed information. 4. When optimizing traversal, paging can be used to avoid processing large amounts of data at one time. This will help you manage and use PHP session data more efficiently in your actual project.

The session realizes user authentication through the server-side state management mechanism. 1) Session creation and generation of unique IDs, 2) IDs are passed through cookies, 3) Server stores and accesses session data through IDs, 4) User authentication and status management are realized, improving application security and user experience.

Tostoreauser'snameinaPHPsession,startthesessionwithsession_start(),thenassignthenameto$_SESSION['username'].1)Usesession_start()toinitializethesession.2)Assigntheuser'snameto$_SESSION['username'].Thisallowsyoutoaccessthenameacrossmultiplepages,enhanc

Reasons for PHPSession failure include configuration errors, cookie issues, and session expiration. 1. Configuration error: Check and set the correct session.save_path. 2.Cookie problem: Make sure the cookie is set correctly. 3.Session expires: Adjust session.gc_maxlifetime value to extend session time.

Methods to debug session problems in PHP include: 1. Check whether the session is started correctly; 2. Verify the delivery of the session ID; 3. Check the storage and reading of session data; 4. Check the server configuration. By outputting session ID and data, viewing session file content, etc., you can effectively diagnose and solve session-related problems.

Multiple calls to session_start() will result in warning messages and possible data overwrites. 1) PHP will issue a warning, prompting that the session has been started. 2) It may cause unexpected overwriting of session data. 3) Use session_status() to check the session status to avoid repeated calls.

Configuring the session lifecycle in PHP can be achieved by setting session.gc_maxlifetime and session.cookie_lifetime. 1) session.gc_maxlifetime controls the survival time of server-side session data, 2) session.cookie_lifetime controls the life cycle of client cookies. When set to 0, the cookie expires when the browser is closed.


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

DVWA
Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is very vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, to help web developers better understand the process of securing web applications, and to help teachers/students teach/learn in a classroom environment Web application security. The goal of DVWA is to practice some of the most common web vulnerabilities through a simple and straightforward interface, with varying degrees of difficulty. Please note that this software

WebStorm Mac version
Useful JavaScript development tools

Atom editor mac version download
The most popular open source editor

EditPlus Chinese cracked version
Small size, syntax highlighting, does not support code prompt function

MinGW - Minimalist GNU for Windows
This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.
