Loading image
how to Integrate Stripe recurring payment into Laravel [2024]

how to Integrate Stripe recurring payment into Laravel [2024]

  • showkat ali
  • 18th Apr, 2024
  • 222
  • 1

Hello,

In this post, we will look at a Laravel stripe example. I simply explained the Laravel Stripe subscription tutorial.We will look at an example of a Laravel subscription. Follow the below steps for the laravel stripe tutorial.
You can use this example with the Laravel 6, Laravel 7, Laravel 8, Laravel 9, Laravel 10, and Laravel 11 versions.

 

 

 

 

Whenever we want to develop our own product in the IT field, we are looking for a subscription-based product. So, we don't have to worry about getting money. It will automatically charge every month or based on the plan. So, if you are working on a Laravel project, you need to add a subscription plan to it. Then Laravel provides a package to add these functions. You can create a stripe plan, and the user can select a plan. Based on the plan, the stripe will charge automatically. I will give you a step-by-step example here.

In this example, I will show you step-by-step how to implement a Stripe subscription using Laravel. In this example, we will create two basic and premium plans based on their price. The user can choose one of those two plans. Based on the plan, the user will get features. You can see the below preview as well. So let's see the below steps and get it done with your app.

 

 

Table of Contents:

  1. Setting Up Your Laravel 10 Environment

  2. Installing Stripe PHP SDK

  3. Configuring Stripe API Keys

  4. Creating Subscription Plans in Stripe Dashboard

  5. Creating Subscription Routes and Controllers

  6. Setting Up Subscription Views

  7. Handling Subscription Payments with Stripe Elements

  8. Managing Subscriptions and Users

  9. Testing Subscription Functionality

  10. Conclusion

  11. Setting Up Your Laravel 10 Environment:

 

Step 1: Install Laravel.


This is optional; however, if you have not created the laravel app, then you may go ahead and execute the below command:

composer create-project laravel/laravel example-app

After successfully installing the Laravel app, configure the database setup. We will open the ".env" file and change the database name, username and password in the env file.

 

Once your Laravel project is set up, you'll need to install the Stripe PHP SDK. You can do this via Composer:

Step 2: Installing the Stripe PHP SDK:

run this command

composer require stripe/stripe-php

Step 3: Create Stripe Account & Get Stripe API Key and SECRET

It is imperative that you complete this step in order to obtain the Stripe Key and Secret. If you do not already have an account, you must create one. Now let us use the following link to access the official website listed below:

1) Visit the Stripe website.
After logging in, you need to go to the Developers tab and get API keys, as shown below: click here

I just saved that key and secret, which we will use in the.env file.

Step 4: Creating Subscription Plans in Stripe Dashboard

Next, you need to go to the Products tab and create the following two plans: click here

1) Basic

2) Premium

3) Standard

You must copy the plan ID, which we will store in the plans table with Seeder. (optional)

You can see the screenshot below:

 

Now, just add the Stripe Key and Secret add-on.env file as below:

STRIPE_KEY=pk_test_MRzwmMVtDyyp1r1q79LGjJ
STRIPE_SECRET=sk_test_eKrHzLozoU4PTjCwhIPdr

Source code : https://github.com/Showkiip/laravel-stripe

Step 5: Creating Subscription Routes and Controllers

Define routes and controllers for handling subscription-related actions, such as

  • Create Route
    Route::get('/plan', [StripeController::class, 'plan'])->name('subscribe');
    Route::post('/subscribe', [StripeController::class, 'subscribe'])->name('subscribe.process');
  • Create model controllers and migrations using single command
     php artisan make:model Stripe -mc
    

Step 6: Create Blade File

Create views for displaying subscription plans, payment forms, and subscription management interfaces using Blade templates.

