Suscripciones con Stripe en Next.js
Checkout, portal del cliente, webhooks idempotentes y un hasEntitlement(user, 'pro'): la parte de cualquier SaaS que nadie quiere reescribir. @core/billing la trae como código fuente que es tuyo.
1. Instala
npx @genpm-net/cli add @core/billingTrae lo que necesita: @core/stripe (un único endpoint de webhooks con firma verificada), @core/auth (quién paga) y @core/db. Si ya seguiste Login con GitHub en Next.js, solo se añaden los módulos nuevos.
El paquete declara el servidor MCP oficial de Stripe. GenPM te pregunta antes de añadirlo; con él, tu agente puede leer tus productos y precios reales en vez de inventarse ids.
2. Claves y precios
# .env.local (modo test mientras desarrollas)
STRIPE_SECRET_KEY=sk_test_…
STRIPE_WEBHOOK_SECRET=whsec_…Asocia cada precio de Stripe con lo que desbloquea en src/lib/billing/plans.ts:
FEATURES_BY_PRICE['price_123'] = ['pro'];Después genera y aplica las migraciones como dice src/lib/db/AGENTS.md.
3. Rutas
Crea app/billing/checkout/route.ts, app/billing/portal/route.ts y app/billing/webhook/route.ts, cada una exportando checkoutRoute, portalRoute o webhookRoute como POST desde @/lib/billing/adapters/next.
En Stripe, apunta un webhook a <tu dominio>/billing/webhook con checkout.session.completed y customer.subscription.created|updated|deleted. En local:
stripe listen --forward-to localhost:3000/billing/webhook4. Vende y limita
- Botón de mejorar plan:
POST /billing/checkoutcon{ priceId }devuelve{ url }; redirige el navegador ahí. - Limitar una función:
if (!(await hasEntitlement(user, 'pro'))) … - "Gestionar suscripción":
POST /billing/portal.
El estado de la suscripción se lee de tu base de datos, sincronizada por el webhook, así que las páginas nunca esperan a Stripe. Cada evento se procesa una sola vez aunque Stripe lo envíe dos veces.
¿Empiezas de cero? La plantilla saas-starter ya trae login con GitHub, suscripciones con Stripe y email montados con GenPM.