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 pagoREDEMPTIONdel 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 elpayment_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 elamount 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
REDEMPTIONsiempre envíaallocation: 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 necesitapayment_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.
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 comoVOIDED 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