<div class="container">
                    <div class="row">
                        <div class="col-lg-4 mb-lg-0 mb-4">
                            <div class="card shadow-lg">
                                <span class="badge rounded-pill bg-light text-dark w-30 mx-auto">Basic Plan</span>
                                <div class="card-header text-center pt-4 pb-3">
                                    <h1 class="font-weight-bold mt-2">
                                        <small class="text-lg align-top me-1">$</small>119<small
                                            class="text-lg">/mo</small>
                                    </h1>
                                </div>
                                <div class="card-body text-lg-start text-center pt-0">
                                    <div class="d-flex justify-content-lg-start justify-content-center p-2">
                                        <i class="material-icons my-auto">done</i>
                                        <span class="ps-3">Lorem ipsum is an dummy</span>
                                    </div>
                                    <div class="d-flex justify-content-lg-start justify-content-center p-2">
                                        <i class="material-icons my-auto">done</i>
                                        <span class="ps-3">Lorem ipsum is an dummy</span>
                                    </div>
                                    <div class="d-flex justify-content-lg-start justify-content-center p-2">
                                        <i class="material-icons my-auto">remove</i>
                                        <span class="ps-3">Lorem ipsum is </span>
                                    </div>
                                    <div class="d-flex justify-content-lg-start justify-content-center p-2">
                                        <i class="material-icons my-auto">remove</i>
                                        <span class="ps-3">SLorem ipsum is an dummy text </span>
                                    </div>
                                    <div class="d-flex justify-content-lg-start justify-content-center p-2">
                                        <i class="material-icons my-auto">remove</i>
                                        <span class="ps-3">Lorem ipsum is an dummy </span>
                                    </div>
                                    <div class="d-flex justify-content-lg-start justify-content-center p-2">
                                        <i class="material-icons my-auto">remove</i>
                                        <span class="ps-3">Lorem ipsum is an dummy</span>
                                    </div>
                                    <a href="javascript:;" data-amount="119"
                                        data-plan-id="price_1P5m7bF5DVUNPpm9jW3IzCsC"
                                        class="btn btn-icon btn-outline-danger d-lg-block mt-3 mb-0 select-plan-btn">
                                        Select
                                        <i class="fas fa-arrow-right ms-1"></i>
                                    </a>
                                </div>
                            </div>
                        </div>
                        <div class="col-lg-4 mb-lg-0 mb-4">
                            <div class="card bg-gradient-dark shadow-lg" style="background:#f305012e">
                                <span class="badge rounded-pill bg-primary w-30 mx-auto">Premium Plan</span>
                                <div class="card-header text-center pt-4 pb-3 bg-transparent">
                                    <h1 class="font-weight-bold mt-2 ">
                                        <small class="text-lg align-top me-1">$</small>159<small
                                            class="text-lg">/mo</small>
                                    </h1>
                                </div>
                                <div class="card-body text-lg-start text-center pt-0">
                                    <div class="d-flex justify-content-lg-start justify-content-center p-2">
                                        <i class="material-icons my-auto ">done</i>
                                        <span class="ps-3 ">Lorem ipsum is </span>
                                    </div>
                                    <div class="d-flex justify-content-lg-start justify-content-center p-2">
                                        <i class="material-icons my-auto ">done</i>
                                        <span class="ps-3 ">Lorem ipsum is an dummy </span>
                                    </div>
                                    <div class="d-flex justify-content-lg-start justify-content-center p-2">
                                        <i class="material-icons my-auto ">done</i>
                                        <span class="ps-3 ">Lorem ipsum is an dummy </span>
                                    </div>
                                    <div class="d-flex justify-content-lg-start justify-content-center p-2">
                                        <i class="material-icons my-auto ">done</i>
                                        <span class="ps-3 ">Lorem ipsum is an dummy text </span>
                                    </div>
                                    <div class="d-flex justify-content-lg-start justify-content-center p-2">
                                        <i class="material-icons my-auto ">remove</i>
                                        <span class="ps-3 ">Lorem ipsum is an dummy</span>
                                    </div>
                                    <div class="d-flex justify-content-lg-start justify-content-center p-2">
                                        <i class="material-icons my-auto ">remove</i>
                                        <span class="ps-3 ">Lorem ipsum is an dummy</span>
                                    </div>
                                    <a href="javascript:;" data-amount="159"
                                        data-plan-id="price_1P5m80F5DVUNPpm9qmQWZ0Rd"
                                        class="btn btn-icon btn-danger d-lg-block mt-3 mb-0 select-plan-btn">
                                        Select
                                        <i class="fas fa-arrow-right ms-1"></i>
                                    </a>
                                </div>
                            </div>
                        </div>
                        <div class="col-lg-4 mb-lg-0 mb-4">
                            <div class="card shadow-lg">
                                <span class="badge rounded-pill bg-light text-dark w-30 mx-auto">Standard Plan</span>
                                <div class="card-header text-center pt-4 pb-3">
                                    <h1 class="font-weight-bold mt-2">
                                        <small class="text-lg align-top me-1">$</small>399<small
                                            class="text-lg">/mo</small>
                                    </h1>
                                </div>
                                <div class="card-body text-lg-start text-center pt-0">
                                    <div class="d-flex justify-content-lg-start justify-content-center p-2">
                                        <i class="material-icons my-auto">done</i>
                                        <span class="ps-3">Lorem ipsum is an dummy</span>
                                    </div>
                                    <div class="d-flex justify-content-lg-start justify-content-center p-2">
                                        <i class="material-icons my-auto">done</i>
                                        <span class="ps-3">Lorem ipsum is </span>
                                    </div>
                                    <div class="d-flex justify-content-lg-start justify-content-center p-2">
                                        <i class="material-icons my-auto">done</i>
                                        <span class="ps-3">Lorem ipsum is an </span>
                                    </div>
                                    <div class="d-flex justify-content-lg-start justify-content-center p-2">
                                        <i class="material-icons my-auto">done</i>
                                        <span class="ps-3">Lorem ipsum is an dummy </span>
                                    </div>
                                    <div class="d-flex justify-content-lg-start justify-content-center p-2">
                                        <i class="material-icons my-auto">done</i>
                                        <span class="ps-3">Lorem ipsum is an dummy text</span>
                                    </div>
                                    <div class="d-flex justify-content-lg-start justify-content-center p-2">
                                        <i class="material-icons my-auto">done</i>
                                        <span class="ps-3">Lorem ipsum is an dummy </span>
                                    </div>
                                    <a href="javascript:;" data-amount="399"
                                        data-plan-id="price_1P5m8HF5DVUNPpm9rWBAKJaJ"
                                        class="btn btn-icon btn-outline-danger d-lg-block mt-3 mb-0 select-plan-btn">
                                        Select
                                        <i class="fas fa-arrow-right ms-1"></i>
                                    </a>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>

 

