Pular para o conteúdo principal

Configuração do SDK

Guia de configuração e do fluxo de inicialização do SDK.

Ciclo de Uso

O fluxo de preparação do terminal segue estas etapas:

  1. Criar a instância de PosPinpad via create().
  2. (Opcional) Configurar os endpoints via setEndpointProvider().
  3. Buscar a personalização do parceiro via getTerminalConfig(slug).
  4. Registrar (register(...)) ou autenticar (authenticate(...)) o terminal.
  5. Inicializar o terminal via terminalInitialization(request) (carrega tabelas EMV).
  6. A partir daí, executar pagamentos e demais operações.

Inicialização

Criar instância do SDK

Implemente PosPinpadCallback e crie a instância passando o Context e o callback. Sempre use PosPinpad.create() — ele inicializa o HttpClient com mTLS antes de qualquer request.

import com.tupifintech.apossdk.sdk.api.PosPinpad
import com.tupifintech.apossdk.sdk.api.PosPinpadCallback

private lateinit var posPinpad: PosPinpad

posPinpad = PosPinpad.create(context, callback)

Configurar endpoints (EndpointProvider)

O SDK separa os endpoints administrativos (não-PCI) dos financeiros (PCI). Use setEndpointProvider() para apontar para o ambiente desejado:

import com.tupifintech.apossdk.sdk.api.EndpointProvider
import com.tupifintech.apossdk.sdk.api.setEndpointProvider

posPinpad.setEndpointProvider(
EndpointProvider(
adminBaseUrl = BuildConfig.ADMIN_BASE_URL, // autenticação, registro, tabelas, config, consultas
financialBaseUrl = BuildConfig.FINANCIAL_BASE_URL // pagamentos, estornos, PIX
)
)

Personalização do Parceiro

Antes do registro, busque a configuração do parceiro (white label). Ela traz a identidade visual, os IDs de escopo (que viram headers nas chamadas), o schema dinâmico de registro, os botões da dashboard e os documentos legais.

val config = posPinpad.getTerminalConfig(slug = "partner-slug")

// Identidade visual
applyTheme(config.partner.primaryColor)
loadLogo(config.partner.logoUrl)
setTitle(config.partner.brandName)

// Campos a renderizar na tela de registro
config.registrationSchema?.fields?.forEach { field ->
renderField(id = field.id, label = field.label, type = field.type)
}

Veja TerminalConfigResponse para a estrutura completa.

Registro e Autenticação

Há dois fluxos de credenciamento. O fluxo atual é CNPJ + Código de Verificação (register); o fluxo email + senha (authenticate) é mantido para reuso futuro.

Registro (CNPJ + Token)

Os fields são preenchidos pelo operador conforme o registrationSchema retornado em getTerminalConfig. A chave de cada campo é o id definido no schema (ex.: "cnpj", "token"). O registro vincula o terminal a um único merchant e retorna o merchantId usado na inicialização.

val registration = posPinpad.register(
fields = mapOf(
"cnpj" to operatorCnpj,
"token" to operatorToken
),
partnerSlug = "partner-slug"
)

if (!registration.success || registration.merchantId.isNullOrBlank()) {
showError(registration.error?.message ?: "Falha no registro do terminal.")
return
}

val merchantId = registration.merchantId!!

Autenticação (email/CNPJ + senha)

val response = posPinpad.authenticate(
AuthenticationRequest(
identifier = "email-ou-cnpj", // o SDK detecta o tipo automaticamente
password = "<senha>"
)
)

if (response.success) {
val user = response.user
}

Logout

posPinpad.logout()

Inicialização do Terminal

Com o merchantId em mãos, inicialize o terminal. Isso carrega as tabelas EMV e as configurações do adquirente. O resultado do carregamento de tabelas chega também por onTablesLoaded(ok).

import com.tupifintech.apossdk.sdk.api.model.TerminalInitializationRequest

val initResponse = posPinpad.terminalInitialization(
request = TerminalInitializationRequest(merchantId = merchantId)
)

// Dados do estabelecimento (header, recibo, senha de acesso)
val merchant = initResponse.merchant

Para verificar o estado depois:

val ready = posPinpad.isTerminalInitialized()
val tables = posPinpad.getTablesInfo() // versões das tabelas EMV por adquirente

Coordenadas do Teclado PIN

Importante: as coordenadas do teclado PIN não são configuradas antecipadamente. O SDK as solicita de forma reativa, durante o pagamento, pelo callback onStartGetPinCoordinates. O app deve medir as posições dos botões na tela e devolvê-las pela função recebida.

override fun onStartGetPinCoordinates(setPinCoordinates: (List<String>) -> Unit) {
// Exiba a tela de PIN, meça os botões e chame setPinCoordinates(coords)
showPinScreen(onCoordinatesReady = { coords -> setPinCoordinates(coords) })
}

Formato e ordem da lista

Cada item é uma string "left,top,right,bottom" em pixels (posição na janela). A ordem esperada é:

ÍndiceTecla
0–8Números 1 a 9
9Número 0
10CANCELAR
11OK / Confirma
12Backspace

No Compose, as coordenadas podem ser obtidas com onGloballyPositioned + positionInWindow(). Veja o exemplo completo em Exemplos.

Informações do Dispositivo

val info = posPinpad.getDeviceInfo()
Log.d("YBY", "Modelo: ${info.hardwareModel}")
Log.d("YBY", "Serial: ${info.serialNo}")
Log.d("YBY", "Firmware: ${info.firmwareVersion}")

Health Check

val health = posPinpad.checkInternetConnection()
if (!health.isConnected) {
showError(health.errorMessage ?: "Sem conexão")
}

Boas Práticas

Tratamento de erros

Implemente os callbacks de erro (onAppError, onNetworkConnectionError, onUnauthorizedError, onSessionExpired, etc.). Veja Callbacks.

override fun onAppError(error: SdkErrorCode, message: String) {
Log.e("YBY", "Erro ${error.name} (${error.code}): $message")
showErrorDialog(message)
}

override fun onNetworkConnectionError() {
showErrorDialog("Sem conexão com a internet")
}

Dados sensíveis

Nunca registre em log dados de pagamento (PAN, PIN, track) nem a accessPassword do merchant.

Próximos Passos