data_forget Helper for Laravel
Since Laravel version 10.15, there is a new utility function called data_forget that allows you to remove keys from an array or object using a "dot" notation.
Webhooks are a powerful way to get real-time notifications for events happening within a system. If you're dealing with payments, Razorpay webhooks can be important in updating your system the moment a payment or refund is processed. Here's how you can use Razorpay webhooks in Laravel to handle payment and refund events efficiently in PHP, particularly using Laravel's job system.
Notice: Please ensure your laravel application has spatie/laravel-webhook-client package installed.
Let's start with a basic code layout inspired by a real-world implementation. The code uses Laravel's job system to handle incoming webhooks and updates the database accordingly.
namespace App\Jobs\RazorpayWebhooks;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Spatie\WebhookClient\Jobs\ProcessWebhookJob;
use Spatie\WebhookClient\Models\WebhookCall;
use App\Events\PaymentReceived;
use App\Events\RefundCreated;
use App\Models\Order;
use Illuminate\Bus\Queueable;
// ... (import statements)
class ProcessRazorpayWebhookJob extends ProcessWebhookJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public WebhookCall $webhookCall;
/**
* Create a new job instance.
*/
public function __construct(WebhookCall $webhookCall)
{
$this->webhookCall = $webhookCall;
}
public function handle(): void
{
if ($this->webhookCall->payload['event'] === 'order.paid') {
$this->processOrderPaidEvent();
}
if ($this->webhookCall->payload['event'] === 'refund.created') {
$this->processRefundCreatedEvent();
}
}
}
Using Laravel jobs for handling webhooks offers several advantages:
Asynchrony: Jobs can be processed asynchronously, freeing your main application from doing the heavy work.
Retries: If the job fails, you can easily configure it to retry.
Logging and Monitoring: Laravel's job system comes with built-in logging and monitoring capabilities.
When an order is paid, Razorpay sends a webhook with the event name 'order.paid'
. Here's how it's handled:
public function processOrderPaidEvent()
{
$order = Order::query()->findOrFail($this->webhookCall->payload['payload']['order']['entity']['receipt']);
$order->payments()->create([
'reference' => $this->webhookCall->payload['payload']['payment']['entity']['id'],
'amount' => $this->webhookCall->payload['payload']['payment']['entity']['amount'] / 100,
'currency' => \Str::upper($this->webhookCall->payload['payload']['payment']['entity']['currency']),
'status' => 'Paid',
]);
$order->payment_status = PaymentStatus::PAID;
$order->save();
}
The code fetches the corresponding order using the receipt.
A new payment record is created with relevant information.
The order status is updated to PAID
.
In your Routes, Add the following route code
Route::webhooks('webhooks/razorpay', 'razorpay');
Similarly, when a refund is created, Razorpay sends a webhook with the event 'refund.created'
.
public function processRefundCreatedEvent()
{
$order = Order::query()->where('razorpay_payment_id', $this->webhookCall->payload['payload']['refund']['entity']['payment_id'])->firstOrFail();
$refund = $order->refunds()->create([
'amount' => $this->webhookCall->payload['payload']['refund']['entity']['amount'] / 100,
'meta' => [
'razorpay_refund_id' => $this->webhookCall->payload['payload']['refund']['entity']['id'],
]
]);
}
The code fetches the corresponding order using the payment_id
.
A new refund record is created.
Create webhook-client.php in config directory
<?php
return [
'configs' => [
// Do not change the order of every services declared here.
[
'name' => 'razorpay',
'signing_secret' => env('RAZORPAY_WEBHOOK_SECRET'),
'signature_header_name' => 'X-Razorpay-Signature',
'signature_validator' => \Spatie\WebhookClient\SignatureValidator\DefaultSignatureValidator::class,
'webhook_profile' => \Spatie\WebhookClient\WebhookProfile\ProcessEverythingWebhookProfile::class,
'webhook_response' => \Spatie\WebhookClient\WebhookResponse\DefaultRespondsTo::class,
'webhook_model' => \Spatie\WebhookClient\Models\WebhookCall::class,
'process_webhook_job' => \App\Jobs\RazorpayWebhooks\ProcessRazorpayWebhookJob::class,
],
],
/*
* The integer amount of days after which models should be deleted.
*
* 7 deletes all records after 1 week. Set to null if no models should be deleted.
*/
'delete_after_days' => 30,
];
Validation: Always validate webhook payloads against the Razorpay signature for security.
Make sure your handlers are never creating duplicate records. If you receive the same webhook event multiple times, it shouldn't create duplicate records. The sample code has this built-in.
Monitoring: Keep an eye on the job queue and set up alerts for failures.
Testing: Always simulate webhook events in your local or staging environments before moving to production.
Webhooks, when used correctly, can offer a significant boost in operational efficiency and user experience. And with a modern PHP framework like Laravel, implementing them is a breeze.
Full-stack developer with a knack for Merging creativity with technical expertise for standout solutions.
Since Laravel version 10.15, there is a new utility function called data_forget that allows you to remove keys from an array or object using a "dot" notation.
The ChatGPT Laravel API Package Generator package for Laravel generates smart API mocks in Laravel using ChatGPT prompts:
You can make your Laravel app multi-tenant using the Tenancy for Laravel Tenant package. This tenancy package lets you make any Laravel application multi-tenant without rewriting it.
Are you ready to take your Laravel skills to the next level and build extraordinary applications? Look no further! In this blog post, we will unveil a treasure trove of top packages that will revolutionize your development process.
The Livewire Tables package brings dynamic tables for models to Laravel Livewire. These are some of the features which you will get out of the box:
ImageMagick is a powerful tool for image manipulation, and integrating it with PHP can enhance your web development projects.
Subscribe for 20+ new Laravel tutorials every week
You can unsubscribe at any time. You'll also get -20% off my courses!