Stripe

Handling failed Stripe payments

The Designyff subscription webhook does not listen for invoice.payment_failed. Past-due subscriptions fall back to the free plan.

1 min read

A failed renewal is an invoice problem. The kits do not subscribe to invoice.payment_failed. They subscribe to checkout completion and to subscription updates.

In the Complete SaaS Starter Kit webhook, a subscription is Pro only when its status is active or trialing:

const active = subscription.status === "active" || subscription.status === "trialing";
await prisma.user.updateMany({
  where: { stripeSubscriptionId: subscription.id },
  data: { plan: active ? "pro" : "free" }
});

When Stripe moves the subscription to past_due, the next customer.subscription.updated event clears plan to "free". The same happens on customer.subscription.deleted. The Stripe Subscription Starter uses that status check too.

What this does not do

There is no dunning email, no retry counter, and no grace period stored in Prisma. Stripe’s own retry settings still run in the Dashboard. If you need a banner that says the card failed while keeping Pro access, you would store the status string instead of folding every non-active status into "free". The current code does not do that.

Signature verification for these events is in Stripe webhooks with Next.js. Customers can update a card in the Customer Portal.

Product updates for developers shipping with Designyff kits.

Purchased source may be used in personal, commercial, and client projects. Do not redistribute or resell the original source. Terms of Service

Designyff © 2026 | Starter kits for developers | Powered by  Tacko