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.
We need to create a boilreplate project to get started, and we can do that in two different ways:
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.
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.
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.
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.
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>
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:
Optional values:
<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.
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.
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.
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>
<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>
<span>return [ </span><span> 'stripe' => [ </span><span> 'secret' => 'Your key' </span><span> ] </span><span>];</span>
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.
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.
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.
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.
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.
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.
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.
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.
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.
Yes, Laravel Cashier supports applying coupons to subscriptions. You can do this by using the withCoupon method when creating a new subscription.
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!