Categories: Laravel

Building a Robust Webhook Handler in Laravel 10

Share your learning

Webhook handler in Laravel 8,9, and 10 is quite easy. This article is inspired by Laravel cashier (stripe) webhooking handling.

Webhooks are an indispensable part of modern web applications, enabling real-time data updates and seamless integrations with third-party services. 

In this tutorial, we will walk you through the process of building a robust webhook handler in Laravel 10. We’ll cover the primary components, including the base webhook controller, webhook controller extension, webhook events, and how to verify webhook signatures to ensure security.

Prerequisites

Before we start building the webhook handler, make sure you have a basic understanding of Laravel development and have Laravel 10 installed on your system.

1. Setting Up the Base Webhook Controller

In Laravel 10, creating a base webhook controller is a breeze. Let’s begin by generating a new controller using the Artisan CLI:

php artisan make:controller BaseWebhookController

The generated controller will be placed in the app/Http/Controllers directory. Inside the BaseWebhookController, we’ll define methods to handle the primary functionalities of receiving and processing incoming webhook requests.

The base webhook controller should:

– Accept incoming webhook requests from external services.

– Parse the incoming payload to extract relevant data.

– Trigger appropriate actions or functions based on the received data.

– Respond with the appropriate status code to acknowledge receipt of the webhook.

2. Extending the Webhook Controller

To handle webhooks from specific services, we’ll create a webhook controller that extends the base webhook controller. This extension allows us to add service-specific logic without modifying the core webhook handling functionalities.

For instance, if you’re integrating with GitHub, Stripe, or other services, you can create separate webhook controllers for each service, all extending the BaseWebhookController.

Let’s generate a GitHub webhook controller as an example:

php artisan make:controller GitHubWebhookController

Inside GitHubWebhookController, extend the base webhook controller and implement the necessary methods to handle GitHub-specific webhook data.

3. Implementing Webhook Received and Webhook Handled Events

In Laravel, we can use events and listeners to implement webhook received and webhook handled events. Events allow us to raise specific occurrences, and listeners respond to those events.

First, let’s create an event for webhook received:

php artisan make:event WebhookReceived

Inside the WebhookReceived event class, define any additional data you want to log or process when a webhook is received.

Next, create a listener for the WebhookReceived event:

php artisan make:listener HandleWebhookReceived --event=WebhookReceived

In the HandleWebhookReceived listener, write the logic to log incoming webhook data, including headers, payload, timestamp, and any other relevant information.

Similarly, we can create events and listeners for webhook handled:

php artisan make:event WebhookHandled
php artisan make:listener HandleWebhookHandled --event=WebhookHandled

In the HandleWebhookHandled listener, you can perform additional actions or integrate with other parts of your application as needed.

4. Verifying Webhook Signatures for Security

To verify webhook signatures for security, we can create a middleware that checks the authenticity of incoming requests.

First, generate the middleware:

php artisan make:middleware VerifyWebhookSignature

In the VerifyWebhookSignature middleware, extract the provided signature from the request headers and compare it to the expected signature for that specific webhook. If the signatures match, the request is valid, and we can proceed with processing it. Otherwise, reject the request to prevent potential security breaches.

5. Create routes to handle webhook in Laravel 10

Create routes to handle webhook and pass to the third party tool from where you will get the webhoook events.

Route::post(
    '/your/webhook',
    [YourWebhookController::class, 'handleWebhook']

);

Example of webhook handler in Laravel

Let’s start with the base controller as below, replace YourWebhook with a specific name. This controller is responsible to verify the webhook signature and redirect the request to a particular webhook handling method. For example if the webhook event is payment.succeed then the base controller will pass the request to handlePaymentSucceed method.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Events\YourWebhookHandled;
use App\Events\YourWebhookReceived;
use App\Http\Middleware\VerifyYourWebhookSignature;
use Illuminate\Support\Facades\Log;
use Symfony\Component\HttpFoundation\Response;
use Illuminate\Support\Str;

class YourWebhook extends Controller
{

    /**
     * Create a new WebhookController instance.
     *
     * @return void
     */    public function __construct()
    {
        if ( config('webhook.keys.secret') ) {
            $this->middleware(VerifyYourWebhookSignature::class);
        }
    }

    /**
     * Handle a Stripe webhook call.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Symfony\Component\HttpFoundation\Response
     */    public function handleWebhook(Request $request)
    {
        $payload = json_decode($request->getContent(), true);
        $method = 'handle'.Str::studly(str_replace('.', '_', $payload['type']));

       YourWebhookReceived::dispatch($payload);

        if (method_exists($this, $method)) {

            $response = $this->{$method}($payload['data']['object']);

            YourWebhookHandled::dispatch($payload);

            return $this->successMethod($payload);
        }

        return $this->missingMethod($payload);
    }

    /**
     * Handle successful calls on the controller.
     *
     * @param  array  $parameters
     * @return \Symfony\Component\HttpFoundation\Response
     */    protected function successMethod($parameters = [])
    {
        return new Response('Webhook Handled', 200);
    }

    /**
     * Handle calls to missing methods on the controller.
     *
     * @param  array  $parameters
     * @return \Symfony\Component\HttpFoundation\Response
     */    protected function missingMethod($parameters = [])
    {
        Log::info("Your webhook Method not found: ", [ $parameters['type'] ]);

        return new Response;
    }
}

Now, the base controller is ready, let’s create the webhook handler controller which simply extends the base controller. You can define all the webhook related methods into this controller.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
use Illuminate\Support\Str;

class YourWebhookController extends YourWebhook
{

    public function handleCandidateCreated($payload)
    {
        // webhook event : candidate.created
    }

    public function handleCandidateUpdated($payload)
    {
        // webhook event : candidate.updated
    }

    Public function handlePaymentSucceed($payload)       
   {
 // webhook event: payment.succeed
   }

   
}

Conclusion

Building a robust webhook handler in Laravel 10 is an essential aspect of modern web application development. By setting up a base webhook controller, creating service-specific webhook controllers, implementing webhook events, and verifying webhook signatures, you can ensure seamless integration with external services while maintaining a secure and efficient application.

Remember to thoroughly test your webhook handler with different scenarios and simulate various webhook requests to validate its reliability. Additionally, keep an eye on the documentation of the services you’re integrating with, as webhook implementations might evolve over time.

With a well-structured webhook handler in place, your Laravel 10 application will be equipped to handle real-time data updates and provide a seamless user experience.

Happy coding!

Satpal

Recent Posts

How to Switch PHP Versions in XAMPP Easily: Managing Multiple PHP Versions on Ubuntu

Today we are going to learn about managing multiple PHP versions on ubuntu with xampp.…

1 year ago

How to Use Coding to Improve Your Website’s SEO Ranking?

Let's understand about how to use coding to improve your website's SEO. In today’s computerized…

1 year ago

Most Important Linux Commands for Web Developers

Let's understand the most important linux commands for web developers. Linux, as an open-source and…

1 year ago

Top 75+ Laravel Interview Questions Asked by Top MNCs

Today we are going to discuss top 75+ Laravel interview questions asked by top MNCs.Laravel,…

1 year ago

Mailtrap Integration for Email Testing with Laravel 10

Today we will discuss about the Mailtrap integration with laravel 10 .Sending and receiving emails…

1 year ago

Firebase Cloud Messaging (FCM) with Ionic 6: Push Notifications

Today we are going to integrate FCM (Firebase Cloud Messaging) push notifications with ionic application.Firebase…

1 year ago