Handling Stripe Webhooks
You may use the Stripe CLI to help test webhooks during local development.
Stripe can notify your application of a variety of events via webhooks. By default, a route that points to Shopkeeper's webhook controller is automatically registered by the Shopkeeper service provider. This controller will handle all incoming webhook requests.
By default, the Shopkeeper webhook controller will automatically handle cancelling subscriptions that have too many failed charges (as defined by your Stripe settings), customer updates, customer deletions, subscription updates, and payment method changes; however, as we'll soon discover, you can extend this controller to handle any Stripe webhook event you like.
To ensure your application can handle Stripe webhooks, be sure to configure the webhook URL in the Stripe control panel. By default, Shopkeeper's webhook controller responds to the /stripe/webhook
URL path. The full list of all webhooks you should enable in the Stripe control panel are:
customer.subscription.created
customer.subscription.updated
customer.subscription.deleted
customer.updated
customer.deleted
payment_method.automatically_updated
invoice.payment_action_required
invoice.payment_succeeded
For convenience, Shopkeeper includes a shopkeeper:webhook
Ace command. This command will create a webhook in Stripe that listens to all of the events required by Shopkeeper:
node ace shopkeeper:webhook
By default, the created webhook will point to the URL defined by the APP_URL
environment variable and the shopkeeper.webhook
route that is included with Shopkeeper. You may provide the --url
option when invoking the command if you would like to use a different URL:
node ace shopkeeper:webhook --url "https://example.com/stripe/webhook"
The webhook that is created will use the Stripe API version that your version of Shopkeeper is compatible with. If you would like to use a different Stripe version, you may provide the --api-version
option:
node ace shopkeeper:webhook --api-version="2019-12-03"
After creation, the webhook will be immediately active. If you wish to create the webhook but have it disabled until you're ready, you may provide the --disabled
option when invoking the command:
node ace shopkeeper:webhook --disabled
Make sure you protect incoming Stripe webhook requests with Shopkeeper's included webhook signature verification middleware.
Defining Webhook Event Handlers
Shopkeeper automatically handles subscription cancellations for failed charges and other common Stripe webhook events. However, if you have additional webhook events you would like to handle, you may do so by listening to the event using the Event Emitter.
The event names follow the semantic stripe:<eventType>
or stripe:<eventType>:handled
.
import emitter from '@adonisjs/core/services/emitter'
import Stripe from 'stripe'
emitter.on(
'stripe:customer.subscription.created',
(event: Stripe.CustomerSubscriptionCreatedEvent) => {
// ...
}
)
// Emitted after the webhook has been handled by Shopkeeper
emitter.on(
'stripe:customer.subscription.created:handled',
(event: Stripe.CustomerSubscriptionCreatedEvent) => {
// ...
}
)
Verifying Webhook Signatures
To secure your webhooks, you may use Stripe's webhook signatures. For convenience, Shopkeeper automatically includes a middleware which validates that the incoming Stripe webhook request is valid.
To enable webhook verification, ensure that the STRIPE_WEBHOOK_SECRET
environment variable is set in your application's .env
file. The webhook secret
may be retrieved from your Stripe account dashboard.