Flujo de pago Flow multi-tenant en Neges
Documentación técnica del ciclo completo de pago: creación de orden, reutilización de checkout, llamada a Flow, confirmación, retorno, estados e invariantes operativas.
El pago en Neges se divide en dos responsabilidades: la tienda crea o reutiliza una orden, y Strapi crea o reutiliza una intención de pago contra Flow. Flow nunca decide a qué tenant pertenece la compra; esa relación vive en la orden guardada.
Resumen ejecutivo
El pedido se crea antes de enviar al cliente a Flow. Esa decisión permite congelar productos, precios, despacho, cliente, tenant y número de orden antes de cualquier interacción con la pasarela.
La creación del pago es idempotente por orden: si existe un checkout pendiente compatible con la configuración actual, Strapi lo reutiliza. Si la configuración de pago cambió, por ejemplo de sandbox a producción, Strapi crea una nueva intención de pago para evitar redirigir al cliente a un checkout antiguo.
La confirmación financiera ocurre siempre en Strapi. El navegador sólo redirige; no aprueba pagos, no calcula montos finales y no decide el tenant de retorno.
Principios de diseño
- El navegador no aprueba pagos.
- neges-store orquesta la experiencia de checkout, crea la orden cuando corresponde y redirige al checkout de Flow.
- neges-strapi es la autoridad de negocio: crea órdenes, crea pagos, guarda eventos y valida el estado contra Flow.
- paymentStatus y status operativo son conceptos separados: pagar una orden no significa prepararla automáticamente.
- El tenant dinámico se obtiene desde la orden guardada, no desde Flow ni desde el navegador.
- Las credenciales de Flow nunca se exponen al frontend.
- Cada evento de pago debe dejar trazabilidad suficiente para auditar monto, ambiente, tenant y configuración usada.
Mapa general del flujo
Este diagrama resume el caso normal: el cliente revisa la compra, la tienda crea la orden, Strapi crea una intención Flow, Flow confirma el pago y Strapi redirige al cliente al tenant correcto.
Flujo paso a paso
Crear la orden desde la tienda
El cliente está en una tienda, por ejemplo https://lumiaonline.cl, y neges-store crea la orden vía POST /storefront-api/orders. El proxy reenvía a Strapi con el tenant resuelto.
Congelar datos de la compra
Strapi guarda la orden asociada al tenant y congela monto, moneda, productos y datos de entrega.
Iniciar pago con Flow
neges-store pide iniciar el pago con POST /storefront-api/orders/:documentId/payments/flow. Strapi llama a Flow payment/create con apiKey, commerceOrder, subject, amount, email, urlConfirmation y urlReturn.
Redirigir al checkout
Flow responde con token y URL de checkout. neges-store redirige al cliente a esa URL.
Validar retorno y confirmación
Flow llama a urlConfirmation y urlReturn con el token. Strapi consulta payment/getStatus(token), valida monto y commerceOrder, y actualiza paymentStatus.
Volver al tenant correcto
Strapi recupera el tenant desde la orden asociada al token y redirige al cliente a la tienda correcta.
Capas y responsabilidades
| Capa | Responsabilidad | Lo que no debe hacer |
|---|---|---|
| neges-store | Validar la experiencia de checkout, mantener la orden finalizada en estado local, llamar al proxy y redirigir al checkout de Flow. | No guarda secretos, no consulta Flow directo, no aprueba pagos. |
| Storefront API | Resolver el tenant desde host o contexto, normalizar errores y reenviar la solicitud a Strapi. | No contiene reglas financieras ni credenciales Flow. |
| neges-strapi | Crear la orden, congelar snapshots, resolver configuración de pago, crear o reutilizar Flow, recibir callbacks y actualizar estados. | No depende del localStorage del cliente ni de datos no validados del navegador. |
| Flow | Autorizar o rechazar el pago y entregar token, checkoutUrl y estado oficial del pago. | No resuelve tenants de Neges ni decide URLs de tienda final. |
| Backoffice | Configurar credenciales, ambiente, modalidad y revisar pedidos después del pago. | No debe asumir que cambiar configuración invalida automáticamente checkouts ya emitidos; esa regla vive en Strapi. |
Cuándo se crea una orden
La tienda llega a review con carrito, cliente, dirección y método de despacho. Desde ahí decide si debe crear una orden nueva o reutilizar una orden ya finalizada en el flujo actual.
| Situación en checkout | Acción | Razón |
|---|---|---|
| No existe orden finalizada y el carrito es válido | Crear orden con POST /storefront-api/orders | Todavía no hay documentId ni orderNumber para iniciar Flow. |
| Existe orden con documentId y paymentStatus pending | No crear otra orden; iniciar o reutilizar pago de esa orden | Evita duplicar pedidos por doble click, refresh o reintento del usuario. |
| Existe orden pagada y el carrito sigue con items | Limpiar la orden actual y crear un pedido nuevo | Una orden paid no debe volver a pagarse ni mezclarse con una nueva intención de compra. |
| Existe orden pagada y el carrito está vacío | Completar la navegación de éxito | El flujo ya terminó y sólo falta mostrar el resultado. |
| El carrito está vacío antes de crear orden | No crear orden | No hay base comercial para congelar monto ni productos. |
| Faltan contacto, despacho o método de entrega | No crear orden; volver al primer paso inválido | La orden debe nacer con datos mínimos consistentes. |
Qué congela Strapi al crear el pedido
La creación del pedido ocurre en Strapi porque ahí se puede validar el tenant, leer productos reales, calcular snapshots y persistir todo en una transacción. La orden inicial queda normalmente con status created, paymentStatus pending, paymentProvider flow y fulfillmentStatus unfulfilled.
- Tenant: la tienda que originó la compra.
- Cliente: datos de contacto y métricas asociadas.
- Items: snapshot de nombre, SKU, cantidad, precio y moneda.
- Totales: subtotal, despacho, descuentos si aplican y total final.
- Entrega: dirección, comuna, región, carrier o retiro según método.
- Identificadores: documentId público y orderNumber humano.
- Estado inicial: pedido creado, pago pendiente y despacho no preparado.
Cuándo se crea o reutiliza Flow
El endpoint de pago recibe el documentId de la orden. Strapi busca esa orden dentro del tenant, valida que se pueda pagar y decide si reutiliza un checkout pendiente o si crea una nueva intención contra Flow.
Reglas de reutilización del checkout
| Condición | Se reutiliza | Motivo |
|---|---|---|
| La orden ya está pagada | No se crea Flow nuevo | La operación es idempotente: se devuelve el estado pagado y se evita un segundo cobro. |
| Existe token pendiente, checkoutUrl y evento flow_payment_created compatible | Sí | El usuario puede reintentar después de refresh o doble click sin abrir múltiples intenciones de pago. |
| El evento pendiente fue creado con otro ambiente | No | Un checkout sandbox no debe reutilizarse si la tienda ahora está en producción. |
| Cambió paymentMethod, timeout o modalidad de credenciales | No | La intención anterior ya no representa la configuración activa del tenant. |
| El pago anterior falló o no tiene checkoutUrl confiable | No | Se necesita una nueva intención trazable. |
| La orden fue cancelada o reembolsada | No | No se permite iniciar cobros sobre órdenes cerradas operacionalmente. |
Snapshot de configuración de pago
Cada intención Flow se guarda con una copia mínima de la configuración usada al crearla. Esa copia no contiene secretos, pero sí los campos necesarios para saber si el checkout sigue siendo compatible con la configuración activa del tenant.
{
"credentialMode": "tenant_flow",
"environment": "production",
"paymentMethod": 9,
"settingDocumentId": "payment-setting-document-id",
"timeoutSeconds": 1800
}Datos enviados a Flow
Strapi arma la solicitud a Flow desde la orden persistida, no desde el payload del navegador. El commerceOrder debe ser único por intento de pago, pero también rastreable al orderNumber interno.
| Campo Flow | Origen en Neges | Consideración |
|---|---|---|
| apiKey | Configuración segura del tenant o credenciales globales | No se expone al frontend. |
| commerceOrder | orderNumber más sufijo único del intento | Permite auditar reintentos sin perder vínculo con la orden. |
| subject | Resumen del pedido | Debe ser legible para el comprador. |
| amount | Total de la orden | Debe ser mayor que cero y validarse al confirmar. |
| Email del cliente | Flow lo usa para la experiencia de pago. | |
| urlConfirmation | Endpoint público de Strapi | Callback servidor-servidor; no depende del navegador. |
| urlReturn | Endpoint público de Strapi | Strapi valida token y redirige a la tienda del tenant. |
Confirmación y retorno
Flow puede avisar por confirmación servidor-servidor y por retorno del navegador. Ambos caminos deben ser defensivos e idempotentes: consultar estado a Flow, validar que corresponde a la orden, actualizar sólo cuando corresponde y no duplicar efectos secundarios.
URLs enviadas a Flow
En producción, ambas URLs apuntan a Strapi. Después de validar el token, Strapi construye el retorno final hacia el dominio del tenant.
urlConfirmation:
https://api.neges.cl/api/storefront/payments/flow/confirmation
urlReturn:
https://api.neges.cl/api/storefront/payments/flow/return
Retorno final esperado:
https://<tenant-host>/checkout/success?order=<orderNumber>&payment=paid
https://<tenant-host>/checkout/review?order=<orderNumber>&payment=failedResolución multi-tenant
Flow no recibe el tenant como autoridad de negocio. La autoridad es la orden. Cuando Flow vuelve con token, Strapi busca la orden, lee su tenant y recién ahí decide el host final de retorno.
Cómo Strapi sabe a qué tenant volver
Cuando se inicia el pago, Strapi ya conoce la orden y su tenant. El backend guarda en metadata.paymentEvents datos como token, commerceOrder, monto, moneda, checkoutUrl y tenant.slug.
Cuando Flow vuelve con token=abc, Strapi busca la orden con paymentProvider=flow y paymentReference=abc. Desde esa orden recupera tenant.slug y construye la URL final.
Pago aprobado:
https://lumiaonline.cl/checkout/success?order=NS-123&payment=paid
Pago fallido o pendiente:
https://lumiaonline.cl/checkout/review?order=NS-123&payment=failedConfiguración recomendada
FLOW_MODE=production
FLOW_PUBLIC_API_BASE_URL=https://api.neges.cl
FLOW_STOREFRONT_RETURN_BASE_URL=https://{tenant}.neges.cl
FLOW_PAYMENT_METHOD=9
FLOW_PAYMENT_TIMEOUT_SECONDS=1800
FLOW_REQUEST_TIMEOUT_MS=10000FLOW_MODE=sandbox
FLOW_PUBLIC_API_BASE_URL=http://localhost:1337
FLOW_STOREFRONT_RETURN_BASE_URL=http://localhost:4200?tenant={tenant}
FLOW_PAYMENT_METHOD=9Estados y eventos relevantes
Neges separa el estado financiero del estado operativo. Esa separación evita que un cobro aprobado cambie automáticamente el flujo de preparación, despacho o cancelación.
| Elemento | Valores o evento | Uso operativo |
|---|---|---|
| order.status | created, preparing, ready, fulfilled, cancelled | Estado operativo del pedido. Backoffice lo mueve según preparación y entrega. |
| order.paymentStatus | pending, paid, failed, refunded | Estado financiero. Lo actualiza Strapi después de consultar a Flow. |
| order.paymentProvider | flow | Permite saber qué integración administra el cobro. |
| order.paymentReference | token Flow vigente | Llave principal para encontrar la orden cuando Flow vuelve con token. |
| metadata.paymentEvents[].type | flow_payment_created | Registra intento creado, token, checkoutUrl, commerceOrder y snapshot de configuración. |
| metadata.paymentEvents[].type | flow_payment_status | Registra cambios o lecturas relevantes de estado desde Flow. |
| metadata.paymentEvents[].type | simulated_payment | Uso de modo fake o pruebas controladas sin proveedor real. |
Fallas, reintentos y efectos secundarios
| Falla | Resultado esperado | Dato para diagnosticar |
|---|---|---|
| Flow responde apiKey not found | La orden queda pendiente y no se guarda checkout válido nuevo. | Ambiente, credentialMode y credenciales configuradas en Backoffice. |
| El cliente cierra la pestaña en Flow | La orden sigue pending y puede reintentar desde checkout/review. | paymentReference y último flow_payment_created. |
| Flow confirma paid pero el navegador no vuelve | Strapi deja paymentStatus paid por callback servidor-servidor. | Evento flow_payment_status y email de confirmación. |
| El navegador vuelve antes de la confirmación | Strapi consulta Flow en urlReturn y actualiza si el estado ya cambió. | Respuesta de payment/getStatus para el token. |
| Backoffice cambia sandbox a producción con una orden pendiente | El siguiente intento crea un checkout production nuevo. | Comparación entre snapshot del evento pendiente y configuración actual. |
Configuración operativa
Backoffice configura la modalidad de cobro del tenant: proveedor Flow, ambiente sandbox o producción, modalidad de credenciales, API key, secret key, método de pago y timeout. El backend cifra secretos y sólo expone a la UI los datos no sensibles necesarios para mostrar la modalidad actual.
- Usar sandbox sólo para pruebas controladas; los checkouts sandbox deben abrir sandbox.flow.cl.
- Usar producción para tiendas reales; los checkouts productivos deben abrir www.flow.cl.
- Validar que API key y secret correspondan al mismo ambiente.
- Después de cambiar ambiente, probar con una orden nueva o reintentar una pendiente y confirmar que se emite un checkout compatible.
- No documentar ni pegar secretos reales en issues, chats o capturas compartidas.
- Mantener un timeout explícito para evitar checkouts infinitamente reutilizables.
Observabilidad mínima
Para analizar incidentes de pago, la información mínima debe permitir responder: qué orden era, qué tenant la originó, qué ambiente Flow se usó, qué commerceOrder se envió, qué token volvió, qué monto reportó Flow y qué transición de estado se aplicó.
| Pregunta de soporte | Dónde mirar primero |
|---|---|
| El cliente fue a sandbox? | paymentEvents.flow_payment_created.config.environment y checkoutUrl. |
| Se cobró dos veces? | Cantidad de eventos flow_payment_created, tokens y estados Flow por commerceOrder. |
| Por qué la orden sigue pending? | Última respuesta payment/getStatus y callbacks recibidos. |
| Qué tenant debe recibir el retorno? | Relación order.tenant y storefrontHost guardado. |
| El monto de Flow coincide? | Comparación entre total congelado de la orden y amount reportado por Flow. |
Preguntas para análisis crítico futuro
- Debemos permitir múltiples intentos Flow activos por orden o invalidar explícitamente los tokens anteriores?
- El paymentReference debe guardar sólo el token vigente o una tabla/evento indexable por todos los tokens históricos?
- Cuánto tiempo se debe reutilizar un checkout pendiente antes de forzar uno nuevo?
- Qué SLA de confirmación y alertas necesitamos cuando Flow no llama urlConfirmation?
- Qué panel necesita soporte para distinguir error de credenciales, rechazo del banco, abandono del usuario y error técnico?
- Qué datos deben quedar firmados o auditados para conciliación contable posterior?
- La preparación del pedido debe seguir siendo manual después de paid o conviene una automatización configurable por tenant?
Checklist de prueba end-to-end
Crear una orden desde checkout/review
Usar un carrito real, contacto válido y método de despacho configurado. La respuesta debe incluir documentId, orderNumber y paymentStatus pending.
Iniciar pago Flow
Llamar a POST /storefront-api/orders/:documentId/payments/flow. La respuesta debe incluir checkoutUrl del ambiente esperado.
Validar reutilización
Repetir la llamada sin cambiar configuración. Debe reutilizar el checkout pendiente compatible.
Validar cambio de configuración
Cambiar sandbox a producción o modificar el método configurado y reintentar. Debe crear un checkout nuevo compatible con el snapshot actual.
Completar pago
Pagar en Flow y confirmar que Strapi actualiza paymentStatus paid, registra evento y redirige al host correcto.
Revisar Backoffice
Confirmar que el pedido aparece pagado, pero el estado operativo sigue disponible para preparación manual.
Riesgos y decisiones abiertas
- Localhost no sirve para validar webhooks servidor-servidor desde Flow; se necesita túnel público.
- Si un usuario cambia de navegador al volver desde Flow, la store puede no tener el pedido en localStorage.
- Si se crea una nueva intención Flow para la misma orden, webhooks tardíos de tokens anteriores podrían requerir búsqueda por metadata además de paymentReference.
- En producción hay que monitorear errores de Flow y registrar paymentEvents para trazabilidad.
- El cambio de ambiente o credenciales debe probarse con una orden nueva y con una orden pendiente existente.
Recursos relacionados
¿Te fue útil este contenido?
Tu feedback nos ayuda a mejorar la documentación de Neges.
¿No encuentras lo que buscas?
Conversa con nuestro equipo de soporte en español. Respondemos por WhatsApp, correo o ticket en menos de 24 horas hábiles.