Verify if Cashier Webhooks Work in Your Local Development Setup

You don’t have much to do really if you don’t want to handle any more webhooks than those that Cashier handles out of the box. If you have:

  1. Updated the webhook secret key in the .env file
  2. Enabled the webhooks in Stripe
  3. Excluded the webhooks path in VerifyCsrfToken

then they should simply work.

Cashier automatically takes care of the webhooks listed in the Laravel documentation. You, the developer, do not need to write any code at all.

If you want to verify if those webhooks work (and are being handled by Cashier as expected in your local dev. environment) then you should use the Stripe CLI. For Windows, just download the .exe file and call it from your cmd. Login to your Stripe account from the CLI and then fire the following command to receive and forward the webhook events to your app:

stripe listen --forward-to 127.0.0.1:8000/stripe/webhook

You should see [200] whenever you manually trigger a test webhook event that is received by your app.

Something like:

[200] POST http://127.0.0.1:8000/stripe/webhook [evt_1MYSlRSANpTgXVl]

If you are not getting status 200 then check if the endpoint is properly set up.

You can start by checking your routes list php artisan route:list. See if the stripe/webhook route is present.

POST      stripe/webhook ...... cashier.webhook › Laravel\Cashier › WebhookController@handleWebhook

if not, you may want to clear cache

php artisan optimize

If you want to verify that Cashier is actually handling webhook events, you can try the following steps: In your subscriptions table (created by Cashier) see if you have a past subscription that is still incomplete. This status will be see in stripe_status column. Note down its id & the stripe_id. Now look for a subscription matching this stripe_id in your Stripe Dashboard.

The list of subscriptions in the Stripe Dashboard

Click on one of them and look for the ID in the details page:

The ID of a subscription in the Stripe Dashboard

If you Cancel this subscription, it will generate event customer.subscription.updated (in addition to few other events) and you should see the row deleted from the subscriptions table. It will also delete the related row from the subscription_items table.