Cambios FISERV · 11 y 12 de noviembre de 2026
UltraHost, modelo de pinpad FISERV: consultas y anulación de compra. Release UltraHost 20261112. APIDRIVER no cambia (sigue en v20261103b).
Resumen
| Commit | Contenido |
|---|---|
5148266 | refactor: extrae la lógica de anulación y consultas de PRISMA para reutilizarla. Sin cambio de comportamiento. |
67d44e1 | feat: consultas y anulación de compra en el modelo FISERV. |
UltraHost.exe y reiniciar. No requiere cambios de base de datos ni de UltraHost.ini.Cambios
Antes
Con MODELO=FISERV, UltraHost solo aceptaba identificación de compra, compra y sincronización de pinpad. Cualquier otra operación respondía Operacion no implementada para modelo FISERV.
Consultas
| Endpoint (APIDRIVER) | Operación | Comportamiento |
|---|---|---|
/consulta_operacion | CONSULTA_OPERACION (135) | Una sola llamada, sin pinpad. Misma lógica que PRISMA. |
/consulta_ultimas_operaciones | ULTIMASOPERACIONES (122) | Una sola llamada, sin pinpad. Hasta CANTIDAD_CONSULTA_ULT_OPER operaciones. |
Anulación de compra
| Paso | Endpoint (APIDRIVER) | Qué hace |
|---|---|---|
| 1 | /identificacion_anulacion_compra_online | Lee la tarjeta (Y41 con ENCRIPTA=2, Y01 si no; luego Y02) y busca la compra original. |
| 2 | /autorizacion_anulacion_compra_online | Autoriza la anulación con FISERV. En chip manda Y03, tanto si se aprueba como si se rechaza. |
- Control de tarjeta: la tarjeta leída debe coincidir con la de la compra original en emisor y últimos 4 dígitos, como en POSDINO (
pos_cara.cpp:361-370). Si no coincide, error 241. Si la compra original no tiene guardados los últimos 4, no se controla. - Manda la autorización: una anulación que FISERV aprueba queda aprobada, responda lo que responda el chip al
Y03. No se reversa. - Importe: debe ser el total de la compra original. No se aceptan anulaciones parciales ni un cashback distinto.
- Sin
Y07: en el manual FISERV,Y07es "mostrar mensaje y leer tecla", no un advice.
Robustez
- Identificación pendiente: la lectura se graba con
iNroMensaje=124y pasa a 120 recién cuando la lectura se completa. Una identificación incompleta o fallida nunca habilita una anulación (error 270). Las filas de error de la identificación también se graban con 124. - Borrado de identificaciones previas: ocurre recién después del control de tarjeta, y si falla corta con error 137.
- Host caído: el POS recibe 28, el chip recibe
Y03conCRE 02,ORH 0yRCP N, y la reversa sale cuando el host vuelve. - Sincro dentro de la anulación: si falla, el POS sigue recibiendo el
idtrxtiprede la compra original. - Log: dice si falló el control de emisor o el de últimos 4 dígitos, sin mostrar dígitos.
- Compra por chip sin respuesta del autorizador: el
Y03llevaRCP N, alineado con POSDINO (pos_ppfd.cpp:4267).
Reutilización de PRISMA
La lógica sin pinpad de PRISMA se extrajo a funciones que ahora usan los dos modelos: ValidarOriginalAnulacion, AutorizarAnulacionCompra, ArmarRespuestaAnulacionAprobada, ConsultaOperacion_SinPinPad y ConsultaUltOps_SinPinPad. FISERV agrega solo lo que depende del pinpad. Una revisión estática línea por línea confirmó que PRISMA hace exactamente lo mismo que antes.
Formato de los requests
Es el mismo JSON que manda el POS a APIDRIVER. Las respuestas del pinpad (datosPinPad) las agrega APIDRIVER, no el POS.
Consulta de operación
{
"datosPos": { "sucursal": 101, "nroPos": 1, "nroTicket": 9999 },
"datosHost": { "idtrxtipre": 4321 }
}
Últimas operaciones
{ "datosPos": { "sucursal": 101, "nroPos": 1 } }
Anulación (los dos pasos, con el mismo ticket de la anulación)
{
"datosPos": { "sucursal": 101, "nroPos": 1, "nroTicket": 5001,
"importe": "100.00", "importe_cashback": "0.00", "documento": "12345678" },
"datosHost": { "idtrxtipre": 4321 }
}
En el paso 1, idtrxtipre es el de la compra a anular. En el paso 2 se manda el que devolvió la identificación.
Pruebas
Simulación local, sin QA ni pinpad real: UltraHost en consola contra la base local UltraHost_Homologaciones, el simulador de autorizador FirstData en 127.0.0.1:28200 y un script Python que hace de APIDRIVER y de pinpad con datos de tarjeta sintéticos. Está en C:\Work\AI\FISERV\sim_fiserv\.
| Grupo | Qué cubre | Resultado |
|---|---|---|
| Compras | Compra aprobada y rechazada, y compra por chip con Y03: aprobada, rechazada con 51 y sin respuesta del host. | OK |
| Consultas | Operación existente, inexistente, campos faltantes, otra sucursal o POS, tope de 15 y operaciones rechazadas. | OK |
| Anulación | Banda, manual, chip y contactless, con ENCRIPTA=0 y ENCRIPTA=2. También segunda anulación, reimpresión y lote cerrado. | OK |
| Anulación, casos negativos | Original inexistente, otra tarjeta, otro importe, original rechazada, errores de pinpad en cada paso y rechazo del host. | OK |
| Últimos 4 dígitos | Misma tarjeta aceptada; mismo emisor con otros 4 dígitos rechazado (241), en todos los modos de lectura. | OK |
| Robustez | Host caído durante la anulación, cashback, pedidos simultáneos, reintentos, V04 y filas de error con borrado fallido. | OK |
| Comparación con PRISMA | Las mismas pruebas sobre PRISMA antes y después del cambio, y sobre FISERV, comparando las respuestas campo por campo. | OK |
Revisiones
| Revisión | Resultado |
|---|---|
| Equivalencia de PRISMA | Sin hallazgos Todas las funciones extraídas son equivalentes. |
| Riesgo | Sin bloqueantes Hallazgo medio abierto: no hay límite de intentos de identificación. |
| Resiliencia | Sin bloqueantes Los dos hallazgos medios están arreglados. |
| Legibilidad | Sin bloqueantes Comentarios, helper único y enum arreglados. |
| Confiabilidad de las pruebas | Resuelta Se agregaron los casos que faltaban. |
| Revisión final de los arreglos | Sin bloqueantes El hallazgo medio (fila de error 120) está arreglado y tiene su prueba. |
Pendientes
- Pinpad real en QA: sobre todo una anulación por chip.
- Límite de intentos de identificación: decisión de negocio. Hoy quien conozca un
idtrxtiprepuede probar finales de tarjeta sin límite. - Doble anulación simultánea: se bloquea en las pruebas (6 rondas), pero no está demostrado que el bloqueo sea atómico.
- V04 con pinpad real: ver el Anexo B.
- Mensajes de
Y0E: hoy dicen solo el número. Ver el Anexo A. - Código 124: la marca de pendiente reutiliza el número de
posOp_PERMITEEXTRACCION. Se aceptó así.
Anexo A · Errores que recibe el POS
Todos llegan en datosHost.codigo_resultado y mensaje_resultado. Ante cualquier código distinto de 0, APIDRIVER manda Y06 para liberar el pinpad.
A.1 · El pinpad responde Y0E
Código al POS = 1000 + código del pinpad. Mensaje: ERROR EN PINPAD (NN). El código extendido (CEX) solo va al log.
- Manuales: V02 y V04 tienen la misma tabla, del 01 al 09 y del 12 al 39, y el mismo formato
Y0E+ comando recibido (3) + código (2) + extendido opcional. - Código: UltraHost lee el código en la misma posición para los dos protocolos y responde 1000 + código para cualquier valor, así que todos quedan contemplados, incluso los que no figuran en el manual. POSDINO hace lo mismo (
pos_ppfd.cpp:2579-2587) y además usa el código 11, error de LRC, que no está en el manual. - Fuera del
Y03: elY0Ese trata igual en cualquier paso: lectura,Y02, sincro e identificación de anulación. - Después del
Y03: elY0Eno cambia el resultado (ver A.4). - Diferencia con POSDINO: POSDINO muestra la descripción en pantalla (
ShowErrorPinPad); UltraHost solo devuelve el número.
| Al POS | Pinpad | Significado (manual) |
|---|---|---|
| 1001 | 01 | Cancelado |
| 1002 | 02 | Error en el ingreso de los últimos 4 dígitos |
| 1003 | 03 | Error de lectura del track 2 |
| 1004 | 04 | Error al ingresar el PIN |
| 1005 | 05 | Error de chip |
| 1006 | 06 | Fecha inválida |
| 1007 | 07 | Timeout |
| 1008 | 08 | Error en la secuencia de comandos |
| 1009 | 09 | Error en el formato del comando |
| 1011 | 11 | Error de LRC (lo usa POSDINO, no figura en el manual) |
| 1012 | 12 | Error al eliminar el registro |
| 1013 | 13 | Registro no encontrado |
| 1014 | 14 | Error de desencripción |
| 1015 | 15 | Error de encripción |
| 1016 | 16 | Falta la definición por Y00 |
| 1017 | 17 | Falta la posición de la master key |
| 1018 | 18 | Falta la working key |
| 1019 | 19 | Falta la master key |
| 1020 | 20 | Debe sincronizar |
| 1021 | 21 | Error de protocolo (por ejemplo, una versión V02/V04 que no coincide) |
| 1022 | 22 | Funcionalidad no disponible (solo PP) |
| 1023 | 23 | Sin papel (solo POS) |
| 1024 | 24 | Error en el formato de línea (solo POS, comando Y05) |
| 1025 | 25 | Error contactless: intente por chip |
| 1026 | 26 | Error en la longitud del certificado |
| 1027 | 27 | Ticket no encontrado |
| 1028 | 28 | Formato de DNI inválido |
| 1029 | 29 | Error de autenticación de archivo |
| 1030 | 30 | Clave RSA disponible |
| 1031 | 31 | Clave RSA ausente |
| 1032 | 32 | Dato inválido |
| 1033 | 33 | Ticket pendiente de envío |
| 1034 | 34 | Retire la tarjeta del lector de chip |
| 1035 | 35 | Error al imprimir y al generar el archivo (solo POS) |
| 1036 | 36 | Cancelado con Y06 |
| 1037 | 37 | Reintentar por banda |
| 1038 | 38 | Terminal ocupada |
| 1039 | 39 | Reintentar EMV (chip o contactless) |
A.2 · Errores que genera APIDRIVER (YEE)
Código 99, con el texto que manda APIDRIVER:
| Mensaje | Causa |
|---|---|
Error PinPad: Existe operacion previa usando puerto serie: COMx | Hay otra operación en curso sobre el puerto. |
Error PinPad: No se pudo abrir el puerto de comunicacion: COMx | Pinpad desenchufado o COM cambiado. |
Error PinPad: Al enviar datos | Falló la escritura al puerto. |
Error PinPad: al esperar ACK luego de envio de datos | El pinpad no confirmó la trama (5 intentos). |
Error PinPad: No se recibe respuesta | Venció el timeout del comando. |
A.3 · Otras respuestas del pinpad
| Código | Mensaje | Cuándo |
|---|---|---|
| 269 | OPERACION CANCELADA EN PINPAD (Y06) | Llega el ack de un Y06 fuera del Y03. |
| 269 | ERROR DENEGADA_POR_PINPAD | El chip deniega con Z1 en la lectura (contactless). |
| 266 | ERROR_COMANDO_PINPAD_NO_ESPERADO | El comando no corresponde al paso. Hay variantes con texto propio: Respuesta Y41/Y00/S00/S01 invalida del pinpad, Pinpad rechazo la sincronizacion (S02) y Contactless sin EPT no soportado. |
| 265 | ERROR_COMANDO_PINPAD_NO_SOPORTADO | El pinpad devolvió un comando que FISERV no maneja. |
| 264 | ERROR_SINCRO_FALTAN_DATOS_IDE | En la sincro faltan los datos del IDE. |
| 262 | ERROR_FALTA_ID_ENCRIPCION | En la sincro falta el ID de encripción. |
A.4 · Anulación
| Código | Mensaje | Cuándo |
|---|---|---|
| 241 | ERROR DIFIERE TARJETA TRX ORIGINAL | No coinciden el emisor o los últimos 4 dígitos. El log dice cuál de los dos. |
| 121 | ERROR EMISOR DESCONOCIDO | No se pudo resolver el emisor de la tarjeta. |
| 270 | NO_ID_ANULACION | Se autoriza sin una identificación completa. |
| 137 | ERROR_SQL_CONNECT | Falló el borrado de las identificaciones previas. |
Respuestas al Y03 que no son error: después de que FISERV aprobó, cualquier respuesta (Z3, Y0E, YEE, Y06 o vacía) deja la operación aprobada. Si el host rechazó, el POS recibe el código del host y no el del pinpad.
A.5 · Errores propios de APIDRIVER
| Código | Mensaje |
|---|---|
| 998 | Error: No responde/faltan datos UltraHost |
| 997 | Error: No hay datos recibidos de UltraHost para enviar al PinPad! |
Anexo B · Bloque de claves del Y02 en V04
La tabla de campos del manual es igual en V02 y V04: PMK(1) LWK(1) WKP(1..48) <FS> WKD(1..48) <FS>.
| Bloque sin claves | PMK | LWK | |
|---|---|---|---|
| Ejemplo del manual | NNN<FS>N<FS> | N | N |
| UltraHost | 02N<FS>N<FS> | 0 | 2 fijo |
- Especificación: los dos son válidos según la tabla. El código se aparta del ejemplo, no de la especificación, y varios ejemplos del manual están mal armados (les falta
WKDy el segundo<FS>). - V02: este formato ya funciona con el pinpad real (compras por chip en QA).
- V04: nunca se probó con el pinpad real. Si el
Y02respondeY0E, el ajuste aNNcuando no hay claves es de una línea enComandoY02.