Modo servicio de Sentinel
Cómo controlar un terminal de pago Sentinel desde una caja registradora, un sistema ECR o una aplicación de terceros mediante HTTP local, un cable USB serie o intents de Android.
| Configuración | Valor |
|---|---|
| Aplicación | Sentinel 4.0.8 |
| Paquete | com.paylands.posms.sentinel |
| Esquema de intents | com.paynopain.sentinelservice |
| Puerto local | 6889 |
1. Introducción
Sentinel expone sus operaciones de pago a otras aplicaciones para que una caja registradora pueda cobrar con tarjeta sin que nadie tenga que interactuar con el terminal. Este documento define el contrato de integración: qué operaciones puedes invocar, qué debes enviar y qué recibirás como respuesta.
Los tres transportes permiten ejecutar las mismas operaciones y devuelven las mismas estructuras de datos. Elige el que se ajuste a la conexión entre tu caja y el terminal:
- HTTP local — tu software se ejecuta en el propio terminal o en el mismo equipo y envía JSON a
127.0.0.1:6889. - USB serie — tu caja es un equipo independiente y detecta el terminal como un puerto COM.
- Intents de Android — tu software es otra aplicación instalada en el mismo terminal Android.
La disponibilidad de cada operación varía según el transporte. Al principio de cada operación se indica si está disponible mediante cada uno de los tres transportes, para que puedas identificar qué admite tu integración.
Modo servicio. El terminal solo acepta operaciones externas cuando el modo servicio está habilitado en su configuración. Si está deshabilitado, las operaciones se rechazan con una respuesta JSON fija y no se realiza ningún cargo. La comprobación de estado es la única excepción: responde en ambos casos, lo que permite distinguir entre un terminal apagado y uno que simplemente no tiene activado el modo servicio.
2. Nombre del paquete y esquema de intents
Sentinel Service se distribuía como una aplicación independiente con el paquete com.paynopain.sentinelservice. Ahora el modo servicio forma parte de la aplicación principal de Sentinel, por lo que también ha cambiado el nombre del paquete.
| Uso | Valor |
|---|---|
| Nombre del paquete | Paquete actual. Úsalo para comprobar la instalación con PackageManager y siempre que hagas referencia a la aplicación instalada: com.paylands.posms.sentinel |
| Esquema de intents | Se mantiene por compatibilidad con versiones anteriores. Sigue utilizándolo en todas las URI de intents: com.paynopain.sentinelservice:// |
Actualiza la comprobación de instalación. Las URI de intents no necesitan cambios, pero cualquier comprobación previa que busque com.paynopain.sentinelservice como paquete instalado indicará que la aplicación no está instalada. Utiliza com.paylands.posms.sentinel. El nombre anterior se conserva únicamente como esquema de URI.
3. Transportes
3.1 HTTP local
Envía JSON mediante POST a la ruta de cada operación en el puerto 6889. Cada operación tiene su propia ruta.
POST http://127.0.0.1:6889/payment
Content-Type: application/json
Authorization: Bearer <token supplied by Paynopain>
{"amount":100,"currencyCode":978,"stan":"7f328336-f3fa-4e37-92d5-b7f1311c0f4d"}
El servidor responde con 200 OK y el resultado de la operación en el cuerpo, o con 404 Not Found si la ruta no existe. Las operaciones con tarjeta que finalizan devuelven el JSON de resultado de transacción descrito en §24; los fallos de validación devuelven un mensaje de texto plano (§4.4).
Rutas disponibles:
/payment /preauthorization /transaction
/refund /confirmation /transaction_by_stan
/referral /cancellation /list_transactions
/reversal /decrement /reports
/cardverify /cft /close_batch
/healthcheck /identify /reprint
/sync
3.2 HTTPS
El mismo puerto utiliza TLS cuando se ha aprovisionado un certificado en el terminal. El certificado y la clave privada se reciben mediante la configuración del dispositivo como un almacén de claves PKCS#12 en base64. Mientras no exista, el servidor escucha mediante HTTP sin cifrar, de modo que las integraciones existentes siguen funcionando sin cambios. Consulta la pantalla de estado del servicio del terminal para comprobar cuál está activo.
3.3 USB serie
El terminal se presenta como un dispositivo USB serie y la caja abre la conexión como un puerto COM. Esta función está disponible en terminales PAX; en otros modelos se indica que no hay enlace ECR y el servidor USB no se inicia.
| Configuración | Valor |
|---|---|
| Línea | 115200 baudios, 8 bits de datos, sin paridad y 1 bit de parada |
| Formato de trama | Cabecera de longitud de 4 bytes en big-endian, seguida de ese número de bytes de JSON en UTF-8 |
| Solicitud | {"id":"…","type":"payment","body":{ …same fields as HTTP… }} |
| Respuesta | {"id":"…","type":"payment","result":"…"} |
El id se devuelve en la respuesta para que puedas asociarla con su solicitud. type utiliza los mismos nombres que las rutas HTTP, sin la barra inicial. Solo se ejecuta una operación a la vez: si llega una segunda solicitud durante una operación, se responde inmediatamente con {"error":"busy: another operation is in progress"}. La comprobación de estado la atiende el hilo de lectura, por lo que sigue respondiendo mientras un pago espera la intervención del titular.
3.4 Intents de Android
Lanza un intent de visualización y lee el resultado en onActivityResult. La autorización se gestiona con el equipo de Paynopain mediante la inclusión de tu aplicación en la lista de aplicaciones permitidas.
String uri = "com.paynopain.sentinelservice://payment?amount=100¤cyCode=978&stan=" + stan;
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
startActivityForResult(intent, PAYMENT_RESULT_CODE);
Los resultados se reciben en dos campos extra de tipo cadena: transactionResult contiene los datos de la operación y error_message explica una cancelación o un fallo. Consulta §26 para ver un ejemplo completo.
4. Convenciones
4.1 Importes
Todos los importes son números enteros expresados en la unidad mínima de la moneda: 100 equivale a un euro. La excepción es ISK, que no tiene unidad fraccionaria y se envía en coronas enteras.
4.2 STAN
El stan es tu referencia de la operación y debes generarlo tú: un UUID único por solicitud. Se devuelve en el resultado y es la clave que permite recuperar una operación cuya respuesta no recibiste; consulta §16. Reutilizar un STAN hace que esa recuperación sea ambigua.
4.3 Moneda
currencyCode es el código numérico ISO 4217: 978 para euros, 840 para dólares estadounidenses y 826 para libras esterlinas. Debe coincidir con la moneda configurada en el terminal; si no coincide, la operación se rechaza antes de acceder a la tarjeta.
4.4 Errores
Los fallos de validación y de políticas devuelven una cadena de texto plano. Comprueba estos casos antes de interpretar el cuerpo de la respuesta como JSON:
| Respuesta | Significado |
|---|---|
| Error: Missing required fields — … | Los campos indicados no se han enviado o están vacíos. La lista aparece después del guion. |
| Error: No data received in the request | El cuerpo de la solicitud está vacío. |
| Max Amount Exceeded | Se supera el límite configurado en el terminal. Si hay una propina fija, el límite se aplica a la suma del importe base y la propina. |
| Currency is not allowed | currencyCode no coincide con la moneda del terminal. |
| Too much pending transactions. Please sync. | La cola de operaciones sin sincronizar está llena. Ejecuta sync y vuelve a intentarlo. |
| Tokenization is not enabled for this merchant | Se ha enviado tokenize: true para un comercio sin tokenización habilitada. |
| Operative not allowed | La operación no está disponible para el operador de este terminal. |
| Error: … | Se ha producido un fallo inesperado; a continuación aparece el mensaje de la excepción. |
Estas cadenas dependen del idioma. Un terminal configurado en castellano devuelve Error: Campos requeridos faltantes en lugar del mensaje en inglés de la tabla anterior. Evita comparar el texto completo: utiliza un prefijo que controles o considera como fallo cualquier cuerpo que no sea JSON.
Hay dos respuestas que se devuelven como JSON. Modo servicio deshabilitado:
{"error":"Service mode disabled: terminal does not accept external operations"}
Y, solo en el transporte USB, una segunda operación concurrente:
{"error":"busy: another operation is in progress"}
4.5 Tiempos de espera
Una operación que no produce ningún resultado, por ejemplo por un pago abandonado o una conexión interrumpida, se cancela a los 100 segundos y devuelve un error de tiempo de espera. La impresión tiene un límite de 30 segundos y, si se supera, se informa de que no se ha impreso. Configura el tiempo de espera de tu cliente por encima de 100 segundos para recibir la respuesta del terminal.
5. Pago
Realiza un cargo en una tarjeta de débito o crédito. Además de una venta simple, esta operación admite propinas, pagos por QR y tokenización por venta.
Operación: payment
| Transporte | Operación | Disponible |
|---|---|---|
| HTTP | /payment | Sí |
| USB | payment | Sí |
| Intent | //payment | Sí |
Disponibilidad: Modo servicio.
Solicitud
| Campo | Tipo | Requisito | Notas |
|---|---|---|---|
| amount | Entero | Obligatorio | Unidad mínima de la moneda. No incluye la propina fija, que se suma al importe. |
| currencyCode | Entero | Obligatorio | Código numérico ISO 4217. Debe coincidir con el del terminal. |
| stan | Cadena | Obligatorio | Tu UUID para esta operación. |
| reference | Cadena | Opcional | Referencia de texto libre que se guarda con la transacción y se muestra en el recibo. |
| customer_ext_id | Cadena | Opcional | Tu identificador de cliente, que se devuelve en el resultado. |
| tip | Booleano o entero | Opcional | true solicita una propina en la pantalla del terminal. Un entero indica una propina fija en la unidad mínima de la moneda, que se suma a amount sin mostrar una solicitud. Omite el campo si no hay propina. |
| channel | Cadena | Opcional | card (por defecto) o qr. |
| qrMethod | Cadena | Opcional | Con channel: "qr", fija el método QR (por ejemplo, BIZUM) y omite el selector en pantalla. Omítelo para que el cajero elija. |
| tokenize | Booleano | Opcional | Sustituye la configuración de tokenización del terminal solo para esta venta. Omítelo para seguir la configuración del terminal. |
Respuesta
Los datos del resultado de la transacción (§24), una vez finalizada la operación con tarjeta.
Ejemplo
POST /payment
{"amount":100,"currencyCode":978,"stan":"7f328336-f3fa-4e37-92d5-b7f1311c0f4d"}
com.paynopain.sentinelservice://payment
?amount=100¤cyCode=978&stan=ebdd1b6a-02f4-4366-9a9e-d19758123746
5.1 Propinas
tip admite dos tipos de valores porque cada modalidad de propina implica un comportamiento distinto para la integración:
"tip": truelleva Sentinel al primer plano y solicita una propina al titular en el terminal. La llamada espera a que termine todo el flujo y después devuelve el resultado habitual."tip": 150añade una propina fija de 1,50 sin mostrar pantallas ni requerir interacción. El importe cobrado esamount + tip, y ese total debe mantenerse dentro del límite del terminal.
5.2 Pago por QR
Con channel: "qr", el terminal muestra un código QR que el cliente puede tardar varios minutos en escanear. La llamada devuelve inmediatamente esta respuesta:
{"status":"QR_SHOWN","stan":"…","message":"QR mostrado en el terminal. Consulta el resultado con transaction_by_stan."}
Consulta periódicamente la transacción por STAN con el mismo stan para obtener el resultado.
5.3 Tokenización
tokenize permite decidir por venta en lugar de seguir la configuración general del terminal. Ten en cuenta estas dos limitaciones:
- La configuración de tokenización del comercio tiene prioridad. Si se solicita un token para un comercio sin tokenización habilitada, la operación se rechaza antes de realizar el cargo.
- El control por venta solo se aplica a la ruta ECOPAYNET. En MONET, la aplicación de pago decide según la configuración del comercio, por lo que
tokenize: falseno impide recibir un token si el comercio está configurado para ello.
6. Preautorización
Reserva un importe en una tarjeta sin capturarlo. Después puedes capturarlo mediante una confirmación, reducirlo mediante un decremento o liberarlo mediante una cancelación.
Operación: preauthorization
| Transporte | Operación | Disponible |
|---|---|---|
| HTTP | /preauthorization | Sí |
| USB | preauthorization | Sí |
| Intent | //preauthorization | Sí |
Disponibilidad: Modo servicio.
Solicitud
| Campo | Tipo | Requisito | Notas |
|---|---|---|---|
| amount | Entero | Obligatorio | Importe que se va a reservar, en la unidad mínima de la moneda. |
| currencyCode | Entero | Obligatorio | Código numérico ISO 4217. |
| stan | Cadena | Obligatorio | Tu UUID para esta operación. |
| reference | Cadena | Opcional | Referencia de texto libre. |
| customer_ext_id | Cadena | Opcional | Tu identificador de cliente. |
Respuesta
Resultado de transacción con operative igual a DEFERRED. Guarda transaction_id, auth_code y refund_id, ya que las operaciones posteriores los necesitan.
7. Confirmación
Captura una preautorización por su importe completo o por un importe inferior al reservado.
Operación: confirmation
| Transporte | Operación | Disponible |
|---|---|---|
| HTTP | /confirmation | Sí |
| USB | confirmation | Sí |
| Intent | //confirmation | Sí |
Disponibilidad: Modo servicio.
Solicitud
| Campo | Tipo | Requisito | Notas |
|---|---|---|---|
| amount | Entero | Obligatorio | Importe que se va a capturar. Puede ser inferior al reservado. |
| currencyCode | Entero | Obligatorio | Código numérico ISO 4217. |
| parentIdentifier | Cadena | Obligatorio | transaction_id de la preautorización. |
| stan | Cadena | Obligatorio | Tu UUID para esta operación. |
| date | Cadena | Condicional | Obligatorio en ECOPAYNET. Fecha de la operación original. |
| authCode | Cadena | Condicional | Obligatorio en ECOPAYNET. Se obtiene del resultado de la preautorización. |
| refundId | Cadena | Condicional | Obligatorio en ECOPAYNET. Se obtiene del resultado de la preautorización. |
| customer_ext_id | Cadena | Opcional | Tu identificador de cliente. |
Respuesta
Resultado de transacción con operative igual a CONFIRMATION.
Los campos condicionales dependen del operador del terminal. En ECOPAYNET, date, authCode y refundId son obligatorios y su ausencia genera un error de campos requeridos. En otros operadores se ignoran. Si no sabes qué operador utiliza un terminal, llama a identify, que devuelve el nombre del operador, o envía siempre los tres campos.
8. Cancelación
Libera una preautorización sin capturarla.
Operación: cancellation
| Transporte | Operación | Disponible |
|---|---|---|
| HTTP | /cancellation | Sí |
| USB | cancellation | Sí |
| Intent | //cancellation | Sí |
Disponibilidad: Modo servicio.
Solicitud
Utiliza los mismos campos que la confirmación: amount, currencyCode, parentIdentifier y stan son obligatorios; date, authCode y refundId son obligatorios en ECOPAYNET; customer_ext_id es opcional.
Respuesta
Resultado de transacción con operative igual a CANCELLATION.
9. Decremento
Reduce el importe retenido por una preautorización y mantiene la reserva abierta. Puede utilizarse cuando la factura final es inferior a la estimación, pero la cuenta sigue abierta.
Operación: decrement
| Transporte | Operación | Disponible |
|---|---|---|
| HTTP | /decrement | Sí |
| USB | decrement | Sí |
| Intent | //decrement | Sí |
Disponibilidad: Modo servicio.
Solicitud
| Campo | Tipo | Requisito | Notas |
|---|---|---|---|
| amount | Entero | Obligatorio | Importe retenido actualmente por la preautorización. |
| decrementAmount | Entero | Obligatorio | Importe que se va a liberar, en la unidad mínima de la moneda. |
| currencyCode | Entero | Obligatorio | Código numérico ISO 4217. |
| parentIdentifier | Cadena | Obligatorio | transaction_id de la preautorización. |
| stan | Cadena | Obligatorio | Tu UUID para esta operación. |
| authCode | Cadena | Opcional | Se obtiene del resultado de la preautorización. |
| refundId | Cadena | Opcional | Se obtiene del resultado de la preautorización. |
| date | Cadena | Opcional | Fecha de la operación original. |
| customer_ext_id | Cadena | Opcional | Tu identificador de cliente. |
Respuesta
Resultado de transacción con operative igual a DECREMENT.
10. Devolución
Devuelve dinero a la tarjeta utilizada en una venta anterior. Es necesario presentar la tarjeta.
Operación: refund
| Transporte | Operación | Disponible |
|---|---|---|
| HTTP | /refund | Sí |
| USB | refund | Sí |
| Intent | //refund | Sí |
Disponibilidad: Modo servicio.
Solicitud
| Campo | Tipo | Requisito | Notas |
|---|---|---|---|
| amount | Entero | Obligatorio | Importe que se va a devolver, en la unidad mínima de la moneda. |
| currencyCode | Entero | Obligatorio | Código numérico ISO 4217. |
| parentIdentifier | Cadena | Obligatorio | transaction_id de la venta original. |
| refundId | Cadena | Obligatorio | refund_id del resultado de la venta original. |
| stan | Cadena | Obligatorio | Tu UUID para esta operación. |
| date | Cadena | Condicional | Obligatorio en ECOPAYNET. |
| authCode | Cadena | Condicional | Obligatorio en ECOPAYNET. |
| customer_ext_id | Cadena | Opcional | Tu identificador de cliente. |
Ejemplo
POST /refund
{"amount":100,"currencyCode":978,
"parentIdentifier":"9c76341c-fcbd-492d-8b7a-ed14d0fc6a8d",
"refundId":"1248529069100765184",
"stan":"79f5ae33-cad9-45f4-983e-d7a9a8fc1cc9"}
11. Devolución sin tarjeta
Devuelve el importe de una venta anterior sin presentar la tarjeta, utilizando las credenciales de la transacción original.
Operación: referral
| Transporte | Operación | Disponible |
|---|---|---|
| HTTP | /referral | Sí |
| USB | referral | Sí |
| Intent | //referral | Sí |
Disponibilidad: Modo servicio.
Solicitud
Utiliza los mismos campos que la devolución: amount, currencyCode, parentIdentifier, refundId y stan son obligatorios; date y authCode son obligatorios en ECOPAYNET; customer_ext_id es opcional.
Respuesta
Resultado de transacción con operative igual a REFERRAL_REFUND.
Ejemplo
com.paynopain.sentinelservice://referral
?amount=100¤cyCode=978
&parentIdentifier=1e7da5d3-4aec-4f97-9029-4dce55216964
&refundId=1334440644315197440
&stan=234ec44e-a377-4380-a4fb-bf15933301e0
12. Anulación
Anula una venta el mismo día en que se realizó, antes de su liquidación. Es más económica y rápida que una devolución y no deja un abono por devolución en el extracto del titular.
Operación: reversal
| Transporte | Operación | Disponible |
|---|---|---|
| HTTP | /reversal | Sí |
| USB | reversal | Sí |
| Intent | //reversal | Sí |
Disponibilidad: Modo servicio.
Solicitud
| Campo | Tipo | Requisito | Notas |
|---|---|---|---|
| currencyCode | Entero | Obligatorio | Código numérico ISO 4217. |
| parentIdentifier | Cadena | Obligatorio | transaction_id de la venta que se va a anular. |
| refundId | Cadena | Obligatorio | refund_id del resultado de la venta original. |
| stan | Cadena | Obligatorio | Tu UUID para esta operación. |
| customer_ext_id | Cadena | Opcional | Tu identificador de cliente. |
No se envía amount: la anulación siempre afecta al importe original completo.
Respuesta
Resultado de transacción con operative igual a REVERSAL. En los terminales ECOPAYNET esta operación no está disponible y devuelve Operative not allowed.
13. Verificación de tarjeta
Lee y valida una tarjeta sin realizar ningún cargo y devuelve un token reutilizable.
Operación: cardverify
| Transporte | Operación | Disponible |
|---|---|---|
| HTTP | /cardverify | Sí |
| USB | cardverify | Sí |
| Intent | //cardverify | Sí |
Disponibilidad: Modo servicio.
Solicitud
| Campo | Tipo | Requisito | Notas |
|---|---|---|---|
| currencyCode | Entero | Obligatorio | Código numérico ISO 4217. |
| stan | Cadena | Obligatorio | Tu UUID para esta operación. |
| dni | Cadena | Opcional | Documento de identidad del titular. |
| reference | Cadena | Opcional | Referencia de texto libre. |
| customer_ext_id | Cadena | Opcional | Tu identificador de cliente. |
Respuesta
Resultado de transacción con operative igual a CARD_VERIFY, junto con los campos de token card_token, par y transaction_type. El importe es cero.
Ejemplo
POST /cardverify
{"currencyCode":978,"stan":"5ad8fb83-9540-4a46-bfaa-d0b3f9bbc196"}
14. CFT — abono a tarjeta
Abona dinero en la tarjeta de un beneficiario. El importe lo fija el backend a partir del token de la orden y el terminal lo confirma con la tarjeta.
Operación: cft
| Transporte | Operación | Disponible |
|---|---|---|
| HTTP | /cft | Sí |
| USB | cft | Sí |
| Intent | //cft | Sí |
Disponibilidad: Modo servicio.
Solicitud
| Campo | Tipo | Requisito | Notas |
|---|---|---|---|
| token | Cadena | Obligatorio | Token de la orden emitido por el backend. Determina el importe. |
| name | Cadena | Obligatorio | Nombre del beneficiario. |
| surname | Cadena | Obligatorio | Apellidos del beneficiario. |
| Cadena | Obligatorio | Correo electrónico del beneficiario. | |
| stan | Cadena | Obligatorio | Tu UUID para esta operación. |
15. Consulta de transacción
Consulta una transacción en el backend mediante su identificador.
Operación: transaction
| Transporte | Operación | Disponible |
|---|---|---|
| HTTP | /transaction | Sí |
| USB | transaction | Sí |
| Intent | //transaction | Sí |
Disponibilidad: Modo servicio.
Solicitud
| Campo | Tipo | Requisito | Notas |
|---|---|---|---|
| transactionId | Cadena | Obligatorio | Identificador de la transacción. |
| stan | Cadena | Obligatorio | Tu UUID para esta consulta. |
Respuesta
{
"id": "665d6dea126521c8926056ef",
"identifier": "919ff6d6-7727-4801-9035-9f57d2e8041a",
"merchant": "649c0329052f100dceea50e9",
"device": "64d1ef302ff0833b33ecffe6",
"operative": "AUTHORIZATION",
"status": "PAID",
"amount": 100,
"currency": "978",
"incoming": "DEVICE",
"integrator": "615d7d35be2246344cc49adf",
"integrator_external_id": "919FF6D6-7727-4801-9035-9F57D2E8041A",
"created_at": "2024-06-03T07:16:58.183Z",
"updated_at": "2024-06-03T07:16:58.384Z",
"historic": [{ "status": "PAID", "date": "2024-06-03T07:16:58.181Z" }]
}
16. Consulta de transacción por STAN
Recupera una operación mediante el STAN que generaste. Permite resolver un pago cuya respuesta no recibiste y obtener el resultado de un pago por QR.
Operación: transaction_by_stan
| Transporte | Operación | Disponible |
|---|---|---|
| HTTP | /transaction_by_stan | Sí |
| USB | transaction_by_stan | Sí |
| Intent | //transactionbystan | Sí |
Disponibilidad: Modo servicio.
El host del intent es transactionbystan, sin guiones bajos. La ruta HTTP y el tipo USB son transaction_by_stan, con guiones bajos.
Solicitud
| Campo | Tipo | Requisito | Notas |
|---|---|---|---|
| stan | Cadena | Obligatorio | El STAN que enviaste con la operación original. |
Respuesta mientras la operación sigue en curso
Sentinel responde desde su cola local de operaciones pendientes, por lo que informa de las operaciones en curso en lugar de indicarlas como inexistentes:
{
"identifier": "4ad6624f-8ad4-4ef7-8557-d41616770f63",
"operative": "AUTHORIZATION",
"amount": 100,
"currency": "978",
"incoming": "DEVICE",
"response_status": "Pending",
"response_message": "In progress",
"stan": "2fdf5900-22ae-46b1-8398-8fcda2bcce04"
}
Respuesta cuando la operación ha finalizado
El registro completo del backend, con el resultado de la operación con tarjeta dentro de result:
{
"id": "67a5f4e1d0a4c0353b3e04d6",
"identifier": "4ad6624f-8ad4-4ef7-8557-d41616770f63",
"merchant": "66e80b75a1a978f055c8fe07",
"device": "64d1ef302ff0833b33ecffe6",
"operative": "AUTHORIZATION",
"status": "PAID",
"amount": 100,
"currency": "978",
"incoming": "DEVICE",
"result": {
"aid": "A0000000031010",
"amount": 100,
"currency": "978",
"auth_code": "050107",
"brand": "VISA",
"pan": "476173******0119",
"reversal": false,
"date_terminal": "2025-02-07T11:56:17.836Z",
"date_server": "2025-02-07T11:56:17.836Z",
"response_status": "PAID",
"card_input": "CLESS",
"cardholder_method": ["[SIGNATURE]"],
"response_message": "OK: success",
"terminal_acquirer": "TPPESNA004",
"merchant_acquirer": "TPPESNA004",
"refund_id": "1337391474924330111",
"stan": "2fdf5900-22ae-46b1-8398-8fcda2bcce04"
},
"created_at": "2025-02-07T11:56:17.872Z",
"updated_at": "2025-02-07T11:56:18.452Z",
"historic": [{ "status": "PAID", "date": "2025-02-07T11:56:17.862Z" }]
}
17. Listado de transacciones
Recupera transacciones recientes para conciliar una caja o recuperarse de una interrupción, por ejemplo cuando se ha perdido el propio STAN y no es posible utilizar las consultas individuales.
Operación: list_transactions
| Transporte | Operación | Disponible |
|---|---|---|
| HTTP | /list_transactions | Sí |
| USB | list_transactions | Sí |
| Intent | — | No |
Disponibilidad: Modo servicio.
Solicitud
Todos los campos son opcionales; un cuerpo vacío devuelve las 50 transacciones más recientes.
| Campo | Tipo | Requisito | Notas |
|---|---|---|---|
| limit | Entero | Opcional | Por defecto, 50. Limitado a un máximo de 200. |
| dateFrom | Cadena | Opcional | Límite inferior. |
| dateTo | Cadena | Opcional | Límite superior. |
| status | Cadena | Opcional | Un valor de TransactionStatus. Si no se reconoce el valor, se devuelve un error con la lista de valores admitidos. |
Respuesta
{
"status": "OK",
"count": 2,
"limit": 50,
"truncated": false,
"transactions": [
{
"identifier": "919ff6d6-7727-4801-9035-9f57d2e8041a",
"amount": 100,
"remaining_amount": null,
"currency": "978",
"operative": "AUTHORIZATION",
"status": "PAID",
"created_at": "2026-08-31T09:14:22Z",
"auth_code": "478893",
"refund_id": "1305910960162082816",
"parent_id": null,
"pan": "476173******0119",
"reference": null,
"aid": "A0000000031010",
"brand": "VISA",
"tip_amount": 0,
"is_qr": false,
"token": null,
"customer_ext_id": null
}
]
}
Las fechas utilizan ISO-8601 en UTC. No hay paginación: truncated es true cuando se han devuelto exactamente limit filas, lo que indica que puede haber más. Acota la consulta con dateFrom y dateTo.
18. Informes
Totales del período que sigue abierto, equivalentes a un informe X. Esta operación es de solo lectura y no modifica datos.
Operación: reports
| Transporte | Operación | Disponible |
|---|---|---|
| HTTP | /reports | Sí |
| USB | reports | Sí |
| Intent | — | No |
Disponibilidad: Modo servicio.
Solicitud
Sin cuerpo.
Respuesta
{
"status": "OK",
"dateFrom": "2026-08-31 06:00:00",
"transactions": 42,
"totalAmount": 128400,
"authorizations": 38,
"totalAuthorizationsAmount": 131900,
"refunds": 2,
"totalRefundsAmount": 3500,
"deferred": 1,
"totalDeferredAmount": 5000,
"confirmations": 1,
"totalConfirmedAmount": 5000,
"cancelled": 0,
"totalCancelledAmount": 0
}
Todos los totales se expresan en la unidad mínima de la moneda y cubren las operaciones desde dateFrom, la fecha de corte establecida por el último cierre.
19. Cierre de lote
Cierra el período de caja, equivalente a un informe Z. Imprime el informe y actualiza la fecha de corte para que el siguiente informe comience donde termina este.
Operación: close_batch
| Transporte | Operación | Disponible |
|---|---|---|
| HTTP | /close_batch | Sí |
| USB | close_batch | Sí |
| Intent | — | No |
Disponibilidad: Modo servicio.
Solicitud
| Campo | Tipo | Requisito | Notas |
|---|---|---|---|
| Booleano | Opcional | Por defecto, true. Utiliza false para cerrar sin imprimir, por ejemplo si la caja imprime su propia copia. |
Respuesta
Los mismos totales que reports, con status igual a CLOSED y los campos adicionales cutoff y printed.
Esta operación no liquida el lote con el adquirente. La liquidación con el adquirente la inicia el backend. El cierre de lote realiza lo mismo que el botón de la aplicación: imprime el informe y actualiza la fecha de corte local. Es una operación de caja.
20. Reimpresión de recibo
Vuelve a imprimir un recibo o solicita al backend que lo emita como enlace. Puede utilizarse si se ha agotado el papel, el corte ha salido mal o el cliente vuelve más tarde a pedir una copia.
Operación: reprint
| Transporte | Operación | Disponible |
|---|---|---|
| HTTP | /reprint | Sí |
| USB | reprint | Sí |
| Intent | — | No |
Disponibilidad: Modo servicio.
Solicitud
| Campo | Tipo | Requisito | Notas |
|---|---|---|---|
| transactionId | Cadena | Opcional | Omítelo para reimprimir la transacción más reciente. La búsqueda se realiza entre las últimas 50. |
| copy | Cadena | Opcional | client (por defecto) o merchant. |
| giftTicket | Booleano | Opcional | Por defecto, false. Con true, esta impresión omite el subtotal, la propina y el total. No modifica la transacción ni las impresiones posteriores. |
| Cadena | Opcional | Envía el recibo por correo electrónico en lugar de imprimirlo y devuelve su URL. |
Respuesta
{"status":"PRINTED","identifier":"919ff6d6-…","copy":"client","giftTicket":false}
{"status":"SENT","identifier":"919ff6d6-…","email":"a@b.com","url":"https://…"}
{"status":"NOT_FOUND","message":"…"}
{"status":"ERROR","message":"El terminal no pudo imprimir (sin papel, sin impresora o error)"}
La impresora solo notifica cuando la impresión se completa correctamente. Si el terminal no tiene papel o impresora, devuelve ERROR al agotarse el tiempo de espera de impresión de 30 segundos.
Cada copia impresa incluye un código QR que contiene únicamente el UUID de la transacción. En la aplicación interactiva, el operador puede escanearlo desde la barra superior de Transacciones para recuperar y abrir esa transacción. El QR no contiene importes ni datos de tarjeta.
21. Comprobación de estado
Comprueba si el terminal está encendido y accesible mediante el transporte elegido. Es la única operación que responde con independencia del modo servicio.
Operación: healthcheck
| Transporte | Operación | Disponible |
|---|---|---|
| HTTP | /healthcheck | Sí |
| USB | healthcheck | Sí |
| Intent | //healthcheck | Sí |
Disponibilidad: Siempre disponible.
Respuesta
La cadena literal READY o NOT_READY, en texto plano.
Esta comprobación permite detectar la presencia del terminal. La caja necesita distinguir entre un terminal apagado o un cable desconectado y un terminal encendido sin el modo servicio activado. Para comprobar este último caso, solicita una operación y lee el error de modo servicio.
En USB, la comprobación de estado la atiende el hilo de lectura, por lo que sigue respondiendo mientras un pago espera la intervención del titular.
22. Identificación
Consulta la identidad del terminal. Suele ser la primera llamada de una integración: necesitas el identificador para conciliar tus recibos con los del backend y el número de serie para tu inventario.
Operación: identify
| Transporte | Operación | Disponible |
|---|---|---|
| HTTP | /identify | Sí |
| USB | identify | Sí |
| Intent | — | No |
Disponibilidad: Modo servicio.
Respuesta
{
"status": "OK",
"identifier": "352966108076163",
"serialNumber": "1853237957",
"model": "A920Pro",
"manufacturer": "PAX",
"appVersion": "4.0.8",
"operator": "MONET"
}
Un terminal cuya configuración no ha finalizado devuelve {"status":"ERROR","message":"Terminal sin identificador: falta configuración"}. operator indica si se aplican los campos condicionales de ECOPAYNET.
23. Sincronización
Envía las operaciones pendientes de la cola sin sincronizar. Si el terminal alcanza su límite de pendientes, rechaza todas las operaciones. En modo servicio puede no haber nadie delante del terminal para resolver esta situación manualmente.
Operación: sync
| Transporte | Operación | Disponible |
|---|---|---|
| HTTP | /sync | Sí |
| USB | sync | Sí |
| Intent | //sync | Sí |
Disponibilidad: Modo servicio.
Respuesta
{"status":"NOTHING_TO_SYNC","pendingBefore":0,"pendingAfter":0}
{"status":"SYNCED","pendingBefore":7,"pendingAfter":0}
{"status":"IN_PROGRESS","pendingBefore":7,"pendingAfter":3,"message":"…"}
{"status":"ERROR","message":"…","pendingBefore":7}
La sincronización inicia el envío, pero no espera a que termine. El terminal no puede saber cuándo ha finalizado el backend, por lo que informa del número de pendientes antes y después de una breve espera y devuelve la respuesta. IN_PROGRESS indica que el trabajo continúa en segundo plano: vuelve a intentar la operación y llama de nuevo a sync si sigue siendo rechazada. SYNCED no garantiza que todas las transacciones en cola hayan llegado al backend.
24. Datos del resultado de transacción
Datos que devuelve cada operación con tarjeta. Los nombres de los campos utilizan snake_case, con la única excepción de panExpiryDate.
| Campo | Tipo | Requisito | Notas |
|---|---|---|---|
| device | Cadena | Siempre | Identificador del terminal. |
| transaction_id | Cadena | Siempre | Identificador del backend. Utilízalo como parentIdentifier en operaciones posteriores. |
| stan | Cadena | Siempre | El STAN que enviaste. |
| operative | Operative | Siempre | Consulta §25. |
| amount | Entero | Siempre | Unidad mínima de la moneda. Incluye la propina cuando la hay. |
| tip_amount | Entero | Opcional | Parte de amount correspondiente a la propina. |
| currency | Cadena | Siempre | Código numérico ISO 4217, como cadena. |
| response_status | TransactionStatus | Siempre | Resultado de la operación. Consulta §25. |
| response_code | Cadena | Opcional | Código de respuesta del adquirente. |
| response_message | Cadena | Siempre | Resultado de la operación en un formato legible. |
| incoming | Incoming | Siempre | DEVICE o API. |
| auth_code | Cadena | Opcional | Código de autorización. Necesario para operaciones posteriores en ECOPAYNET. |
| refund_id | Cadena | Opcional | Necesario para devolver o anular esta transacción. Guárdalo. |
| parent_transaction_id | Cadena | Opcional | Se incluye en operaciones que hacen referencia a una anterior. |
| aid | Cadena | Opcional | Identificador de la aplicación EMV. |
| brand | Cadena | Opcional | Marca de la tarjeta. |
| pan | Cadena | Opcional | Número de tarjeta enmascarado. |
| panExpiryDate | Cadena | Opcional | Fecha de caducidad enmascarada. |
| card_input_type | CardInputType | Opcional | Cómo se leyó la tarjeta. Consulta §25. |
| cvm_type_list | Cadena | Opcional | Método de verificación del titular. |
| reversal | Booleano | Opcional | Indica si esta transacción se ha anulado. |
| date_terminal | Fecha | Opcional | Fecha y hora del terminal. |
| date_server | Fecha | Opcional | Fecha y hora del backend. Utilízala de forma preferente si difiere de la del terminal. |
| emv_response | Objeto | Opcional | Detalle EMV. |
| terminal_acquirer | Cadena | Opcional | Identificador de terminal del adquirente. |
| merchant_acquirer | Cadena | Opcional | Identificador de comercio del adquirente. |
| terminal_issuer | Cadena | Opcional | Identificador de terminal del emisor. |
| merchant_issuer | Cadena | Opcional | Identificador de comercio del emisor. |
| card_token | Cadena | Opcional | Token de tarjeta obtenido mediante una verificación de tarjeta. |
| additional_token | Cadena | Opcional | Token obtenido en una venta tokenizada, en cualquiera de las rutas de operador. |
| par | Cadena | Opcional | Referencia de cuenta de pago. |
| transaction_type | Cadena | Opcional | Tipo de transacción de la marca. |
| card_holder_message | Cadena | Opcional | Mensaje mostrado al titular. |
| invoice_number | Cadena | Opcional | Número de factura del adquirente. |
| reference | Cadena | Opcional | La referencia que enviaste. |
| customer_ext_id | Cadena | Opcional | El identificador de cliente que enviaste. |
24.1 Ejemplo — un euro, aprobado
{
"device": "352966108076163",
"transaction_id": "1876c5dd-3450-4f65-9ca4-872398aa61c6",
"stan": "cec60447-7467-4457-a542-40a791f11f02",
"operative": "AUTHORIZATION",
"amount": 100,
"currency": "978",
"response_status": "PAID",
"response_message": "success",
"incoming": "DEVICE",
"aid": "A0000000031010",
"auth_code": "478893",
"brand": "VISA",
"pan": "476173******0119",
"panExpiryDate": "****",
"card_input_type": "CLESS",
"cvm_type_list": "SIGNATURE",
"reversal": false,
"date_terminal": "Nov 12, 2024 04:03:44 PM",
"date_server": "Nov 12, 2024 04:03:48 PM",
"emv_response": { "smartCardScheme": 1, "authorisationResponseCode": "00" },
"terminal_acquirer": "TPPESNA004",
"merchant_acquirer": "TPPESNA004",
"refund_id": "1305910960162082816"
}
24.2 Ejemplo — un euro, rechazado
Un rechazo es una respuesta normal: se recibe como un resultado válido con un estado distinto de PAID. Evalúa response_status para decidir cómo continuar.
{
"device": "352966108076163",
"transaction_id": "e1d7a4b1-2a8a-43e6-be62-001154f0d2f4",
"stan": "6162ab8a-92ab-4d7d-8393-26d3fd6b666c",
"operative": "AUTHORIZATION",
"amount": 100,
"currency": "978",
"response_status": "REFUSED",
"response_message": "KO - refused",
"incoming": "DEVICE",
"aid": "A0000000041010",
"auth_code": "327674",
"brand": "MASTERCARD",
"pan": "****************",
"card_input_type": "CLESS",
"cvm_type_list": "NO",
"reversal": false,
"terminal_acquirer": "M1TPNP0005",
"merchant_acquirer": "TPNP0005",
"refund_id": "128937286421796"
}
25. Enumeraciones
Operative
| Valor | Significado |
|---|---|
| AUTHORIZATION | Venta. |
| DEFERRED | Preautorización. |
| CONFIRMATION | Captura de una preautorización. |
| CANCELLATION | Liberación de una preautorización. |
| DECREMENT | Liberación parcial de una preautorización. |
| DEFERRED_UPDATE | Ajuste de una preautorización. |
| REFUND | Devolución con tarjeta presente. |
| REFERRAL_REFUND | Devolución sin tarjeta presente. |
| REVERSAL | Anulación en el mismo día. |
| CARD_VERIFY | Validación de tarjeta sin cargo. |
| CFT | Abono a una tarjeta. |
| PAYOUT | Desembolso. |
| LIMITED_PAYMENT | Pago restringido. |
TransactionStatus
| Valor | Significado |
|---|---|
| PAID | Aprobado y liquidado localmente. Es el único valor que indica éxito. |
| REFUSED | Rechazado por el emisor o el adquirente. |
| PENDING | En curso; todavía no se conoce el resultado. |
| STARTED | Iniciado en el terminal. |
| CANCELLED | Cancelado antes de finalizar. |
| EXPIRED | Se ha agotado el tiempo de espera antes de finalizar. |
| ERROR | Ha fallado por un motivo técnico. |
| DUPLICATED | Rechazado por estar duplicado. |
CHIP_ERROR no es un estado de transacción. Aparecía en versiones anteriores de este documento, pero no es uno de los valores que puede devolver el SDK. Un fallo de chip se indica mediante ERROR y se detalla en response_message.
CardInputType
| Valores | Significado |
|---|---|
| CONTACT | Chip insertado. |
| CLESS | Sin contacto. |
| CLESS_MAGSTRIPE | Perfil de banda magnética sin contacto. |
| MAGNETIC | Lectura de banda magnética. |
| MAGNETIC_FALLBACK | Lectura de banda magnética tras un fallo del chip. |
| CHIP | Chip. |
| MANUAL | Introducida manualmente por el operador. |
| KEY_ENTRY | Entrada manual. |
| NON_PRESENTIAL | Tarjeta no presente. |
| UNKNOWN | El terminal no lo ha indicado. |
Incoming
DEVICE — iniciada en el terminal; incluye todas las operaciones de este documento. API — iniciada por el backend.
26. Integración mediante intents
26.1 Lanzamiento de una operación
const val PAYMENT_RESULT_CODE = 1001
val stan = UUID.randomUUID()
val uri = "com.paynopain.sentinelservice://payment" +
"?amount=100¤cyCode=978&stan=$stan"
startActivityForResult(Intent(Intent.ACTION_VIEW, Uri.parse(uri)), PAYMENT_RESULT_CODE)
26.2 Lectura del resultado
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode != PAYMENT_RESULT_CODE) return
when (resultCode) {
RESULT_OK -> {
// Same payload as the HTTP and USB transports return.
val result = data?.getStringExtra("transactionResult")
}
RESULT_CANCELED -> {
val errorMessage = data?.getStringExtra("error_message")
}
}
}
26.3 Hosts de intents disponibles
Todas las URI tienen el formato com.paynopain.sentinelservice://<host>?<query>. Los nombres de los parámetros de consulta coinciden con los campos JSON de la operación correspondiente.
payment confirmation transaction
preauthorization cancellation transactionbystan
refund decrement healthcheck
referral cardverify sync
reversal cft
Las operaciones que no aparecen en esta lista —listado de transacciones, informes, cierre de lote, reimpresión e identificación— solo están disponibles mediante HTTP y USB.
26.4 Comprobación previa de disponibilidad
val installed = try {
packageManager.getPackageInfo("com.paylands.posms.sentinel", 0)
true
} catch (e: PackageManager.NameNotFoundException) {
false
}
Comprueba el nombre del paquete al verificar la instalación. El esquema de intents utiliza un nombre distinto; consulta §2.
La información contenida en este documento es propiedad de PAYNOPAIN SL y no puede copiarse, utilizarse ni divulgarse, total o parcialmente, salvo con el consentimiento previo por escrito de PAYNOPAIN SL.