Home Laravel How To Create Cashier Stripe Subscription In Laravel ?

How To Create Cashier Stripe Subscription In Laravel ?

by Shahriar Sagor

Hello Dev’s, Today i am back with an very important example. Now in this post, i will show laravel Cashier Stripe Subscription example. Here I will explained the simply about laravel cashier stripe with subscription tutorial. Here I will be explained the simply step by step stripe subscription example in laravel. Here i will look at an example of laravel cashier subscription. Just need to follow the below step for laravel cashier with stripe tutorial.

We can use this example with any of laravel 6, laravel 7, laravel 8 and laravel 9 versions.

Whenever we want to develop our own product in IT fields, and then if we are looking this subscription-based product. So, we don’t have to worry about the getting money. It will be automatically charge in every month or based on your plan. So, if you are working on a laravel project and if you need to add the subscription plan to it. Then in laravel is provides a Cashier package to add these functions. So we can easily create a stripe plan and the any user can select a plan, based on the plan stripe will be charge automatically. Here I will give you this step by step example here.

Now in this example, I will show you this example step-by-step how we can implement a stripe subscription by using laravel cashier. So in this example, i will be create Basic and Premium two plans with it’s price. So the user can choose one of that two plans. then the based on the plan user will get the features.

So let’s start and see the below steps and get it done with your app.

Step 1: Install Laravel

At first of all we have to get the fresh Laravel version application by using the bellow command. So open your terminal OR command prompt and then run the bellow command:

composer create-project laravel/laravel example-app
Step 2: Setup Database Configuration

Then after successfully installing the laravel application then after configuring the database setup. Now i will open the “.env” file and then change the database name, username and password in the env file.

.env

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=Enter_Your_Database_Name
DB_USERNAME=Enter_Your_Database_Username
DB_PASSWORD=Enter_Your_Database_Password

Step 3: Install Auth Scaffold

Now in Laravel’s laravel/ui package is provides a quick way to scaffold all of the routes and also views we need for authentication by using a few simple commands:

composer require laravel/ui

Next, i have to generate the auth scaffold with bootstrap, so just let’s run the below command:

php artisan ui bootstrap --auth

Then, need to install npm packages by using the below command:

npm install

At last, need to built bootstrap CSS by using the below command:

npm run build
Step 4: Install Cashier Package

Now in this step, i will be install laravel/cashier on that way i can use stripe API and methods to create subscriptions. So let’s run the below command:

composer require laravel/cashier

Next, i have to publish the cashier migration for creating the tables, So let’s run the below command:

php artisan vendor:publish --tag="cashier-migrations"

Then, just run the migration command for create a table by using the below command:

php artisan migrate
Step 5: Create Stripe Account & Get Stripe API Key and SECRET

Now this step is a very important step, if you don’t have any stripe account then just you need to create and if you have then just proceeded to get Stripe Key and also Secret. So, Let’s start and open the below stripe official website by using the below link:

1) Open Stripe official website

After the login, we have to go on Developers tab and get the API keys as like below:

Cashier Stripe Subscription In Laravel

Just, saved that Key and Secret we have to use in .env file.

Next, we have to go on Products tab and then create following two plans:

1) Basic

2) Premium

We must have to copy Plan ID, so that we will store in plans table with the seeder.

You can see as like as below screenshot:

Cashier Stripe Subscription In Laravel
Cashier Stripe Subscription In Laravel

Now, just need to add Stripe Key and Secret add on .env file as like as below:

.env

STRIPE_KEY=pk_test_MRzwmMVtDyyp1r1q79LGjJ
STRIPE_SECRET=sk_test_eKrHzLozoU4PTjCwhIPdr
Step 6: Configure Cashier

Now in this step, i will use the cashier Laravel\Cashier\Billable class in User model, So let’s add it in below:

app/Models/User.php

<?php
  
namespace App\Models;
  
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use Laravel\Cashier\Billable;
  
