How to Build a Laravel-Based SaaS Subscription System with PayPal and PayTM (Without Stripe/Paddle) — Self-Hosted, Spark-Like Module

Posted by

Limited Time Offer!

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

Enroll Now

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?

ReasonExplanation
❌ Stripe/Paddle LimitationsThese don’t support Indian merchants natively (especially recurring logic).
❌ Hosted Payment UIYou can’t fully control the look and flow of your payment pages.
❌ Vendor Lock-inYou’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

CategoryTools
FrameworkLaravel 10+
AuthLaravel Breeze / Jetstream
UI ComponentsBlade / Inertia + TailwindCSS
Payment GatewaysPayPal REST API, PayTM Checksum
PDF InvoicingDomPDF / Laravel Snappy
Admin PanelLaravel Nova (optional)
DeploymentYour 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.

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x