Back to Homepage

Stripe Webhooks in Laravel: Professional Approach

4 min read


Stripe Webhooks in Laravel: Professional Approach

Webhooks are a powerful way to get real-time notifications for events happening within a system. If you're dealing with payments, Stripe webhooks can be important in updating your system the moment a payment or refund is processed. Here's how you can use Stripe 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.

Setting Up Stripe Webhooks in Laravel

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\StripeWebhooks;
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\Models\Order;
use Illuminate\Bus\Queueable;
// ... (import statements)

class ProcessStripeWebhookJob 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
        $order = Order::query()->findOrFail($this->webhookCall->payload['data']['object']['client_reference_id']);

            'reference' => $this->webhookCall->payload['data']['object']['payment_intent'],
            'amount' => $this->webhookCall->payload['data']['object']['amount_total'] / 100,
            'currency' => \Str::upper($this->webhookCall->payload['data']['object']['currency']),
            'status' => 'Paid',



Create stripe-webhook.php in config directory and add below code


return [
     * Stripe will sign each webhook using a secret. You can find the used secret at the
     * webhook configuration settings:
    'signing_secret' => env('STRIPE_WEBHOOK_SECRET'),

     * You can define a default job that should be run for all other Stripe event type
     * without a job defined in next configuration.
     * You may leave it empty to store the job in database but without processing it.
    'default_job' => '',

     * You can define the job that should be run when a certain webhook hits your application
     * here. The key is the name of the Stripe event type with the `.` replaced by a `_`.
     * You can find a list of Stripe webhook types here:
    'jobs' => [
        // 'source_chargeable' => \App\Jobs\StripeWebhooks\HandleChargeableSource::class,
        // 'charge_failed' => \App\Jobs\StripeWebhooks\HandleFailedCharge::class,
        'checkout_session_completed' => \App\Jobs\StripeWebhooks\HandleCheckoutSessionCompleted::class,

     * The classname of the model to be used. The class should equal or extend
     * Spatie\WebhookClient\Models\WebhookCall.
    'model' => \Spatie\WebhookClient\Models\WebhookCall::class,

     * This class determines if the webhook call should be stored and processed.
    'profile' => \Spatie\StripeWebhooks\StripeWebhookProfile::class,

     * When disabled, the package will not verify if the signature is valid.
     * This can be handy in local environments.
    'verify_signature' => env('STRIPE_SIGNATURE_VERIFY', true),

Why Use Jobs?

Using Laravel jobs for handling webhooks offers several advantages:

  1. Asynchrony: Jobs can be processed asynchronously, freeing your main application from doing the heavy work.

  2. Retries: If the job fails, you can easily configure it to retry.

  3. Logging and Monitoring: Laravel's job system comes with built-in logging and monitoring capabilities.

In your Routes, Add the following route code

Route::webhooks('webhooks/stripe', 'stripe');

Opinions and Recommendations

  1. Validation: Always validate webhook payloads against the Stripe signature for security.

  2. 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.

  3. Monitoring: Keep an eye on the job queue and set up alerts for failures.

  4. 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.

Follow @LaravelSage on X → Follow @LaravelSage on Facebook →
Aniket Singh

Aniket Singh

View All Articles

Full-stack developer with a knack for Merging creativity with technical expertise for standout solutions.

Related Articles

data_forget Helper for Laravel

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.

Laravel Tenant Application with Tenancy

Laravel Tenant Application with Tenancy

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.

Top Laravel Packages for Building Powerful Applications

Top Laravel Packages for Building Powerful Applications

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.

Subscribe for 20+ new Laravel tutorials every week

You can unsubscribe at any time. You'll also get -20% off my courses!

© 2024


Laravel Sage

   |    Privacy Policy