Implementar os serviços de hardware
Este guia mostra as chamadas exatas que a Middleware App e o Devkit fazem contra sua Manufacturer Service App, serviço por serviço. Use-o para confirmar que sua implementação responde como o software da Getnet espera.
Como funciona
Todas as chamadas abaixo chegam ao seu serviço por mainService, o stub IMainService que a Middleware App obtém depois de se vincular ao seu serviço. Cada serviço — cartão, impressora, beeper e assim por diante — está vinculado ao mainService como uma propriedade própria. A maioria das operações reporta seu resultado por um callback, e não por um valor de retorno.
Antes de começar
Conclua a configuração da integração HAL para que seu serviço se vincule corretamente e execute o Devkit para testar cada chamada conforme a implementa.
Beeper
O Devkit chama custom com uma duração em milissegundos:
mainService.beeper.custom(500) // 500 millisecondsSua implementação de IBeeperService também deve suportar quatro sons nomeados, cada um com duração fixa:
| Som | Duração |
|---|---|
success | Bipe de 500 ms. |
error | Bipe de 1000 ms. |
digit | Bipe de 100 ms. |
nfc | Bipe de 100 ms, pausa de 300 ms, bipe de 100 ms. |
Cartão
Obtenha o serviço de cartão uma vez e depois chame o método de busca correspondente ao tipo de leitura que quem chama precisa:
val cardService = mainService.cardCada tipo de busca usa uma constante fixa:
| Constante | Valor |
|---|---|
MAG | "1" |
CHIP | "2" |
NFC | "3" |
Busca 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()
}
})A busca por tarja magnética devolve track1, track2 e track3 em onCard, em vez de pan. A busca NFC devolve o mesmo formato de CardResponse que a busca por chip.
As duas seguem o mesmo padrão onCard / onMessage / onError, e as duas devem chamar stopAllReaders() assim que um resultado chega.
Mifare
O IMifareService cobre presença de cartão, autenticação e leitura/escrita em nível de bloco:
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 */ }
})A autenticação de setor e de bloco recebe uma chave 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)Depois da autenticação, seu serviço deve suportar decrement, increment, readBlock, restore, transfer e writeBlock sobre um índice de bloco dado. Também deve suportar close, isExist, activate e halt para controle de sessão. getCardSerialNo devolve o UID do cartão como string hexadecimal.
LED
O ILedService expõe um par liga/desliga por cor — vermelho, azul, amarelo e verde:
mainService.led.turnOnRed()
mainService.led.turnOffRed()Implemente o mesmo par para azul, amarelo e verde.
Impressora
Todo método de IPrinterService deve lançar IllegalStateException se seu serviço ainda não tiver inicializado a impressora:
mainService.printer?.init()
?: throw IllegalStateException("service isn't initiated")Uma vez inicializada, seu serviço monta um trabalho de impressão a partir de uma sequência de chamadas — addText, addBarCode, addQrCode, addImageBitmap, addImageByteArray — seguida de print ou 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 define o nível de escala de cinza, e defineFontFormat define a fonte ativa. Consulte a referência de interfaces de serviço para as especificações fixas de impressora — tamanho de imagem, limites de caracteres e o limiar de escala de cinza que seu serviço deve aplicar.
Câmera
readFront lê a câmera frontal com um tempo limite e reporta o resultado por um 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 */ }
},
)Estatísticas do sistema
O IStatService reporta as contagens de sucesso e de falha por tipo de leitura, tanto no dispositivo inteiro quanto por aplicação chamadora:
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 */ }
})Alguns métodos HAL, como print(userId, callback) e searchMag(userId, timeout, callback), recebem um parâmetro userId que identifica a aplicação chamadora. Resolva-o para um nome de pacote com packageManager.getNameForUid(userId). Use esse nome de pacote para atribuir as estatísticas à aplicação correta.
Ler o resultado
Uma implementação correta sempre reporta os eventos de hardware pelo callback de quem chama, nunca só por um valor de retorno. Ela também chama stopAllReaders() depois que uma leitura de cartão termina, tendo tido sucesso ou não.
Os métodos de impressora são a única exceção que merece menção própria: qualquer um deles chamado antes de init() deve lançar IllegalStateException em vez de falhar em silêncio.
Próximos passos
- Enviar sua integração para validação — assim que todas as chamadas acima responderem corretamente.
- Referência de interfaces de serviço — assinaturas completas de método, incluindo as interfaces que não aparecem aqui.
- Máquina de estados EMV — o fluxo que segue uma leitura de cartão por chip ou contactless bem-sucedida.