class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable, Billable;
  
    /**
     * The attributes that are mass assignable.
     *
     * @var array

     */
    protected $fillable = [
        'name',
        'email',
        'password',
    ];
  
    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array

     */
    protected $hidden = [
        'password',
        'remember_token',
    ];
  
    /**
     * The attributes that should be cast.
     *
     * @var array

     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];
}
Step 7: Create Migration and Model for Plan

Here, we need to create the migration for “plans” table by using Laravel php artisan command, So at first fire the bellow command:

php artisan make:migration create_plans_table

After this command we will find one file in the following the path “database/migrations” and we have to put the below code in our migration file for create the plans table.

<?php
  
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
  
return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('plans', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('slug');
            $table->string('stripe_plan');
            $table->integer('price');
            $table->string('description');
            $table->timestamps();
        });
    }
  
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('plans');
    }
};

Now we need to run this migration by using the following command:

php artisan migrate

Now in this step, i will create the Plan.php model. Let’s copy the below code and then paste it.

app/Models/Plan.php

<?php
  
namespace App\Models;
  
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
  
class Plan extends Model
{
    use HasFactory;
  
    /**
     * The attributes that are mass assignable.
     *
     * @var array

     */
    protected $fillable = [
        'name',
        'slug',
        'stripe_plan',
        'price',
        'description',
    ];
  
    /**
     * Write code on Method
     *
     * @return response()
     */
    public function getRouteKeyName()
    {
        return 'slug';
    }
}
Step 8: Create Routes

Now in this step, i will create three routes for plans, plans show and subscription buy. So, let’s start and add a new route to that file.

routes/web.php

<?php
  
use Illuminate\Support\Facades\Route;
 
use App\Http\Controllers\PlanController;
  
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
  
Route::get('/', function () {
    return view('welcome');
});
 
Auth::routes();
  
Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home');
  
Route::middleware("auth")->group(function () {
    Route::get('plans', [PlanController::class, 'index']);
    Route::get('plans/{plan}', [PlanController::class, 'show'])->name("plans.show");
    Route::post('subscription', [PlanController::class, 'subscription'])->name("subscription.create");
});

Step 9: Create Controller File

Then now in the next step, i have created a new controller as PlanController and then write the three methods on it like as below, So let’s create a new controller:

app/Http/Controllers/PlanController.php

<?php
  
namespace App\Http\Controllers;
  
use Illuminate\Http\Request;
use App\Models\Plan;
  
class PlanController extends Controller
{
    /**
     * Write code on Method
     *
     * @return response()
     */
    public function index()
    {
        $plans = Plan::get();
  
        return view("plans", compact("plans"));
    }  
  
    /**
     * Write code on Method
     *
     * @return response()
     */
    public function show(Plan $plan, Request $request)
    {
        $intent = auth()->user()->createSetupIntent();
  
        return view("subscription", compact("plan", "intent"));
    }
    /**
     * Write code on Method
     *
     * @return response()
     */
    public function subscription(Request $request)
    {
        $plan = Plan::find($request->plan);
  
        $subscription = $request->user()->newSubscription($request->plan, $plan->stripe_plan)
                        ->create($request->token);
  
        return view("subscription_success");
    }
}
Step 10: Create Blade File

In this step, i have to create the three blade file with the plans.blade.php, subscription.blade.php and subscription_success.blade.php,

so let’s update the following code on it:

resources/views/plans.blade.php
@extends('layouts.app')
  
@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">Select Plane:</div>
 
                <div class="card-body">
 
                    <div class="row">
                        @foreach($plans as $plan)
                            <div class="col-md-6">
                                <div class="card mb-3">
                                  <div class="card-header"> 
                                        ${{ $plan->price }}/Mo
                                  </div>
                                  <div class="card-body">
                                    <h5 class="card-title">{{ $plan->name }}</h5>
                                    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
  
                                    <a href="{{ route('plans.show', $plan->slug) }}" class="btn btn-primary pull-right">Choose</a>
  
                                  </div>
                                </div>
                            </div>
                        @endforeach
                    </div>
  
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

