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.
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.
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.
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.
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.
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.
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'] );
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 } }
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!
Today we are going to learn about managing multiple PHP versions on ubuntu with xampp.…
Let's understand about how to use coding to improve your website's SEO. In today’s computerized…
Let's understand the most important linux commands for web developers. Linux, as an open-source and…
Today we are going to discuss top 75+ Laravel interview questions asked by top MNCs.Laravel,…
Today we will discuss about the Mailtrap integration with laravel 10 .Sending and receiving emails…
Today we are going to integrate FCM (Firebase Cloud Messaging) push notifications with ionic application.Firebase…