Limited Time Offer!
For Less Than the Cost of a Starbucks Coffee, Access All DevOpsSchool Videos on YouTube Unlimitedly.
Master DevOps, SRE, DevSecOps Skills!

Laravel Spark offers a pre-built SaaS solution with Stripe/Paddle integration—but what if you want full control, Indian-friendly payments, and no dependency on Stripe/Paddle?
This tutorial walks you through building your own subscription-based SaaS module in Laravel—with PayPal and PayTM as your payment gateways.
It’s fully self-hosted, integrates easily into other Laravel projects, and works for both web and mobile platforms.
🧠 Why Avoid Laravel Spark + Stripe/Paddle?
Reason | Explanation |
---|---|
❌ Stripe/Paddle Limitations | These don’t support Indian merchants natively (especially recurring logic). |
❌ Hosted Payment UI | You can’t fully control the look and flow of your payment pages. |
❌ Vendor Lock-in | You’re tied to their terms, limits, and region availability. |
✅ Instead, you’ll build a Spark-like system that’s modular, flexible, and fully yours!
Features You’ll Build
- User Auth (Register/Login)
- Plan Management (Free, Monthly, Yearly)
- Payment Gateways: PayPal + PayTM
- Subscription Logic (Start, Cancel, Expire)
- Webhook Listeners (for transaction updates)
- Invoicing (PDF download)
- Admin Panel
- API Support for App Integration
🛠️ Tools You’ll Use
Category | Tools |
---|---|
Framework | Laravel 10+ |
Auth | Laravel Breeze / Jetstream |
UI Components | Blade / Inertia + TailwindCSS |
Payment Gateways | PayPal REST API, PayTM Checksum |
PDF Invoicing | DomPDF / Laravel Snappy |
Admin Panel | Laravel Nova (optional) |
Deployment | Your VPS / Shared Hosting |
🗂️ Project Setup (Day 0)
composer create-project laravel/laravel saas-system
cd saas-system
composer require laravel/breeze --dev
php artisan breeze:install
npm install && npm run dev
php artisan migrate

📋 Step 1: Build Plans & Subscriptions Schema
php artisan make:migration create_plans_table
php artisan make:migration create_subscriptions_table
php artisan make:migration create_invoices_table
plans
table
Schema::create('plans', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->decimal('price');
$table->string('interval'); // monthly/yearly
$table->text('features')->nullable(); // JSON
$table->timestamps();
});
subscriptions
table
Schema::create('subscriptions', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->onDelete('cascade');
$table->foreignId('plan_id')->constrained()->onDelete('cascade');
$table->string('status'); // active, cancelled, expired
$table->timestamp('start_date');
$table->timestamp('end_date')->nullable();
$table->string('gateway'); // paypal, paytm
$table->string('transaction_id')->nullable();
$table->timestamps();
});
invoices
table
Schema::create('invoices', function (Blueprint $table) {
$table->id();
$table->foreignId('subscription_id')->constrained()->onDelete('cascade');
$table->decimal('amount');
$table->string('pdf_url')->nullable();
$table->string('status'); // paid, pending
$table->timestamps();
});
php artisan migrate
💳 Step 2: Integrate PayPal Checkout (Server-Side)
Install SDK:
composer require paypal/rest-api-sdk-php
Setup PayPal Config in .env
PAYPAL_CLIENT_ID=your_client_id
PAYPAL_SECRET=your_secret
PAYPAL_MODE=sandbox
Create service class PayPalService.php
to handle:
- Order Creation
- Approval Redirection
- Capture Payment
- Store Transaction in DB
👉 [Want full PayPal code? Let me know in the comments!]
🇮🇳 Step 3: Integrate PayTM Gateway
Use PayTM’s official checksum kit in Laravel.
Steps:
- Set keys in
.env
- Create
PaytmController
to handle:- Form submission
- Generate checksum
- Redirect to PayTM
- Callback route to verify checksum
- Update subscription status post payment
👉 [Full PayTM integration tutorial here — coming soon!]
📄 Step 4: Blade UI – Plans & Subscriptions
/plans.blade.php
@foreach ($plans as $plan)
<div class="plan-box">
<h2>{{ $plan->name }}</h2>
<p>{{ $plan->price }} INR</p>
<a href="{{ route('checkout', $plan->id) }}">Choose Plan</a>
</div>
@endforeach
Subscription Controller Flow:
public function checkout($planId)
{
$plan = Plan::findOrFail($planId);
return view('checkout', compact('plan'));
}
🧾 Step 5: Generate Invoices (PDF)
Install package:
composer require barryvdh/laravel-dompdf
$pdf = PDF::loadView('invoice-pdf', ['subscription' => $sub]);
$path = 'invoices/' . uniqid() . '.pdf';
Storage::put($path, $pdf->output());
🛠️ Step 6: Admin Panel
Use Laravel Nova, Filament, or a custom admin UI:
- View all subscriptions
- Create/edit/delete plans
- View payments and invoices
📱 Step 7: API Support for Mobile
Install Sanctum:
composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate
Add routes:
Route::middleware('auth:sanctum')->get('/subscriptions', function () {
return auth()->user()->subscriptions;
});
🚀 Deployment Guide
- Use Forge, DigitalOcean, or manually deploy to your VPS.
- Use Laravel scheduler to handle subscription expiry.
- Use Supervisor to queue webhook handling and PDF generation jobs.