Saltar al contenido principal

Cobrar desde una caja registradora

Beta

El modo de escucha del servidor ECR del terminal está en revisión de seguridad: las próximas versiones del terminal podrían aceptar órdenes solo desde el propio equipo y exigir que el administrador habilite la red local de forma explícita. Confirma con FINORA la versión instalada en tus terminales antes de integrar. Si la caja y el terminal no comparten red, usa el cobro empujado.

Tu caja registradora (ERP, punto de venta) envía el monto y la referencia de la venta al terminal FINORA. El terminal muestra el monto, el cliente presenta la tarjeta y escribe el PIN en el terminal, y la caja recibe el veredicto en la misma respuesta. La caja nunca ve el número de la tarjeta: queda fuera del alcance de la certificación de tarjetas.

Antes de empezar​

NecesitasDónde
La dirección del terminal en la red de la tiendaConfiguración del terminal. El servidor ECR escucha en el puerto 8080.
El token del terminalEl administrador lo ve en la configuración global del terminal y lo copia en la caja.
Una clave de idempotencia por ventaLa genera tu caja (por ejemplo, un UUID) y la guarda junto a la venta.

Los ejemplos usan terminal.tienda.example como dirección del terminal.

1. Comprobar que el terminal está libre​

GET /estado no requiere token: no mueve dinero y sirve para descubrir el terminal.

curl -s http://terminal.tienda.example:8080/estado
{
"terminal": "AuroraPOS",
"disponible": true,
"operacionEnCurso": null,
"tokenRequerido": true
}

Si disponible es false, hay un cobro en curso: muestra el aviso al cajero y no envíes otro.

2. Cobrar​

CLAVE=$(uuidgen)
curl -s -X POST http://terminal.tienda.example:8080/pagos \
-H "Content-Type: application/json" \
-H "X-Terminal-Token: $FINORA_TERMINAL_TOKEN" \
--max-time 200 \
-d '{
"montoCentavos": 125000,
"referencia": "F-00123",
"cajaId": "CAJA-03",
"cajeroId": "cajero.demo",
"idempotencyKey": "'"$CLAVE"'",
"documentoPagador": "V12345678",
"tipoDocumentoPagador": "V"
}'
CampoObligatorioNotas
montoCentavossíEntero en la menor unidad de la moneda: Bs 1.250,00 es 125000. Nunca decimal.
referenciasíNúmero de factura o de venta en tu caja.
idempotencyKeyrecomendadoPermite reintentar sin riesgo de doble cobro.
cajaId, cajeroIdnoPara cuadrar por caja y por turno.
documentoPagador, tipoDocumentoPagadornoDocumento del cliente si la caja ya lo capturó (V, E, J, P…). Vuelven como eco en la respuesta; el terminal no los guarda.

El token también se acepta como Authorization: Bearer <token>. Sin token, o con uno que no coincide, el terminal responde 401 con estado: "NO_AUTORIZADO".

La respuesta es síncrona: llega cuando el cliente termina de pagar. Una venta con PIN puede tardar; el terminal espera hasta 180 segundos, así que configura en tu cliente un tiempo de espera mayor.

{
"estado": "APROBADA",
"aprobada": true,
"codigoRespuesta": "00",
"codigoAutorizacion": "A1B2C3",
"rrn": "622916125320",
"panEnmascarado": "990500******0015",
"marcaTarjeta": "VISA",
"montoCentavos": 125000,
"numeroLote": 52,
"stan": 125320,
"referencia": "F-00123",
"idempotencyKey": "550e8400-e29b-41d4-a716-446655440000",
"documentoPagador": "V12345678",
"tipoDocumentoPagador": "V"
}

3. Actuar según el estado​

estadoHTTPQué significaQué hace la caja
APROBADA200Cobro aprobado.Imprimir el comprobante y cerrar la venta.
RECHAZADA200El banco rechazó; codigoRespuesta dice por qué.Ofrecer otro medio de pago.
CANCELADA200El cliente o el operador cancelaron.Volver al cobro.
EN_DUDA200No se sabe si cobró.No entregar ni cobrar de nuevo. Consultar la clave (paso 4).
TERMINAL_OCUPADO409Ya hay un cobro en curso.Esperar; no reintentar de inmediato.
MONTO_INVALIDO400Monto menor o igual a cero.Corregir.
PETICION_INVALIDA400JSON mal formado.Corregir.
NO_AUTORIZADO401Falta el token o no coincide.Revisar el token configurado en la caja.
Un tiempo agotado nunca es un rechazo

Si la conexión se corta o vence tu tiempo de espera, trata la venta como EN_DUDA. Dar por rechazada una venta que el banco aprobó deja al cliente sin mercancía y con el cargo hecho.

4. Salir de la duda: consultar la clave​

GET /pagos/{idempotencyKey} no dispara ningún cobro: dice lo que el terminal recuerda de esa clave.

curl -s http://terminal.tienda.example:8080/pagos/$CLAVE \
-H "X-Terminal-Token: $FINORA_TERMINAL_TOKEN"
CasoHTTPCuerpo
Resuelta200La misma respuesta que devolvió (o debió devolver) el POST.
En curso200{ "estado": "EN_CURSO", "aprobada": false, "idempotencyKey": "…" }: sigue consultando.
Desconocida404{ "estado": "DESCONOCIDA", "aprobada": false }

Reenviar el mismo POST /pagos con la misma clave también es seguro: si la clave está en curso, el terminal se engancha a la operación viva; si ya se resolvió, devuelve el mismo veredicto sin cobrar otra vez. Lo que nunca es seguro es reintentar con una clave nueva.

El terminal recuerda en memoria los últimos 100 desenlaces. Si la app del terminal se reinicia, una clave puede pasar a DESCONOCIDA: eso no significa que no se cobró. Concilia contra las ventas del comercio en el portal o el cierre de lote antes de volver a cobrar.

Un cobro a la vez​

Un terminal atiende un solo cobro. Una segunda orden recibe 409 TERMINAL_OCUPADO en lugar de encolarse: encolar cobros en un punto de venta produce cargos que el cajero no espera.

Complemento para cajas Windows​

Próximamente

FINORA prepara un complemento para cajas Windows (biblioteca .NET y ejecutable con código de retorno para Delphi, VB6 o FoxPro) compatible con el token del terminal. Mientras tanto, integra el contrato HTTP de esta guía o usa FINORA Pago, que cobra desde el propio equipo de la caja.

Lo que sigue​