# 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](/pt/pos-manufacturers/first-steps-pos-mfg/hal-integration-setup) para que seu serviço se vincule corretamente e execute o [Devkit](/pt/pos-manufacturers/first-steps-pos-mfg/quick-start-devkit) para testar cada chamada conforme a implementa.

## Beeper

O Devkit chama `custom` com uma duração em milissegundos:

```kotlin
mainService.beeper.custom(500) // 500 milliseconds
```

Sua 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:

```kotlin
val cardService = mainService.card
```

Cada tipo de busca usa uma constante fixa:

| Constante | Valor |
| :--- | :--- |
| `MAG` | `"1"` |
| `CHIP` | `"2"` |
| `NFC` | `"3"` |

Busca por chip:

```kotlin
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:

```kotlin
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:

```kotlin
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:

```kotlin
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:

```kotlin
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`:

```kotlin
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](/pt/pos-manufacturers/reference-pos-mfg/service-interfaces) 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:

```kotlin
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:

```kotlin
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](/pt/pos-manufacturers/how-to-guides-pos-mfg/submit-integration-for-validation) — assim que todas as chamadas acima responderem corretamente.
* [Referência de interfaces de serviço](/pt/pos-manufacturers/reference-pos-mfg/service-interfaces) — assinaturas completas de método, incluindo as interfaces que não aparecem aqui.
* [Máquina de estados EMV](/pt/pos-manufacturers/core-concept-pos-mfg/emv-state-machine) — o fluxo que segue uma leitura de cartão por chip ou contactless bem-sucedida.