Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

tjmahaffey's avatar

Cashier Listener Does not Fire

I've got Stripe's CLI running locally and my Laravel+Livewire checkout process is working as it should. BUT my event is never fired in Laravel, so my cart is never recorded back to my local DB.

Laravel (v12) has registered the listener. Here's the output of php artisan event:list

App\Listeners\WebhookReceived ....................................................................................................................
⇂ App\Listeners\StripeEventListener@handle
Illuminate\Auth\Events\Registered ................................................................................................................
⇂ Illuminate\Auth\Listeners\SendEmailVerificationNotification
Illuminate\Console\Events\CommandFinished ........................................................................................................
⇂ Closure at: /vendor/laravel/framework/src/Illuminate/Foundation/Providers/FoundationServiceProvider.php:212
Illuminate\Console\Events\CommandStarting ........................................................................................................
⇂ Closure at: /vendor/laravel/pail/src/PailServiceProvider.php:52
Illuminate\Database\Events\QueryExecuted .........................................................................................................
⇂ Closure at: /vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Renderer/Listener.php:60
Illuminate\Foundation\Events\LocaleUpdated .......................................................................................................
⇂ Closure at: /vendor/nesbot/carbon/src/Carbon/Laravel/ServiceProvider.php:66
Illuminate\Foundation\Http\Events\RequestHandled .................................................................................................
⇂ Closure at: /vendor/livewire/livewire/src/Features/SupportAutoInjectedAssets/SupportAutoInjectedAssets.php:24
Illuminate\Foundation\Support\Providers\WebhookReceived ..........................................................................................
⇂ App\Listeners\StripeEventListener
Illuminate\Log\Events\MessageLogged ..............................................................................................................
⇂ Closure at: /vendor/laravel/pail/src/PailServiceProvider.php:45
Illuminate\Queue\Events\JobAttempted .............................................................................................................
⇂ Closure at: /vendor/laravel/framework/src/Illuminate/Foundation/Providers/FoundationServiceProvider.php:217
Illuminate\Queue\Events\JobExceptionOccurred .....................................................................................................
⇂ Closure at: /vendor/laravel/pail/src/PailServiceProvider.php:52
Illuminate\Queue\Events\JobProcessed .............................................................................................................
⇂ Closure at: /vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Renderer/Listener.php:33
⇂ Closure at: /vendor/laravel/pail/src/PailServiceProvider.php:59
Illuminate\Queue\Events\JobProcessing ............................................................................................................
⇂ Closure at: /vendor/laravel/framework/src/Illuminate/Log/Context/ContextServiceProvider.php:42
⇂ Closure at: /vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Renderer/Listener.php:33
⇂ Closure at: /vendor/laravel/pail/src/PailServiceProvider.php:52

--- Excerpt of the Stripe CLI output for the event: -----------_

}, "id": "evt_1S7o5nRuxuvn9d2kZeRsRdkm", "livemode": false, "object": "event", "pending_webhooks": 2, "request": { "id": null, "idempotency_key": null }, "type": "checkout.session.completed" }

2025-09-15 20:54:03 <-- [200] POST http://myproject.test/stripe/webhook [evt_1S7o5nRuxuvn9d2kZeRsRdkm]

--- My Stripe event listener: --------------

0 likes
1 reply
LaryAI's avatar
Level 58

Certainly! Here's a checklist and solution steps for why your Stripe webhook might not be firing your Laravel event, even though your CLI and HTTP 200 responses look good.

1. Confirm Stripe CLI is Forwarding to the correct URL

Make sure Stripe CLI is forwarding events to the webhook that your Laravel app is listening on:

stripe listen --forward-to http://myproject.test/stripe/webhook

2. Verify the Route

Check that the /stripe/webhook route exists and is handled by the appropriate controller. With Laravel Cashier, the webhook is usually set up like this:

// routes/web.php OR routes/api.php

use Laravel\Cashier\Http\Controllers\WebhookController;

Route::post('/stripe/webhook', [WebhookController::class, 'handleWebhook']);

OR if you have customized it:

Route::post('/stripe/webhook', [App\Http\Controllers\StripeWebhookController::class, '__invoke']);

Make sure there's only one route for Stripe webhook and it’s not protected by auth or CSRF middleware.

3. Check Stripe Webhook Secret

In your .env file, ensure the secret is set:

STRIPE_WEBHOOK_SECRET=whsec_XXXXXXXXX

And in config/cashier.php:

'webhook' => [
    'secret' => env('STRIPE_WEBHOOK_SECRET'),
    // ...
],

4. Listener Registration

From your event:list, it looks like the listener is registered properly (e.g., App\Listeners\StripeEventListener@handle). Confirm your event and listener names are correct and match what's being fired.

5. Debug the Webhook Handler

Add a quick log at the start of your listener or webhook controller:

// In your handler/controller:
\Log::info('Stripe webhook received', request()->all());

If you don't see this in your logs, your controller isn't being hit at all.

6. Stripe Event Handling

If using Laravel Cashier, it fires Laravel\Cashier\Events\WebhookReceived and others for Stripe webhooks.

Check your EventServiceProvider:

protected $listen = [
    \Laravel\Cashier\Events\WebhookReceived::class => [
        \App\Listeners\WebhookReceived::class,
    ],
    // or your custom event/handler
];

7. Return a 200 Response

Your webhook controller must return a 200 HTTP response even for unhandled events, or Stripe will retry. The Cashier controller does this by default.

8. CSRF Exclusion

If you placed your webhook in web.php, be sure to exclude it from CSRF in VerifyCsrfToken middleware:

protected $except = [
    'stripe/webhook',
];

9. Queued Listeners

If your listener is queued and the queue worker isn't running, the logic won’t execute:

php artisan queue:work

Simplified Checklist

  • Webhook Route exists and is public (no auth or CSRF).
  • Stripe CLI forwards to correct local URL.
  • Listener is registered and not queued (test sync first).
  • .env has the correct STRIPE_WEBHOOK_SECRET.
  • Controller/Listener logs confirm it’s being hit.

Example Minimal Setup

routes/web.php:

use Laravel\Cashier\Http\Controllers\WebhookController;

Route::post('/stripe/webhook', [WebhookController::class, 'handleWebhook']);

App\Providers\EventServiceProvider.php:

protected $listen = [
    \Laravel\Cashier\Events\WebhookReceived::class => [
        \App\Listeners\WebhookReceived::class,
    ],
];

App\Listeners\WebhookReceived.php:

namespace App\Listeners;

use Laravel\Cashier\Events\WebhookReceived;

class WebhookReceived
{
    public function handle(WebhookReceived $event)
    {
        \Log::info('WebhookReceived event:', $event->payload);
        // Handle your logic here...
    }
}

If the log at the start of your handler never appears:

  • Your route/webhook controller is incorrect
  • Stripe CLI is forwarding to a wrong/mistyped URL
  • CSRF/auth is blocking
  • There's a typo in your EventServiceProvider registration

If logging works but your cart logic doesn’t:

  • Check your listener’s logic
  • Check your queue status (if listener is queued)

If you've checked all the above and still have trouble, please post your route and controller code for further diagnosis!

Please or to participate in this conversation.