Building a Robust Webhook Handler in Laravel 10
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 { public function __construct() { if ( config('webhook.keys.secret') ) { $this->middleware(VerifyYourWebhookSignature::class); } } 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); } protected function successMethod($parameters = []) { return new Response('Webhook Handled', 200); } 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) { } public function handleCandidateUpdated($payload) { } Public function handlePaymentSucceed($payload) { } }
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!