Arquitectura de la facturación centralizada
Cómo encajan UTILIA OS, tu aplicación y la pasarela de pago al facturar y cobrar: identificadores, puente de identidad, cobro recurrente y avisos.
Actualizado el . 8 min de lectura
Incluido en todos los planes. Ver precios
UTILIA OS actúa como centro fiscal y centro de cobro de las aplicaciones que conectas: numera y firma las facturas, guarda el estado de cada cobro y avisa a tu aplicación de todo lo que pasa. Con la clave de API de tu aplicación, y la facturación activada para ella, puedes emitir facturas con la numeración de la organización, guardar tarjetas, montar cuotas y cobrarlas. Esta página explica cómo encajan las piezas para que diseñes esa integración sabiendo qué hace cada una. El recorrido práctico, paso a paso, está en la guía de facturación y cobro.
Visión general
Tres actores trabajan juntos:
- UTILIA OS: numera las facturas (correlativo AEAT), firma VeriFactu, mantiene el estado fiscal, guarda el metadato de cada cobro y expone la API externa.
- Stripe: gestiona los datos de tarjeta (PCI DSS), ejecuta los cobros, enruta el dinero a la cuenta bancaria de la organización y notifica por webhooks.
- Tu aplicación externa: da de alta a sus usuarios, emite facturas, monta suscripciones, recoge la autorización de cobro, lanza cobros y recibe los avisos de todo lo anterior.
Pagos con tarjeta: una cuenta de Stripe por organización
Cada organización de UTILIA OS conecta su propia cuenta de Stripe, de tipo estándar. UTILIA OS actúa como plataforma, pero los cobros se enrutan a la cuenta de la organización con la cabecera Stripe-Account en cada llamada.
Ventajas de este modelo:
- El dinero llega directamente al banco de la organización, no al de UTILIA OS, y sin comisión de UTILIA OS por transacción.
- Cada organización mantiene independencia total sobre su cuenta de Stripe: panel propio, devoluciones y disputas.
- Los datos sensibles de las tarjetas viven solo en Stripe: ni UTILIA OS ni tu aplicación los ven.
Al navegador solo llega la clave publicable de la plataforma, que es pública por diseño, acompañada del identificador de la cuenta conectada (stripeAccount). No existe una clave publicable propia de cada cuenta conectada: con cargos directos, Stripe exige exactamente esa combinación.
Saber si la organización puede cobrar
Antes de intentar un cobro, tu aplicación puede preguntar si la organización está lista para cobrar con tarjeta con GET /external/v1/payment-methods/readiness. Devuelve platformAvailable, organizationCanCharge, livemode y un motivo estable (PLATFORM_DISABLED, NO_ACCOUNT, ONBOARDING_INCOMPLETE, CHARGES_DISABLED, ACCOUNT_DEAUTHORIZED o READY). Es el mismo criterio que usan las pantallas del panel.
Identificadores que verás
En las respuestas y en los avisos aparecen identificadores de Stripe (acct_… de la cuenta conectada, cus_… del cliente, pm_… de la tarjeta y pi_… de cada intento de cobro) junto a los de UTILIA OS. Una factura emitida por tu aplicación lleva source: EXTERNAL_APP y la referencia a tu aplicación y a su usuario externo.
Los usuarios de tu aplicación no se mezclan con el CRM
El CRM no ve a los usuarios externos de ninguna aplicación como tales, solo sus propios clientes. Cuando un usuario externo necesita facturarse, el puente de identidad crea su ficha de cliente (se explica más abajo).
Flujo: cobro desde el portal del cliente
Cuando el cliente paga una factura desde el portal del cliente:
- Pulsa Pagar ahora y el portal llama a
POST /portal-invoices/:id/pay. - UTILIA OS comprueba sus permisos y el estado de la factura, crea el cobro en Stripe con el cliente delante y devuelve el
clientSecret. - El portal confirma el pago con Stripe Elements.
- Stripe avisa a UTILIA OS con
payment_intent.succeeded. UTILIA OS comprueba la firma, registra el aviso para no procesarlo dos veces y marca la factura como cobrada. - El cliente recibe el correo, el portal se actualiza al momento y, si la factura es de una aplicación externa, esta recibe el aviso
INVOICE_PAID.
Flujo: cobro automático de una factura recurrente nativa
Este flujo es el de las suscripciones creadas desde el panel para un cliente del CRM. Una aplicación externa usa el mismo motor por su propia vía, que se describe más abajo.
- Cada día a las 08:00 UTC, el proceso de facturas recurrentes emite las que vencen ese día, con su número y su firma VeriFactu.
- Si el cliente tiene una tarjeta predeterminada, UTILIA OS la cobra sin el cliente delante, con clave de idempotencia. Si no la tiene, la factura queda emitida.
- Si Stripe confirma el cobro, la factura pasa a cobrada. Si el banco pide verificar al cliente, este recibe un correo para completarlo en el portal.
- Si el cobro falla, se reintenta a los 3, 7 y 14 días (valores por defecto). Agotados los reintentos, el cobro programado queda en fallo definitivo, se avisa al equipo y sale el evento
INVOICE_PAYMENT_FAILED.
Flujo: factura creada por aplicación externa, pagada desde la propia app
Factura de tu aplicación, pagada en tu aplicación
Participan: Tu aplicación, UTILIA OS, Stripe.
De Tu aplicación a UTILIA OS:
POST /external/v1/invoices
Con el usuario y las líneas de la factura.Nota en UTILIA OS:
Comprueba que la facturación de la aplicación está activa y su tope, numera la factura y la firma con VeriFactu.De UTILIA OS a Tu aplicación:
La factura emitida (respuesta)
Con origen EXTERNAL_APP.De Tu aplicación a UTILIA OS:
POST /external/v1/invoices/:id/pay
Cuando tu usuario pulsa Pagar.De UTILIA OS a Tu aplicación:
clientSecret, publishableKey y stripeAccountId (respuesta)
De Tu aplicación a Stripe:
Confirma el pago con Stripe Elements
Con la clave publicable de la plataforma y stripeAccount.De Stripe a UTILIA OS:
payment_intent.succeeded (respuesta)
La factura pasa a cobrada.De UTILIA OS a Tu aplicación:
Aviso INVOICE_PAID
Actualizas tu base de datos y avisas a tu usuario.
UTILIA OS recibe de Stripe la confirmación de cada cobro, verifica su firma y la procesa una sola vez aunque Stripe la reintente.
Flujo: cuota recurrente de una aplicación externa
Es el caso de una aplicación que cobra cada mes a sus usuarios. La pieza que lo hace posible es el puente de identidad: el usuario de la aplicación se materializa como ficha de cliente del CRM, y a partir de ahí reutiliza el motor financiero entero.
Cuota recurrente de una aplicación externa
Participan: Tu aplicación, UTILIA OS, Stripe.
De Tu aplicación a UTILIA OS:
POST /external/v1/users/identify
Da de alta al usuario o actualiza sus datos fiscales.Nota en UTILIA OS:
Puente de identidad: la primera vez que se factura, se guarda tarjeta o se crea suscripción, crea su ficha de cliente del CRM.De Tu aplicación a UTILIA OS:
POST /external/v1/payment-methods/setup-intent
Prepara el guardado de la tarjeta del usuario.De Tu aplicación a UTILIA OS:
POST /external/v1/payment-authorizations
Tras enseñar el texto de consent-text: versión, momento, IP y navegador.De Tu aplicación a UTILIA OS:
POST /external/v1/subscriptions
chargeMode AUTO_STRIPE con la autorización recién firmada.Nota en UTILIA OS:
Cada periodo emite la factura de tu aplicación y, si el correo está activo, la envía con su PDF.De UTILIA OS a Tu aplicación:
SUBSCRIPTION_INVOICE_GENERATED
Aviso con la factura y emailSent.De UTILIA OS a Stripe:
Cobro sin el usuario delante
Contra la autorización firmada.De Stripe a UTILIA OS:
payment_intent.succeeded (respuesta)
La factura pasa a cobrada.De UTILIA OS a Tu aplicación:
CHARGE_SUCCEEDED
Renuevas el servicio.
Lo que puede torcerse por el camino:
- Sin autorización vigente,
POST /subscriptionsen cobro automático responde409 PAYMENT_AUTHORIZATION_REQUIRED. Si la organización tiene apagado el cobro automático,409 AUTO_CHARGE_DISABLED_FOR_ORGANIZATION, sinnextStep. Nunca se pasa a cobro manual en silencio. - Si el cobro falla, llegan
CHARGE_FAILEDyCHARGE_RETRY_SCHEDULEDen cada reintento, hastaCHARGE_RETRIES_EXHAUSTED. Antes de cada intento llegaCHARGE_STARTED. - Si el banco pide verificar al usuario, llega
CHARGE_REQUIRES_ACTION: pides el enlace público de la factura y llevas allí a tu usuario. - Con
clientIdenidentify, el puente reutiliza una ficha que creó tu propia aplicación. Una ficha dada de alta por el equipo desde el panel no se toca (se explica más abajo).
Consecuencias de que el usuario externo sea un cliente del CRM: sus facturas aparecen en Finanzas con el origen visible y el filtro por aplicación, cuentan en la contabilidad y en las comisiones como cualquier otra, y su ficha en el CRM muestra de qué aplicación viene.
El puente no cruza hacia las fichas nativas
Cada ficha de cliente guarda qué aplicación externa la creó. El puente solo reutiliza, converge o enlaza fichas con esa marca, o que ya tengan un usuario de la misma aplicación. Una ficha dada de alta por el equipo desde el panel queda fuera del alcance de la API externa, aunque coincidan el identificador fiscal o el correo: en ese caso se crea una ficha nueva y la coincidencia se registra en el histórico de auditoría para que el equipo decida.
Unir las dos fichas sigue siendo posible desde el panel, con sesión iniciada, permiso y alcance sobre la ficha. En ese camino la aplicación gana la facturación de esa persona, pero no hereda sus tarjetas guardadas ni las autorizaciones de cobro que firmó en el portal del cliente: el cliente de la pasarela no converge sobre una ficha nativa.
Avisos salientes hacia las aplicaciones externas
Para cada cambio relevante, UTILIA OS entrega un aviso firmado a las aplicaciones suscritas. Los del ciclo de facturación y cobro son:
| Dominio | Eventos |
|---|---|
| Facturación | INVOICE_CREATED, INVOICE_SENT, INVOICE_PAID, INVOICE_PARTIALLY_PAID, INVOICE_PAYMENT_FAILED, INVOICE_OVERDUE, INVOICE_CANCELLED, INVOICE_REFUNDED, INVOICE_REFUND_CANCELLED, INVOICE_RECTIFIED, INVOICE_RECTIFICATION_CREATED, INVOICE_RECTIFICATION_METADATA_UPDATED |
| Métodos de pago | PAYMENT_METHOD_ADDED, PAYMENT_METHOD_REMOVED, PAYMENT_METHOD_EXPIRING |
| Autorizaciones de cobro | PAYMENT_AUTHORIZATION_GRANTED, PAYMENT_AUTHORIZATION_REVOKED, PAYMENT_AUTHORIZATION_CONSUMED |
| Suscripciones | SUBSCRIPTION_CREATED, SUBSCRIPTION_UPDATED, SUBSCRIPTION_PAUSED, SUBSCRIPTION_RESUMED, SUBSCRIPTION_CANCELLED, SUBSCRIPTION_COMPLETED, SUBSCRIPTION_INVOICE_GENERATED, SUBSCRIPTION_PAYMENT_AUTHORIZATION_PENDING |
| Cobros programados | CHARGE_SCHEDULED, CHARGE_STARTED, CHARGE_SUCCEEDED, CHARGE_FAILED, CHARGE_REQUIRES_ACTION, CHARGE_RETRY_SCHEDULED, CHARGE_RETRIES_EXHAUSTED, CHARGE_CANCELLED |
Regla de enrutado:
- Los dieciséis de suscripciones y cobros son siempre dirigidos: sin aplicación dueña no hay destinatario.
- Los de facturas, métodos de pago y autorizaciones son dirigidos cuando el recurso pertenece a un usuario de una aplicación externa, y por difusión cuando es propio de la organización.
El catálogo completo, con el contenido de cada aviso campo a campo, está en Avisos: contenido y catálogo de eventos.
Permisos del equipo implicados
Estos son permisos de personas del equipo, no de aplicaciones externas. Se asignan a los roles desde los ajustes de la organización, y no deben confundirse con los permisos de la API externa, que se conceden por aplicación desde el panel de aplicaciones externas.
- Configuración y consulta de la pasarela, y devoluciones desde el panel.
- Consulta y gestión de las tarjetas guardadas de un cliente.
- Cobro de una factura desde el panel.
- Consulta y gestión de las suscripciones del CRM.
- Consulta y cancelación de los cobros programados.
- Pago y gestión de tarjetas desde el portal del cliente.
El catálogo de permisos de la API externa, que es otra cosa, está en Gestión de scopes de aplicaciones externas.
Siguiente paso
Pon en práctica el recorrido completo, del alta del usuario a la renovación sin nadie delante, con la guía de facturación y cobro.