Webhook de prueba de Stripe: prueba pagos en local con la CLI

Cómo ejecutar un webhook de prueba de Stripe en local con la Stripe CLI: stripe listen, stripe trigger, fallas, duplicados y salir de un constructor de IA.

Illustration of payment events routed through a listener into a local laptop, depicting a Stripe test webhook setup
En esta página · 7 secciones
  1. ¿Cómo envío un webhook de prueba en Stripe?
  2. ¿Cómo uso stripe listen para reenviar eventos a localhost?
  3. ¿Cómo disparo eventos específicos con la Stripe CLI?
  4. ¿Qué casos de falla debo probar antes del lanzamiento?
  5. ¿Cómo pruebo eventos duplicados y fuera de orden?
  6. ¿Cómo pruebo después de salir del constructor?
  7. ¿Quieres un segundo par de ojos?

Puntos clave

  • Usa el modo de prueba de Stripe y la Stripe CLI; nunca pruebes con claves de producción ni tarjetas reales.
  • stripe listen –forward-to envía eventos a tu endpoint local y muestra un secreto de firma válido solo para esa sesión.
  • stripe trigger crea eventos de ejemplo, pero tu flujo real de checkout es una mejor prueba de tu propia lógica de negocio.
  • Prueba fallas, duplicados y entregas fuera de orden, no solo el camino feliz.
  • Unas pocas revisiones enfocadas encuentran la mayor parte del riesgo; corregir errores de pago cuesta más cuando ya llegaron usuarios y pagos reales.

La forma más rápida de ejecutar un webhook de prueba de Stripe es con la Stripe CLI. Inicias sesión, ejecutas stripe listen para reenviar eventos del modo de prueba de Stripe a una URL local y luego ejecutas stripe trigger para disparar eventos de ejemplo. Tu app recibe solicitudes reales y firmadas sin ningún deploy.

Esto importa sobre todo en apps construidas con herramientas de IA como Lovable, Bolt o Base44, donde el flujo de pago suele verse bien en una demo pero nunca se ha enfrentado a una tarjeta rechazada, un reintento o un evento duplicado. Soy un ingeniero brasileño, y esta es la rutina que uso antes de que pase dinero real por una app.

¿Cómo envío un webhook de prueba en Stripe?

Tienes tres opciones, y cada una prueba cosas distintas.

  • Stripe CLI: la mejor para desarrollo local. Reenvía eventos a localhost y te permite dispararlos desde la terminal.
  • Event destinations en el dashboard: en modo de prueba puedes apuntar Stripe a una URL pública y enviar un evento de prueba desde el dashboard. Útil para un despliegue de staging.
  • Acciones reales en modo de prueba: completar un Checkout con una tarjeta de prueba genera exactamente la secuencia de eventos que tu app verá en producción.

En el trabajo diario combino la primera y la tercera. La CLI da feedback rápido, y un checkout de prueba real confirma toda la cadena: tu frontend, tu servidor, Stripe y de vuelta a tu base de datos.

¿Cómo uso stripe listen para reenviar eventos a localhost?

Instala la Stripe CLI y luego autentícate con stripe login. Abre el navegador para vincular la CLI con tu cuenta. Asegúrate de estar trabajando en modo de prueba.

Levanta tu app en local y luego ejecuta:

  1. stripe listen –forward-to localhost:3000/api/stripe/webhook (usa tu propio puerto y tu propia ruta).
  2. Copia el secreto de firma que muestra la CLI. Empieza con whsec_.
  3. Pon ese valor en tu variable de entorno local para el secreto del webhook.
  4. Reinicia tu app para que lea el nuevo valor.

El error más común que veo es usar en local el secreto del endpoint del dashboard. La sesión de la CLI tiene su propio secreto, así que la verificación de la firma falla con un error confuso. Si tu handler devuelve 400 en cada evento, revisa esto primero.

Confirma también que tu handler verifique la firma contra el cuerpo crudo de la solicitud. Los frameworks que parsean el JSON antes de que tu código lo vea rompen la verificación. Es un problema del código, no de Stripe.

Dos ventanas de terminal lado a lado en una laptop, una de ellas reenviando eventos de webhook de prueba de Stripe a un servidor local
Una terminal reenvía los eventos y la otra ejecuta tu app.

¿Cómo disparo eventos específicos con la Stripe CLI?

Con el listener en marcha, abre una segunda terminal y ejecuta stripe trigger seguido del nombre de un evento. Los más comunes para una app de pagos:

  • checkout.session.completed
  • payment_intent.succeeded
  • payment_intent.payment_failed
  • invoice.paid e invoice.payment_failed
  • customer.subscription.deleted

Observa la salida del listener. Cada línea muestra el evento y el estado HTTP que devolvió tu endpoint. Quieres un 200 para los eventos manejados, y también quieres ver tus propios logs y los cambios en la base de datos.

Una advertencia: los eventos disparados usan datos de fixture generados. No van a contener tu ID de cliente, tu ID de pedido ni tus metadatos. Así que un trigger demuestra que tu endpoint recibe y verifica eventos, pero puede que no demuestre que tu lógica de pedidos funciona. Para eso, haz un checkout de prueba real con la tarjeta 4242 4242 4242 4242 y deja que la CLI reenvíe los eventos resultantes.

¿Qué casos de falla debo probar antes del lanzamiento?

Las apps construidas con IA suelen manejar el caso de éxito. En las fallas es donde se pierden dinero y datos. Esta es la lista que recorro.

