1. Visión General
Nvito integra Stripe como procesador de pagos para dos casos de uso principales:
| Caso de uso | Descripción | Flujo |
|---|---|---|
| Sobre de Regalo (Cash Fund) | Los invitados contribuyen dinero al organizador via Stripe Connect | App móvil → PaymentIntent con transfer_data → Webhook → Registro |
| Cobro de servicios | Pagos de paquetes del evento via links de pago | PaymentLink interno → Stripe Checkout → Webhook → Activación |
Stripe Connect Express
Desde marzo 2026, las contribuciones del Cash Fund usan Stripe Connect Express. El dinero va directo al organizador (1 cuenta Connect por evento), con Nvito cobrando application_fee automática. Nvito nunca recibe dinero de contribuciones en su cuenta.
1.1 Modelo de Pagos Cash Fund
Invitado → PaymentIntent (Stripe Connect) → Organizador (directo) + application_fee → Nvito
| Actor | Rol |
|---|---|
| Invitado | Pagador — contribuye desde la app móvil |
| Organizador | Beneficiario — recibe el dinero en su cuenta Connect |
| Nvito | Plataforma — cobra comisión via application_fee |
| Stripe | Procesador — maneja PCI, transferencias, disputes |
2. Arquitectura de Pagos
Arquitectura de Pagos
Frontend (nvito-admin / nvito-invitations)
nvito-api
Stripe
nvito-api
Stripe
nvito-api
PostgreSQL
Stripe
3. Creación de PaymentLinks
El organizador crea un PaymentLink desde el panel de administración.
3.1 Flujo de Creación
Creacion de PaymentLink
3.2 Modelo PaymentLink
| Campo | Tipo | Descripción |
|---|---|---|
id | UUID | Identificador interno |
token | string (32) | Token público 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 | Descripción 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 expiración opcional |
createdBy | UUID | Usuario que lo creo |
4. Flujo de Checkout
4.1 Mesa de Regalos (Cash Fund)
Checkout — Mesa de Regalos (Cash Fund)
4.2 Metodos de Pago Soportados
| Metodo | Paises | Tipo |
|---|---|---|
| Tarjeta de crédito/débito | Global | Inmediato |
| OXXO | Mexico | Diferido (hasta 3 dias) |
| SPEI | Mexico | Diferido (minutos a horas) |
| Apple Pay | Global | Inmediato |
| Google Pay | Global | Inmediato |
5. Webhooks de Stripe
5.1 Flujo de Webhook
Webhook de Stripe
5.2 Eventos de Webhook Procesados
| Evento Stripe | Acción 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 |
5.3 Seguridad del Webhook
| Medida | Descripción |
|---|---|
| Firma | Validación con stripe.webhooks.constructEvent() usando el webhook secret |
| Idempotencia | Cada evento tiene un ID unico; se ignoran duplicados |
| Timeout | Respuestá en menos de 5 segundos (procesamiento asincrono via colas) |
| IP whitelist | Solo IPs de Stripe permitidas (configurado en infraestructura) |
6. Estados del Pago
Estados del Pago
start→pendingCheckout iniciadopending→processingStripe procesandoprocessing→succeededPago exitosoprocessing→failedPago rechazadosucceeded→refundedReembolso completosucceeded→partially_refundedReembolso parcialpending→cancelledCheckout abandonado (30 min timeout)pending→expiredPaymentLink expirado| Estado | Descripción | 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 |
7. Mesa de Regalos (Gift Registry)
7.1 Tipos de Items
| Tipo | Descripción | 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 |
7.2 Contribuciones
Cada contribucion se registra como un Payment asociado a un GiftRegistryItem:
| Campo | Tipo | Descripción |
|---|---|---|
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 |
7.3 Progreso del Fondo
Para Cash Funds, se calcula el progreso:
progress = (sum of contributions) / targetAmount * 100
El frontend muestra una barra de progreso con el porcentaje alcanzado.
8. Reembolsos
8.1 Flujo de Reembolso
Flujo de Reembolso
8.2 Reglas de Reembolso
| Regla | Descripción |
|---|---|
| Solo SUCCEEDED | Solo se pueden reembolsar pagos exitosos |
| Max monto | No se puede reembolsar más del monto pagado |
| Multiples parciales | Se permiten múltiples reembolsos parciales (sum no excede total) |
| Roles | Solo OWNER y ADMIN pueden procesar reembolsos |
| Auditoria | Se registra quien proceso el reembolso y cuando |
9. Seguridad
| Aspecto | Implementación |
|---|---|
| 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 creación de PaymentIntents |
| Token no predecible | PaymentLink tokens generados con nanoid (32 chars, cripto-random) |
| Expiracion | PaymentLinks expiran automáticamente si se configura expiresAt |
| Rate limiting | Endpoints de checkout limitados (10 req/IP/min) |
| Montos | Validación server-side de rangos permitidos (min/max por organización) |
| Moneda | Solo monedas habilitadas para la organización (MXN, USD) |
10. Metricas y Reportes
El organizador puede ver metricas de pagos en el dashboard:
| Metrica | Descripción |
|---|---|
| Total recaudado | Suma de pagos SUCCEEDED |
| Numero de contribuciones | Total de pagos exitosos |
| Monto promedio | Total recaudado / número de contribuciones |
| Tasa de exito | SUCCEEDED / (SUCCEEDED + FAILED) * 100 |
| Progreso por item | Contribuciones vs meta para cada item de regalo |
| Top contribuyentes | Invitados que más han contribuido |
11. Stripe Connect — Cuentas por Evento
11.1 Modelo 1:1 Evento-Cuenta
Cada evento con Sobre de Regalo tiene su propia cuenta Stripe Connect Express. La cuenta pertenece al cliente/beneficiario del evento, no a la organización.
| Campo | Descripción |
|---|---|
stripeAccountId | ID de la cuenta en Stripe (acct_xxx) |
status | NOT_STARTED, ONBOARDING_PENDING, RESTRICTED, VERIFIED, DISABLED, COMPLETED, ARCHIVED |
chargesEnabled | Si puede recibir pagos (true cuando verificada) |
legalName, email, rfc | Datos del beneficiario (anonimizados 6 meses post-evento) |
11.2 Ciclo de Vida de la Cuenta
| Fase | Estado | Acción |
|---|---|---|
| Creación | ONBOARDING_PENDING | Equipo Nvito crea cuenta desde admin |
| Verificación | VERIFIED | Cliente completa onboarding en Stripe |
| Evento activo | VERIFIED | Recibe contribuciones via transfer_data |
| Evento completado | COMPLETED | No acepta nuevos pagos, disputes activos |
| 6+ meses | ARCHIVED | PII anonimizado, stripeAccountId se mantiene |
11.3 Comisiones (application_fee)
| Concepto | Valor |
|---|---|
| Stripe México (tarjeta) | ~3.6% + $3 MXN |
| Comisión Nvito (configurable) | 10-15% (default 15%) |
| Organizador recibe | ~82-87% |
La comisión se calcula en el backend: application_fee = amount * (cashFundFeePercent / 100)
11.4 Límites de Seguridad
| Límite | Valor default | Configurable |
|---|---|---|
| Máximo por contribución | $50,000 MXN | Sí, por evento |
| Máximo del fondo | $500,000 MXN | Sí, por evento |
| Mínimo por contribución | $1 MXN (100 centavos) | No |
12. Archivos Clave
| Archivo | Ubicación | Responsabilidad |
|---|---|---|
payments.service.ts | src/modules/payments/ | Cash Fund con Stripe Connect (createCashFundIntent) |
payments.controller.ts | src/modules/payments/ | Endpoints REST de pagos |
payments-webhook.controller.ts | src/modules/payments/ | Webhooks de Stripe y Stripe Connect |
stripe.provider.ts | src/modules/payments/ | Wrapper del SDK de Stripe (incluye métodos Connect) |
stripe-connect.service.ts | src/modules/payments/services/ | Gestión de cuentas Connect |
stripe-connect.controller.ts | src/modules/payments/ | Endpoints admin para Connect |
contract-balance.service.ts | src/modules/payments/services/ | Cálculo compartido de balance de contratos |
12. Relación con Otros Flujos
| Flujo relacionado | Relación |
|---|---|
| Ciclo de Vida del Evento | Los PaymentLinks solo funcionan para eventos ACTIVE |
| Flujo del Invitado | Los invitados acceden a la mesa de regalos desde la invitación o la app |
| Flujo de Comunicaciones | Los recibos de pago se envian via el sistema de comunicaciones |
| Ciclo de Vida de la Invitación | La sección GiftRegistry de la invitación incluye links de pago |