Laravel Spark + Paytm Subscription Integration Tutorial

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 natively supports Stripe and Paddle. Paytm is not supported out-of-the-box, so to support Indian payment preferences such as UPI and net banking, we must manually integrate Paytmโ€™s recurring subscription feature.

Paytm supports:

  • UPI Autopay (โ‚น5000 limit per mandate)
  • e-NACH Mandates (bank auto-debit, higher limits)

This guide uses the anandsiddharth/laravel-paytm-wallet package for Paytm integration.


Prerequisites

  • Laravel Spark app set up and working
  • Laravel 8+ installed
  • Verified Paytm Business Account with subscription billing enabled
  • Access to Paytm Merchant Dashboard and Developer Portal
  • Paytm credentials: Merchant ID, Merchant Key, Website

Install Paytm Wallet Package

Run the following command in your Laravel project:

composer require anandsiddharth/laravel-paytm-wallet

Configure Paytm in Laravel

.env

PAYTM_ENVIRONMENT=local
PAYTM_MERCHANT_ID=YOUR_MERCHANT_ID
PAYTM_MERCHANT_KEY=YOUR_MERCHANT_KEY
PAYTM_MERCHANT_WEBSITE=DEFAULT
PAYTM_CHANNEL=WEB
PAYTM_INDUSTRY_TYPE=Retail

config/services.php

'paytm-wallet' => [
    'env' => env('PAYTM_ENVIRONMENT'),
    'merchant_id' => env('PAYTM_MERCHANT_ID'),
    'merchant_key' => env('PAYTM_MERCHANT_KEY'),
    'merchant_website' => env('PAYTM_MERCHANT_WEBSITE'),
    'channel' => env('PAYTM_CHANNEL'),
    'industry_type' => env('PAYTM_INDUSTRY_TYPE'),
],

If using Laravel < 5.5, manually add the provider and alias in config/app.php.


Create Subscription Payment Flow

Create Controller

php artisan make:controller PaytmSubscriptionController

app/Http/Controllers/PaytmSubscriptionController.php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use PaytmWallet;

class PaytmSubscriptionController extends Controller
{
    public function initiate(Request $request)
    {
        $order_id = 'ORDER_' . time();

        $payment = PaytmWallet::with('receive');
        $payment->prepare([
            'order' => $order_id,
            'user' => auth()->id(),
            'mobile_number' => auth()->user()->phone,
            'email' => auth()->user()->email,
            'amount' => $request->amount,
            'callback_url' => route('paytm.callback')
        ]);

        return $payment->receive();
    }

    public function callback()
    {
        $transaction = PaytmWallet::with('receive');
        $response = $transaction->response();

        if ($transaction->isSuccessful()) {
            auth()->user()->update([
                'subscription_status' => 'active',
                'paytm_order_id' => $response['ORDERID'],
                'subscription_renewal_date' => now()->addMonth(), // for monthly plan
            ]);

            return redirect('/dashboard')->with('success', 'Subscription activated successfully.');
        }

        return redirect('/subscribe')->with('error', 'Payment failed or cancelled.');
    }
}

Routes

Add the following routes in routes/web.php:

Route::middleware(['auth'])->group(function () {
    Route::post('/paytm/initiate', [PaytmSubscriptionController::class, 'initiate'])->name('paytm.initiate');
    Route::post('/paytm/callback', [PaytmSubscriptionController::class, 'callback'])->name('paytm.callback');
});

Create Blade View for Subscription

Create or update a blade file where users can initiate payment:

<form action="{{ route('paytm.initiate') }}" method="POST">
    @csrf
    <input type="hidden" name="amount" value="999"> <!-- Set dynamically -->
    <button type="submit" class="btn btn-primary">Subscribe with Paytm</button>
</form>

Enable Recurring Payment with Paytm

Paytm offers two ways to handle recurring billing:

A. UPI Autopay

  • Maximum โ‚น5000
  • User approves mandate via UPI app
  • Use createSubscription API from Paytm to initiate UPI mandate

B. e-NACH

  • Works via net banking or debit card
  • Suitable for high-value yearly subscriptions

You must call Paytm’s Subscription APIs to:

  • Initiate a subscription plan
  • Track mandate approval
  • Handle renewals via webhook or periodic API check

Refer: Paytm Subscriptions


Subscription Management

Since Spark is tightly integrated with Stripe, you need to manually:

  • Track Paytm mandates
  • Update your own subscription table or user model
  • Handle failures or renewal issues via a scheduled command or webhook from Paytm

Create a custom table like paytm_subscriptions to store:

  • user_id
  • subscription_id
  • status
  • next_renewal_date
  • mandate_type (upi/nach)

Laravel Command to Check Renewals (Optional)

You can create a Laravel console command to query Paytm API for recurring status and renewals and update your database accordingly.


Key Differences and Summary

FeatureLaravel Spark (Default)Paytm Integration (Manual)
Built-in supportStripe, PaddleNot available
UPI SupportNoYes
Net Banking SupportNoYes
Mandate SupportNoYes (UPI/e-NACH)
Automated BillingYesManual/Webhook
Integration ComplexityLowMedium
Recurring Subscription UXSeamlessRequires Custom Work

Final Notes

  • Paytm integration with Spark requires manual subscription handling.
  • You can still use Sparkโ€™s UI and subscription management by syncing states.
  • For users preferring Indian payments, this gives you full flexibility.
  • Ensure you test in Paytmโ€™s staging environment before production.
  • UPI Autopay and e-NACH require proper configuration and approval from Paytm.

Senior Software Development Engineer at Cotocus

Related Posts

How We Fixed a Stubborn Laravel MeiliSearch Bulk Indexing Failure (16,000+ Records)

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 If…

Read More

Laravel Search Without Docker, Queues, or Horizon

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 Modern…

Read More

Laravel Scout with Typesense vs Meilisearch

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 Modern…

Read More

SESSION_DRIVER=file vs SESSION_DRIVER=database in Laravel

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 Which…

Read More

Laravel Logging: Complete Step-by-Step Guide to Enable, Debug, Verify, and Master Logs in Any Laravel Project

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 Logging…

Read More

Complete Tutorial: Setting Up Laravel Telescope Correctly (Windows + XAMPP + Custom Domain)

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 This…

Read More
Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments