Stripe + Next.js Comercio sin cabeza: Guía de Integración 2026
He conectado Stripe a proyectos Next.js más veces de las que puedo contar. Cada vez, el panorama cambia un poco — nuevas versiones de API, nuevos métodos de pago, nuevos casos extremos que te muerden a las 2 AM cuando un webhook falla silenciosamente. Esta guía es todo lo que desearía que existiera la primera vez que construí un stack de comercio sin cabeza. Cubriremos Checkout Sessions, Payment Intents, webhooks, suscripciones, Apple Pay, Google Pay, Link, y checkout de un clic. Sin rodeos. Código real, decisiones de arquitectura real, problemas reales.
A mediados de 2026, la API de Stripe está en la versión 2025-12-18.acacia, Next.js 15.x es estable con el App Router como predeterminado, y los paquetes @stripe/stripe-js y @stripe/react-stripe-js han madurado considerablemente. Si estás construyendo en versiones anteriores, la mayoría de esto sigue siendo aplicable, pero algunos patrones de server action diferirán.
Tabla de Contenidos
- Por qué Stripe + Next.js para Comercio sin Cabeza
- Descripción General de la Arquitectura
- Configurando Stripe en un Proyecto Next.js 15
- Checkout Sessions: El Camino Rápido
- Payment Intents: Modo Control Total
- Manejo de Webhooks que Realmente Funciona
- Suscripciones y Facturación Recurrente
- Apple Pay, Google Pay, y Link
- Checkout de Un Clic con Link
- Seguridad, Pruebas, e Ir en Vivo
- Consideraciones de Desempeño
- Preguntas Frecuentes

Por qué Stripe + Next.js para Comercio sin Cabeza
Stripe procesa más de $1 billón en volumen de pagos anualmente. Next.js alimenta una cuota creciente de escaparates de comercio electrónico — Vercel reporta que más del 40% de nuevos proyectos Next.js en 2025 tenían alguna forma de funcionalidad de comercio. La combinación tiene sentido por algunas razones concretas:
- Server Components y Server Actions te permiten llamar al SDK de Stripe del lado del servidor sin construir una capa de API separada.
- Despliegue en Edge y serverless en Vercel, Netlify, o AWS significa que tus endpoints de pago se escalan automáticamente.
- React Server Components mantienen tu clave secreta de Stripe en el servidor donde pertenece, sin gimnasia adicional.
- El App Router te proporciona layouts, estados de carga, y límites de error que se mapean bien a flujos de checkout.
Si estás evaluando arquitecturas de comercio sin cabeza, hemos construido docenas de estas en Social Animal — consulta nuestras capacidades de desarrollo Next.js y desarrollo de CMS sin cabeza para más contexto sobre cómo estas piezas encajan.
Descripción General de la Arquitectura
Antes de escribir ningún código, obtengamos la arquitectura correcta. Así es como las piezas se conectan en una configuración típica de comercio sin cabeza:
┌─────────────────┐ ┌──────────────────┐ ┌─────────────┐
│ Aplicación │────▶│ API de Stripe │────▶│ Webhooks │
│ Next.js (App │◀────│ (Lado del │ │ Endpoint │
│ Router) │ │ servidor) │ └──────┬──────┘
└─────────────────┘ └──────────────────┘ │
│ │
│ ▼
▼ ┌─────────────┐
┌─────────────────┐ │ Base de │
│ CMS sin Cabeza │ │ Datos / │
│ (Productos) │ │ Gestión de │
└─────────────────┘ │ Pedidos │
└─────────────┘
La decisión crítica es si usar Checkout Sessions (alojadas en Stripe o incrustadas) o Payment Intents (interfaz de usuario completamente personalizada). Aquí está cuándo usar cada una:
| Característica | Checkout Sessions | Payment Intents |
|---|---|---|
| Velocidad de desarrollo | Rápida — días | Más lenta — semanas |
| Personalización de interfaz | Limitada (temática de Stripe) | Control total |
| Alcance de cumplimiento PCI | SAQ A (más simple) | SAQ A-EP |
| Soporte de método de pago | Automático (40+ métodos) | Manual por método |
| Soporte de suscripción | Integrado | Requiere código adicional |
| Apple Pay / Google Pay | Automático | Manual vía Payment Request API |
| Optimización de conversión | Optimizado por Stripe | Depende de ti |
| Impacto de precios | Mismas tarifas de Stripe | Mismas tarifas de Stripe |
Mi recomendación honesta: comienza con Checkout Sessions a menos que tengas una razón específica para no hacerlo. Siempre puedes migrar a Payment Intents después, y el checkout incrustado de Stripe se ha vuelto notablemente bueno en 2025-2026.
Configurando Stripe en un Proyecto Next.js 15
Configuremos la base. Asumo que tienes un proyecto Next.js 15 con el App Router.
npm install stripe @stripe/stripe-js @stripe/react-stripe-js
Crea tus variables de entorno:
# .env.local
STRIPE_SECRET_KEY=sk_test_...
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...
Configura una instancia de Stripe del lado del servidor. Siempre pongo esto en un archivo lib/stripe.ts:
// lib/stripe.ts
import Stripe from 'stripe';
export const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
apiVersion: '2025-12-18.acacia',
typescript: true,
});
Y un cargador del lado del cliente:
// lib/stripe-client.ts
import { loadStripe } from '@stripe/stripe-js';
export const stripePromise = loadStripe(
process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!
);
Una cosa que desorienta a la gente: nunca importes lib/stripe.ts en un componente cliente. El paquete npm stripe incluye tu clave secreta y solo debe ejecutarse del lado del servidor. Next.js 15 lanzará un error de compilación si accidentalmente lo importas en un archivo 'use client', lo cual es en realidad una buena barrera.

Checkout Sessions: El Camino Rápido
Checkout Sessions son la forma más rápida de aceptar pagos. Stripe aloja el formulario de pago (o lo incrustas), maneja el cumplimiento de PCI, y automáticamente soporta docenas de métodos de pago incluyendo Apple Pay, Google Pay, y Link.
Creando una Checkout Session con Server Actions
// app/actions/checkout.ts
'use server';
import { stripe } from '@/lib/stripe';
import { redirect } from 'next/navigation';
export async function createCheckoutSession(formData: FormData) {
const priceId = formData.get('priceId') as string;
const quantity = Number(formData.get('quantity')) || 1;
const session = await stripe.checkout.sessions.create({
mode: 'payment',
line_items: [
{
price: priceId,
quantity,
},
],
success_url: `${process.env.NEXT_PUBLIC_URL}/checkout/success?session_id={CHECKOUT_SESSION_ID}`,
cancel_url: `${process.env.NEXT_PUBLIC_URL}/checkout/canceled`,
automatic_tax: { enabled: true },
// Habilita todos los métodos de pago relevantes
payment_method_types: undefined, // Deja que Stripe autodetecte
});
redirect(session.url!);
}
Checkout Incrustado (Enfoque Recomendado 2026)
El checkout incrustado de Stripe mantiene a los usuarios en tu dominio. Esto tiene mejores tasas de conversión — los datos propios de Stripe de 2025 muestran una mejora del 10-15% sobre checkout basado en redirecciones para clientes recurrentes.
// app/checkout/embedded/page.tsx
'use client';
import { useCallback } from 'react';
import { loadStripe } from '@stripe/stripe-js';
import {
EmbeddedCheckoutProvider,
EmbeddedCheckout,
} from '@stripe/react-stripe-js';
const stripePromise = loadStripe(
process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!
);
export default function CheckoutPage() {
const fetchClientSecret = useCallback(async () => {
const res = await fetch('/api/checkout/embedded', {
method: 'POST',
body: JSON.stringify({ priceId: 'price_xxx', quantity: 1 }),
});
const { clientSecret } = await res.json();
return clientSecret;
}, []);
return (
<div className="max-w-lg mx-auto py-12">
<EmbeddedCheckoutProvider
stripe={stripePromise}
options={{ fetchClientSecret }}
>
<EmbeddedCheckout />
</EmbeddedCheckoutProvider>
</div>
);
}
Y la ruta de API:
// app/api/checkout/embedded/route.ts
import { stripe } from '@/lib/stripe';
import { NextResponse } from 'next/server';
export async function POST(req: Request) {
const { priceId, quantity } = await req.json();
const session = await stripe.checkout.sessions.create({
mode: 'payment',
line_items: [{ price: priceId, quantity }],
ui_mode: 'embedded',
return_url: `${process.env.NEXT_PUBLIC_URL}/checkout/success?session_id={CHECKOUT_SESSION_ID}`,
});
return NextResponse.json({ clientSecret: session.client_secret });
}
Payment Intents: Modo Control Total
Cuando necesitas una interfaz de usuario de checkout completamente personalizada — quizás estés construyendo un checkout de una página, o tu equipo de diseño tiene requisitos específicos — Payment Intents te dan control total.
La compensación es real: escribirás más código, manejarás más casos extremos, y asumirás una carga de cumplimiento de PCI ligeramente más alta. Pero para algunos productos, vale la pena.
Lado del Servidor: Creando Payment Intents
// app/api/payment-intent/route.ts
import { stripe } from '@/lib/stripe';
import { NextResponse } from 'next/server';
export async function POST(req: Request) {
const { amount, currency = 'usd', metadata } = await req.json();
const paymentIntent = await stripe.paymentIntents.create({
amount, // en centavos
currency,
metadata,
automatic_payment_methods: {
enabled: true, // Esto habilita Apple Pay, Google Pay, Link, etc.
},
});
return NextResponse.json({
clientSecret: paymentIntent.client_secret,
});
}
Lado del Cliente: El Formulario de Pago
// components/PaymentForm.tsx
'use client';
import { useState } from 'react';
import {
PaymentElement,
useStripe,
useElements,
} from '@stripe/react-stripe-js';
export function PaymentForm() {
const stripe = useStripe();
const elements = useElements();
const [error, setError] = useState<string | null>(null);
const [processing, setProcessing] = useState(false);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!stripe || !elements) return;
setProcessing(true);
setError(null);
const { error: submitError } = await stripe.confirmPayment({
elements,
confirmParams: {
return_url: `${window.location.origin}/checkout/success`,
},
});
if (submitError) {
setError(submitError.message ?? 'Pago fallido');
setProcessing(false);
}
// Si no hay error, Stripe redirige automáticamente
};
return (
<form onSubmit={handleSubmit}>
<PaymentElement
options={{
layout: 'accordion',
wallets: {
applePay: 'auto',
googlePay: 'auto',
},
}}
/>
{error && <p className="text-red-500 mt-2">{error}</p>}
<button
type="submit"
disabled={!stripe || processing}
className="mt-4 w-full bg-black text-white py-3 rounded-lg disabled:opacity-50"
>
{processing ? 'Procesando...' : 'Pagar ahora'}
</button>
</form>
);
}
Nota el automatic_payment_methods: { enabled: true } en el lado del servidor. Esta es la forma 2025-2026 de manejar el soporte de métodos de pago. Stripe mostrará automáticamente los métodos de pago correctos basados en el dispositivo del cliente, ubicación, y la moneda. No más listas manuales de payment_method_types.
Manejo de Webhooks que Realmente Funciona
Los webhooks son donde la mayoría de integraciones de Stripe se rompen. He visto sistemas de producción perder pedidos porque alguien olvidó verificar la firma del webhook, o porque el manejador lanzó un error antes de enviar un 200.
Aquí está mi manejador de webhook probado en batalla:
// app/api/webhooks/stripe/route.ts
import { stripe } from '@/lib/stripe';
import { headers } from 'next/headers';
import { NextResponse } from 'next/server';
import type Stripe from 'stripe';
export async function POST(req: Request) {
const body = await req.text();
const headersList = await headers();
const signature = headersList.get('stripe-signature');
if (!signature) {
return NextResponse.json({ error: 'Firma faltante' }, { status: 400 });
}
let event: Stripe.Event;
try {
event = stripe.webhooks.constructEvent(
body,
signature,
process.env.STRIPE_WEBHOOK_SECRET!
);
} catch (err) {
console.error('Verificación de firma de webhook fallida:', err);
return NextResponse.json({ error: 'Firma inválida' }, { status: 400 });
}
try {
switch (event.type) {
case 'checkout.session.completed': {
const session = event.data.object as Stripe.Checkout.Session;
await handleCheckoutComplete(session);
break;
}
case 'payment_intent.succeeded': {
const paymentIntent = event.data.object as Stripe.PaymentIntent;
await handlePaymentSuccess(paymentIntent);
break;
}
case 'payment_intent.payment_failed': {
const paymentIntent = event.data.object as Stripe.PaymentIntent;
await handlePaymentFailure(paymentIntent);
break;
}
case 'customer.subscription.created':
case 'customer.subscription.updated':
case 'customer.subscription.deleted': {
const subscription = event.data.object as Stripe.Subscription;
await handleSubscriptionChange(subscription);
break;
}
case 'invoice.payment_failed': {
const invoice = event.data.object as Stripe.Invoice;
await handleInvoiceFailure(invoice);
break;
}
default:
console.log(`Tipo de evento no manejado: ${event.type}`);
}
} catch (err) {
console.error(`Error procesando ${event.type}:`, err);
// Aún devuelve 200 para prevenir que Stripe reintente
// Registra el error para investigación manual
}
return NextResponse.json({ received: true });
}
Problemas con Webhooks que Aprendí de la Manera Difícil
Siempre devuelve 200, incluso si tu procesamiento falla. De otra manera Stripe reintenta, y podrías procesar el mismo evento más de una vez. Registra el error y lidia con él de manera asincrónica.
Haz manejadores idempotentes. Stripe puede y enviará el mismo evento más de una vez. Usa el ID de evento o los metadatos del objeto para verificar si ya lo has procesado.
Usa
req.text()noreq.json()para la verificación de firma. La firma se calcula sobre la cadena de cuerpo sin procesar. Si la analizas primero, la verificación siempre fallará.Configura la CLI de Stripe para pruebas locales. Es innegociable.
stripe listen --forward-to localhost:3000/api/webhooks/stripe
- En Vercel, las rutas de webhook necesitan configuración específica. Asegúrate de que tu ruta no esté detrás de ningún middleware que modifique el cuerpo de la solicitud. En Next.js 15, las rutas de API en el App Router manejan esto correctamente por defecto, pero verifica si tienes middleware personalizado.
Suscripciones y Facturación Recurrente
Las suscripciones añaden una capa de complejidad. No solo estás manejando un pago único — estás gestionando un ciclo de vida: pruebas, actualizaciones, degradaciones, cancelaciones, pagos fallidos, dunning.
Creando una Suscripción vía Checkout
El enfoque más fácil:
// app/actions/subscribe.ts
'use server';
import { stripe } from '@/lib/stripe';
import { redirect } from 'next/navigation';
export async function createSubscriptionCheckout(
customerId: string,
priceId: string
) {
const session = await stripe.checkout.sessions.create({
mode: 'subscription',
customer: customerId,
line_items: [{ price: priceId, quantity: 1 }],
success_url: `${process.env.NEXT_PUBLIC_URL}/account/billing?success=true`,
cancel_url: `${process.env.NEXT_PUBLIC_URL}/pricing`,
subscription_data: {
trial_period_days: 14,
metadata: {
plan: 'pro', // Tus propios metadatos
},
},
allow_promotion_codes: true,
tax_id_collection: { enabled: true },
});
redirect(session.url!);
}
Gestionando Suscripciones
Para el portal del cliente (actualizar, degradar, cancelar, actualizar método de pago), el Customer Portal de Stripe es genuinamente excelente en 2026:
// app/actions/billing.ts
'use server';
import { stripe } from '@/lib/stripe';
import { redirect } from 'next/navigation';
export async function createBillingPortalSession(customerId: string) {
const session = await stripe.billingPortal.sessions.create({
customer: customerId,
return_url: `${process.env.NEXT_PUBLIC_URL}/account/billing`,
});
redirect(session.url);
}
Eventos Clave de Suscripción Webhook
| Evento | Cuándo se Dispara | Qué Hacer |
|---|---|---|
customer.subscription.created |
Nueva suscripción | Provisionar acceso |
customer.subscription.updated |
Cambio de plan, renovación | Actualizar nivel de acceso |
customer.subscription.deleted |
Cancelación (fin del período) | Revocar acceso |
invoice.payment_succeeded |
Renovación exitosa | Actualizar registros de facturación |
invoice.payment_failed |
Renovación fallida | Enviar email de dunning, marcar cuenta |
customer.subscription.trial_will_end |
3 días antes del fin de prueba | Enviar email recordatorio |
No dependas únicamente del estado de suscripción de la llamada a la API. Los webhooks son la fuente de verdad para cambios de estado de suscripción. He visto equipos sondear la API de Stripe en lugar de usar webhooks y es tanto más lento como más frágil.
Apple Pay, Google Pay, y Link
La belleza del Payment Element de Stripe 2025-2026 es que los pagos con billetera en su mayoría simplemente funcionan. Pero hay algunos requisitos de configuración que la gente se pierde.
Configuración de Apple Pay
La verificación de dominio es requerida. Necesitas alojar un archivo
.well-known/apple-developer-merchantid-domain-associationen la raíz de tu dominio. Stripe proporciona este archivo en tu Dashboard bajo Configuración → Métodos de Pago → Apple Pay.En Next.js, coloca el archivo en
public/.well-known/apple-developer-merchantid-domain-association.Registra tu dominio en el Dashboard de Stripe.
Apple Pay solo aparece en Safari/iOS. No te alarmes si no aparece en Chrome durante las pruebas.
Configuración de Google Pay
Google Pay requiere menos configuración — funciona automáticamente con el Payment Element siempre que tu cuenta de Stripe esté correctamente configurada. Aparece en Chrome y en dispositivos Android.
Link (Checkout de Un Clic de Stripe)
Link es la respuesta de Stripe a Shop Pay. Los clientes guardan su información de pago una vez y pueden pagar con un clic en cualquier comerciante de Stripe que use Link.
A partir de 2026, Link está habilitado por defecto en nuevas cuentas de Stripe. El aumento de conversión es real — Stripe reporta un 7% más alto de finalización de checkout cuando Link está disponible. Para usuarios de Link recurrentes, es mucho más alto.
Con el Payment Element, Link aparece automáticamente. Con Checkout Sessions, también es automático. No necesitas hacer nada especial.
// Link es automático con Payment Element, pero puedes personalizar:
<PaymentElement
options={{
wallets: {
applePay: 'auto',
googlePay: 'auto',
},
// Link aparece en el campo de email automáticamente
}}
/>
Checkout de Un Clic con Link
Link merece su propia sección porque se ha convertido en un impulsor serio de conversión. Así es como funciona:
- El cliente ingresa su email en tu formulario de checkout.
- Si tiene una cuenta de Link, recibe un código de verificación vía SMS.
- Después de la verificación, su dirección guardada y método de pago se rellenan automáticamente.
- Hacen clic en "Pagar" — listo.
La idea clave: Link funciona entre comerciantes. Si tu cliente usó Link en un sitio completamente diferente, obtendrán la experiencia de un clic en el tuyo también. El efecto de red de Stripe es real — reportan más de 100 millones de usuarios de Link a principios de 2026.
Para maximizar la adopción de Link, asegúrate de que el campo de email sea lo primero con lo que los clientes interactúen en tu flujo de checkout. El Payment Element maneja esto bien con el diseño accordion.
Si quieres ir más allá, puedes usar el Express Checkout Element para mostrar Apple Pay, Google Pay, y Link como botones prominentes encima de tu formulario:
// components/ExpressCheckout.tsx
'use client';
import { ExpressCheckoutElement } from '@stripe/react-stripe-js';
export function ExpressCheckout() {
return (
<ExpressCheckoutElement
onConfirm={async (event) => {
// Manejar la confirmación de pago express
console.log('Checkout express confirmado:', event);
}}
options={{
buttonType: {
applePay: 'buy',
googlePay: 'buy',
},
}}
/>
);
}
Seguridad, Pruebas, e Ir en Vivo
Lista de Verificación de Seguridad
- La clave secreta de Stripe solo se usa del lado del servidor
- Las firmas de webhook se verifican en cada solicitud
- HTTPS se aplica en producción
- Los cálculos de cantidad suceden del lado del servidor (nunca confíes en cantidades enviadas por el cliente)
- Las rutas de API tienen limitación de velocidad
- Los datos de cliente se manejan según tu política de privacidad
- Los encabezados CSP permiten dominios de Stripe (
js.stripe.com,api.stripe.com)
Pruebas
El modo de prueba de Stripe es excelente. Usa estos números de tarjeta de prueba:
| Número de Tarjeta | Escenario |
|---|---|
4242 4242 4242 4242 |
Pago exitoso |
4000 0000 0000 3220 |
3D Secure requerido |
4000 0000 0000 9995 |
Rechazado |
4000 0025 0000 3155 |
Requiere autenticación |
4000 0000 0000 0341 |
Adjuntar falla (para tarjetas guardadas) |
Para pruebas de suscripción, usa los relojes de prueba de Stripe para simular el paso del tiempo sin esperar realmente.
Ir en Vivo
- Cambia tus claves de
sk_test_ask_live_ypk_test_apk_live_. - Configura tu endpoint de webhook en vivo en el Dashboard de Stripe.
- Verifica tu dominio de Apple Pay para producción.
- Habilita los métodos de pago que desees en el Dashboard de Stripe.
- Asegúrate de que tu cuenta de Stripe esté completamente activada (verificación de identidad, cuenta bancaria, etc.).
Consideraciones de Desempeño
Stripe.js es ~40KB comprimido. Eso no es nada. Aquí hay algunos consejos:
Carga Stripe.js de manera perezosa. No lo cargues en cada página — solo en páginas relacionadas con checkout. La función
loadStripemaneja esto bien; no traerá el script hasta que lo llames.Usa
@stripe/stripe-js/puresi quieres controlar exactamente cuándo se carga el script:
import { loadStripe } from '@stripe/stripe-js/pure';
// El script no se cargará hasta que se llame a loadStripe()
Server Components para páginas de producto. Mantén el código de cliente de Stripe fuera de tu listado de productos y páginas de detalle. Solo trae los componentes de cliente cuando el usuario realmente inicia el checkout.
Edge runtime para rutas de API. El SDK de Node.js de Stripe funciona en el tiempo de ejecución de Edge a partir de 2025. Puedes agregar
export const runtime = 'edge'a tus rutas de API de Stripe para menor latencia.
Para equipos que construyen escaparates de alto desempeño sin cabeza, marcos como Astro también pueden ser una buena opción para páginas con mucho contenido mientras Next.js maneja los flujos dinámicos de checkout. Hemos hecho este enfoque híbrido para varios clientes — nuestros equipos de desarrollo con Astro y desarrollo con Next.js colaboran en estas arquitecturas regularmente.
Preguntas Frecuentes
¿Cuáles son las tarifas de transacción de Stripe en 2026? La fijación de precios estándar de Stripe es 2.9% + $0.30 por cargo de tarjeta exitoso en los EE.UU. Para tarjetas europeas, es 1.5% + €0.25. Los descuentos por volumen están disponibles para empresas que procesan más de $1M anualmente. No hay cargos de configuración, cargos mensuales, o cargos ocultos en el plan estándar. Stripe cobra un 0.5% adicional para tarjetas ingresadas manualmente y 1% para tarjetas internacionales.
¿Debería usar Checkout Sessions o Payment Intents? Usa Checkout Sessions en la mayoría de casos. Son más rápidas de implementar, automáticamente soportan 40+ métodos de pago, manejan el cumplimiento de PCI, y Stripe continuamente optimiza la tasa de conversión. Usa Payment Intents cuando necesites una interfaz de usuario de checkout completamente personalizada que no pueda lograrse con Checkout incrustado, o cuando necesites control de grano fino sobre el flujo de pago (como pagos divididos o captura manual).
¿Cómo manejo fallas de webhook en producción? Siempre devuelve un estado 200 de tu manejador de webhook, incluso si tu lógica de negocio falla. Registra el error y procésalo de manera asincrónica. Haz tus manejadores idempotentes verificando el ID de evento contra tu base de datos antes de procesar. Stripe reintenta webhooks hasta 3 días con retroceso exponencial. Configura alertas de falla de webhook en el Dashboard de Stripe, y considera usar una cola (como AWS SQS o Inngest) para procesar cargas de webhook de manera asincrónica.
¿Puedo usar Stripe con un CMS sin cabeza como Sanity o Contentful? Absolutamente. El patrón típico es: almacenar información de producto y contenido en tu CMS sin cabeza, almacenar precios y datos de pago en Stripe, y conectarlos vía un ID de producto o SKU compartido. Tu frontend Next.js obtiene contenido del CMS y crea Checkout Sessions o Payment Intents de Stripe cuando el cliente está listo para comprar. Cubrimos este patrón extensamente en nuestro trabajo de desarrollo de CMS sin cabeza.
¿Cómo pruebo Apple Pay localmente?
No puedes probar fácilmente Apple Pay en localhost porque requiere HTTPS y verificación de dominio. El mejor enfoque es usar el modo de prueba de Stripe con la tarjeta de prueba 4242 en el Payment Element — simula el flujo de pago. Para pruebas reales de Apple Pay, despliega a un entorno de staging con HTTPS. La CLI de Stripe también soporta reenvío de eventos webhook para transacciones de Apple Pay.
¿Vale la pena habilitar Stripe Link? Sí. Link es gratuito para comerciantes — Stripe no cobra extra por él. Aparece automáticamente en el Payment Element y Checkout Sessions. Stripe reporta que Link aumenta la finalización de checkout hasta un 7% en promedio, con números más altos para usuarios de Link recurrentes. No hay desventaja para habilitarlo, y con 100M+ usuarios de Link en 2026, el efecto de red es significativo.
¿Cómo manejo suscripciones con facturación medida en Next.js?
Crea una suscripción con un precio medido en Stripe. Luego, usa la API de Usage Records para reportar uso desde tu backend. Al final de cada período de facturación, Stripe automáticamente calcula el total y cobra al cliente. Tu manejador de webhook debe escuchar los eventos invoice.payment_succeeded e invoice.payment_failed para mantener tu sistema sincronizado. Reporta uso del lado del servidor usando un cron job o arquitectura impulsada por eventos.
¿Cuál es la mejor manera de manejar moneda y precios para clientes internacionales? Stripe Adaptive Pricing (lanzado 2025) automáticamente convierte precios a la moneda local del cliente en el checkout. Configuras precios en tu moneda base, y Stripe maneja la conversión, visualización, y liquidación. Alternativamente, puedes crear múltiples precios por producto en diferentes monedas en Stripe para más control. Usa la IP del cliente o la configuración regional del navegador para determinar qué moneda mostrar en tus páginas de producto.
¿Cuánto cuesta construir una integración de comercio sin cabeza con Stripe? Depende del alcance. Una integración básica de Checkout Sessions se puede hacer en unos pocos días. Una configuración completa con suscripciones, portal de cliente, webhooks, e interfaz de usuario personalizada típicamente toma 2-6 semanas de tiempo de desarrollo. Si quieres discutir tus necesidades específicas, consulta nuestra página de precios o ponte en contacto — hemos construido estas integraciones en una amplia gama de industrias y podemos darte una estimación realista.