Laravel Webhook Handling with spatie/laravel-webhook-client

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

📦 What is This?

The spatie/laravel-webhook-client package:

  • Accepts incoming webhooks from any service
  • Validates webhook authenticity
  • Stores payloads
  • Processes the data via a queueable job

It’s especially useful when you’re not using Stripe, Paddle, or Laravel Cashier.


⚙️ Use Case Example: Paytm Payment Webhook

We’ll implement a webhook receiver for Paytm’s payment response using this package.


✅ Step-by-Step Tutorial


🪜 Step 1: Install the Package

Run:

composer require spatie/laravel-webhook-client

🪜 Step 2: Publish the Config and Migration Files

php artisan vendor:publish --provider="Spatie\WebhookClient\WebhookClientServiceProvider"
php artisan vendor:publish --tag="webhook-client-migrations"
php artisan migrate

This will:

  • Create the webhook_calls table to store webhook logs
  • Publish the config file: config/webhook-client.php

🪜 Step 3: Create a Paytm Signature Validator

Paytm sends a CHECKSUMHASH in the payload that must be validated.

  1. Create the validator class:
php artisan make:class PaytmSignatureValidator
  1. Add the following code to the class:
namespace App\Validators;

use Illuminate\Http\Request;
use Spatie\WebhookClient\SignatureValidator\SignatureValidator;
use PaytmChecksum; // Ensure this is imported properly from Paytm SDK

class PaytmSignatureValidator implements SignatureValidator
{
    public function isValid(Request $request, array $config): bool
    {
        $paytmParams = $request->except('CHECKSUMHASH');
        $paytmChecksum = $request->input('CHECKSUMHASH');

        return PaytmChecksum::verifySignature(
            $paytmParams,
            $config['signing_secret'], // Your merchant key
            $paytmChecksum
        );
    }
}
  1. Install Paytm’s checksum utility via their SDK:
  • Download Paytm PHP SDK
  • Copy the PaytmChecksum.php class to your Laravel app (app/Helpers/PaytmChecksum.php) and autoload it via Composer if needed.

🪜 Step 4: Create Webhook Job

php artisan make:job ProcessPaytmWebhook

Then in app/Jobs/ProcessPaytmWebhook.php:

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Spatie\WebhookClient\Models\WebhookCall;

class ProcessPaytmWebhook implements ShouldQueue
{
    use InteractsWithQueue, Queueable, SerializesModels;

    public WebhookCall $webhookCall;

    public function __construct(WebhookCall $webhookCall)
    {
        $this->webhookCall = $webhookCall;
    }

    public function handle(): void
    {
        $payload = $this->webhookCall->payload;

        // Example: Check transaction status
        if ($payload['STATUS'] === 'TXN_SUCCESS') {
            // Mark order as paid
        }
    }
}

🪜 Step 5: Update config/webhook-client.php

return [
    'configs' => [
        [
            'name' => 'paytm',
            'signing_secret' => env('PAYTM_MERCHANT_KEY'), // Set this in .env
            'signature_header_name' => 'CHECKSUMHASH',
            'signature_validator' => \App\Validators\PaytmSignatureValidator::class,
            'webhook_profile' => \Spatie\WebhookClient\WebhookProfile\ProcessEverythingWebhookProfile::class,
            'webhook_model' => \Spatie\WebhookClient\Models\WebhookCall::class,
            'process_webhook_job' => \App\Jobs\ProcessPaytmWebhook::class,
        ],
    ],
];

In your .env file:

PAYTM_MERCHANT_KEY=your_paytm_merchant_key

🪜 Step 6: Set up Webhook Route

In routes/api.php or routes/web.php:

use Spatie\WebhookClient\Http\Controllers\WebhookController;

Route::post('/paytm-webhook', WebhookController::class);

Provide this URL to Paytm dashboard as the webhook endpoint.


🪜 Step 7: Run Your Queue Worker

Ensure jobs are processed:

php artisan queue:work

Or for testing without queues, use:

QUEUE_CONNECTION=sync

🔎 Optional: View Webhook Logs

Check the stored webhook logs in the database using:

use Spatie\WebhookClient\Models\WebhookCall;

$logs = WebhookCall::latest()->get();

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