Laravel Webhook Handling with spatie/laravel-webhook-client

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

๐Ÿ“ฆ 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();

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