Webhooks
Handle Stripe events, update billing states, and trigger custom logic.
Use Stripe webhooks to correctly keep track of billing states, send user email notifications, and trigger custom post-purchase logic.
The core Stripe webhook handler is located at:
src/app/api/payments/webhook/stripe/route.ts
Required Stripe events
Configure these events in your Stripe webhook dashboard to ensure billing operates correctly:
checkout.session.completedinvoice.payment_succeededcustomer.subscription.updatedcustomer.subscription.deleted
Custom Payment Callbacks
When specific billing events occur, the webhook handler fires corresponding callback functions. You can add your custom business logic (e.g., 3rd-party integrations, CRM updates, logging, offboarding flows) inside these functions.
The callback service is located at:
src/features/common/payments/service/payment-callback.service.ts
Subscriptions
Subscription Success
Called after a new subscription is activated or an existing one is upgraded.
export async function onSubscriptionSuccess(
payload: SubscriptionSuccessPayload,
): Promise<void> {
// Available fields in payload:
// userId, email, name, planId, planName, amountText
console.log('[subscription] success', payload);
}Subscription Cancelled
Called after a user cancels their subscription.
export async function onSubscriptionCancelled(
payload: SubscriptionCancelledPayload,
): Promise<void> {
// Available fields in payload:
// userId, email, name, periodEndText
console.log('[subscription] cancelled', payload);
}One-Time Purchases
One-Time Purchase Success
Called after a successful one-time purchase (for both guest and authenticated checkouts).
export async function onOneTimePurchaseSuccess(
payload: OneTimePurchaseSuccessPayload,
): Promise<void> {
// Available fields in payload:
// productId, productName, email, name, amountText, isGuest, userId
console.log('[one-time] purchase success', payload);
}Credits
Credits Top-Up
Called after a user purchases a credits top-up package.
export async function onCreditsTopUp(
payload: CreditsTopUpPayload,
): Promise<void> {
// Available fields in payload:
// userId, email, name, creditsAdded, amountText
console.log('[credits] top-up', payload);
}