Skip to main content
Fire spark mantiene un catálogo global de proveedores y métodos de pago. Un merchant activa un método creando un pago en el dashboard. Un pedido guarda cómo se paga como intents de pago. Cada intent es una lista de tenders. Los tenders son la fuente de verdad del método, el monto, el estado y dónde se cobra.

El modelo

Los tipos de método significan:
  • CASH: lo cobra el personal en caja o en la puerta.
  • CARD: tarjeta no presente (checkout web o app).
  • PIN_PAD: tarjeta presente, en un terminal junto al kiosco o la caja.
  • WALLET: QR o billeteras.
  • BANK_TRANSFER: el cliente paga desde su banco y el canal lo verifica.
  • FINANCING: compra ahora, paga después. Cubre una parte del pedido; el resto se paga con otro método.
  • REDEMPTION: vales, recompensas o saldo. No es un método que el cliente elige en el checkout. Sale de un canje que nombra el pago REDEMPTION del merchant.
REDEMPTION no es un método real. Los métodos reales son todos los demás. is_mixed es verdadero cuando un intent tiene dos o más tenders reales. Un canje junto a una tarjeta no vuelve mixto el intent. primary_tender_id es el primer tender real. Es null solo cuando todos los tenders son REDEMPTION. Un pedido tiene como máximo un intent DRAFT o LOCKED. Los intents anteriores se quedan en payment_intents como COMPLETED o ABANDONED.

Dónde se cobra un tender

collect_at es DEVICE, KIOSK, COUNTER, DOOR u OTHER. Un nodo PAYING del fulfillment puede fijar payment_scope en digital o in_person. Sin alcance, el nodo espera todos los tenders vivos. El nodo avanza a PAID cuando cada tender de ese alcance está liquidado. Un alcance vacío queda pagado apenas el pedido entra. Un alcance solo de canjes queda pagado cuando esas recompensas ya están reservadas (PENDING con reserva cuenta como liquidado).

Estados del intent

Estados del tender

También son el payment_status del pedido, derivado de los tenders vivos del intent activo. Derivación: sin tenders es IDLE. Cualquier FAILED es FAILED. Todos CANCELLED es CANCELLED. Todos REFUNDED o CANCELLED es REFUNDED. Todos liquidados es PAID. Todos IDLE es IDLE. Cualquier otro caso es PENDING. Cada tender tiene un attempt_reference. Los reintentos usan uno nuevo. La misma referencia nunca crea un segundo cobro.

Pagos mixtos y allocation

Envía los tenders antes de colocar. El servidor calcula el amount de cada tender y allocation.amounts. Tú envías allocation sin amounts. allocation es { lines: [{ line_uid, units? }], fees: [line_uid] } o null.
  • Un solo tender real puede enviar allocation: null. Ese tender cubre lo que ningún otro cubre.
  • Un tender REDEMPTION siempre envía allocation: null. Cubre un monto, no líneas.
  • Con más de un tender real, un tender real sin allocation se rechaza (PAYMENT_UNALLOCATED_LINES).
  • La propina y el delivery van solo en el tender real primario.
  • Como máximo un tender es CASH.

Canjes

Un canje es un vale, una recompensa o saldo. Todo canje necesita payment_id (un pago REDEMPTION activo del merchant) y amount (el dinero que cubre para toda la entrada, no por unidad). quantity es informativo. Un canje sin payment_id se rechaza con REDEEM_PAYMENT_REQUIRED. El canje se muestra como descuento en su línea (lines[].redeem) o en el pedido (redeem), pero el dinero de la línea y del pedido no cambia: group_total, los impuestos y totals.total quedan completos. El tender REDEMPTION paga el monto canjeado y el método del cliente paga el resto. before_taxes (por defecto true) limita el canje al valor antes de impuestos de su línea o pedido, así los impuestos quedan para el método del cliente. Con before_taxes: false el canje también puede cubrir los impuestos. Además, todo canje tiene tope en el total del pedido menos propina y delivery. Los canjes que comparten un payment_id se vuelven un tender REDEMPTION. details.rewards lista cada recompensa. Cada recompensa tiene su amount con tope, y details.amount es la suma. El monto del tender es esa suma. Un tender que no coincide con los canjes agrupados es PAYMENT_REDEMPTION_MISMATCH. Cada canje también tiene un paso en redemption_steps, en orden de aplicación: los canjes de líneas raíz en el orden de las líneas y luego los del pedido. Un paso lleva payment_id, before_taxes, target (LINE con target_id, u ORDER) y discount_amount, el amount con tope. before y after tienen value (lo que aún paga el método del cliente), discount_amount (lo cubierto hasta ahí) y discount_rate (cubierto / total); los pasos LINE también tienen target_before y target_after. Así, los pasos de un payment_id suman su tender REDEMPTION y los pasos de una línea suman el descuento que se muestra en ella. El servidor recalcula y guarda los pasos. Validate y place rechazan pasos del cliente con otros canjes u otro orden (REDEMPTION_STEPS_MISMATCH) o con otro dinero (REDEMPTION_MISMATCH). redemptionSteps(order) del SDK da los mismos pasos.
Un tender no lleva datos de descuento. Su amount es { currency, total }: lo que paga ese tender. Un tender REDEMPTION solo agrega lo que necesitan la anulación y el reembolso: payment_id y details (rewards[] con reward_id, quantity y amount, más details.amount). services.payments.list oculta los pagos REDEMPTION. Pasa { includeRedemptions: true } cuando un flujo de canje los necesita. Esa bandera no es un query param: la API sigue devolviendo esos pagos y el SDK los filtra.

Reapertura

Reabrir pedido anula los tenders sin cobrar (los canjes reservados se liberan), cancela el origen como VOIDED y devuelve un pedido OPEN nuevo. El vínculo está en metadata.reopen: { as_order_id } en el origen y { from_order_id } en el nuevo. El pedido nuevo puede guardar los dos cuando se reabre otra vez. Un tender real vivo que ya está PAID o REFUNDED devuelve 400 ORDER_PAYMENT_CAPTURED. Un pedido ya VOIDED / REVERSED / CANCELLED (legacy) que nunca se cumplió se reabre tal cual cuando todos los tenders reales están CANCELLED, FAILED o REFUNDED completo (por ejemplo, tras una inyección fallida reversada en el dispositivo); ahí un tender PAID sigue siendo 400 y uno IDLE / PENDING es 422. order_id es opcional y puede ser cualquier id que arme genId (isGenId: [A-Za-z0-9-], una racha de al menos 8 [0-9a-z], hasta 64 caracteres; genOrderId es una opción). Ejemplo: BB2192100000001. Un formato inválido es 400 ORDER_ID_INVALID y un id ocupado es 409 ORDER_ID_EXISTS. Si omites order_id, el comportamiento sigue igual. REDEMPTION no bloquea la reapertura. En un kiosco, el botón Cancelar durante la espera de liberación del checkout llama a este endpoint.

Relacionado

Métodos de pago soportados

Qué hay hoy y qué viene

Usar pagos en el SDK

Instala un paquete y cobra un pedido

Pedidos

A qué pertenece un intent de pago

Errores de pago

Códigos del proveedor, reintentos y qué mostrar al cliente