Implementar los servicios de hardware
Esta guía muestra las llamadas exactas que la Middleware App y el Devkit hacen contra tu Manufacturer Service App, servicio por servicio. Úsala para confirmar que tu implementación responde como el software de Getnet espera.
Cómo funciona
Todas las llamadas de abajo llegan a tu servicio a través de mainService, el stub IMainService que la Middleware App obtiene tras vincularse a tu servicio. Cada servicio — tarjeta, impresora, beeper, etc. — cuelga de mainService como una propiedad propia. La mayoría de las operaciones informan de su resultado mediante un callback, no mediante un valor de retorno.
Antes de empezar
Completa la configuración de la integración HAL para que tu servicio se vincule correctamente, y luego ejecuta el Devkit para probar cada llamada a medida que la implementas.
Beeper
El Devkit llama a custom con una duración en milisegundos:
mainService.beeper.custom(500) // 500 millisecondsTu implementación de IBeeperService también debe soportar cuatro sonidos con nombre, cada uno con una duración fija:
| Sonido | Duración |
|---|---|
success | Pitido de 500 ms. |
error | Pitido de 1000 ms. |
digit | Pitido de 100 ms. |
nfc | Pitido de 100 ms, pausa de 300 ms, pitido de 100 ms. |
Tarjeta
Obtén el servicio de tarjeta una vez y luego llama al método de búsqueda que corresponda al tipo de lectura que necesita quien llama:
val cardService = mainService.cardCada tipo de búsqueda usa una constante fija:
| Constante | Valor |
|---|---|
MAG | "1" |
CHIP | "2" |
NFC | "3" |
Búsqueda por chip:
cardService.searchChip(1000, object : ICardCallback.Stub() {
override fun onCard(cardResponse: CardResponse?) {
val pan = cardResponse?.pan
cardService.stopAllReaders()
}
override fun onMessage(message: String?) {
cardService.stopAllReaders()
}
override fun onError(error: String?) {
cardService.stopAllReaders()
}
})La búsqueda por banda magnética devuelve track1, track2 y track3 en onCard en lugar de pan. La búsqueda NFC devuelve la misma forma de CardResponse que la búsqueda por chip.
Ambas siguen el mismo patrón onCard / onMessage / onError, y ambas deben llamar a stopAllReaders() en cuanto llega un resultado.
Mifare
IMifareService cubre la presencia de tarjeta, la autenticación y la lectura/escritura a nivel de bloque:
mainService.mifare.searchCard(object : IMifareCallback.Stub() {
override fun onCard(type: Int) { /* card type detected */ }
override fun onError(error: String?) { /* handle error */ }
})
mainService.mifare.searchCardAndActivate(object : IMifareActivateCallback.Stub() {
override fun onActivate(key: ByteArray?) { /* card activated */ }
override fun onError(error: String?) { /* handle error */ }
})La autenticación de sector y de bloque toma una clave de 6 bytes:
val key = byteArrayOf(0xff.toByte(), 0xff.toByte(), 0xff.toByte(), 0xff.toByte(), 0xff.toByte(), 0xff.toByte())
mainService.mifare.authenticateSectorWithKeyA(sector = 2, key)
mainService.mifare.authenticateBlockWithKeyA(block = 10, key)
mainService.mifare.authenticateSectorWithKeyB(sector = 2, key)
mainService.mifare.authenticateBlockWithKeyB(block = 10, key)Tras la autenticación, tu servicio debe soportar decrement, increment, readBlock, restore, transfer y writeBlock sobre un índice de bloque dado. También debe soportar close, isExist, activate y halt para el control de sesión. getCardSerialNo devuelve el UID de la tarjeta como cadena hexadecimal.
LED
ILedService expone un par encendido/apagado por color — rojo, azul, amarillo y verde:
mainService.led.turnOnRed()
mainService.led.turnOffRed()Implementa el mismo par para azul, amarillo y verde.
Impresora
Todos los métodos de IPrinterService deben lanzar IllegalStateException si tu servicio aún no ha inicializado la impresora:
mainService.printer?.init()
?: throw IllegalStateException("service isn't initiated")Una vez inicializada, tu servicio construye un trabajo de impresión a partir de una secuencia de llamadas — addText, addBarCode, addQrCode, addImageBitmap, addImageByteArray — seguida de print o printAndRemovePaper:
mainService.printer?.addText(align, text)
mainService.printer?.print(object : IPrinterCallback.Stub() {
override fun onSuccess() { /* job printed */ }
override fun onError(cause: Int) { /* map cause to a status */ }
})setGray fija el nivel de escala de grises, y defineFontFormat fija la fuente activa. Consulta la referencia de interfaces de servicio para las especificaciones fijas de impresora — tamaño de imagen, límites de caracteres y el umbral de escala de grises que tu servicio debe aplicar.
Cámara
readFront lee la cámara frontal con un tiempo de espera e informa del resultado mediante un callback:
mainService.camera.readFront(
timeout = 2000,
callback = object : ICameraCallback.Stub() {
override fun onSuccess(code: String?) { /* code read */ }
override fun onTimeout() { /* no result within timeout */ }
override fun onCancel() { /* caller canceled the read */ }
override fun onError(error: String?) { /* handle error */ }
},
)Estadísticas del sistema
IStatService informa de los recuentos de éxito y de fallo por tipo de lectura, tanto a nivel de dispositivo como por aplicación llamante:
mainService.stats.getAllStatisticsByApp(object : IStatCallback.Stub() {
override fun onStatistic(statResponse: StatResponse?) {
val paperStatus = statResponse?.generalPaperStatus
val mifareStatus = statResponse?.generalMifareStatus
}
override fun onError(error: String?) { /* handle error */ }
})Algunos métodos HAL, como print(userId, callback) y searchMag(userId, timeout, callback), reciben un parámetro userId que identifica a la aplicación llamante. Resuélvelo a un nombre de paquete con packageManager.getNameForUid(userId). Usa ese nombre de paquete para atribuir las estadísticas a la aplicación correcta.
Leer el resultado
Una implementación correcta informa siempre de los eventos de hardware por el callback de quien llama, nunca solo por un valor de retorno. También llama a stopAllReaders() cuando termina una lectura de tarjeta, tanto si tuvo éxito como si no.
Los métodos de impresora son la única excepción que merece mención propia: cualquiera de ellos llamado antes de init() debe lanzar IllegalStateException en lugar de fallar en silencio.
Próximos pasos
- Enviar tu integración para validación — cuando todas las llamadas anteriores respondan correctamente.
- Referencia de interfaces de servicio — firmas completas de métodos, incluidas las interfaces que no aparecen aquí.
- Máquina de estados EMV — el flujo que sigue a una lectura de tarjeta por chip o contactless con éxito.