Step 7: Handling Subscription Payments with Stripe Elements:

Integrate Stripe elements into your Laravel views to securely collect payment information from users and handle subscription payments.

modal file:

 {{-- stripe card modal --}}
    <div class="modal fade" id="stripeModal" tabindex="-1" aria-labelledby="stripeModalLabel" aria-hidden="true">
        <div class="modal-dialog modal-dialog-centered">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title" id="stripeModalLabel">Subscribe to Plan</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>
                <div class="modal-body">
                    <!-- Stripe Elements Container -->
                    <div id="stripe-elements-container"></div>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
                    <button type="button" class="btn btn-primary" id="subscribe-btn">Subscribe</button>
                </div>
            </div>
        </div>
    </div>

script file

{{-- stripe js --}}
    <script src="https://js.stripe.com/v3/"></script>
    <script>
        $(document).ready(function() {
            // Get all select plan buttons
            $('.select-plan-btn').click(function(event) {
                event.preventDefault();

                // Fetch plan details from button's data attributes
                var amount = $(this).data('amount');
                var planId = $(this).data('plan-id');
                console.log(planId)
                var csrfToken = $('meta[name="csrf-token"]').attr('content');

                // Open modal
                var modal = new bootstrap.Modal($('#stripeModal'));
                modal.show();

                // Initialize Stripe Elements
                var stripe = Stripe(
                    'pk_test_51IaGwxF5DVUNPpm9xmPgrNdzNji9zGfJXqxdu1sbctKIHBmORI3inRgVXpflBFRHyR4QwJyfXHNgIcLBtV1yxsHf00AsaqUoOE'
                );
                var elements = stripe.elements();
                var card = elements.create('card');
                card.mount('#stripe-elements-container');

                // Handle subscription when user clicks subscribe button
                $('#subscribe-btn').click(function() {
                    stripe.createPaymentMethod({
                        type: 'card',
                        card: card,
                    }).then(function(result) {
                        console.log(result)
                        if (result.error) {
                            // Show error to user
                            alert(result.error.message);
                        } else {
                            // Send payment method to server to create subscription
                            $.ajax({
                                url: '{{ route('subscribe.process') }}',
                                type: 'POST',
                                headers: {
                                    'Content-Type': 'application/json',
                                    'X-CSRF-TOKEN': csrfToken
                                },
                                dataType: 'json',
                                data: JSON.stringify({
                                    payment_method: result.paymentMethod.id,
                                    plan_id: planId,
                                    amount: amount,
                                }),
                                success: function(data) {
                                    console.log(data)
                                    if (data.success) {
                                        alert('Thanks for subscription')
                                        window.location.href = data
                                            .redirect_url;
                                    } else {
                                        alert('Error:', data.error);
                                    }
                                },
                                error: function(error) {
                                    alert('Error:', error);
                                }
                            });
                        }
                    });
                });
            });
        });
    </script>