CasoCómo probarloQué deberías ver
Tarjeta rechazadaTarjeta de prueba 4000 0000 0000 0002No se otorga acceso, el usuario ve un error claro
Firma inválidaEnvía una solicitud con un secreto incorrectoRespuesta 400, no se escribe nada
Caída del handlerLanza un error en tu handlerRespuesta 500, Stripe reintenta más tarde
Tipo de evento desconocidoDispara un evento que no manejasRespuesta 200, el evento se ignora de forma segura
Checkout abandonadoCierra la página antes de pagarNo se crea ningún pedido pagado

La regla clave: tu app debe otorgar acceso o marcar un pedido como pagado solo después de que un webhook verificado confirme el pago, no porque el navegador llegó a una página de éxito. Cualquiera puede abrir una URL de éxito a mano. Un escáner de seguridad genérico no va a detectar esto, porque es lógica de negocio, no un patrón de vulnerabilidad conocido.

Revisa también que los errores devuelvan un estado distinto de 2xx. Si tu handler se traga una excepción y devuelve 200, Stripe cree que el evento se manejó y no reintenta, y pierdes el registro del pago sin darte cuenta.

¿Cómo pruebo eventos duplicados y fuera de orden?

Stripe puede entregar el mismo evento más de una vez y no garantiza el orden. Tu handler debe resistir ambas cosas.

Duplicados

Usa stripe events resend con un ID de evento de tu dashboard de prueba para entregar el mismo evento otra vez. Tu app no debería crear un segundo pedido, enviar un segundo email ni extender una suscripción dos veces. La solución habitual es guardar los IDs de los eventos procesados en una tabla con una restricción de unicidad y saltarte los que ya viste. Mejor aún, haz que la actualización en sí sea idempotente, por ejemplo poniendo el estado de un pedido como pagado en lugar de incrementar un contador.

Fuera de orden

Puedes recibir invoice.paid antes que checkout.session.completed, o una actualización de suscripción antes de que exista el registro. Pruébalo reenviando eventos en otro orden, o borrando temporalmente la fila relacionada y reenviando. Un handler robusto o bien obtiene el objeto actual desde la API de Stripe, o bien falla con un 500 para que Stripe reintente más tarde.

Sobres mezclados y duplicados llegando a un escritorio, que representan eventos de webhook de Stripe fuera de orden y duplicados
Los eventos pueden llegar dos veces y en el orden equivocado.

Concurrencia

Si dos copias llegan casi en el mismo momento, un patrón de verificar y luego insertar todavía puede crear duplicados. Lo que realmente te protege es la restricción de unicidad en la base de datos, así que apóyate en ella y no solo en el código de la aplicación.

¿Cómo pruebo después de salir del constructor?

El código construido en Lovable se puede llevar a GitHub y a tu propio hosting. Cuando lo haces, la configuración del webhook cambia, y este es un punto común donde los pagos se rompen en silencio.

  1. Registra un nuevo endpoint en Stripe para la nueva URL pública, primero en modo de prueba.
  2. Usa el secreto del nuevo endpoint en las variables de entorno del nuevo hosting. No reutilices el secreto de la CLI ni uno antiguo.
  3. Revisa dónde corre la lógica en el servidor. Si los webhooks antes corrían en una función administrada por el constructor, confirma que la misma lógica ahora existe en tu propio backend.
  4. Haz un checkout de prueba completo contra la URL de staging desplegada y confirma que cambia la fila en la base de datos.
  5. Repite en modo de producción con un pago real pequeño que reembolsas después, cuando todo pase.

Elimina el endpoint antiguo en Stripe cuando termines para que los eventos no se envíen a dos lugares. Quedarse en el constructor a veces es la mejor decisión, sobre todo para una app simple con poco tráfico. Pero si migras, trata el webhook como lo primero que vuelves a probar, porque el dueño de la app es responsable de la confirmación del pago incluso cuando la plataforma opera la infraestructura.

Corrige el código existente antes de considerar una reescritura. Cuando reviso un flujo de pago, empiezo buscando correcciones puntuales en el código existente antes de cualquier cosa más grande.

¿Quieres un segundo par de ojos?

Si quieres una segunda opinión sobre tu handler de webhooks o tu flujo de pago, escríbeme a me@filipeeduardo.dev con una descripción de tu configuración y te diré qué revisaría primero.

Preguntas frecuentes

¿Necesito una URL pública para probar un webhook de Stripe?

No. La Stripe CLI reenvía eventos de Stripe a localhost, así que puedes probar sin hacer deploy ni usar una herramienta de túnel.

¿Por qué mi webhook local devuelve un error de firma?

Normalmente el secreto es incorrecto o el cuerpo se parseó antes de la verificación. Usa el valor whsec_ que muestra stripe listen y verifica contra el cuerpo crudo.

¿stripe trigger crea mis pedidos reales?

No. Crea objetos de fixture genéricos que no tienen tus metadatos. Usa un checkout de prueba real para poner a prueba tu propia lógica de pedidos.

¿Puedo volver a enviar un evento que ya recibí?

Sí. Usa stripe events resend con el ID del evento, o reenvíalo desde el dashboard en modo de prueba, para comprobar el manejo de duplicados.

¿Basta con el modo de prueba antes del lanzamiento?

Cubre la mayor parte de la lógica, pero haz un pago pequeño en modo de producción después del despliegue para confirmar que las claves de producción y el secreto del endpoint de producción estén bien configurados.

stripe test webhook

Filipe Eduardo

Ingeniero de Software Sénior. Siete años creando productos web y móviles de punta a punta y liderando los equipos que los entregan.

Sígueme

¿Quieres hablar
de esto?

Trabajo en problemas así todos los días. Cuéntame el tuyo.

Contáctame