1. Visión General
El Sobre de Regalo permite a los invitados contribuir dinero directamente al anfitrión del evento via Stripe Connect Express. Nvito actúa como intermediario tecnológico y cobra una comisión automática (application_fee).
Arquitectura de pagos — Stripe Connect Express
Actores
Stripe
nvito-api
nvito-api
PostgreSQL
Stripe
PostgreSQL
Actores
1 cuenta = 1 evento
Cada evento tiene su propia cuenta Connect porque cada evento tiene un beneficiario distinto (el cliente que contrató el evento). La cuenta Connect NO es por organización.
2. Requisitos Previos
Antes de configurar el Sobre de Regalo para un evento:
| Prerequisito | Verificación |
|---|---|
| Stripe Connect habilitado en Dashboard | Settings → Connect → Platform Settings |
| Variables de entorno configuradas | STRIPE_CONNECT_WEBHOOK_SECRET, URLs de onboarding |
| Webhook de Connect registrado en Stripe | Endpoint /webhooks/stripe-connect |
| Evento creado en Nvito | Estado DRAFT o ACTIVE |
| Contrato firmado con el cliente | Datos del beneficiario disponibles |
Datos necesarios del cliente
- Nombre legal completo del beneficiario (persona física o moral)
- Email de contacto (recibirá notificaciones de Stripe)
- RFC (10 a 13 caracteres, formato XAXX010101000)
- Tipo de persona: física (INDIVIDUAL) o moral (COMPANY)
3. Paso a Paso en el Admin
3.1 Activar el Sobre de Regalo
- Abrir admin → seleccionar evento → Mesa de Regalos → tab Sobre de Regalo
- Clic en "Activar Sobre de Regalo"
- Aparecen 3 secciones configurables con indicador de progreso
3.2 Configurar el Fondo (Sección 1)
- Ingresar Meta del fondo en MXN (ejemplo: $50,000)
- Escribir Mensaje para invitados (visible en la app: "Fondo para nuestra luna de miel")
- Clic "Guardar fondo"
- El indicador del paso 1 cambia a ✓ verde
3.3 Crear la Cuenta de Cobro (Sección 2)
Creacion y verificacion de cuenta Connect
- Abrir sección "Cuenta de cobro del cliente"
- Llenar datos del beneficiario:
- Nombre legal: Tal como aparece en documentos fiscales
- Email: Email del cliente
- Tipo de persona: Física o Moral
- RFC: Formato válido
- Clic "Crear cuenta de cobro"
- Estado: "Verificación pendiente"
3.4 Completar Verificación en Stripe
- Clic "Completar verificación" → nueva pestaña en Stripe
- Completar formulario de onboarding:
- Datos personales o de la empresa
- Información bancaria (CLABE)
- Verificación de identidad (INE/pasaporte)
- Regresar al admin → clic "Actualizar estado"
- Estado cambia a "Verificada" (badge verde)
3.5 Configurar Comisiones (Sección 3)
Desglose de comisiones por contribucion
Cobro
Comisiones
Destino
- Comisión Nvito (%): Default 15%, mínimo 3.6% (costo base de Stripe)
- Máximo por contribución: Límite por invitado (default $50,000 MXN)
- Máximo del fondo: Tope total (default $500,000 MXN)
- Clic "Guardar comisiones"
3.6 Checklist Pre-Publicación
Antes de publicar el evento, verificar:
- ✓ Los 3 pasos están en verde (3/3 completados)
- ✓ Status card dice "Listo para recibir contribuciones"
- ✓ Preview muestra mensaje y barra de progreso correctamente
- ✓ Comisiones y límites configurados según el paquete del cliente
4. Estados de la Cuenta Connect
Estados de la cuenta Stripe Connect
not_started→onboardingAdmin crea cuenta(createConnectedAccount)onboarding→verifiedchargesEnabled = true(webhook account.updated)onboarding→restrictedRequisitos pendientes(webhook account.updated)restricted→verifiedDocumentos OK(webhook account.updated)restricted→disabledCuenta rechazada(rejected.fraud)verified→disabledStripe desactiva(rejected.*)verified→completedEvento termina(event-lifecycle)completed→archived6 meses post-evento(cron job)verified→archivedAdmin archiva(archiveAccount)disabled→archivedAdmin archiva(archiveAccount)| Estado | Significado | Acción |
|---|---|---|
| Sin cuenta | No se ha creado | Crear con datos del cliente |
| Onboarding pendiente | Creada, falta verificación | Completar en Stripe |
| Restringida | Stripe requiere documentos | Revisar requisitos y completar |
| Verificada | Lista para recibir pagos | Ninguna — contribuciones activas |
| Deshabilitada | Stripe rechazó la cuenta | Contactar soporte o archivar y crear nueva |
| Completada | Evento terminó | Automático — disputes activos 120 días |
| Archivada | 6+ meses post-evento | PII anonimizado, stripeAccountId se mantiene |
5. Flujo de Contribución del Invitado
Flujo completo de contribucion — Cash Fund via Stripe Connect
Conversión de Unidades (crítico)
| Punto del flujo | Unidad | Ejemplo |
|---|---|---|
| UI del invitado (selecciona monto) | Pesos | $100 |
DTO al API (amount) | Centavos | 10,000 |
| Validaciones backend | Centavos | 10,000 vs maxContribution |
Payment.amount en BD | Pesos (Decimal) | 100.00 |
Stripe PaymentIntent.amount | Centavos | 10,000 |
cashFundCurrent en BD | Centavos | incrementado por 10,000 |
| API mobile response | Pesos | 100.00 (convertido /100) |
Regla de oro
La API mobile convierte TODO a pesos antes de enviar al cliente. El backend valida TODO en centavos. Stripe recibe TODO en centavos. Payment.amount se almacena en pesos.
6. Webhooks
Webhooks de Stripe y Stripe Connect
| Evento Stripe | Endpoint | Acción |
|---|---|---|
payment_intent.succeeded | /webhooks/stripe | Marca SUCCEEDED + incrementa cashFundCurrent |
payment_intent.payment_failed | /webhooks/stripe | Marca FAILED |
charge.dispute.created | /webhooks/stripe | Decrementa cashFundCurrent + marca REFUNDED |
charge.refunded | /webhooks/stripe | Decrementa cashFundCurrent + marca REFUNDED |
account.updated | /webhooks/stripe-connect | Sincroniza estado de cuenta Connect |
7. Troubleshooting
La cuenta queda en "Restringida"
- Revisar requisitos pendientes en la sección 2
- Clic "Completar verificación" → subir documentos faltantes
- Clic "Actualizar estado"
El invitado ve "Este fondo no está disponible aún"
Causas: cuenta Connect no verificada, evento no ACTIVE, o cashFund desactivado.
Error al crear la cuenta
Verificar: email válido y único, RFC formato correcto, evento no tiene ya una cuenta activa.
Cambio de beneficiario
Solo un Super Admin puede archivar la cuenta actual (botón "Cambiar cuenta") y crear una nueva. Los pagos anteriores se conservan vinculados a la cuenta original.
8. Protecciones Financieras
Cadena de validaciones de seguridad — createCashFundIntent
Validaciones
Procesamiento
| Protección | Implementación |
|---|---|
| cashFundCurrent inmutable | Solo el webhook y confirm pueden modificarlo. El admin no puede resetearlo |
| Desactivar preserva datos | Al desactivar el fondo, los datos financieros y la cuenta Connect se conservan |
| Confirmación con fondos | Si hay fondos recaudados, se pide confirmación antes de desactivar |
| Meta no menor que recaudado | El backend rechaza cashFundGoal menor que cashFundCurrent |
| Eliminación protegida | No se puede eliminar un evento con pagos PROCESSING |
| Auto-desactivación | Si Stripe deshabilita la cuenta, cashFundEnabled se desactiva automáticamente |
| Disputes decrementan | Un chargeback decrementa cashFundCurrent (atómico en transacción) |
9. Archivos Clave
| Archivo | Responsabilidad |
|---|---|
stripe-connect.service.ts | Gestión cuentas Connect (crear, sync, archivar, verificar) |
stripe-connect.controller.ts | Endpoints admin + archivo (Super Admin) |
payments.service.ts | createCashFundIntent con Connect obligatorio |
payments-webhook.controller.ts | Endpoints webhook (Stripe + Connect) |
stripe-webhook.service.ts | Handlers de payment_intent, charge.dispute, charge.refunded |
stripe.provider.ts | Wrapper Stripe SDK (métodos Connect) |
gift-registry.service.ts | Protección de cashFundCurrent contra escritura manual |