Documento tecnico que describe la integracion de pagos en Nvito con Stripe: creacion de PaymentLinks, flujo de checkout con Stripe Elements, procesamiento de webhooks, estados de pago, contribuciones a la mesa de regalos y medidas de seguridad.
| Campo | Valor |
|---|
| Version | 1.0 |
| Fecha | Marzo 2026 |
| Estado | Publicado |
| Audiencia | Equipo de desarrollo, arquitectos |
Nvito integra Stripe como procesador de pagos para dos casos de uso principales:
| Caso de uso | Descripcion | Flujo |
|---|
| Mesa de regalos (Cash Fund) | Los invitados contribuyen dinero a un fondo definido por el organizador | PaymentLink publico → Stripe Checkout → Webhook → Registro |
| Paquetes del evento | Pagos de servicios adicionales asociados al evento | PaymentLink interno → Stripe Elements → Webhook → Activacion |
El organizador crea un PaymentLink desde el panel de administracion.
| Campo | Tipo | Descripcion |
|---|
id | UUID | Identificador interno |
token | string (32) | Token publico para la URL |
eventId | UUID | Evento asociado |
type | enum | CASH_FUND, PACKAGE |
amount | number | Monto en centavos (o null si es abierto) |
currency | string | MXN, USD |
description | string | Descripcion visible al pagador |
stripeProductId | string? | ID del producto en Stripe |
stripePriceId | string? | ID del precio en Stripe |
isActive | boolean | Si acepta pagos |
expiresAt | DateTime? | Fecha de expiracion opcional |
createdBy | UUID | Usuario que lo creo |
| Metodo | Paises | Tipo |
|---|
| Tarjeta de credito/debito | Global | Inmediato |
| OXXO | Mexico | Diferido (hasta 3 dias) |
| SPEI | Mexico | Diferido (minutos a horas) |
| Apple Pay | Global | Inmediato |
| Google Pay | Global | Inmediato |
| Evento Stripe | Accion en Nvito |
|---|
checkout.session.completed | Marcar sesion como completada |
payment_intent.succeeded | Registrar pago exitoso, enviar recibo |
payment_intent.payment_failed | Registrar fallo, notificar si corresponde |
charge.refunded | Registrar reembolso |
charge.dispute.created | Alertar al organizador |
| Medida | Descripcion |
|---|
| Firma | Validacion con stripe.webhooks.constructEvent() usando el webhook secret |
| Idempotencia | Cada evento tiene un ID unico; se ignoran duplicados |
| Timeout | Respuesta en menos de 5 segundos (procesamiento asincrono via colas) |
| IP whitelist | Solo IPs de Stripe permitidas (configurado en infraestructura) |
| Estado | Descripcion | Final? |
|---|
| PENDING | Checkout creado, esperando pago | No |
| PROCESSING | Stripe procesando el pago (OXXO, SPEI) | No |
| SUCCEEDED | Pago completado exitosamente | Si (salvo reembolso) |
| FAILED | Pago rechazado por el banco o procesador | Si |
| REFUNDED | Reembolso completo procesado | Si |
| PARTIALLY_REFUNDED | Reembolso parcial procesado | Si |
| CANCELLED | Checkout abandonado (timeout de 30 minutos) | Si |
| EXPIRED | PaymentLink expiro antes del pago | Si |
| Tipo | Descripcion | Pago |
|---|
| Producto fisico | Item con precio fijo (ej. licuadora) | Monto fijo |
| Cash Fund | Fondo abierto (ej. luna de miel) | Monto libre o sugerido |
| Experience | Experiencia (ej. cena romantica) | Monto fijo o libre |
Cada contribucion se registra como un Payment asociado a un GiftRegistryItem:
| Campo | Tipo | Descripcion |
|---|
paymentId | UUID | Referencia al pago |
giftRegistryItemId | UUID | Item de la mesa de regalos |
guestId | UUID? | Invitado que contribuyo (si identificado) |
amount | number | Monto contribuido |
message | string? | Mensaje del contribuyente |
Para Cash Funds, se calcula el progreso:
progress = (sum of contributions) / targetAmount * 100
El frontend muestra una barra de progreso con el porcentaje alcanzado.
| Regla | Descripcion |
|---|
| Solo SUCCEEDED | Solo se pueden reembolsar pagos exitosos |
| Max monto | No se puede reembolsar mas del monto pagado |
| Multiples parciales | Se permiten multiples reembolsos parciales (sum no excede total) |
| Roles | Solo OWNER y ADMIN pueden procesar reembolsos |
| Auditoria | Se registra quien proceso el reembolso y cuando |
| Aspecto | Implementacion |
|---|
| PCI Compliance | Stripe maneja todos los datos sensibles de tarjeta (nivel 1 PCI DSS) |
| Webhook signature | stripe.webhooks.constructEvent() valida firma HMAC |
| Idempotencia | Idempotency keys en creacion de PaymentIntents |
| Token no predecible | PaymentLink tokens generados con nanoid (32 chars, cripto-random) |
| Expiracion | PaymentLinks expiran automaticamente si se configura expiresAt |
| Rate limiting | Endpoints de checkout limitados (10 req/IP/min) |
| Montos | Validacion server-side de rangos permitidos (min/max por organizacion) |
| Moneda | Solo monedas habilitadas para la organizacion (MXN, USD) |
El organizador puede ver metricas de pagos en el dashboard:
| Metrica | Descripcion |
|---|
| Total recaudado | Suma de pagos SUCCEEDED |
| Numero de contribuciones | Total de pagos exitosos |
| Monto promedio | Total recaudado / numero de contribuciones |
| Tasa de exito | SUCCEEDED / (SUCCEEDED + FAILED) * 100 |
| Progreso por item | Contribuciones vs meta para cada item de regalo |
| Top contribuyentes | Invitados que mas han contribuido |
| Archivo | Ubicacion | Responsabilidad |
|---|
payments.service.ts | src/modules/payments/ | Logica de negocio de pagos, checkout, reembolsos |
payments.controller.ts | src/modules/payments/ | Endpoints REST de pagos |
payments-webhook.controller.ts | src/modules/payments/ | Handler de webhooks de Stripe |
stripe-client.service.ts | src/modules/payments/services/ | Wrapper del SDK de Stripe |
gift-registry.service.ts | src/modules/gift-registry/ | Mesa de regalos, items, contribuciones |
gift-registry.controller.ts | src/modules/gift-registry/ | Endpoints REST de mesa de regalos |