Pular para o conteúdo principal

Homologação

Antes de ir a campo, execute cada cenário num terminal de homologação com o app host ativado. Os cenários de falhas e recuperação são os que evitam cobrança em dobro e fraude.

Checklist​

Preparação​

  • verifyHost retorna Trusted com o host oficial instalado.
  • Com o host desinstalado, o app detecta NotInstalled e não libera o pagamento.
  • A primeira operação sem credenciamento recebe unauthorized_caller e o app dispara requestAuthorization.
  • A recusa do credenciamento (authorization_denied) não é repetida automaticamente.
  • Builds debug e release foram credenciados separadamente.
  • Com o terminal não ativado, o app oferece a ativação e dispara activateTerminal; concluída, terminalStatus passa a responder initialized = true.
  • Cancelar o formulário de ativação no terminal devolve cancelled, e o app continua oferecendo a ativação.
  • Num terminal já ativado, activateTerminal responde approved sem abrir formulário.
  • As telas de pagamento mostram o logo (ou nome) e a cor do parceiro cadastrados no portal.

Operações​

  • Venda no crédito à vista, parcelada sem juros e parcelada com juros.
  • Venda no débito.
  • Venda com voucher, exibindo o saldo quando voucherBalanceInCents vier preenchido.
  • Venda por Pix aprovada e Pix não pago dentro do prazo.
  • Venda recusada pelo emissor mostra error.message.
  • Cancelamento pelo botão Cancelar do terminal durante a espera do cartão volta ao carrinho.
  • Estorno total e parcial com transactionId, e estorno escolhendo a transação na tela.
  • Estorno de voucher informando paymentMethod = VOUCHER.
  • Impressão livre com texto, colunas, QR Code e imagem por content://.
  • Reimpressão das vias do lojista e do cliente.
  • terminal_status e list_transactions com paginação por nextCursor.

Falhas e recuperação​

  • O clientTransactionId é persistido antes do launch.
  • O seu app é encerrado à força durante a autorização; ao reabrir, recupera o desfecho e não cobra de novo.
  • Uma resposta no_response leva à recuperação, nunca a uma nova cobrança direta.
  • Durante uma venda, uma segunda operação recebe busy e o app aguarda.
  • Um duplo toque no botão de pagar gera uma única cobrança (a segunda Intent recebe busy).
  • Depois de um operation_timeout, o app recupera o desfecho e, se ainda vier operation_timeout passados 2 minutos, confirma por list_transactions ou pelo portal antes de cobrar de novo.
  • Terminal sem rede: a venda volta com erro e a mensagem é exibida ao operador.
  • As decisões são tomadas por status e error.code, nunca por resultCode ou pelo texto de message.

Problemas comuns​

SintomaCausa provávelSolução
ActivityNotFoundException ao dispararHost não instalado, ou app sem visibilidade do pacote no Android 11+Instalar o host; usar o contrato, que já declara <queries>
Toda operação volta unauthorized_callerApp não credenciadoCredenciar com requestAuthorization
O app não recebe resposta nenhumaIntent disparada com startActivityDisparar com ActivityResultLauncher ou startActivityForResult
malformed_request numa Intent montada sem o PosIntegrationClientAction diferente da família da operação, ou clientTransactionId vazioUsar a action da tabela de operações e gerar um id por requisição
Funcionava em debug e parou em releaseAssinaturas diferentes, cada uma com seu credenciamentoCredenciar o build de release
terminal_not_initializedTerminal não ativado, ou sem rede para carregar as tabelasAbrir a ativação com activateTerminal(); se o terminal já estiver cadastrado, verificar a rede dele
Formulário de ativação ou telas com título, logo ou cor de outro parceiroApp host gerado para outro parceiro, ou cadastro do parceiro no portal preenchido com dados de outra marcaConfirmar com a Tupi o app host do parceiro, ou corrigir o cadastro no portal; o terminal aplica quando o app host é iniciado ou a tela local do terminal é aberta
Telas sem logo, só com o nome do parceiroLogo cadastrado só em SVG, fora de https:// ou acima de 512 KBCadastrar um logo de impressão (bitmap) ou ajustar o logo no portal
terminal_busy logo após um timeoutO terminal ainda aguarda a autorização anterior, por até 2 minutosRecuperar o desfecho da anterior e aguardar
Voltar não fecha a tela de pagamentoComportamento esperado durante a operaçãoCancelar pelo botão Cancelar do terminal
RESULT_CANCELED sem respostaO host encerrou sem responderTratar como no_response e recuperar
malformed_request com metadataMais de 20 chaves, chave fora de [A-Za-z0-9_.-], valor acima de 256 caracteres, total acima de 4 KB, ou valor com cara de número de cartão (13 a 19 dígitos)Reduzir o conteúdo de metadata e retirar qualquer dado de portador
Impressão responde internal_errorDocumento sem blocos, aligns com tamanho diferente de texts, ou imagem ilegívelCorrigir o documento conforme error.message
Imagem não sai na impressãocontent:// fora de um FileProvider, ou permissão de leitura ausenteUsar PosIntegrationClient.print, que concede a permissão
Reimpressão responde transaction_not_foundTransação de outro terminal, feita por outro app ou pelo app do terminal, ou com mais de 24 hObter a via no portal
verifyHost retorna SignatureMismatch após atualizar o hostHost assinado com chave nova sem vínculo com a anteriorConfirmar com a Tupi e atualizar o HOST_SHA256

Suporte​

Para chamados, envie o clientTransactionId, o status, o error.code, o error.vendorCode e o horário da operação.