Step 8: Managing Subscriptions and Users:

Implement logic in your controllers to manage user subscriptions, handle subscription status changes, and update user records accordingly.

use App\Models\Stripe as ModelsStripe;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Stripe\Customer;
use Stripe\Stripe;
use Stripe\Subscription;



   public function plan()
    {
        return view('subscribe');
    }

   public function subscribe(Request $request)
    {
        try {
            DB::beginTransaction();

            // Check if the user is already subscribed
            if (Auth::check()) {
                $existingSubscription = ModelsStripe::where('user_id', Auth()->user()->id)->first();
                if ($existingSubscription) {
                    return response()->json(['error' => 'User is already subscribed.'], JsonResponse::HTTP_BAD_REQUEST);
                }
            }


            $data = $request->session()->get('business');
            Stripe::setApiKey(env('STRIPE_SECRET'));
            $customer = Customer::create([
                'email' => "test@gmail.com",
                'payment_method' => $request->payment_method,
            ]);
            $customer->invoice_settings->default_payment_method = $request->payment_method;
            $customer->save();

            $subscription = Subscription::create([
                'customer' => $customer->id,
                'items' => [
                    [
                        'price' => $request->plan_id,
                    ],
                ],
            ]);
            if ($subscription) {
                $subscribe = new ModelsStripe;
                $subscribe->subscription_id = $subscription->id;
                $subscribe->user_id = Auth()->user()->id ?? 1;
                $subscribe->plain_id = $request->plan_id;
                $subscribe->stripe_customer_id = $subscription->customer;
                $subscribe->status = "paid";
                $subscribe->save();
            }
            DB::commit();
            return response()->json(['success' => true, 'redirect_url' => route('subscribe')]);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json(['error' => $e->getMessage()], JsonResponse::HTTP_BAD_REQUEST);
        }
   }

Step 9: Testing Subscription Functionality 

Test your subscription functionality thoroughly in a development environment to ensure everything works as expected. Use Stripe's test mode to simulate subscription payments without charging real money.

 

Source code : https://github.com/Showkiip/laravel-stripe

Now you can check the following card details:

 

Conclusion:

 Congratulations! You've successfully implemented Stripe subscriptions into your Laravel 10 application. With subscription-based monetization, you can now generate recurring revenue from your digital products or services while providing value to your customers.

 

Source code : https://github.com/Showkiip/laravel-stripe

 

showkat ali

Greetings, I'm a passionate full-stack developer and entrepreneur based in Pakistan. I specialize in PHP, Laravel, React.js, Node.js, JavaScript, and Python. I own interviewsolutionshub.com, where I share tech tutorials, tips, and interview questions. I'm a firm believer in hard work and consistency. Welcome to interviewsolutionshub.com, your source for tech insights and career guidance

0 Comments

Please log in to leave a comment.