resources/views/subscription.blade.php

@extends('layouts.app')
    
@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">
                    You will be charged ${{ number_format($plan->price, 2) }} for {{ $plan->name }} Plan
                </div>
  
                <div class="card-body">
  
                    <form id="payment-form" action="{{ route('subscription.create') }}" method="POST">
                        @csrf
                        <input type="hidden" name="plan" id="plan" value="{{ $plan->id }}">
  
                        <div class="row">
                            <div class="col-xl-4 col-lg-4">
                                <div class="form-group">
                                    <label for="">Name</label>
                                    <input type="text" name="name" id="card-holder-name" class="form-control" value="" placeholder="Name on the card">
                                </div>
                            </div>
                        </div>
  
                        <div class="row">
                            <div class="col-xl-4 col-lg-4">
                                <div class="form-group">
                                    <label for="">Card details</label>
                                    <div id="card-element"></div>
                                </div>
                            </div>
                            <div class="col-xl-12 col-lg-12">
                            <hr>
                                <button type="submit" class="btn btn-primary" id="card-button" data-secret="{{ $intent->client_secret }}">Purchase</button>
                            </div>
                        </div>
  
                    </form>
  
                </div>
            </div>
        </div>
    </div>
</div>
  
<script src="https://js.stripe.com/v3/"></script>
<script>
    const stripe = Stripe('{{ env('STRIPE_KEY') }}')
  
    const elements = stripe.elements()
    const cardElement = elements.create('card')
  
    cardElement.mount('#card-element')
  
    const form = document.getElementById('payment-form')
    const cardBtn = document.getElementById('card-button')
    const cardHolderName = document.getElementById('card-holder-name')
  
    form.addEventListener('submit', async (e) => {
        e.preventDefault()
  
        cardBtn.disabled = true
        const { setupIntent, error } = await stripe.confirmCardSetup(
            cardBtn.dataset.secret, {
                payment_method: {
                    card: cardElement,
                    billing_details: {
                        name: cardHolderName.value
                    }   
                }
            }
        )
  
        if(error) {
            cardBtn.disable = false
        } else {
            let token = document.createElement('input')
            token.setAttribute('type', 'hidden')
            token.setAttribute('name', 'token')
            token.setAttribute('value', setupIntent.payment_method)
            form.appendChild(token)
            form.submit();
        }
    })
</script>
@endsection

resources/views/subscription_success.blade.php

@extends('layouts.app')
  
@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
  
                <div class="card-body">
  
                    <div class="alert alert-success">
                        Subscription purchase successfully!
                    </div>
  
                </div>
            </div>
        </div>
    </div>
</div>
@endsection
Step 11: Create Seeder For Plans

Now in this step, i will create the seeder for creating the Basic and Premium plans.

Make sure we have to copy our plan ID from stripe website

So, create the seeder by using bellow command:

php artisan make:seeder PlanSeeder

And then need to put the bellow code in PlanSeeder seeder this way:

database/seeders/PlanSeeder.php

<?php
  
namespace Database\Seeders;
  
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use App\Models\Plan;
  
class PlanSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $plans = [
            [
                'name' => 'Basic', 
                'slug' => 'basic', 
                'stripe_plan' => 'price_1LXOzsGzlk2XAanfTskz9n', 
                'price' => 25, 
                'description' => 'Basic'
            ],
            [
                'name' => 'Premium', 
                'slug' => 'premium', 
                'stripe_plan' => 'price_1LXP23Gzlk2XAanf4zQZdi', 
                'price' => 75, 
                'description' => 'Premium'
            ]
        ];
  
        foreach ($plans as $plan) {
            Plan::create($plan);
        }
    }
}

After this i have to run the bellow command for run PermissionTableSeeder seeder:

php artisan db:seed --class=PlanSeeder

Run Laravel App:

Now we can run by using bellow command:

php artisan serve

Read Also: php artisan serve not working in Laravel

Thanks for read. I hope it help you. For more you can follow us on facebook

close

You may also like