Facturar cuando cobras con tu propia pasarela
Facturar con UTILIA OS cuando cobras con tu propia pasarela: factura simplificada ya cobrada, devolución en tu pasarela y rectificativa.
Actualizado el . 3 min de lectura
Incluido en todos los planes. Ver precios
Si tu aplicación cobra con su propia cuenta de Stripe (o con otra pasarela) y usa UTILIA OS solo para facturar, el recorrido es más corto: no hacen falta tarjetas guardadas, autorizaciones ni el aplicativo Pagos con tarjeta. Basta con Finanzas.
Venta cobrada fuera y devolución posterior
Tu pasarela
Cobras en tu pasarela
El cliente paga 39,99 € y obtienes el identificador del cobro (pi_...).Tu pasarela
Devuelves el dinero en tu pasarela
Obtienes el identificador de la devolución (re_...).POST /invoices/:id/rectifications
Con la causa y el bloque refund. UTILIA OS decide el código legal.
Permisos de la aplicación: crm:invoices:write y crm:invoices:issue
para emitir, crm:invoices:send si UTILIA OS envía los correos, y
crm:invoices:rectify para las rectificativas (lo concede un Super
Administrador, con un motivo).
Ventas a consumidores de otros países de la Unión
Si vendes servicios electrónicos a consumidores de otros Estados miembros (o, desde Canarias, Ceuta o Melilla, también a consumidores de la península y Baleares), esas ventas pueden tener que llevar el IVA del país del consumidor por la ventanilla única del IVA. Esa forma de facturar está en «Próximamente». Las ventas que cobra una tienda de aplicaciones (App Store, Google Play) o cuyas condiciones fija la tienda son de la tienda, no tuyas: no las factures como ventas a consumidores.
1. Emitir la factura ya cobrada
Para una venta a un consumidor de hasta 400 €, emite una simplificada
con el precio que cobraste (pricesIncludeTax: true) y el bloque
payment. La factura nace cobrada y, si se envía, el cliente recibe un
solo correo con la plantilla de factura pagada.
const factura = await sdk.invoices.create({
type: 'SIMPLIFIED',
user: { externalId: 'user_01HXYZ', email: 'ana@example.com' },
taxSystem: 'IGIC',
pricesIncludeTax: true,
lines: [{ name: 'Plan Básico mensual', quantity: 1, unitPrice: 39.99, taxType: 'IGIC_7' }],
payment: { method: 'CARD', reference: 'pi_3QabcDEF' },
consumerResidence: { region: 'CANARIAS', evidence: 'País de la tarjeta: ES; código postal de facturación: 38' },
idempotencyKey: 'pedido-4471',
});
// factura.totalAmount: 39.99 (base 37,37 más 2,62 de IGIC)
// factura.paymentRegistered: trueSi tu organización está en el régimen del pequeño empresario del IGIC
(REPEP), la línea va con taxType: 'EXEMPT' y sin causa: el total es
39,99 € sin cuota y la factura lleva «Exención franquicia fiscal». Los
detalles están en Facturas.
Antes de la primera venta real, prueba ese mismo cuerpo con
POST /external/v1/invoices/validate, que no numera nada (ver
Probar la facturación sin emitir facturas).
La emisión puede tardar varios segundos: usa un tiempo de espera de al
menos 30 y, si se corta, repite con la misma clave. Si el cobro no se
pudiera registrar, la factura sigue emitida con paymentRegistered: false y el correo retenido; regístralo con mark-paid. Lo que pasó con
el correo lo dice emailDelivery.
2. Devolver el dinero en tu pasarela
La devolución la haces tú, en tu cuenta. UTILIA OS no puede ni debe mover ese dinero. Guarda el identificador de la devolución.
3. Emitir la rectificativa con la devolución
const resultado = await sdk.invoices.rectifications.create(factura.id, {
userId: 'user_01HXYZ',
idempotencyKey: 'devolucion-pedido-4471',
cause: 'REFUND',
refund: { reference: 're_3QabcDEF' },
});
// resultado.rectification.rectificationCode: 'R5'
// resultado.rectification.totalAmount: -39.99
// resultado.originalInvoice.status: 'RECTIFIED'
// resultado.refund.source: 'EXTERNAL_GATEWAY'Para una devolución parcial, añade amount con el importe devuelto,
impuestos incluidos. La clave de idempotencia es obligatoria: si la
respuesta trae operationStatus: 'review_required', repite la misma
llamada con la misma clave para terminarla. Un contracargo se rectifica
igual, con cause: 'CHARGEBACK', solo si la venta queda sin efecto.
Antes de pedirla, puedes comprobarla con el mismo cuerpo en
POST /external/v1/invoices/:id/rectifications/validate, que no numera
ni registra nada. Si la respuesta es 409 RECTIFICATION_NOT_ALLOWED con
retryable: true (la factura todavía se está emitiendo o su PDF se está
preparando), repítela igual pasados retryAfterSeconds. Un correo o un
cobro de la emisión que no salieron no la impiden. Y registra cada
devolución por una sola vía: si tu equipo ya la anotó a mano en la
ficha de la factura con la misma referencia, la API responde
409 REFUND_REFERENCE_ALREADY_USED. Ver
Cuándo se puede rectificar.
4. Recibir los avisos
| Aviso | Cuándo |
|---|---|
INVOICE_CREATED | Se emite la factura. invoice.type dice si es SIMPLIFIED. |
INVOICE_PAID | Queda cobrada con el bloque payment. payment.source es manual. |
INVOICE_RECTIFICATION_CREATED e INVOICE_RECTIFIED | Se crea y se emite la rectificativa. |
INVOICE_REFUNDED | Se registra la devolución, con refund.source: "EXTERNAL_GATEWAY". |
Todos llegan solo a tu aplicación.