# Developer Platform

Welcome to your team’s developer platform

<h2 align="center"><mark style="color:$primary;"><strong>First Code</strong></mark></h2>

<p align="center">Guias, referências e manuais para integração de segurança criptográfica e ecossistemas de pagamento.</p>

### Construa o futuro dos pagamentos.

Explore a documentação oficial da First Tech. Descubra como os nossos produtos funcionam, entenda os fluxos de integração e acesse as referências técnicas para escalar a sua operação financeira com segurança e agilidade.

### Explore os Nossos Produtos

<table data-view="cards"><thead><tr><th></th><th></th><th data-type="content-ref"></th><th data-hidden data-card-target data-type="content-ref"></th><th data-hidden data-card-cover data-type="image">Cover image</th></tr></thead><tbody><tr><td><strong>Hop API</strong></td><td>Criptografia e segurança de ponta a ponta abstraída em APIs REST. Ideal para emissores e processadoras que precisam de gerir PIN, EMV, CVV e chaves criptográficas sem gerir hardware.</td><td><a href="/spaces/OCh65KuQWNmf7esv0xUl">/spaces/OCh65KuQWNmf7esv0xUl</a></td><td><a href="/spaces/OCh65KuQWNmf7esv0xUl">/spaces/OCh65KuQWNmf7esv0xUl</a></td><td><a href="/files/ebMoLMpZFyLqpzByuzrk">/files/ebMoLMpZFyLqpzByuzrk</a></td></tr><tr><td><strong>Tap To Phone</strong></td><td>A solução SoftPOS que transforma dispositivos Android em terminais de pagamento. Aceda aos guias de experiência do utilizador (UX) e às documentações do SDK para captura segura de dados.</td><td><a href="/spaces/0woQ0gWPzU3Qf5sP0Hxl">/spaces/0woQ0gWPzU3Qf5sP0Hxl</a></td><td><a href="https://template.gitbook.com/space-product-docs">https://template.gitbook.com/space-product-docs</a></td><td><a href="/files/LHIOZGoI6dPF36TuRaxH">/files/LHIOZGoI6dPF36TuRaxH</a></td></tr><tr><td><strong>HoP GO</strong></td><td>Infraestrutura criptográfica em nuvem (Cloud HSM) orientada a ambientes críticos de produção. Os manuais operacionais detalham a arquitetura de alta disponibilidade, resiliência e escalabilidade para operações de geração de chaves, criptografia de dados, assinatura digital e validação de transações.</td><td><a href="/spaces/LvAi2DYpj9IDUWK1S7dH">/spaces/LvAi2DYpj9IDUWK1S7dH</a></td><td><a href="https://template.gitbook.com/space-api-reference">https://template.gitbook.com/space-api-reference</a></td><td><a href="/files/IaUMODRBBSBL8eUaPX09">/files/IaUMODRBBSBL8eUaPX09</a></td></tr></tbody></table>

### Conceitos e Fluxos de Integração

Entenda o funcionamento da plataforma antes de iniciar a implementação técnica.

* 🏢 Arquitetura e Ambientes Aprenda como separamos Homologação (Staging) e Produção, e quais as topologias de rede recomendadas para a sua integração.
* 🛡️ Conformidade e Segurança (PCI) Veja como as nossas soluções garantem a conformidade do seu negócio com as normas rigorosas PCI-PIN, PCI-DSS e PCI-HSM.
* 🔑 Autenticação de Sistemas Compreenda os fluxos de permissão, gestão de utilizadores e a autenticação segura baseada em tokens (OAuth2/JWT).

### Referência Técnica e Ferramentas

Acelere o desenvolvimento com as nossas ferramentas prontas a usar.

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Recurso</th><th>Descrição</th></tr></thead><tbody><tr><td>API References</td><td>Contratos Swagger interativos. Valide <em>schemas</em> de <em>request/response</em> e teste requisições diretamente no navegador.</td></tr><tr><td>SDKs (Bibliotecas)</td><td>Guias detalhados de implementação, chamadas de métodos e arquitetura do SDK Android para o TTP.</td></tr><tr><td>Catálogo Global de Erros</td><td>Resolução de problemas (<em>Troubleshooting</em>), tradução de códigos de falha do HSM, erros de paridade e recusas operacionais.</td></tr><tr><td>Release Notes</td><td>Acompanhe o ciclo de vida das plataformas, depreciação de <em>endpoints</em> e <em>changelogs</em> técnicos.</td></tr></tbody></table>


# 👋 Bem-vindo - HoP API v4

Esta página contém a introdução para a documentação HoP API da First Tech

O HoP, a plataforma de HSM-as-a-Service da First Tech para o mercado de pagamentos, foi atualizado para a versão 4.0.

O Hop V4 é a nova geração de uma plataforma que já atende algumas das principais fintechs e processadoras do Brasil. Reescrevemos a arquitetura para resolver dores reais que clientes da v3 reportaram nos últimos anos e aproveitamos para embarcar tecnologias novas, como a **cripto-agilidade**, que garante que sua operação não fique refém de um único padrão.

### Público Alvo deste Documento

Este documento é destinado a:

* **Cliente novo do Hop V4**: você está conhecendo a plataforma agora e quer entender o que ela faz, como contratar e como começar a integrar.
* **Cliente em migração da V3**: você já é cliente Hop e precisa migrar do ambiente V3 (que será descontinuado em 31 de maio de 2026) para o V4.

### Pule direto para...

Se você só tem 5 minutos, pule direto para a seção que interessa:

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-cover data-type="image"></th></tr></thead><tbody><tr><td><h4>Visão de Produto</h4></td><td>O que é o Hop V4</td><td></td></tr><tr><td><h4>V3 → V4</h4></td><td>O que muda na migração</td><td></td></tr><tr><td><h4>Documentação</h4></td><td>Mapa da Documentação</td><td></td></tr><tr><td><h4>FAQ</h4></td><td>Sobre o Hop V4</td><td></td></tr><tr><td><h4>Suporte e Contatos</h4></td><td>Fale conosco</td><td></td></tr></tbody></table>

### Visão do Produto

O Hop é a plataforma de criptografia como serviço da First Tech para o mundo dos pagamentos. Através de uma API REST simples e segura, o cliente consome todas as operações criptográficas que tradicionalmente exigiriam um HSM (Hardware Security Module) dedicado, com geração e gestão de chaves, validação e tradução de PIN, geração de CVV dinâmico, validação EMV, operações RSA e criptografia de dados, sem precisar comprar, operar ou manter hardware próprio.

#### O que o Hop V4 entrega

O HoP API é uma plataforma de operações criptográficas de pagamento entregues via API REST. Autenticação OAuth2/JWT, chamadas padrão HTTPS, documentação completa em formato OpenAPI e cobertura ampla de cenários de pagamento (cartão de crédito, débito, PIN, EMV, pagamentos por aproximação e cartões virtuais).

• Principais Módulos

* **PayShield Key Manager**: Geração e importação de chaves de trabalho (ZMK, ZPK, CVK, DEK, ZEK, BDK, ZAK, KERG). Gestão centralizada do ciclo de vida de chaves criptográficas.
* **PayShield Crypto**: Criptografia e descriptografia de dados sensíveis (ECB, CBC, CFB8, CFB64) e geração/validação de MAC.
* **PayShield PIN**: Validação e tradução de PIN Blocks em todos os formatos ISO e proprietários de mercado (0, 1, 2, 3, 4 e variantes Visa, Amex, Mastercard).
* **PayShield CVV**: Geração e validação de CVV/CVC estáticos e dinâmicos, com suporte a múltiplos códigos de serviço por requisição.
* **PayShield EMV**: Validação de ARPC 4.x para transações EMV, com suporte completo às principais bandeiras (Visa, Mastercard, Elo, JCB, Hipercard, American Express, Discover, UnionPay).
* **PayShield PAN**: Operações sobre o PAN (geração de PIN, translate de PAN, internalization, embossing, tradução entre LMK e ZPK em 3DES e AES).
* **PayShield RSA**: Importação e exportação de chaves criptográficas sob chave pública RSA, com suporte a PKCS#1 v1.5 e OAEP (SHA-1 até SHA-512).

#### Os planos comerciais

O Hop V4 é oferecido em três planos, escolhidos a partir do volume e da maturidade da operação:

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Plano</th><th>Para quem</th><th>Faixa</th></tr></thead><tbody><tr><td>Start</td><td>Times técnicos avaliando a plataforma; fintechs em estágio inicial.</td><td>Ambientes de desenvolvimento, POCs e operações de baixo volume.</td></tr><tr><td>Fintech</td><td>Fintechs em produção, sub-adquirentes e processadoras em crescimento.</td><td>Volume médio, exigências de SLA produtivo.</td></tr><tr><td>Enterprise</td><td>Adquirentes, bandeiras e operações com necessidades específicas de SLA, customização e integração dedicada.</td><td>Alto volume, ambientes mission-critical, atendimento dedicado.</td></tr></tbody></table>

### Mudanças - V3 → V4

A versão V4 representa a nova geração da plataforma, com arquitetura reescrita para entregar mais performance, mais capacidade, mais resiliência e — pela primeira vez no mercado brasileiro de pagamentos — chaves geradas a partir de entropia de origem quântica certificada.

HSM na nuvem. Chaves de origem quântica. Cripto-agilidade de verdade.

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Cripto-agilidade</th><th>Mais Performance</th><th>Mais Segurança</th></tr></thead><tbody><tr><td>Garantia que sua operação não fique refém de um único padrão, permitindo a troca rápida e transparente de componentes criptográficos críticos </td><td><p>10 vezes mais Rápidos.</p><p>A nova versão mantém o mesmo consumo de recursos entregando 10 vezes mais performance paralela. Isso é mais robustez para você. </p></td><td><p>Entropia quântica</p><p>Chaves geradas a partir de aleatoriedade de origem quântica certificada, eliminando a previsibilidade de PRNGs tradicionais.</p></td></tr></tbody></table>

Para mais detalhes da migração verificar Manifesto\_Migracao\_Hop\_V4

### &#x20;Documentação

#### Materiais de apoio

Para entender o produto, suporte com a migração de versão, release notes:

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Documento</th><th>O que é</th><th>Quando ler</th><th>Para quem</th></tr></thead><tbody><tr><td>Autenticação (OAuth2)</td><td>Guia detalhado do fluxo OAuth2 do HoP V4: Obtenção de token, escopos, refresh, expiração e tratamento de credenciais. Incluí exemplos de requisição</td><td>Antes da primeira chamada à API. Releitura ao implementar rotação de credenciais ou ao intefgrar novo ambiente.</td><td>Time técnico, desenvolvedores responsáveis pela integração</td></tr><tr><td>Tratamento de Erros</td><td>Catálogo de códigos de rro do HoP V4, com significado, causa provável, ação recomendada e severidade. Cobre erros HTTP. erros de negócio e erros criptográficos</td><td>Durante o desenvolvimento, ao implementar lógica de retry/fallback e em troubleshooting de produção.</td><td>Desenvolvedores, time de operações/SRE e suporte técnico.</td></tr><tr><td>Release Notes HoP API V4</td><td>Histórico cronológico de versões do HoP V4: Novas funcionalidades, correções, breaking changes e depreciações por versão.</td><td>Ao subir de versão, antes de planejar atualização de integração e períodicamente para acompanhar a evolução do produto.</td><td>Time técnico, arquitetos, time de produtos.</td></tr><tr><td>Manifesto de Migração V3 → V4</td><td>Documento detalhado com as 5 etapas da migração, prazos, responsáveis e checklists.</td><td>No kickoff da migração e durante toda a execução.</td><td>Cliente migrando da V3, time técnico do cliente, Onboarding.</td></tr></tbody></table>

#### Documentação Técnica — Módulos Criptográficos

Sete documentos técnicos completos, um por módulo. Cada documento traz: visão conceitual do módulo, referência completa de endpoints (estilo Swagger, com requests e responses), exemplos práticos e casos de uso reais.

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Módulo</th><th>Endpoints principais</th><th>Status</th></tr></thead><tbody><tr><td>Key Manager</td><td>Geração e importação de chaves (ZMK, ZPK, CVK, DEK, ZEK, BDK, ZAK, KERG).</td><td>✅ Disponível</td></tr><tr><td>Crypto</td><td>EncryptData, DecryptData, SuperDecryptData, GenerateMac, ValidateMac.</td><td>✅ Disponível</td></tr><tr><td>PIN</td><td>Geração, tradução e validação de blocos de PIN.</td><td>✅ Disponível</td></tr><tr><td>CVV</td><td>Generate, Super Generate, Validate.</td><td>✅ Disponível</td></tr><tr><td>PAN</td><td>Encriptação e manipulação de PAN.</td><td>✅ Disponível</td></tr><tr><td>EMV</td><td>ARQC, ARPC, derivação de chaves de sessão.</td><td>✅ Disponível</td></tr><tr><td>RSA</td><td>Import/Export PKCS#1 v1.5, OAEP SHA-1 a SHA-512.</td><td>✅ Disponível</td></tr></tbody></table>

{% hint style="info" %}
💡 DICA - Como escolher por onde começar

Se sua integração envolve PIN ou autorização de pagamento, comece por PIN. Se envolve emissão de cartão, comece por CVV e Key Manager. Se envolve transações EMV, abra PIN, EMV e Key Manager juntos. Em caso de dúvida, fale com o time técnico.
{% endhint %}


# Autenticação (OAuth2)

### Visão Geral

A segurança é a base do **HoP API v4**. Como lidamos com operações criptográficas e dados sensíveis, todas as requisições aos nossos serviços devem ser obrigatoriamente autenticadas.

Para facilitar sua integração e garantir o mais alto nível de segurança, utilizamos o padrão de mercado **OAuth2** (gerenciado via Auth0).

Nesta seção, você aprenderá como obter suas credenciais, gerar um token de acesso (`access_token`) e como enviá-lo corretamente no cabeçalho das suas requisições.

{% hint style="warning" %}
Atenção: Suas credenciais (`client_secret`) e seus tokens de acesso dão poder total sobre o seu ambiente criptográfico. Nunca exponha esses dados no front-end (navegadores ou aplicativos móveis) ou em repositórios públicos (como o GitHub).
{% endhint %}

***

### O Protocolo OAuth2 (M2M)

A HoP API v4 utiliza o padrão **OAuth2** através do fluxo de **Client Credentials** (Credenciais de Cliente).

Como a nossa infraestrutura foi desenhada para operações de backend (comunicação de servidor para servidor), este é o fluxo ideal para interações **Máquina-a-Máquina (M2M)**. Ele permite que a sua aplicação se autentique de forma autônoma e contínua, sem a necessidade de intervenção humana (como telas de login de usuários).

Essa abordagem garante o isolamento total da sua aplicação e a proteção dos dados durante operações criptográficas críticas, mantendo a sua integração em total conformidade com as normas de segurança do mercado.

### Obtenção de Credenciais (Webadmin)

Para se comunicar com a HoP API, sua aplicação precisará de duas chaves exclusivas: um **`Client_Id`** e um **`Client_Secret`**.

Por questões de segurança e controle de acesso, essas credenciais **não são geradas dinamicamente via API.**

{% hint style="warning" %}
**Pré-requisito Obrigatório:**\
Antes de prosseguir com qualquer teste ou integração, acesse a plataforma Webadmin (nosso portal de gestão de chaves) para provisionar e validar as suas credenciais. A geração do token de acesso não funcionará sem este passo.
{% endhint %}

### Endpoints de Autenticação (Auth0)

Para gerar o seu token de acesso, você fará uma requisição <mark style="color:green;">**`POST`**</mark> para o nosso servidor de autorização.

Lembre-se da regra de ouro: as credenciais geradas no **Webadmin de Sandbox** só funcionam na URL de Sandbox, e as credenciais do **Webadmin de Produção** só funcionam na URL de Produção.

Utilize o endpoint correspondente ao seu ambiente:

{% tabs %}
{% tab title="🧪 Ambiente de Testes (Sandbox)" %}

```http
https://auth-sandbox.first-tech.net/oauth/token
```

{% endtab %}

{% tab title="🚀 Ambiente de Produção" %}

```http
https://auth.first-tech.net/oauth/token
```

{% endtab %}
{% endtabs %}

### Parâmetros da Requisição (Payload)

A solicitação do token deve ser enviada via método <mark style="color:green;">**`POST`**</mark>. O corpo da requisição (body) deve conter os seguintes parâmetros no formato JSON:

`client_id` · *<mark style="color:blue;">string</mark>* · **Obrigatório** &#x20;

O identificador único da sua aplicação. Você deve obter este valor no painel do Webadmin.

`client_secret` · *<mark style="color:blue;">string</mark>* · **Obrigatório** &#x20;

A chave secreta da sua aplicação, também obtida no Webadmin. Nunca exponha este valor.

`audience`  · *<mark style="color:blue;">string</mark>* · **Obrigatório** &#x20;

O identificador único do recurso (API) que você deseja acessar.

`grant_type`  · *<mark style="color:blue;">string</mark>* · **Obrigatório** &#x20;

Define o fluxo de autenticação. Para interações máquina-a-máquina, deve ser estritamente

{% hint style="warning" %}
**Atenção ao campo** `audience`

O valor deste campo muda de acordo com o ambiente. Se você usar o `audience` de Sandbox apontando para a URL de Produção (ou vice-versa), o Auth0 emitirá um token inválido e suas chamadas ao HoP API serão rejeitadas. Confirme o valor correto no Webadmin.
{% endhint %}

### Exemplo de Requisição

Abaixo, apresentamos a estrutura da chamada. Lembre-se de configurar o cabeçalho `Content-Type` como `application/json` e substituir os valores de exemplo pelas suas credenciais reais obtidas no painel do Webadmin.

{% tabs %}
{% tab title="cURL" %}

```bash
curl --request POST \
  --url https://auth.first-tech.net/oauth/token \
  --header 'Content-Type: application/json' \
  --data '{
    "client_id": "SEU_CLIENT_ID_AQUI",
    "client_secret": "SEU_CLIENT_SECRET_AQUI",
    "audience": "https://api.first-tech.net/hop",
    "grant_type": "client_credentials"
  }'
```

{% endtab %}

{% tab title="HTTP (Raw)" %}

```http
POST /oauth/token HTTP/1.1
Host: auth.first-tech.net
Content-Type: application/json

{
  "client_id": "SEU_CLIENT_ID_AQUI",
  "client_secret": "SEU_CLIENT_SECRET_AQUI",
  "audience": "https://api.first-tech.net/hop",
  "grant_type": "client_credentials"
}
```

{% endtab %}
{% endtabs %}

### Resposta de Sucesso

Se as credenciais estiverem corretas, o servidor retornará um status <mark style="color:$success;">**`200 OK`**</mark>. O corpo da resposta conterá o seu token de acesso (JWT) e o tempo de validade dele em segundos.

```json
{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6...",
  "token_type": "Bearer",
  "expires_in": 86400
}
```

{% hint style="success" %}
**Melhor Prática: Faça cache do seu Token**

Para garantir altíssimo desempenho e evitar latência nas suas transações, **não gere um novo token a cada requisição.**

O valor retornado em `expires_in` (ex: 86400 segundos = 24 horas) indica quanto tempo essa chave é válida. A estratégia correta é salvar o `access_token` na memória da sua aplicação (cache) e reutilizá-lo em todas as chamadas ao HSM, solicitando um token novo apenas quando o atual estiver a poucos minutos de expirar. Isso também evita que você seja bloqueado por excesso de chamadas (*Rate Limiting*).
{% endhint %}


# Tratamento de Erros

Ao integrar com o HoP API, é importante entender que os erros podem ocorrer em duas camadas distintas: a camada de transporte (HTTP) e a camada de aplicação (HSM).

### Códigos de Status HTTP

A API utiliza os códigos de status padrão do protocolo HTTP para indicar o sucesso ou a falha básica de uma requisição. Falhas nesta camada geralmente indicam problemas de comunicação, formatação ou autenticação, antes mesmo da requisição chegar ao HSM.

`200` · ***Success***

A requisição foi recebida, compreendida e processada com sucesso.

{% hint style="info" %}
Nota: Um status **HTTP 200** não garante que a operação no HSM foi um sucesso, apenas que a comunicação ocorreu sem falhas. Sempre verifique o `retCode` no corpo da resposta.
{% endhint %}

`400` · ***Bad Request***

A requisição está malformada, faltando parâmetros obrigatórios ou com sintaxe JSON inválida.

`401` · ***Unauthorized***

O seu `access_token` é inválido, expirou ou não foi enviado no cabeçalho `Authorization`.

`402` · ***Over Quota***

A cota do seu plano para este endpoint foi excedida.

`404` · ***Not Found***&#x20;

O endpoint ou recurso solicitado não existe. Verifique a URL da requisição.

`422` · ***Validation Error***&#x20;

A requisição está bem formatada, mas contém erros de validação semântica (ex: um `keyName` que não existe).

`429` · ***Too Many Requests***&#x20;

Você atingiu o limite de requisições por segundo (Rate Limit). Aguarde alguns instantes antes de tentar novamente.

`50X` · ***Internal Server Error***&#x20;

Ocorreu um erro interno nos servidores do HoP API. Caso o erro persista, entre em contato com o suporte.

### Códigos de Resposta do HSM (retCode)

Mesmo que a sua requisição retorne um HTTP `200 Success`, a operação criptográfica dentro do HSM pode falhar (por exemplo, se você tentar validar um PIN incorreto ou usar uma chave incompatível).

O resultado real da operação do HSM sempre estará no campo `retCode` do corpo da resposta (JSON). Abaixo está a lista de códigos padrão e seus significados:

#### ✅ Sucesso

`00` · ***No error***&#x20;

A operação criptográfica foi executada com sucesso absoluto. Não há erros.

***

#### 🔑 Erros de Validação e Chaves (01 a 29)

`01` · ***Verification failure or warning of imported key parity error***

Falha na verificação de criptogramas (ex: MAC ou Assinatura incorreta) ou aviso de que a chave importada possui erro de paridade.

`02` · ***Key inappropriate length for algorithm***&#x20;

O tamanho da chave fornecida não é adequado para o algoritmo criptográfico solicitado (ex: tentar usar uma chave DES simples em uma operação TDES).

`04` · ***Invalid key type code***&#x20;

O código do tipo de chave (`keyType` / `keyName`) enviado é inválido ou não é suportado por este endpoint.

`05` · ***Invalid key length flag***&#x20;

A flag que define o tamanho da chave (Key Scheme, como U, T, X) é inválida.

`10` · ***Source key parity error***&#x20;

Erro de paridade detectado na chave de origem (Source Key). A chave pode estar corrompida.

`11` · ***Destination key parity error or key all zeros***&#x20;

Erro de paridade na chave de destino, ou a chave fornecida é composta apenas por zeros (chave nula).

`12` **·&#x20;*****Contents of user storage not available. Reset, power-down or overwrite***&#x20;

O conteúdo do armazenamento seguro não está disponível no momento.

`13` · ***Invalid LMK Identifier***&#x20;

O identificador da Local Master Key (LMK) enviado ou configurado é inválido.

`14` · ***PIN encrypted under LMK pair 02-03 is invalid***&#x20;

O bloco de PIN fornecido é inválido. Este é o erro mais comum quando um usuário digita a senha incorreta ou quando o PIN Block foi malformado na origem.

`15` · ***Invalid input data (invalid format, invalid characters, or not enough data provided)***&#x20;

Os dados de entrada enviados na requisição são inválidos. Pode ser um formato incorreto, caracteres não permitidos ou falta de dados obrigatórios.

`16` · ***Console or printer not ready or not connected***&#x20;

O HSM não consegue se comunicar com o console ou impressora interna (erro de infraestrutura).

`17` · ***Unrecognized message header***&#x20;

O cabeçalho da mensagem enviada ao HSM não foi reconhecido.

`20` · ***PIN block does not contain valid values***&#x20;

O formato do PIN Block fornecido contém valores que não respeitam o padrão matemático exigido (ex: ISO 0, ISO 1).

`21` · ***Invalid index value***&#x20;

O valor de índice (Index Value) fornecido para derivação de chaves é inválido.

`22` · ***Invalid account number***&#x20;

O Número da Conta (PAN / Número do Cartão) fornecido é inválido ou não condiz com o bloco de PIN.

`23` · ***Invalid PIN block format code***&#x20;

O código que define o formato do PIN Block (ex: 01 para ISO-1) não é suportado ou é inválido.

`24` · ***PIN is fewer than 4 or more than 12 digits in length***&#x20;

A senha (PIN) extraída possui um tamanho não permitido pela norma. Deve ter entre 4 e 12 dígitos.

`25` · ***Decimalization table error***

&#x20;A tabela de decimalização fornecida (usada em validações de PIN legadas, como IBM3624) contém erros.

`26` · ***Invalid key scheme***&#x20;

O esquema de chaves (Key Scheme) é inválido para a operação solicitada.

`27` · ***Incompatible key length***&#x20;

O tamanho da chave é incompatível com a chave de transporte (ex: tentar criptografar uma chave TDES sob uma chave ZMK que é apenas DES simples).

`28` · ***Invalid key type***&#x20;

O tipo de chave fornecido é inválido.

`29` · ***Key function not permitted***&#x20;

A função solicitada não é permitida para esta chave específica.

`30` · ***Invalid reference number***&#x20;

O número de referência da transação é inválido.

`31` · ***Insufficient solicitation entries for batch***&#x20;

Entradas de solicitação insuficientes para o processamento em lote.

`32` · ***AES not licensed***&#x20;

O HSM não possui licença para executar operações com o algoritmo AES.

`33` · ***LMK key change storage is corrupted***&#x20;

O armazenamento de alteração de chaves LMK está corrompido.

`39` · ***Fraud detection***&#x20;

Detecção de fraude. O HSM bloqueou a transação por anomalias.

***

#### ⚙️ Erros de Hardware, Criptografia e Sistema (40 a 90)

`40` · ***Invalid checksum***&#x20;

O checksum (KCV) fornecido ou calculado é inválido.

`41` · ***Internal hardware/software error: bad RAM, invalid error codes, etc.***&#x20;

Erro crítico interno de hardware ou software no HSM.

`42` · ***DES failure***&#x20;

Falha interna na execução do algoritmo DES.

`43` · ***RSA Key Generation Failure***&#x20;

Falha ao gerar as chaves assimétricas RSA.

`46` · ***Invalid tag for encrypted PIN***&#x20;

A tag fornecida para o PIN criptografado é inválida.

`47` · ***Algorithm not licensed***&#x20;

O algoritmo criptográfico não possui licença ativada no equipamento.

`48` · ***Key cannot be encrypted by a 3DES LMK***&#x20;

A chave não pode ser criptografada por uma LMK do tipo 3DES.

`49` · ***Private key error, report to supervisor***&#x20;

Erro na chave privada; contate o administrador do HSM.

`51` · ***Invalid message header***&#x20;

O cabeçalho da mensagem interna é inválido.

`65` · ***Transaction Key Scheme set to None***&#x20;

O esquema de chaves da transação foi definido como nulo (None).

`67` · ***Command not licensed***&#x20;

O HSM não possui licença para executar este comando.

`68` · ***Command has been disabled***&#x20;

O comando solicitado foi desativado nas configurações do HSM.

`69` · ***PIN block format has been disabled***&#x20;

O formato de PIN Block solicitado foi desativado (comum em padrões inseguros).

`74` · ***Invalid digest info syntax (no hash mode only)***&#x20;

Sintaxe de informações de digest inválida.

`75` · ***Single length key masquerading as double or triple length key***&#x20;

Uma chave de tamanho simples está tentando se passar por uma chave dupla ou tripla.

`76` · ***RSA public key length error or RSA encrypted data length error***&#x20;

Erro no tamanho da chave pública RSA ou no tamanho dos dados criptografados.

`77` · ***Clear data block error***&#x20;

Erro no bloco de dados em texto claro.

`78` · ***Private key length error***&#x20;

Erro no tamanho da chave privada.

`79` · ***Hash algorithm object identifier error***&#x20;

Erro no identificador do objeto do algoritmo de hash.

`80` · ***Data length error***&#x20;

A quantidade de dados do MAC (ou outros dados) é maior ou menor do que o esperado.

`81` · ***Invalid certificate header 82 Invalid check value length***&#x20;

Cabeçalho de certificado inválido ou tamanho do valor de checagem inválido.

`83` · ***Key block format error***&#x20;

Erro geral de formato no Key Block.

`84` · ***Key block check value error***&#x20;

Erro no valor de checagem (Check Value) do Key Block.

`85` · ***Invalid OAEP Mask Generation Function***&#x20;

Função de geração de máscara OAEP inválida.

`86` · ***Invalid OAEP MGF Hash Function***&#x20;

Função de hash OAEP MGF inválida.

`87` · ***OAEP Parameter Error***&#x20;

Erro de parâmetro no encapsulamento OAEP.

`90` · ***Data parity error in the request message received by the HSM***&#x20;

Erro de paridade de dados na mensagem de requisição recebida pelo equipamento.

***

#### 📦 Erros de Blocos de Chaves (Key Blocks / TR-31) (A1 a D3)

`A1` · ***Incompatible LMK schemes***&#x20;

Os esquemas da LMK são incompatíveis.

`A2` · ***Incompatible LMK identifiers***&#x20;

Os identificadores da LMK são incompatíveis.

`A3` · ***Incompatible key block LMK identifiers***&#x20;

Os identificadores da LMK do Key Block são incompatíveis.

`A4` · ***Key block authentication failure***&#x20;

Falha na autenticação da assinatura/MAC do Key Block.

`A5` · ***Incompatible key length***&#x20;

O tamanho da chave encapsulada é incompatível.

`A6` · ***Invalid key usage***&#x20;

O uso pretendido para a chave encapsulada é inválido.

`A7` · ***Invalid algorithm***&#x20;

O algoritmo definido no Key Block é inválido.

`A8` · ***Invalid mode of use***&#x20;

O modo de uso (Mode of Use) da chave é inválido.

`A9` · ***Invalid key version number***&#x20;

O número de versão da chave é inválido.

`AA` · ***Invalid export field***&#x20;

O campo de controle de exportação é inválido.

`AB` · ***Invalid number of optional blocks***&#x20;

A quantidade de blocos opcionais informada no cabeçalho é inválida.

`AC` · ***Optional header block error***&#x20;

Erro no bloco de cabeçalho opcional.

`AD` · ***Key status optional block error***&#x20;

Erro no bloco opcional de status da chave.

`AE` · ***Invalid start date/time***&#x20;

A data e hora de início definidas no Key Block são inválidas.

`AF` · ***Invalid end date/time***&#x20;

A data e hora de término definidas no Key Block são inválidas.

`B0` · ***Invalid encryption mode***&#x20;

O modo de criptografia (Encryption Mode) é inválido.

`B1` · ***Invalid authentication mode***&#x20;

O modo de autenticação do bloco é inválido.

`B2` · ***Miscellaneous key block error***&#x20;

Erro diversificado ou não classificado na estrutura do Key Block.

`B3` · ***Invalid number of optional blocks***&#x20;

A contagem de blocos opcionais está incorreta.

`B4` · ***Optional block data error***&#x20;

Os dados contidos em um bloco opcional estão inválidos.

`B5` · ***Incompatible components***&#x20;

Os componentes da chave fornecidos são incompatíveis.

`B6` · ***Incompatible key status optional blocks***&#x20;

Os blocos de status de chave opcionais são incompatíveis.

`B7` · ***Invalid change field***&#x20;

O campo de alteração do bloco está inválido.

`B8` · ***Invalid old value***&#x20;

O valor antigo (Old Value) fornecido está incorreto.

`B9` · ***Invalid new value***&#x20;

O novo valor (New Value) fornecido está incorreto.

`BA` · ***No key status block in the key block***&#x20;

Não foi encontrado o bloco de status da chave dentro do Key Block.

`BB` · ***Invalid wrapping key***&#x20;

A chave de transporte (Wrapping Key) utilizada é inválida.

`BC` · ***Repeated optional block***&#x20;

Existe um bloco opcional repetido dentro do pacote.

`BD` · ***Incompatible key types***&#x20;

Tipos de chaves incompatíveis detectados.

`BE` · ***Invalid key block header ID***&#x20;

A identificação (ID) do cabeçalho do Key Block é inválida.

`D3` · ***The wrapping key has a lower security strength than the key being wrapped***&#x20;

**Violação PCI**: A chave de transporte possui uma força de segurança menor que a chave que está sendo protegida.


# Release Notes HoP API V4

### Por que Migrar para a V4

A versão 4 do Hop API não é apenas uma atualização incremental. É uma reescrita dos pontos mais sensíveis da plataforma, endereçando limitações históricas de performance, resiliência e agilidade criptográfica. Abaixo, os benefícios principais que os clientes obtêm ao migrar.

#### 1. Capacidade escalada:

&#x20;A V4 foi desenhada para ser 10x mais eficiente utilizando o mesmo consumo de recursos, e sem aumento de custo para o cliente.

#### 2. Criptoagilidade

A camada criptográfica foi melhorada. Trocas de algoritmo, atualização de tamanho de chave, adequação a novas exigências PCI e, futuramente, migração para algoritmos pós-quânticos -  acontecerão de forma transparente para o código do cliente. Essa é uma das mudanças mais estratégicas da V4: isolar a agilidade criptográfica da First Tech do release cycle da aplicação do cliente.

#### 3. Novo ciclo de homologação PCI HSM

O novo ciclo de homologação PCI HSM acontece exclusivamente sobre a V4. Clientes que dependem da cadeia de certificação PCI para seus próprios processos regulatórios precisam estar na V4 para permanecerem cobertos.

#### 4. Evolução contínua exclusiva

Melhorias de performance e integração com outros serviços First Tech passam a ser entregues apenas na V4.&#x20;


# Introdução: Módulo EMV

O módulo EMV da plataforma Hop V4 é destinado à validação de ARQC e à geração de ARPC em transações EMV (chip) de crédito e débito.

O módulo EMV da plataforma Hop V4 é destinado à validação de ARQC e à geração de ARPC em transações EMV (chip) de crédito e débito. Este guia fornece as referências técnicas necessárias para o consumo seguro e eficiente das operações criptográficas expostas pela API da First Tech.

### Público-alvo e Pré-requisitos

Este documento é direcionado a desenvolvedores, integradores e arquitetos de sistemas de pagamento que precisam implementar as funcionalidades de validação e geração de criptogramas.

{% hint style="info" %}
**Conhecimento Prévio Necessário**\
Presume-se que o leitor conheça os fundamentos do padrão EMV e compreenda a estrutura de uma mensagem de autorização de pagamento com cartão chip. Termos técnicos específicos utilizados ao longo do texto podem ser consultados diretamente no Glossário.
{% endhint %}

### O que este documento cobre

A documentação está desenhada para cobrir de ponta a ponta a implementação do módulo, englobando:

* **Fundamentos EMV:** Conceitos essenciais relevantes para o uso dos endpoints.
* **Especificação da API:** Detalhamento completo dos endpoints `ValidateARQC4x` e `GenerateARPC4x`.
* **Modelagem de Dados:** Estrutura completa de payloads de requisição e resposta.
* **Regras de Validação:** Matriz de obrigatoriedade condicional de campos de acordo com o modo de operação.
* **Operação e Suporte:** Códigos de erro, estratégias de *troubleshooting*, fluxos de integração e exemplos práticos.

### O que este documento não cobre

Para manter o foco no processamento EMV, os tópicos abaixo não fazem parte deste escopo:

* **Outros Módulos PayShield da Hop V4:** Funcionalidades de Key Manager, Crypto, PIN, CVV, PAN e RSA possuem documentação própria.
* **Autenticação:** O fluxo OAuth2 para emissão de tokens JWT é coberto em um documento separado de autenticação da Hop V4.
* **Onboarding Comercial:** O credenciamento de clientes é conduzido exclusivamente pelos times de pré-vendas e comercial.
* **Especificação Oficial EMVCo:** Este material é um guia de uso do módulo Hop, e não uma referência normativa ao padrão EMV.


# Fundamentos e Fluxo Transacional

Esta seção detalha a base conceitual do padrão EMV, o papel do HSM na infraestrutura de chaves e como a troca de mensagens ocorre na prática durante uma transação.

### O que é EMV?

EMV é o padrão internacional para transações com cartões chip, originalmente estabelecido por Europay, Mastercard e Visa, e atualmente mantido pelo consórcio EMVCo. O padrão especifica as regras de autenticação entre o cartão e o terminal por meio de criptogramas.

### A Necessidade do HSM

O pilar da segurança EMV baseia-se nas Chaves Mestras do Emissor (*Issuer Master Keys*, ou MK), que são armazenadas em hardware criptográfico seguro.

Através destas chaves mestras, o emissor deriva chaves únicas por cartão e por transação. Como as chaves mestras jamais devem ser expostas em texto claro, toda operação de validação ou geração de criptograma precisa ser executada rigorosamente dentro do ambiente criptográfico. O módulo Hop V4 expõe essas operações via API REST, garantindo a manutenção da cadeia PCI HSM de ponta a ponta.

### Os Criptogramas do Fluxo EMV

Em um fluxo típico de autorização, quatro tipos principais de criptogramas podem interagir:

| Sigla    | Nome                                    | Significado / Papel no Fluxo                                                                                                                               |
| -------- | --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **ARQC** | *Authorization Request Cryptogram*      | Gerado pelo cartão. Transportado no campo 55 da ISO 8583 (tag 9F26). Indica que o cartão está solicitando autorização online ao emissor.                   |
| **ARPC** | Authorization Response Cryptogram       | Gerado pelo emissor como resposta ao ARQC. Confirma ao cartão que a resposta do emissor é legítima. É justamente o que o endpoint `GenerateARPC4x` produz. |
| **TC**   | Transaction Certificate                 | Gerado pelo cartão ao final de uma transação offline aprovada. Garante a integridade da transação para posterior captura.                                  |
| **AAC**  | *Application Authentication Cryptogram* | Gerado pelo cartão quando a transação é negada (offline ou online). Encerra o fluxo EMV.                                                                   |

## ARQC e ARPC no Fluxo Transacional

Para integrar a API, é necessário compreender onde os endpoints se encaixam em uma autorização típica de crédito ou débito.

### Atores e Sequência de Mensagens

* **Cartão (chip):** Gera o ARQC a partir dos dados da transação e da chave derivada da MK do emissor.
* **Terminal (POS / maquininha):** Monta o campo 55 com as tags EMV e encaminha a autorização para o adquirente.
* **Adquirente e Bandeira:** O adquirente encaminha a autorização para a bandeira, que roteia para o emissor.
* **Emissor (backend):** Recebe a autorização, valida o ARQC via Hop, toma a decisão de autorização e gera o ARPC via Hop para retornar ao cartão.
* **Hop V4 (Módulo EMV):** Atua como HSM-as-a-service que executa a validação e geração de criptogramas com as chaves mestras do emissor.

### Sequência do Fluxo de Autorização Online

O fluxo abaixo apresenta, de forma linear, as trocas entre os atores:

1. O Cartão chip gera o ARQC (tag 9F26) e os dados EMV (campo 55) e envia ao Terminal.
2. O Terminal encaminha a mensagem ISO 8583 com o campo 55 passando pelo Adquirente e pela Bandeira até chegar ao backend do Emissor.
3. O Emissor aciona a Hop V4 (`POST /v4/PayShieldEMV/ValidateARQC4x`) para que o ARQC seja validado contra a chave mestra do cartão .
4. Com a resposta, o Emissor toma a decisão de autorização (aprovar ou negar).
5. O Emissor aciona novamente a Hop V4 (`POST /v4/PayShieldEMV/GenerateARPC4x`) para gerar o ARPC com base no ARC ou CSU.
6. O Emissor devolve a resposta ISO 8583 com o ARPC transportado no campo 55 (tag 91), que trafega pela Bandeira e Adquirente até o Terminal .
7. O Terminal repassa o ARPC e o status ao Cartão, que valida o ARPC e encerra a transação.

{% hint style="info" %}
**Otimização:**

Validar e Gerar em uma Única Chamada É possível combinar as etapas 3 e 5 em uma única chamada ao Hop, utilizando modos de operação que validam o ARQC e já geram o ARPC no mesmo request. Em cenários de alto volume (ex.: autorização de débito em tempo real), combinar validação e geração na mesma chamada (`mode=1,3,5`) tipicamente reduz em aproximadamente metade o tempo total gasto no serviço criptográfico, por evitar o *round-trip* adicional.
{% endhint %}


# Modos de Operação e Bandeiras

Esta página detalha os parâmetros centrais para a correta integração com os endpoints EMV: a escolha do modo de operação (`mode`), o formato do criptograma de resposta (ARC vs CSU) e o mapeamento correto da bandeira do cartão (`schemeId`).

## Modos de Operação

O campo `mode` é o parâmetro central da integração EMV, pois controla exatamente o que o endpoint fará em uma única chamada. Entender os modos disponíveis evita o envio de requisições com dados faltantes e chamadas desnecessárias ao HSM.

### Tabela de Modos Disponíveis

A tabela abaixo relaciona o valor do `mode`, a operação que ele executa e qual método de ARPC é utilizado:

| mode | O que faz                                                       | Método ARPC Utilizado |
| ---- | --------------------------------------------------------------- | --------------------- |
| 0    | Validar ARQC apenas.                                            | -                     |
| 1    | Validar ARQC e gerar ARPC.                                      | Método 1 - ARC        |
| 2    | Gerar ARPC sem validar ARQC.                                    | Método 1 - ARC        |
| 3    | Validar ARQC e gerar ARPC.                                      | Método 2 - CSU        |
| 4    | Gerar ARPC sem validar ARQC.                                    | Método 2 - CSU        |
| 5    | Validar ARQC e gerar ARPC (ambos os métodos simultaneamente).   | Métodos 1 e 2         |
| 6    | Gerar ARPC sem validar ARQC (ambos os métodos simultaneamente). | Métodos 1 e 2         |
| 8    | Validar TC ou AAC (encerramento de transação offline).          | -                     |
| 9    | Validar TC/AAC e gerar ARPC.                                    | Método 1 - ARC        |

### Método 1 (ARC) vs Método 2 (CSU)

A diferença fundamental entre os métodos de geração de ARPC está na forma como a resposta do emissor é codificada no criptograma :

* **Método 1 — ARC (Authorization Response Code):** Utiliza o campo `arc`, que consiste em um par de bytes em hexadecimal codificando a resposta do emissor segundo a tabela padrão ISO 8583 (tag 8A) . **Exemplos comuns:** `00` = aprovado, `01` = referir, `05` = negado. É o formato mais amplamente utilizado em fluxos tradicionais de autorização.
* **Método 2 — CSU (Card Status Update):** Utiliza o campo `csu`, composto por quatro bytes em hexadecimal que fornecem informações estendidas sobre o status do cartão, além da própria resposta de autorização .

{% hint style="warning" %}

#### **Quando usar cada método**

* Utilize `mode=1` (ARC) para a maioria das autorizações convencionais, especialmente em fluxos legados ou quando o `schemeId` for do tipo VIS (`0`) ou M/Chip CVN 10/11 (`1`) .
* Utilize `mode=3` (CSU) quando o `schemeId` indicar M/Chip Advance, Visa qVSDC (`9`) ou esquemas mais modernos.
* Utilize `mode=5` (Ambos) apenas quando a arquitetura do emissor exigir a resposta simultânea em ambos os formatos.
  {% endhint %}

### Obrigatoriedade Condicional de `arc` e `csu`

A API valida se os campos `arc` e `csu` foram enviados dependendo estritamente do `mode` escolhido. O não envio gerará falha na requisição:

| mode  | arc                                              | cs                                               |
| ----- | ------------------------------------------------ | ------------------------------------------------ |
| **0** | Ignorado                                         | Ignorado                                         |
| **1** | <mark style="color:$warning;">Obrigatório</mark> | Ignorado                                         |
| **2** | <mark style="color:$warning;">Obrigatório</mark> | Ignorado                                         |
| **3** | Ignorado                                         | <mark style="color:$warning;">Obrigatório</mark> |
| **4** | Ignorado                                         | <mark style="color:$warning;">Obrigatório</mark> |
| **5** | <mark style="color:$warning;">Obrigatório</mark> | <mark style="color:$warning;">Obrigatório</mark> |
| **6** | <mark style="color:$warning;">Obrigatório</mark> | <mark style="color:$warning;">Obrigatório</mark> |
| **9** | <mark style="color:$warning;">Obrigatório</mark> | Ignorado                                         |

## Scheme ID e Bandeiras Suportadas

O campo `schemeId` identifica a variante do esquema criptográfico EMV que o cartão utiliza. Note que o mesmo número de cartão (PAN) pode estar vinculado a esquemas diferentes dependendo da bandeira, versão e do CVN (Cryptogram Version Number).

### Tabela de Scheme IDs

<table data-header-hidden="false" data-header-sticky><thead><tr><th>schemeId</th><th>Esquema</th><th>Observações</th></tr></thead><tbody><tr><td>0</td><td>Visa VIS (CVN 10 ou 17)</td><td>Esquema Visa tradicional, amplamente utilizado em crédito e débito Visa.</td></tr><tr><td>1</td><td>Mastercard M/Chip (CVN 10 ou 11)</td><td>Esquema Mastercard tradicional.</td></tr><tr><td>2</td><td>American Express AEIPS</td><td>Esquema proprietário American Express.</td></tr><tr><td>3</td><td>Mastercard M/Chip com PAN length</td><td>Variação do esquema M/Chip que inclui o tamanho do PAN no cálculo.</td></tr><tr><td>5</td><td>Visa VIS com PAN length</td><td>Variação do esquema VIS que inclui o tamanho do PAN.</td></tr><tr><td>6</td><td>JCB</td><td>Esquema JCB.</td></tr><tr><td>7</td><td>Discover</td><td>Esquema Discover.</td></tr><tr><td>9</td><td>Visa qVSDC</td><td>Esquema Visa contactless, típico de transações sem contato e tokenizadas.</td></tr><tr><td>A</td><td>Mastercard PayPass</td><td>Esquema Mastercard contactless (PayPass).</td></tr></tbody></table>

{% hint style="info" %}

#### Relação entre Brand e Scheme ID:

O campo `brand` aceita exclusivamente os valores `MASTERCARD`, `VISA` e `AMEX`, sendo utilizado para a seleção do perfil mestre no HSM. O `schemeId`, por sua vez, atua como um refinamento da variante criptográfica.

**Nota sobre outras bandeiras:** Embora a tabela de `schemeId` suporte esquemas como JCB (6) e Discover (7), e existam menções comerciais a bandeiras como Elo e Hipercard, esses nomes não são valores válidos atualmente para o campo `brand` na requisição. É fundamental garantir que a combinação enviada entre o `brand` (limitado aos três valores aceitos) e o `schemeId` seja consistente com o cartão para evitar erros de validação.
{% endhint %}


# Referência da API - EMV

Esta secção apresenta a especificação técnica completa para o consumo dos endpoints do módulo EMV da Hop V4.

## Autenticação e Base URL

Todos os endpoints do módulo EMV da Hop V4 exigem um token Bearer obtido via OAuth2 (`grant_type: client_credentials`). O token é transportado no cabeçalho `Authorization` em toda a requisição.

### Configurações de Conexão:

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Parâmetro</th><th>Valor</th></tr></thead><tbody><tr><td>Base URL (API)</td><td><code>https://apivin.first-tech.net</code> <em>[A confirmar host definitivo de PRD/HML]</em></td></tr><tr><td>Endpoint de autenticação</td><td><code>https://auth.first-tech.net/oauth/token</code></td></tr><tr><td>grant_type</td><td><code>client_credentials</code></td></tr><tr><td>audience</td><td><code>https://auth-jwt-authorize-prd-first-tech</code></td></tr><tr><td>token_type</td><td><code>Bearer</code></td></tr><tr><td>Tempo de vida (padrão)</td><td><em>[A confirmar TTL do token com a equipa técnica]</em></td></tr></tbody></table>

### Cabeçalhos Obrigatórios (`Headers`):

```http
HTTP
Authorization: Bearer <TOKEN_JWT>
Content-Type: application/json
Accept: */*
```

{% hint style="info" %}

#### Estratégia de Renovação de Token:

Recomenda-se renovar o token antes da expiração, mantendo um *cache* no lado do cliente. Evite solicitar um novo token a cada chamada EMV, pois isso adiciona latência desnecessária e onera o serviço de autenticação . Em caso de resposta HTTP `401`, descarte o token em *cache*, solicite um novo e reenvie a requisição.
{% endhint %}

### POST /ValidateARQC4x

## Validar ARQC (Request Cryptogram)

> Valida o ARQC (Authorization Request Cryptogram) recebido no campo 55 da transação EMV.\
> Retorna \`true\` em \`retValid\` se o ARQC for válido, \`false\` caso contrário.\
> Retorna o ARPC gerado em \`retValue\` em formato Hex.\
> \
> O campo \`field55EmvTags\` deve conter os dados EMV da transação em formato TLV hexadecimal.\
> O ARQC é extraído automaticamente da tag \`9F26\` do campo 55.\
> \
> Em caso de erro, retorna os campos de erro (\`retCode\` e \`retDesc\`).<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield EMV API","version":"4.1.32"},"tags":[{"name":"EMV","description":"Operações de geração e validação de criptogramas EMV (ARPC/ARQC)"}],"servers":[{"url":"https://apivin.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"ArpcInput":{"type":"object","required":["client_id","brand","mode","schemeId","mkacKeyId","pan","panSeqNr","field55EmvTags"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"brand":{"type":"string","enum":["MASTERCARD","VISA","AMEX"],"description":"Bandeira do cartão"},"mode":{"type":"string","description":"Modo de operação do comando EMV:\n- `0`: Validar ARQC\n- `1`: Validar ARQC e gerar ARPC método 1 (ARC)\n- `2`: Gerar ARPC método 1 (ARC) sem validar ARQC\n- `3`: Validar ARQC e gerar ARPC método 2 (CSU)\n- `4`: Gerar ARPC método 2 (CSU) sem validar ARQC\n- `5`: Validar ARQC e gerar ARPC métodos 1 e 2\n- `6`: Gerar ARPC métodos 1 e 2 sem validar ARQC\n- `8`: Validar TC/AAC\n- `9`: Validar TC/AAC e gerar ARPC método 1\n"},"schemeId":{"type":"string","description":"Identificador do esquema EMV:\n- `0`: Visa VIS (CVN 10 ou 17)\n- `1`: Mastercard M/Chip (CVN 10 ou 11)\n- `2`: American Express AEIPS\n- `3`: Mastercard M/Chip com PAN length\n- `5`: Visa VIS com PAN length\n- `6`: JCB\n- `7`: Discover\n- `9`: Visa qVSDC\n- `A`: Mastercard PayPass\n- `B`: Mastercard PayPass com PAN length\n- `C`: Mastercard PayPass com padding flag\n"},"iv_ac":{"type":"string","nullable":true,"description":"IV para derivação de chave de sessão EMV 2000.\nObrigatório apenas para `schemeId` = `0` ou `1`.\n"},"branch_height_params":{"type":"string","nullable":true,"description":"Parâmetros de branch/height para derivação de chave de sessão EMV 2000.\nObrigatório apenas para `schemeId` = `0` ou `1`.\n- `0`: Branch factor 2, Tree Height 16\n- `1`: Branch factor 4, Tree Height 8\n"},"mkacKeyId":{"type":"string","description":"Alias/identificador da chave MKAC no banco de dados"},"pan":{"type":"string","description":"PAN do cartão"},"panSeqNr":{"type":"string","description":"Número de sequência do PAN (PSN) — usar `00` se não disponível"},"field55EmvTags":{"type":"string","description":"Dados EMV da transação em formato TLV hexadecimal (campo 55 da ISO 8583).\nO ARQC é extraído automaticamente da tag `9F26`.\nTags relevantes utilizadas: `9F26` (ARQC), `9F36` (ATC), `9F10` (Issuer Application Data), `8C` (CDOL1).\n"},"arc":{"type":"string","nullable":true,"description":"Authorization Response Code — obrigatório para `mode` = `1`, `2`, `5`, `6` ou `9`.\nValor em Hex (ex: `00` = aprovado, `01` = negado).\n"},"arqc":{"type":"string","nullable":true,"description":"ARQC (Authorization Request Cryptogram) em Hex.\nQuando informado, sobrescreve o valor extraído automaticamente da tag `9F26` do `field55EmvTags`.\nUtilizado principalmente no endpoint `ValidateARQC4x`.\n"},"csu":{"type":"string","nullable":true,"description":"Card Status Update — obrigatório para `mode` = `3`, `4`, `5` ou `6`.\n4 bytes em Hex.\n"}}},"ReturnSingle":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValue":{"type":"string","nullable":true,"description":"ARPC gerado em Hex (quando aplicável)"},"retValid":{"type":"boolean","description":"Indica se o ARQC foi validado com sucesso"},"retDescription":{"type":"string"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `01`: Falha na verificação do ARQC/TC/AAC/MPVV\n- `03`: Padding Flag inválido\n- `04`: Mode Flag não reconhecido\n- `05`: Scheme ID não reconhecido\n- `06`: Valor YHHHHCC inválido\n- `10`: Erro de paridade na chave MK\n- `52`: Branch/Height inválido\n- `68`: Comando desabilitado\n- `F1`: Método de derivação de chave inválido\n- `F2`: Método de validação ARQC inválido\n- `F3`: Algoritmo da chave MK-AC não é AES\n- `F5`: Método de chave de sessão inválido\n- `F8`: Método de geração de chave OTPK inválido\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDesc":{"type":"string","description":"Descrição do erro"}}}}},"paths":{"/v4/PayShieldEMV/ValidateARQC4x":{"post":{"tags":["EMV"],"summary":"Validar ARQC (Request Cryptogram)","description":"Valida o ARQC (Authorization Request Cryptogram) recebido no campo 55 da transação EMV.\nRetorna `true` em `retValid` se o ARQC for válido, `false` caso contrário.\nRetorna o ARPC gerado em `retValue` em formato Hex.\n\nO campo `field55EmvTags` deve conter os dados EMV da transação em formato TLV hexadecimal.\nO ARQC é extraído automaticamente da tag `9F26` do campo 55.\n\nEm caso de erro, retorna os campos de erro (`retCode` e `retDesc`).\n","operationId":"validateARQC4x","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArpcInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnSingle"}}}},"400":{"description":"Requisição inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"404":{"description":"Chave não encontrada no banco de dados","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

### POST /GenerateARPC4x

## Gerar ARPC (Response Cryptogram)

> Gera o ARPC (Authorization Response Cryptogram) a partir do ARQC recebido no campo 55 da transação EMV.\
> Retorna o ARPC gerado em \`retMultiValue\[0]\` em formato Hex.\
> \
> O campo \`field55EmvTags\` deve conter os dados EMV da transação em formato TLV hexadecimal.\
> Os campos \`arc\` e \`csu\` são utilizados dependendo do \`mode\` de operação.\
> \
> Em caso de erro, retorna os campos de erro (\`retCode\` e \`retDesc\`).<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield EMV API","version":"4.1.32"},"tags":[{"name":"EMV","description":"Operações de geração e validação de criptogramas EMV (ARPC/ARQC)"}],"servers":[{"url":"https://apivin.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"ArpcInput":{"type":"object","required":["client_id","brand","mode","schemeId","mkacKeyId","pan","panSeqNr","field55EmvTags"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"brand":{"type":"string","enum":["MASTERCARD","VISA","AMEX"],"description":"Bandeira do cartão"},"mode":{"type":"string","description":"Modo de operação do comando EMV:\n- `0`: Validar ARQC\n- `1`: Validar ARQC e gerar ARPC método 1 (ARC)\n- `2`: Gerar ARPC método 1 (ARC) sem validar ARQC\n- `3`: Validar ARQC e gerar ARPC método 2 (CSU)\n- `4`: Gerar ARPC método 2 (CSU) sem validar ARQC\n- `5`: Validar ARQC e gerar ARPC métodos 1 e 2\n- `6`: Gerar ARPC métodos 1 e 2 sem validar ARQC\n- `8`: Validar TC/AAC\n- `9`: Validar TC/AAC e gerar ARPC método 1\n"},"schemeId":{"type":"string","description":"Identificador do esquema EMV:\n- `0`: Visa VIS (CVN 10 ou 17)\n- `1`: Mastercard M/Chip (CVN 10 ou 11)\n- `2`: American Express AEIPS\n- `3`: Mastercard M/Chip com PAN length\n- `5`: Visa VIS com PAN length\n- `6`: JCB\n- `7`: Discover\n- `9`: Visa qVSDC\n- `A`: Mastercard PayPass\n- `B`: Mastercard PayPass com PAN length\n- `C`: Mastercard PayPass com padding flag\n"},"iv_ac":{"type":"string","nullable":true,"description":"IV para derivação de chave de sessão EMV 2000.\nObrigatório apenas para `schemeId` = `0` ou `1`.\n"},"branch_height_params":{"type":"string","nullable":true,"description":"Parâmetros de branch/height para derivação de chave de sessão EMV 2000.\nObrigatório apenas para `schemeId` = `0` ou `1`.\n- `0`: Branch factor 2, Tree Height 16\n- `1`: Branch factor 4, Tree Height 8\n"},"mkacKeyId":{"type":"string","description":"Alias/identificador da chave MKAC no banco de dados"},"pan":{"type":"string","description":"PAN do cartão"},"panSeqNr":{"type":"string","description":"Número de sequência do PAN (PSN) — usar `00` se não disponível"},"field55EmvTags":{"type":"string","description":"Dados EMV da transação em formato TLV hexadecimal (campo 55 da ISO 8583).\nO ARQC é extraído automaticamente da tag `9F26`.\nTags relevantes utilizadas: `9F26` (ARQC), `9F36` (ATC), `9F10` (Issuer Application Data), `8C` (CDOL1).\n"},"arc":{"type":"string","nullable":true,"description":"Authorization Response Code — obrigatório para `mode` = `1`, `2`, `5`, `6` ou `9`.\nValor em Hex (ex: `00` = aprovado, `01` = negado).\n"},"arqc":{"type":"string","nullable":true,"description":"ARQC (Authorization Request Cryptogram) em Hex.\nQuando informado, sobrescreve o valor extraído automaticamente da tag `9F26` do `field55EmvTags`.\nUtilizado principalmente no endpoint `ValidateARQC4x`.\n"},"csu":{"type":"string","nullable":true,"description":"Card Status Update — obrigatório para `mode` = `3`, `4`, `5` ou `6`.\n4 bytes em Hex.\n"}}},"ReturnMultiValue":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValue":{"type":"string","nullable":true},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string"},"description":"Array com os valores de retorno — `retMultiValue[0]` contém o ARPC gerado em Hex"},"retValid":{"type":"boolean"},"retDesc":{"type":"string"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `01`: Falha na verificação do ARQC/TC/AAC/MPVV\n- `03`: Padding Flag inválido\n- `04`: Mode Flag não reconhecido\n- `05`: Scheme ID não reconhecido\n- `06`: Valor YHHHHCC inválido\n- `10`: Erro de paridade na chave MK\n- `52`: Branch/Height inválido\n- `68`: Comando desabilitado\n- `F1`: Método de derivação de chave inválido\n- `F2`: Método de validação ARQC inválido\n- `F3`: Algoritmo da chave MK-AC não é AES\n- `F5`: Método de chave de sessão inválido\n- `F8`: Método de geração de chave OTPK inválido\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDesc":{"type":"string","description":"Descrição do erro"}}}}},"paths":{"/v4/PayShieldEMV/GenerateARQC4x":{"post":{"tags":["EMV"],"summary":"Gerar ARPC (Response Cryptogram)","description":"Gera o ARPC (Authorization Response Cryptogram) a partir do ARQC recebido no campo 55 da transação EMV.\nRetorna o ARPC gerado em `retMultiValue[0]` em formato Hex.\n\nO campo `field55EmvTags` deve conter os dados EMV da transação em formato TLV hexadecimal.\nOs campos `arc` e `csu` são utilizados dependendo do `mode` de operação.\n\nEm caso de erro, retorna os campos de erro (`retCode` e `retDesc`).\n","operationId":"generateARQC4x","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArpcInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnMultiValue"}}}},"400":{"description":"Requisição inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"404":{"description":"Chave não encontrada no banco de dados","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

## Modelos de Objeto

Esta seção detalha os modelos de objeto utilizados pelos endpoints EMV. Todos os modelos seguem a convenção de nomenclatura adotada na Hop V4.

### Arpcinput (Modelo de Request)

Modelo único de request, utilizado por ambos os endpoints.

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Campo</th><th>Tipo</th><th>Obrigatório</th><th>Observação</th></tr></thead><tbody><tr><td><code>client_id</code></td><td>integer (int64, min 1)</td><td>Sim</td><td>Identificador do cliente.</td></tr><tr><td><code>brand</code></td><td>string (enum)</td><td>Sim</td><td><code>MASTERCARD</code>, <code>VISA</code> ou <code>AMEX</code>.</td></tr><tr><td><code>mode</code></td><td>string</td><td>Sim</td><td>Modo de operação — ver seção 4.</td></tr><tr><td><code>schemeId</code></td><td>string</td><td>Sim</td><td>Esquema EMV — ver seção 5.</td></tr><tr><td><code>iv_ac</code></td><td>string (nullable)</td><td>Não</td><td>IV do AC — <code>null</code> quando não aplicável.</td></tr><tr><td><code>branch_height_params</code></td><td>string (nullable)</td><td>Não</td><td>Parâmetros de árvore de chaves.</td></tr><tr><td><code>mkacKeyId</code></td><td>string</td><td>Sim</td><td>Identificador da chave MK-AC do emissor.</td></tr><tr><td><code>pan</code></td><td>string</td><td>Sim</td><td>Primary Account Number.</td></tr><tr><td><code>panSeqNr</code></td><td>string</td><td>Sim</td><td>PSN — usar <code>"00"</code> se não disponível.</td></tr><tr><td><code>field55EmvTags</code></td><td>string</td><td>Sim</td><td>Campo 55 em TLV hexadecimal.</td></tr><tr><td><code>arc</code></td><td>string (nullable)</td><td>Condicional</td><td>Obrigatório para mode = <code>1</code>, <code>2</code>, <code>5</code>, <code>6</code>, <code>9</code>.</td></tr><tr><td><code>csu</code></td><td>string (nullable)</td><td>Condicional</td><td>Obrigatório para mode = <code>3</code>, <code>4</code>, <code>5</code>, <code>6</code>.</td></tr><tr><td><code>arqc</code></td><td>string (nullable)</td><td>Não</td><td>Sobrescreve o ARQC da tag 9F26.</td></tr></tbody></table>

### Modelos de Resposta (Responses)

#### ReturnSingle (Response de `ValidateARQC4x` com sucesso):

* `retCode` (integer):&#x20;

`0` indica sucesso.

* `retValue` (string):&#x20;

ARPC gerado em hexadecimal (modos de validação + geração).

* `retValid` (boolean):&#x20;

`true` se validado com sucesso.

* `retDescription` (string):&#x20;

Descrição textual do resultado.

#### ReturnMultiValue (Response de `GenerateARPC4x` com sucesso):

* `retCode` (integer): `0` indica sucesso.
* `retValue` (string): Sempre vazio em caso de sucesso.
* `retMultiValue` (string\[]): Array; `retMultiValue[0]` contém o ARPC gerado.
* `retValid` (boolean): Indica operação bem-sucedida.
* `retDesc` (string): Descrição textual do resultado.

ReturnError (Response de Erro - 400, 404, 500) :

* `retCode` (integer): Código de erro específico (ver taxonomia).
* `retValue` (string): Não utilizado.
* `retMultiValue` (any): Não utilizado.
* `retValid` (boolean): `false` em erros.
* `retDesc` (string): Descrição textual do erro


# Códigos de Erro e Troubleshooting

Esta secção unifica o catálogo completo de erros da API e o guia de resolução rápida para os problemas mais comuns encontrados durante a integração.

### Taxonomia Completa de Códigos de Erro (`retCode`)

Nas respostas de erro (HTTP `400`, `404`, `500`), o campo `retCode` carrega um código específico que identifica a categoria exata da falha.

A tabela abaixo consolida todos os códigos documentados, com a respetiva orientação de diagnóstico e ação sugerida:

<table data-header-hidden="false" data-header-sticky><thead><tr><th>retCode</th><th>Significado</th><th>Ação Sugerida</th></tr></thead><tbody><tr><td><code>01</code></td><td>Falha na verificação do ARQC/TC/AAC/MPVV</td><td>O ARQC recebido não é válido para o cartão/chave informados. Verificar PAN, PSN, <code>mkacKeyId</code> e o conteúdo do campo 55.</td></tr><tr><td><code>03</code></td><td>Padding Flag inválido</td><td>Configuração de <em>padding</em> do criptograma está incompatível com o esquema selecionado. Revisar <code>schemeId</code>.</td></tr><tr><td><code>04</code></td><td>Mode Flag não reconhecido</td><td>Valor de <code>mode</code> fora da faixa suportada. Ver secção de modos de operação.</td></tr><tr><td><code>05</code></td><td>Scheme ID não reconhecido</td><td>Valor de <code>schemeId</code> fora da faixa suportada. Ver secção de bandeiras suportadas.</td></tr><tr><td><code>06</code></td><td>Valor YHHHHCC inválido</td><td>Parâmetro interno de derivação inválido. Validar combinação <code>schemeId</code> x <code>brand</code> e reportar ao suporte se persistir.</td></tr><tr><td><code>10</code></td><td>Erro de paridade na chave MK</td><td>Problema na chave MK-AC armazenada. Não é um erro de payload. Abrir chamado com o suporte técnico da First Tech.</td></tr><tr><td><code>52</code></td><td>Branch/Height inválido</td><td>Parâmetro <code>branch_height_params</code> incompatível com o esquema. Confirmar se o esquema requer esse parâmetro.</td></tr><tr><td><code>68</code></td><td>Comando desabilitado</td><td>O comando EMV está desabilitado para o <code>client_id</code>/contrato. Contatar o suporte First Tech para validar a habilitação.</td></tr><tr><td><code>F1</code></td><td>Método de derivação de chave inválido</td><td>O método de derivação inferido a partir do <code>schemeId</code> está incompatível com a MK-AC. Revisar perfil do cartão.</td></tr><tr><td><code>F2</code></td><td>Método de validação ARQC inválido</td><td>Método de validação inconsistente com o esquema. Revisar <code>schemeId</code> e <code>mode</code>.</td></tr><tr><td><code>F3</code></td><td>Algoritmo da chave MK-AC não é AES</td><td>O esquema selecionado exige MK-AC AES, mas a chave provisionada usa outro algoritmo. Verificar onboarding da chave.</td></tr><tr><td><code>F5</code></td><td>Método de chave de sessão inválido</td><td>Incompatibilidade entre o método de <em>session key</em> do esquema e a configuração do HSM.</td></tr><tr><td><code>F8</code></td><td>Método de geração de chave OTPK inválido</td><td>Método OTPK incompatível com o esquema. Revisar <code>schemeId</code>.</td></tr></tbody></table>

### Interpretação Rápida dos Códigos

* **Problemas na Aplicação (Cliente):** A maioria dos códigos (`01`, `03-06`, `52`, `F1-F8`) indica problema no payload enviado ou na configuração do cartão/esquema. A correção deve ser feita no seu código.
* **Problemas de Infraestrutura (First Tech):** Os códigos `10` (paridade da chave MK) e `68` (comando desabilitado) indicam falha no provisionamento do lado da First Tech. A correção depende da abertura de chamado técnico.

### Guia de Troubleshooting

A tabela abaixo organiza os sintomas mais frequentes relatados nas integrações, as suas causas prováveis e as ações sugeridas. Para casos não cobertos, abra um chamado em `api.hop@first-tech.com`

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Sintoma Observado</th><th>Causa Provável</th><th>Ação Sugerida</th></tr></thead><tbody><tr><td>HTTP 401 intermitente</td><td>Token JWT a expirar entre chamadas.</td><td>Implementar renovação proativa do token e <em>fallback</em> reativo em caso de 401.</td></tr><tr><td>HTTP 401 consistente</td><td>Credenciais OAuth2 inválidas ou <em>audience</em> errada.</td><td>Validar <code>client_id</code>/<code>client_secret</code> e se a <em>audience</em> é a correta (<code>https://auth-jwt-authorize-prd-first-tech</code>).</td></tr><tr><td>HTTP 404 ("chave não encontrada")</td><td><code>mkacKeyId</code> inexistente para o <code>client_id</code> atual ou ambiente trocado (PRD vs HML).</td><td>Confirmar o <code>mkacKeyId</code> com a equipa da First Tech e validar o ambiente.</td></tr><tr><td>HTTP 400 (retCode = 01)</td><td>ARQC não confere com a chave/cartão.</td><td>Revisar PAN, PSN, <code>field55EmvTags</code> e <code>schemeId</code>. Se tudo estiver correto, o cartão foi adulterado ou sofreu colisão; recusar transação.</td></tr><tr><td>HTTP 400 (retCode = 04)</td><td><code>mode</code> fora da faixa suportada.</td><td>Revisar os valores permitidos: 0, 1, 2, 3, 4, 5, 6, 8, 9.</td></tr><tr><td>HTTP 400 (retCode = 05)</td><td><code>schemeId</code> fora da faixa suportada.</td><td>Confirmar o perfil criptográfico do cartão com o emissor/bandeira.</td></tr><tr><td>retCode = F1 / F2 / F5 / F8</td><td>O <code>schemeId</code> selecionado não é compatível com o método de derivação da chave MK-AC provisionada.</td><td>Revisar combinação <code>schemeId</code> x <code>brand</code> e verificar se a chave referenciada em <code>mkacKeyId</code> é a correta.</td></tr><tr><td>HTTP 500 ocasional</td><td>Falha transitória do serviço.</td><td><p>Aplicar <em>retry</em> com <em>backoff</em> (ex.: 3 tentativas com 100ms, 400ms, 1s). Se persistir, abrir chamado.</p><p><a class="button secondary"></a></p></td></tr><tr><td>Latência acima do esperado</td><td><em>Round-trip</em> adicional por uso de <code>mode=0</code> seguido de <code>mode=2</code> ou <code>4</code>.</td><td><p>Migrar para um modo combinado (<code>1</code>, <code>3</code> ou <code>5</code>) quando a lógica do emissor permitir.</p><p><a class="button secondary"></a></p></td></tr></tbody></table>

## Integração Prática: Fluxos e Exemplos

Esta secção reúne o roteiro prático para colocar o módulo EMV em produção, incluindo boas práticas, armadilhas comuns e exemplos reais de JSON para os cenários mais frequentes .

### Fluxo Recomendado de Integração

A integração típica segue cinco etapas lógicas que aceleram o tempo até a primeira transação validada :

* **Onboarding de Credenciais:** Obtenha o `client_id`, `client_secret` e o identificador da chave (`mkacKeyId`). Valide o fluxo OAuth2 e teste uma chamada trivial em homologação para confirmar o token .
* **Mapeamento dos Dados EMV:** Identifique onde os dados EMV chegam (geralmente via campo 55 da ISO 8583). Mapeie o PAN, PSN e garanta que o formato TLV hexadecimal é preservado no `field55EmvTags` .
* **Decisão do Modo de Operação:** Para autorizações online, selecione `mode=1` (ARC) ou `mode=3` (CSU). Dê preferência a modos combinados para poupar *round-trips* ao HSM .
* **Testes em Homologação:** Execute os seguintes cenários de teste obrigatórios:
  * ARQC válido + aprovação (`arc=00`)
  * ARQC válido + negação (`arc=05`)
  * ARQC inválido (cartão adulterado)
  * Chave inexistente / Modo inválido.
* **Go-Live e Monitorização:** Na janela de corte produtivo, monitorize nas primeiras 24-72h a latência, a taxa de sucesso e possíveis erros 401 (problemas de token) . Configure alertas críticos para `retCode` 10 e 68.

### Boas Práticas e Armadilhas Comuns

Antes de analisar os payloads, valide se a sua implementação cumpre estes requisitos vitais:

**Boas Práticas:**

* **Preservar o formato TLV do campo 55:** O valor de `field55EmvTags` deve ser passado exatamente como recebido, em hexadecimal. Evite manipulações de *string* (remoção de espaços, conversão de *case*), pois isso corrompe o formato. A extração da tag `9F26` é feita internamente pelo serviço.
* **Pin de `schemeId` por BIN:** Mantenha uma tabela interna no emissor que mapeia `BIN` ➔ `brand` ➔ `schemeId`. É a forma mais segura de selecionar os parâmetros corretos por cartão.
* **Idempotência no Cliente:** A API não oferece idempotência nativa. Implemente-a localmente com um *cache* de respostas por alguns segundos para contornar *timeouts* ou *retries* de rede.

{% hint style="warning" %}

#### As 5 Armadilhas mais comuns na integração:

1\. `mkacKeyId` com `client_id` errado (Gera HTTP 404) .

2\. `schemeId` incompatível com o cartão (Gera retCode F1, F2 ou F5) .

3\. Enviar `mode` que obriga `arc` ou `csu`, mas esquecer de preencher o campo (Gera HTTP 400 com retCode 04).

4\. Alterar qualquer byte no `field55EmvTags`, corrompendo o TLV.

5\. Reutilizar token JWT já expirado, travando o lote de transações.
{% endhint %}

### Exemplos Práticos por Cenário

Os exemplos abaixo ilustram os usos mais frequentes. *Nota: Os payloads estão simplificados para foco didático e os valores reais dependerão do cartão e do ambiente* .

#### Cenário 1: Autorização online com ARPC método 1 (ARC)

Fluxo mais comum em emissores tradicionais. Em uma única chamada, o ARQC é validado e o ARPC é gerado com base no código de resposta (`arc=00`) .

**Request** (`POST /ValidateARQC4x`):

```json
JSON
{
  "client_id": 8,
  "brand": "VISA",
  "mode": "1",
  "schemeId": "0",
  "iv_ac": null,
  "branch_height_params": null,
  "mkacKeyId": "client-8-mk-ac-visa",
  "pan": "4111111111111111",
  "panSeqNr": "00",
  "field55EmvTags": "9F2608...9F3602003F...",
  "arc": "00"
}
```

**Response** (Aprovação):

```json
JSON
{
  "retCode": 0,
  "retValue": "70EFBFBDD89DEFBF",
  "retValid": true,
  "retDescription": "OK"
}
```

#### Cenário 2: Autorização online com ARPC método 2 (CSU)

Fluxo para esquemas modernos (Visa qVSDC, Mastercard M/Chip Advance). O `csu` de 4 bytes substitui o `arc` e o `mode` é alterado para `3` .

**Request** (`POST /ValidateARQC4x`):

```json
JSON
{
  "client_id": 8,
  "brand": "VISA",
  "mode": "3",
  "schemeId": "9",
  "iv_ac": null,
  "branch_height_params": null,
  "mkacKeyId": "client-8-mk-ac-visa-qvsdc",
  "pan": "4111111111111111",
  "panSeqNr": "00",
  "field55EmvTags": "9F2608...",
  "csu": "03820000"
}
```

#### Cenário 3: Apenas validar ARQC (Sem gerar ARPC)

Útil quando a geração do ARPC acontece numa etapa posterior. O `retValue` ficará vazio .

```json
JSON
{
  "client_id": 8,
  "brand": "MASTERCARD",
  "mode": "0",
  "schemeId": "1",
  "mkacKeyId": "client-8-mk-ac-mc",
  "pan": "5555555555554444",
  "panSeqNr": "00",
  "field55EmvTags": "9F2608..."
}
```

#### Cenário 4: Gerar ARPC sem revalidar ARQC

Evita uma segunda verificação criptográfica, reduzindo latência, útil quando a validação já foi feita antes. Obriga informar o `arc` (ou `csu`) .

```json
JSON
{
  "client_id": 8,
  "brand": "MASTERCARD",
  "mode": "2",
  "schemeId": "1",
  "mkacKeyId": "client-8-mk-ac-mc",
  "pan": "5555555555554444",
  "panSeqNr": "00",
  "field55EmvTags": "9F2608...",
  "arc": "00"
}
```

#### Cenário 5: ARQC Inválido (Cartão Recusado)

Quando o ARQC recebido não corresponde à chave do emissor, a API retorna erro com `retCode = 1`. A aplicação deve tratar este caso imediatamente como transação recusada .

**Response de Erro:**

```json
JSON
{
  "retCode": 1,
  "retValue": "",
  "retMultiValue": null,
  "retValid": false,
  "retDesc": "Warning: ARQC/TC/AAC/MPVV verification failure"
}
```


# Apêndices

Esta secção contém materiais de consulta rápida e referências normativas que auxiliam na compreensão dos dados processados pelo módulo EMV e no entendimento da terminologia técnica utilizada.

### Apêndice A. Tags EMV (Campo 55) Relevantes

As tags listadas abaixo são as mais relevantes para a integração com o módulo. Todas elas trafegam no payload dentro do campo `field55EmvTags`, codificadas no formato TLV (Tag-Length-Value) em hexadecimal .

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Tag</th><th>Nome</th><th>Descrição Técnica</th></tr></thead><tbody><tr><td><code>9F26</code></td><td><em>Application Cryptogram</em></td><td>O ARQC propriamente dito (8 bytes). É extraído automaticamente pelos endpoints EMV.</td></tr><tr><td><code>9F36</code></td><td><em>Application Transaction Counter</em> (ATC)</td><td>Contador sequencial de transações do cartão (2 bytes). Utilizado na derivação da chave de sessão.</td></tr><tr><td><code>9F10</code></td><td><em>Issuer Application Data</em> (IAD)</td><td>Dados proprietários do emissor usados na verificação do ARQC. O tamanho é variável dependendo da bandeira e CVN.</td></tr><tr><td><code>8C</code></td><td>CDOL1</td><td><em>Card Risk Management Data Object List 1</em>. Lista de tags que o cartão solicitou ao terminal para gerar o ARQC.</td></tr><tr><td><code>9F02</code></td><td><em>Amount, Authorised</em></td><td>Valor da transação autorizada, em centavos, formato de 12 dígitos BCD.</td></tr><tr><td><code>5F2A</code></td><td><em>Transaction Currency Code</em></td><td>Código ISO 4217 numérico da moeda (ex.: <code>986</code> para BRL).</td></tr><tr><td><code>9A</code></td><td><em>Transaction Date</em></td><td>Data da transação no formato YYMMDD (3 bytes).</td></tr><tr><td><code>9C</code></td><td><em>Transaction Type</em></td><td>Código do tipo de transação (<code>00</code> = compra, <code>01</code> = compra com cashback, <code>20</code> = refund).</td></tr><tr><td><code>91</code></td><td><em>Issuer Authentication Data</em></td><td>Tag na qual o ARPC é transportado de volta ao cartão. Tipicamente contém o ARPC (8 bytes) + ARC (2 bytes) ou ARPC + CSU.</td></tr></tbody></table>

{% hint style="info" %}
Referência Normativa\
A especificação EMV completa sobre as tags está disponível no documento EMV 4.x, Book 3 — Application Specification, publicado pela EMVCo . Para particularidades de cada bandeira, consulte também os cadernos proprietários (ex.: Visa VIS, Mastercard M/Chip Requirements).
{% endhint %}

### Apêndice B. Glossário

Dicionário de siglas e termos técnicos que aparecem ao longo da documentação da Hop V4 .

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Termo / Sigla</th><th>Definição</th></tr></thead><tbody><tr><td>AAC</td><td><em>Application Authentication Cryptogram</em>. Criptograma gerado pelo cartão quando a transação é recusada.</td></tr><tr><td>AES</td><td><em>Advanced Encryption Standard</em>. Algoritmo simétrico usado em esquemas EMV modernos.</td></tr><tr><td>ARC</td><td><em>Authorization Response Code</em>. Código de 2 bytes em hexadecimal que representa a resposta do emissor (ex.: <code>00</code> = aprovado, <code>05</code> = negado). Usado no método 1 de ARPC.</td></tr><tr><td>ARPC</td><td><em>Authorization Response Cryptogram</em>. Criptograma gerado pelo emissor em resposta ao ARQC.</td></tr><tr><td>ARQC</td><td><em>Authorization Request Cryptogram</em>. Criptograma gerado pelo cartão no início da autorização online.</td></tr><tr><td>ATC</td><td><em>Application Transaction Counter</em>. Contador sequencial do cartão, incrementado a cada transação.</td></tr><tr><td>BIN</td><td><em>Bank Identification Number</em>. Primeiros 6 a 8 dígitos do PAN, que identificam o emissor e o produto.</td></tr><tr><td>CDOL1</td><td><em>Card Risk Management Data Object List 1</em>. Lista de tags que o cartão solicita do terminal para gerar o ARQC.</td></tr><tr><td>CSU</td><td><em>Card Status Update</em>. Campo de 4 bytes em hexadecimal que representa a resposta do emissor no método 2 de ARPC.</td></tr><tr><td>CVN</td><td><em>Cryptogram Version Number</em>. Versão do esquema criptográfico usado pelo cartão.</td></tr><tr><td>EMV</td><td>Padrão internacional para transações com cartões chip, mantido pela EMVCo.</td></tr><tr><td>EMVCo</td><td>Consórcio mantenedor do padrão EMV, composto por Amex, Discover, JCB, Mastercard, UnionPay e Visa.</td></tr><tr><td>HSM</td><td><em>Hardware Security Module</em>. Dispositivo dedicado para armazenamento e uso de chaves criptográficas.</td></tr><tr><td>IAD</td><td><em>Issuer Application Data</em>. Tag <code>9F10</code> — dados proprietários do emissor usados na verificação do ARQC.</td></tr><tr><td>ISO 8583</td><td>Padrão internacional de mensageria para transações de cartão de pagamento.</td></tr><tr><td>JWT</td><td><em>JSON Web Token</em>. Formato do token emitido pelo OAuth2 e usado no cabeçalho <code>Authorization</code>.</td></tr><tr><td>MK-AC</td><td><em>Master Key for Application Cryptogram</em>. Chave mestra do emissor usada para derivar a chave de sessão do cartão.</td></tr><tr><td>MPVV</td><td><em>Mastercard PIN Verification Value</em>. Algoritmo proprietário Mastercard para verificação de PIN.</td></tr><tr><td>OAuth2</td><td>Protocolo de autorização. A Hop V4 utiliza o fluxo <code>client_credentials</code>.</td></tr><tr><td>OTPK</td><td><em>One-Time Pin Key</em>. Chave de uso único em alguns esquemas.</td></tr><tr><td>PAN</td><td><em>Primary Account Number</em>. Número do cartão.</td></tr><tr><td>PCI HSM</td><td>Padrão do <em>PCI Security Standards Council</em> para HSMs que processam dados de cartão.</td></tr><tr><td>PIN</td><td><em>Personal Identification Number</em>.</td></tr><tr><td>PSN</td><td><em>PAN Sequence Number</em>. Identifica aplicações adicionais no mesmo cartão.</td></tr><tr><td>qVSDC</td><td><em>Quick Visa Smart Debit/Credit</em>. Esquema contactless da Visa.</td></tr><tr><td>Scheme ID</td><td>Identificador do esquema criptográfico EMV utilizado pelo cartão.</td></tr><tr><td>TC</td><td><em>Transaction Certificate</em>. Criptograma gerado pelo cartão ao final de uma transação offline aprovada.</td></tr><tr><td>TLV</td><td><em>Tag-Length-Value</em>. Formato de codificação usado em EMV para estruturar os dados do campo 55.</td></tr><tr><td>VIS</td><td><em>Visa Integrated Circuit Card Specification</em>. Esquema tradicional Visa.</td></tr></tbody></table>


# Introdução e Fundamentos

### Módulo Crypto

O módulo PayShield Crypto da plataforma Hop V4 oferece um conjunto de operações criptográficas simétricas executadas integralmente dentro do HSM (Hardware Security Module) gerenciado pela First Tech. A principal premissa deste serviço é garantir que o material de chave nunca deixe a fronteira segura do hardware.

Este documento fornece ao integrador a referência técnica completa, englobando fundamentos, modelos de dados, fluxo de integração, casos de uso práticos e taxonomia de erros.

### Público-Alvo e Pré-requisitos

Esta documentação é desenhada para:

* Desenvolvedores que integram aplicações ou *hosts* ao Hop V4.
* Arquitetos que avaliam o uso de criptografia gerenciada como serviço.
* Times de Segurança da Informação responsáveis por validar o desenho criptográfico da solução.

#### Pré-requisitos de Integração

Para consumir os endpoints descritos neste guia, certifique-se de que o seu ambiente cumpre os seguintes requisitos:&#x20;

1. Cliente provisionado na plataforma Hop V4, com um `client_id` atribuído.&#x20;
2. Pelo menos uma chave criptográfica cadastrada e associada ao seu `client_id`, com o respectivo alias (`keyId`) conhecido.&#x20;
3. Credenciais Auth0 (token JWT) válidas para o ambiente de destino.
4. Conectividade de rede autorizada para o endpoint `apivin.first-tech.net`.

### Fundamentos do PayShield Crypto

#### Operações Suportadas

O serviço expõe quatro famílias principais de operações criptográficas simétricas:

1. Cifragem de dados (`EncryptData`): Proteção de informações sensíveis para armazenamento seguro ou trânsito.
2. Decifragem de dados (`DecryptData` e `SuperDecryptData`): Recuperação do conteúdo original em texto claro (incluindo suporte a múltiplos blocos).
3. Geração de MAC (`GenerateMac`): Produção de um código de autenticação (Message Authentication Code) para garantir a integridade e autenticidade de mensagens.
4. Validação de MAC (`ValidateMac`): Verificação da integridade e autenticidade do código gerado.

#### Princípio Operacional e Algoritmos

Toda operação criptográfica atua sobre uma chave referenciada pelo seu `keyId`, que funciona como um alias armazenado no banco de dados gerenciado pela First Tech. O material criptográfico real nunca trafega pela API. A sua aplicação envia apenas o identificador da chave e os dados a serem processados; o HSM executa o cálculo e o resultado retorna em formato hexadecimal .

O algoritmo simétrico aplicado (como DES, 3DES ou AES) é determinado automaticamente pelo tipo da chave que foi provisionada. O integrador não precisa enviar o algoritmo no payload; o seu controle resume-se à escolha do modo de operação através do campo `modeEncFlag`

#### Modelo Padrão de Chamada

Para garantir consistência na integração, todos os endpoints do módulo Crypto seguem o mesmo contrato base:

* **Método HTTP:** `POST`.
* **Autenticação:** Bearer Token (JWT obtido via Auth0).
* **Content-Type:** `application/json`.
* **Identificação do Tenant:** Informada obrigatoriamente no campo `client_id` do corpo da requisição (*body*).
* **Identificação da Chave:** Informada no campo `keyId` do *body*.
* **Resposta Padronizada:** Os objetos de retorno sempre conterão os campos `retCode`, `retValue`, `retMultiValue`, `retValid` e `retDesc`.


# Modos de Operação e Retornos

Para integrar com sucesso o módulo PayShield Crypto, é fundamental compreender como a API encadeia os dados durante a cifragem/decifragem e como os objetos de retorno são estruturados.

### Modos de Operação (`modeEncFlag`)

Os modos de operação determinam como blocos sucessivos de dados são encadeados durante a cifragem ou decifragem. A escolha do modo impacta diretamente os requisitos de envio do Vetor de Inicialização (IV) e a resistência da criptografia a determinados ataques.

#### Tabela de Modos Suportados

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Código (modeEncFlag)</th><th>Modo</th><th>IV Obrigatório?</th><th>Característica Principal</th></tr></thead><tbody><tr><td><code>00</code></td><td>ECB</td><td>Não</td><td>Padrão se o campo for <code>null</code> ou ausente. Cada bloco é cifrado independentemente. Não recomendado para dados estruturados.</td></tr><tr><td><code>01</code></td><td>CBC</td><td>Sim</td><td>Encadeia blocos via XOR com o cifrado anterior. É o padrão de mercado para dados em repouso.</td></tr><tr><td><code>02</code></td><td>CFB8</td><td>Sim</td><td>Cifra o fluxo em janelas de 8 bits. Adequado para dados de comprimento arbitrário.</td></tr><tr><td><code>03</code></td><td>CFB64</td><td>Sim</td><td>Variante do CFB com janela de 64 bits.</td></tr></tbody></table>

#### Regras do Vetor de Inicialização (IV)

* Quando é obrigatório: Nos modos `01` (CBC), `02` (CFB8) e `03` (CFB64), o campo `iv` tem de ser enviado na requisição obrigatoriamente. No modo `00` (ECB), pode ser omitido ou enviado como `null`.
* Geração e Formato: O valor deve ser expresso em hexadecimal e tem de ser único por operação (nunca reutilize IVs entre transações com a mesma chave).
* Retorno em Cifragem: Nas operações de `EncryptData` que exigem IV, o vetor utilizado é refletido na resposta através do campo `retMultiValue[1]` (como `ivResp`). Esse valor retornado deve ser armazenado, pois será obrigatório como entrada na decifragem subsequente.

#### Uso de Chaves Derivadas (DUKPT)

Quando a chave referenciada pelo campo `keyId` for do tipo BDK (*Base Derivation Key*), a API passa a exigir parâmetros de DUKPT (*Derived Unique Key Per Transaction*). Neste cenário, os campos `ksn_desc` e `ksn` tornam-se obrigatórios na requisição. A plataforma Hop encarrega-se de derivar a chave de transação correspondente ao KSN informado e utilizá-la para a operação solicitada.

### Mensagem de Retorno

Todos os endpoints da API Crypto retornam o mesmo "envelope" de resposta padronizado.

#### Estrutura Base do Response

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Campo</th><th>Tipo</th><th>Significado</th></tr></thead><tbody><tr><td><code>retCode</code></td><td>integer</td><td>Código numérico de retorno. <code>0</code> indica sucesso; valores diferentes de zero indicam erro (ver secção de códigos de erro).</td></tr><tr><td><code>retValue</code></td><td>string</td><td>Valor de retorno simples. Em operações Crypto, geralmente vem vazio (este campo é mais utilizado noutros módulos PayShield).</td></tr><tr><td><code>retMultiValue</code></td><td>array</td><td>Valores estruturados da operação. O conteúdo deste <em>array</em> varia de acordo com o endpoint acionado (ver tabela abaixo).</td></tr><tr><td><code>retValid</code></td><td>boolean</td><td>Indica se a operação foi bem-sucedida. No endpoint <code>ValidateMac</code>, indica também se o MAC analisado é válido.</td></tr><tr><td><code>retDesc</code></td><td>string</td><td>Descrição textual do resultado. Retorna <code>"OK"</code> em caso de sucesso; ou uma mensagem detalhada em caso de erro.</td></tr></tbody></table>

#### &#x20;`retMultiValue` por Endpoint

O "coração" da resposta em criptografia reside no campo `retMultiValue`. Ele comporta-se de maneira diferente conforme a operação:

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Endpoint</th><th>Posição [0]</th><th></th></tr></thead><tbody><tr><td><code>EncryptData</code></td><td><code>msgRespEncrypted</code> (Hexadecimal)</td><td><code>ivResp</code> (Hexadecimal). Retorna apenas nos modos <code>01</code>, <code>02</code> ou <code>03</code>.</td></tr><tr><td><code>DecryptData</code></td><td><code>msgRespDecrypted</code> (Hexadecimal)</td><td><code>ivResp</code> (Hexadecimal). Retorna apenas nos modos <code>01</code>, <code>02</code> ou <code>03</code>.</td></tr><tr><td><code>SuperDecryptData</code></td><td><em>Array</em> de <em>arrays</em> — Cada item do lote segue estritamente o formato de resposta do <code>DecryptData</code>.</td><td>-</td></tr><tr><td><code>GenerateMac</code></td><td><code>mac</code> gerado (Hexadecimal)</td><td><code>ivResp</code> — Apenas quando <code>macModeFlag</code> for <code>1</code> ou <code>2</code> (encadeamento multi-bloco).</td></tr><tr><td><code>ValidateMac</code></td><td>Confirmação do MAC (echo)</td><td><code>ivResp</code> — Apenas quando <code>macModeFlag</code> for <code>1</code> ou <code>2</code>.</td></tr></tbody></table>


# Referência da API - CRYPTO

Esta página detalha os endpoints responsáveis pela proteção (cifragem) e recuperação (decifragem) de dados, incluindo a operação de decifragem em lote (*SuperDecryptData*).

### Autenticação

Todas as chamadas para os endpoints do módulo Crypto exigem o cabeçalho `Authorization` preenchido com um token Bearer JWT válido.

#### Exemplo de Cabeçalho:

```http
HTTP
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ii4uLiJ9...
```

## Criptografar dados

> Retorna os dados criptografados e o IV (se aplicável) em formato Hex.\
> Em caso de erro, retorna os campos de erro (retCode e retDescription).\
> \
> Retorna em \`retMultiValue\`:\
> \- \`retMultiValue\[0]\` = msgRespEncrypted → Mensagem criptografada\
> \- \`retMultiValue\[1]\` = ivResp → IV para a próxima chamada de descriptografia,\
> &#x20; apenas nos modos modeEncFlag 01, 02, 03. Caso contrário, será null.<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield Crypto API","version":"4.1.32"},"tags":[{"name":"Crypto","description":"Operações de criptografia e descriptografia de dados"}],"servers":[{"url":"https://api-research.first-tech.net/qseed","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"EncryptDataInput":{"allOf":[{"$ref":"#/components/schemas/CryptoInputBase"},{"type":"object","required":["p_ht_data"],"properties":{"p_ht_data":{"type":"string","description":"Dados a serem criptografados em formato H (Hex) ou T (Texto)"},"b_data":{"type":"string","nullable":true,"description":"Dados em formato binário (uso reservado)"}}}]},"CryptoInputBase":{"type":"object","required":["client_id","keyId","modeEncFlag","data_fmt"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave no banco de dados"},"modeEncFlag":{"type":"string","description":"Modo de operação da cifra:\n- `00`: ECB (padrão se null ou valor não listado)\n- `01`: CBC (requer IV)\n- `02`: CFB8 (requer IV)\n- `03`: CFB64 (requer IV)\n"},"ksn_desc":{"type":"string","nullable":true,"description":"Descritor KSN — necessário apenas se o keyId for do tipo BDK (DUKPT)"},"ksn":{"type":"string","nullable":true,"description":"KSN — necessário apenas se o keyId for do tipo BDK (DUKPT)"},"iv":{"type":"string","nullable":true,"description":"Vetor de inicialização em Hex — obrigatório nos modos 01, 02, 03"},"data_fmt":{"type":"string","enum":["H","T"],"description":"Formato dos dados de entrada:\n- `H`: Hexadecimal\n- `T`: Texto\n"}}},"ReturnMultiValue":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValue":{"type":"string","description":"Valor de retorno simples (geralmente vazio em sucesso)"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com os valores de retorno da operação"},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retDesc":{"type":"string","description":"Descrição do resultado"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `-1`: Erro interno\n- `-2`: Formato inválido\n- `137`: Malformação da requisição\n- `155`: Chave não encontrada no banco de dados\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDesc":{"type":"string","description":"Descrição do erro"}}}}},"paths":{"/demo/generate":{"post":{"tags":["Crypto"],"summary":"Criptografar dados","description":"Retorna os dados criptografados e o IV (se aplicável) em formato Hex.\nEm caso de erro, retorna os campos de erro (retCode e retDescription).\n\nRetorna em `retMultiValue`:\n- `retMultiValue[0]` = msgRespEncrypted → Mensagem criptografada\n- `retMultiValue[1]` = ivResp → IV para a próxima chamada de descriptografia,\n  apenas nos modos modeEncFlag 01, 02, 03. Caso contrário, será null.\n","operationId":"encryptData","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EncryptDataInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnMultiValue"}}}},"400":{"description":"Requisição inválida (campo obrigatório ausente ou formato incorreto)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"404":{"description":"Chave não encontrada no banco de dados","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

***

## Descriptografar dados

> Retorna os dados descriptografados e o IV (se aplicável) em formato Hex.\
> Em caso de erro, retorna os campos de erro (retCode e retDescription).\
> \
> Retorna em \`retMultiValue\`:\
> \- \`retMultiValue\[0]\` = msgRespDecrypted → Mensagem descriptografada\
> \- \`retMultiValue\[1]\` = ivResp → IV para a próxima chamada de criptografia,\
> &#x20; apenas nos modos modeEncFlag 01, 02, 03. Caso contrário, será null.\
> \
> O campo \`data\_fmt\` aceita apenas \`H\` (Hexadecimal) ou \`T\` (Texto). O formato \`B\` não é suportado.<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield Crypto API","version":"4.1.32"},"tags":[{"name":"Crypto","description":"Operações de criptografia e descriptografia de dados"}],"servers":[{"url":"https://apivin.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"DecryptDataInput":{"allOf":[{"$ref":"#/components/schemas/CryptoInputBase"},{"type":"object","required":["p_h_data"],"properties":{"p_h_data":{"type":"string","description":"Dados criptografados a serem descriptografados em formato Hex"}}}]},"CryptoInputBase":{"type":"object","required":["client_id","keyId","modeEncFlag","data_fmt"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave no banco de dados"},"modeEncFlag":{"type":"string","description":"Modo de operação da cifra:\n- `00`: ECB (padrão se null ou valor não listado)\n- `01`: CBC (requer IV)\n- `02`: CFB8 (requer IV)\n- `03`: CFB64 (requer IV)\n"},"ksn_desc":{"type":"string","nullable":true,"description":"Descritor KSN — necessário apenas se o keyId for do tipo BDK (DUKPT)"},"ksn":{"type":"string","nullable":true,"description":"KSN — necessário apenas se o keyId for do tipo BDK (DUKPT)"},"iv":{"type":"string","nullable":true,"description":"Vetor de inicialização em Hex — obrigatório nos modos 01, 02, 03"},"data_fmt":{"type":"string","enum":["H","T"],"description":"Formato dos dados de entrada:\n- `H`: Hexadecimal\n- `T`: Texto\n"}}},"ReturnMultiValue":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValue":{"type":"string","description":"Valor de retorno simples (geralmente vazio em sucesso)"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com os valores de retorno da operação"},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retDesc":{"type":"string","description":"Descrição do resultado"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `-1`: Erro interno\n- `-2`: Formato inválido\n- `137`: Malformação da requisição\n- `155`: Chave não encontrada no banco de dados\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDesc":{"type":"string","description":"Descrição do erro"}}}}},"paths":{"/v4/PayShieldCrypto/DecryptData":{"post":{"tags":["Crypto"],"summary":"Descriptografar dados","description":"Retorna os dados descriptografados e o IV (se aplicável) em formato Hex.\nEm caso de erro, retorna os campos de erro (retCode e retDescription).\n\nRetorna em `retMultiValue`:\n- `retMultiValue[0]` = msgRespDecrypted → Mensagem descriptografada\n- `retMultiValue[1]` = ivResp → IV para a próxima chamada de criptografia,\n  apenas nos modos modeEncFlag 01, 02, 03. Caso contrário, será null.\n\nO campo `data_fmt` aceita apenas `H` (Hexadecimal) ou `T` (Texto). O formato `B` não é suportado.\n","operationId":"decryptData","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecryptDataInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnMultiValue"}}}},"400":{"description":"Requisição inválida — formato de data_fmt incorreto ou campo obrigatório ausente","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"404":{"description":"Chave não encontrada no banco de dados","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

## The CryptoInputBase object

```json
{"openapi":"3.0.3","info":{"title":"PayShield Crypto API","version":"4.1.32"},"components":{"schemas":{"CryptoInputBase":{"type":"object","required":["client_id","keyId","modeEncFlag","data_fmt"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave no banco de dados"},"modeEncFlag":{"type":"string","description":"Modo de operação da cifra:\n- `00`: ECB (padrão se null ou valor não listado)\n- `01`: CBC (requer IV)\n- `02`: CFB8 (requer IV)\n- `03`: CFB64 (requer IV)\n"},"ksn_desc":{"type":"string","nullable":true,"description":"Descritor KSN — necessário apenas se o keyId for do tipo BDK (DUKPT)"},"ksn":{"type":"string","nullable":true,"description":"KSN — necessário apenas se o keyId for do tipo BDK (DUKPT)"},"iv":{"type":"string","nullable":true,"description":"Vetor de inicialização em Hex — obrigatório nos modos 01, 02, 03"},"data_fmt":{"type":"string","enum":["H","T"],"description":"Formato dos dados de entrada:\n- `H`: Hexadecimal\n- `T`: Texto\n"}}}}}}
```

## The EncryptDataInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield Crypto API","version":"4.1.32"},"components":{"schemas":{"EncryptDataInput":{"allOf":[{"$ref":"#/components/schemas/CryptoInputBase"},{"type":"object","required":["p_ht_data"],"properties":{"p_ht_data":{"type":"string","description":"Dados a serem criptografados em formato H (Hex) ou T (Texto)"},"b_data":{"type":"string","nullable":true,"description":"Dados em formato binário (uso reservado)"}}}]},"CryptoInputBase":{"type":"object","required":["client_id","keyId","modeEncFlag","data_fmt"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave no banco de dados"},"modeEncFlag":{"type":"string","description":"Modo de operação da cifra:\n- `00`: ECB (padrão se null ou valor não listado)\n- `01`: CBC (requer IV)\n- `02`: CFB8 (requer IV)\n- `03`: CFB64 (requer IV)\n"},"ksn_desc":{"type":"string","nullable":true,"description":"Descritor KSN — necessário apenas se o keyId for do tipo BDK (DUKPT)"},"ksn":{"type":"string","nullable":true,"description":"KSN — necessário apenas se o keyId for do tipo BDK (DUKPT)"},"iv":{"type":"string","nullable":true,"description":"Vetor de inicialização em Hex — obrigatório nos modos 01, 02, 03"},"data_fmt":{"type":"string","enum":["H","T"],"description":"Formato dos dados de entrada:\n- `H`: Hexadecimal\n- `T`: Texto\n"}}}}}}
```

## The DecryptDataInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield Crypto API","version":"4.1.32"},"components":{"schemas":{"DecryptDataInput":{"allOf":[{"$ref":"#/components/schemas/CryptoInputBase"},{"type":"object","required":["p_h_data"],"properties":{"p_h_data":{"type":"string","description":"Dados criptografados a serem descriptografados em formato Hex"}}}]},"CryptoInputBase":{"type":"object","required":["client_id","keyId","modeEncFlag","data_fmt"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave no banco de dados"},"modeEncFlag":{"type":"string","description":"Modo de operação da cifra:\n- `00`: ECB (padrão se null ou valor não listado)\n- `01`: CBC (requer IV)\n- `02`: CFB8 (requer IV)\n- `03`: CFB64 (requer IV)\n"},"ksn_desc":{"type":"string","nullable":true,"description":"Descritor KSN — necessário apenas se o keyId for do tipo BDK (DUKPT)"},"ksn":{"type":"string","nullable":true,"description":"KSN — necessário apenas se o keyId for do tipo BDK (DUKPT)"},"iv":{"type":"string","nullable":true,"description":"Vetor de inicialização em Hex — obrigatório nos modos 01, 02, 03"},"data_fmt":{"type":"string","enum":["H","T"],"description":"Formato dos dados de entrada:\n- `H`: Hexadecimal\n- `T`: Texto\n"}}}}}}
```

## The ReturnMultiValue object

```json
{"openapi":"3.0.3","info":{"title":"PayShield Crypto API","version":"4.1.32"},"components":{"schemas":{"ReturnMultiValue":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValue":{"type":"string","description":"Valor de retorno simples (geralmente vazio em sucesso)"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com os valores de retorno da operação"},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retDesc":{"type":"string","description":"Descrição do resultado"}}}}}}
```

## The ReturnError object

```json
{"openapi":"3.0.3","info":{"title":"PayShield Crypto API","version":"4.1.32"},"components":{"schemas":{"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `-1`: Erro interno\n- `-2`: Formato inválido\n- `137`: Malformação da requisição\n- `155`: Chave não encontrada no banco de dados\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDesc":{"type":"string","description":"Descrição do erro"}}}}}}
```


# Integração Prática e Casos de Uso

Esta secção apresenta o roteiro recomendado para colocar o módulo Crypto em produção e detalha cenários reais de aplicação no ecossistema de pagamentos, ilustrando a sequência exata de chamadas de API .

### Fluxo de Integração Recomendado

As cinco etapas abaixo cobrem o ciclo de vida completo da integração da sua aplicação cliente ao módulo PayShield Crypto, desde o setup até à monitorização em produção .

#### 1. Provisionamento e Setup

* Solicite à equipa da **First Tech** a criação do seu `client_id` e o cadastro das chaves criptográficas necessárias .
* Armazene os `keyId` recebidos de forma segura nas configurações da sua aplicação.
* Defina, em conjunto com o seu time de segurança, os modos de operação (`modeEncFlag`) adequados para cada caso de uso.

#### 2. Gestão de Autenticação

* Obtenha o token Bearer junto ao serviço Auth0 da First Tech .
* Implemente cache do token: Respeite o *Time-To-Live* (TTL) fornecido.
* Renovação proativa: Implemente a renovação do token antes da sua expiração para evitar picos de erros `401` em transações críticas.

#### 3. Operação Padrão

* Construa o payload da requisição com atenção redobrada aos campos de dados (lembre-se: `p_ht_data` para cifragem/MAC e `p_h_data` para decifragem) .
* Configure *timeouts* HTTP adequados ao seu caso de uso (mais curtos para tráfego transacional online, mais longos para processamento *batch*).
* Analise sempre o `retCode` no envelope de resposta antes de validar a flag `retValid`.

#### 4. Tratamento de Erros e Resiliência

* Erros `4xx`: Geralmente indicam problemas estruturais na requisição (ex.: payload inválido, chave incorreta). Não aplique *retry* cego sem corrigir a origem do problema .
* Erros `5xx`: Podem representar falhas transitórias do serviço ou de rede. Implemente políticas de *retry* com *backoff* exponencial e *jitter* .
* Regra de Segurança: Registe nos *logs* os campos `retCode` e `retDesc`, mas nunca imprima o conteúdo em claro de `p_ht_data` ou os retornos criptografados.

#### 5. Observabilidade em Produção

* Métricas Mínimas: Monitorize a taxa de chamadas por endpoint, a latência nos percentis `p50`/`p95`/`p99`, e a volumetria de erros agrupada por `retCode` .
* Alertas: Configure alarmes para desvios de SLA (latência), incrementos súbitos do `retCode 155` (Chave não encontrada) ou respostas `401` persistentes.

### Casos de Uso Reais da Indústria

#### Cenário 1: Tokenização de PAN para Armazenamento

Desafio: Uma aplicação necessita de armazenar números de cartão (PAN) em base de dados própria, mantendo o dado cifrado em repouso e garantindo que as chaves não fiquem na posse da própria aplicação .

**Sequência de Operações:**

1. Ingestão: A aplicação recebe o PAN em claro via canal seguro (TLS) .
2. Cifragem: A API do cliente consome o endpoint `EncryptData` (modo CBC ou ECB) .
3. Retorno Seguro: O Hop devolve o PAN cifrado e o IV utilizado. Imediatamente, a API descarta o PAN em claro da memória .
4. Persistência: O PAN cifrado, o IV e o `keyId` são armazenados na base de dados .
5. Recuperação: Ao necessitar do dado (ex.: autorização), a base de dados fornece a cifra e o IV à API .
6. Decifragem: A API consome o endpoint `DecryptData` .
7. Entrega: O Hop devolve o PAN em claro, que é entregue à aplicação final e descartado da memória após o uso .

#### Cenário 2: Proteção de Campo Sensível em Mensagem ISO 8583

Desafio: Um *host* adquirente recebe mensagens transacionais (ISO 8583) de um POS contendo campos sensíveis cifrados com chave de sessão. O *host* precisa de os decifrar e re-cifrar com chave de zona antes de encaminhar à bandeira.

**Sequência de Operações:**

1. Origem: O POS envia a mensagem ISO 8583 com o campo sensível cifrado .
2. Decifragem Transitória: O *host* adquirente extrai o campo e consome o `DecryptData` no Hop (modo CBC) .
3. Tratamento: O Hop devolve o dado em claro. O *host* valida o conteúdo (ex.: formato, expiração do cartão) .
4. Re-cifragem (Roteamento): O *host* consome novamente o `EncryptData`, desta vez aplicando a chave ZPK específica para a bandeira ou emissor .
5. Finalização: A autorização retorna do emissor e é devolvida ao POS .

#### Cenário 3: Migração de Base com Rotação de Chaves

Desafio: Troca programada da chave criptográfica de uma base inteira de dados para cumprir exigências de conformidade (PCI DSS). A operação é feita em *batch* .

**Sequência de Operações:**

1. Leitura: O *Job* lê um lote de `N` registos cifrados e os seus respetivos IVs da base antiga .
2. Decifragem em Massa: O *Job* invoca o `SuperDecryptData` referenciando a chave antiga .
3. Memória Volátil: O Hop devolve a lista de dados em claro. Estes dados são mantidos apenas em memória e não são guardados em ficheiros intermediários .
4. Re-cifragem Individual: O *Job* itera sobre cada registo invocando `EncryptData` com o `keyId` da nova chave .
5. Recepção: O Hop devolve o novo conteúdo cifrado e o novo IV .
6. Persistência Atualizada: O *Job* grava o registo na base de dados utilizando o novo `keyId` e IV .

#### Cenário 4: MAC Multi-bloco em Comunicação Host-to-Host

Desafio: Envio de ficheiros de remessa ou mensagens muito longas entre dois *hosts* que precisam de ser autenticados com um único MAC, exigindo o particionamento do ficheiro em blocos suportáveis .

**Sequência de Operações:**

1. Primeiro Bloco: O *Host* de origem invoca `GenerateMac` com `macModeFlag = 1` no primeiro segmento .
2. IV Intermediário: O Hop devolve um IV parcial para encadeamento .
3. Blocos Intermediários: O *Host* itera sobre o ficheiro invocando `GenerateMac` com `macModeFlag = 2`, alimentando-o com o IV recebido na etapa anterior .
4. Bloco Final: O *Host* invoca `GenerateMac` com `macModeFlag = 3` com o segmento final. O Hop devolve o MAC definitivo .
5. Transmissão: A mensagem completa e o MAC são enviados ao destino .
6. Validação Rigorosa: O *Host* de destino reproduz o particionamento exato e invoca o `ValidateMac` (com flags 1, 2 e 3). O Hop devolve `retValid: true` se o ficheiro estiver intacto .


# Erros, Troubleshooting e Apêndices

Esta página consolida as diretrizes operacionais, o catálogo de resolução de falhas e o material de referência rápida para garantir uma integração segura, resiliente e de alta performance.

### Boas Práticas de Integração

#### Segurança

* Proteção de Logs: Nunca registe dados em claro (como o conteúdo não-cifrado de `p_ht_data`, PINs ou PANs) em *logs* da aplicação, ferramentas de APM (Application Performance Monitoring) ou consolas.
* Gestão do Vetor de Inicialização (IV): Utilize sempre IVs aleatórios e únicos por cada operação quando utilizar os modos encadeados (`01`, `02` ou `03`). Nunca reutilize um IV com a mesma chave.
* Preparação para Rotação de Chaves: Armazene sempre o `keyId`, os dados cifrados e o IV em conjunto na sua base de dados. Esta prática é essencial para suportar processos futuros de rotação de chave sem a necessidade de refazer a ingestão dos dados originais.
* Controlo de Acesso: Restrinja o acesso de rede ao endpoint `apivin.first-tech.net` através de uma *allowlist* de IPs, sempre que a arquitetura o permitir.

#### Performance

* Operações em Lote: Para cenários de alta volumetria, prefira utilizar o endpoint `SuperDecryptData` em vez de invocar o `DecryptData` individualmente para cada registo.
* Reutilização de Conexões: Reaproveite conexões HTTP (*keep-alive*). O serviço Hop V4 mantém uma conexão persistente e otimizada com o HSM.
* Gestão de Carga: Agende e distribua o processamento de *batch jobs* (lotes pesados) durante as janelas de menor movimento (*off-peak*), preservando assim a capacidade de processamento para as transações *online* de tempo real.

### Códigos de Erro e Troubleshooting

O envelope de erro segue a mesma estrutura do envelope de sucesso. O campo `retCode` indica o tipo específico da falha, enquanto o `retDesc` carrega a descrição textual do problema .

#### Status HTTP e a Taxonomia de `retCode`

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Status HTTP</th><th>Significado Padrão</th><th>retCode</th><th>Descrição do Erro Interno</th></tr></thead><tbody><tr><td><code>200</code></td><td>Operação realizada com sucesso .</td><td><code>0</code></td><td>Sucesso absoluto.</td></tr><tr><td><code>400</code></td><td>Requisição inválida (campo ausente ou formato incorreto) .</td><td><code>-2</code></td><td>Formato inválido (ex.: <code>data_fmt</code> fora do <em>enum</em> esperado).</td></tr><tr><td><code>400</code></td><td>-</td><td><code>137</code></td><td>Malformação da requisição (estrutura comprometida).</td></tr><tr><td><code>401</code></td><td>Não autorizado (Token Bearer ausente ou inválido) .</td><td>-</td><td>Ocorre verificação antes de atingir o HSM.</td></tr><tr><td><code>404</code></td><td>Chave não encontrada no banco de dados.</td><td><code>155</code></td><td>O <code>keyId</code> fornecido não existe ou não pertence ao seu cliente.</td></tr><tr><td><code>400, 404, 500</code></td><td>Erro interno do servidor ou falha genérica .</td><td><code>-1</code></td><td>Erro interno.</td></tr></tbody></table>

#### Guia de Resolução Rápida (Troubleshooting)

A tabela abaixo cruza os sintomas mais comuns com as suas prováveis causas e ações corretivas recomendadas:

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Sintoma Observado</th><th>Causa Provável</th><th>Ação Corretiva</th></tr></thead><tbody><tr><td>HTTP 401 em todas as chamadas</td><td>Token expirado ou ausente.</td><td>Renovar o token no Auth0; verificar se o cabeçalho <code>Authorization</code> está bem formatado.</td></tr><tr><td><code>retCode</code> 155</td><td>O <code>keyId</code> não está cadastrado para o <code>client_id</code> informado.</td><td>Conferir o provisionamento da chave com a equipa da First Tech.</td></tr><tr><td><code>retCode</code> 137 (com payload "aparentemente" correto)</td><td>Campo obrigatório ausente, formato inválido ou erro de digitação (ex.: enviar <code>p_h_data</code> quando o endpoint exige <code>p_ht_data</code>).</td><td>Validar de forma rigorosa o JSON contra o dicionário de dados da API.</td></tr><tr><td><code>retCode</code> -2 no <code>DecryptData</code></td><td>O campo <code>data_fmt</code> é incompatível com o conteúdo fornecido.</td><td>Garantir que o <code>data_fmt</code> é igual a <code>"H"</code> para todo e qualquer dado cifrado enviado para decifragem.</td></tr><tr><td><code>iv</code> retornando <code>null</code> em <code>retMultiValue[1]</code></td><td>O modo de operação selecionado não consome nem gera IV (ex.: ECB).</td><td>Trata-se do comportamento normal e esperado para o modo <code>00</code>.</td></tr><tr><td>Latência alta em <code>SuperDecryptData</code></td><td>Tamanho do lote excede a capacidade ideal por requisição.</td><td>Reduzir a quantidade de itens no <em>array</em> <code>p_h_data</code>.</td></tr><tr><td>MAC inválido (<code>retValid: false</code>) no <code>ValidateMac</code></td><td>A sequência multi-bloco executada no <em>Host</em> de destino está incorreta.</td><td>Validar que os valores de <code>macModeFlag</code>, a ordem das chamadas e o repasse do IV intermediário replicam exatamente o que foi feito na geração do MAC.</td></tr><tr><td>HTTP 400 sem <code>retCode</code> útil</td><td>O conteúdo (<em>body</em>) da requisição está malformado a nível do próprio JSON.</td><td>Validar o JSON antes do envio (usar um <em>linter</em> ou esquema validador).</td></tr></tbody></table>

***

### Apêndice A. Glossário de Termos

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Termo / Sigla</th><th>Definição</th></tr></thead><tbody><tr><td>BDK</td><td><em>Base Derivation Key</em>. Chave-mãe DUKPT a partir da qual as chaves de transação são derivadas.</td></tr><tr><td>CBC</td><td><em>Cipher Block Chaining</em>. Modo de operação simétrico que encadeia os blocos via operação lógica XOR.</td></tr><tr><td>CFB</td><td><em>Cipher Feedback</em>. Modo de operação que transforma uma cifra de bloco numa cifra de fluxo contínuo.</td></tr><tr><td>client_id</td><td>Identificador único do <em>tenant</em> (cliente) na plataforma Hop V4.</td></tr><tr><td>DUKPT</td><td><em>Derived Unique Key Per Transaction</em>. Esquema criptográfico onde cada transação utiliza uma chave única que é derivada através do KSN.</td></tr><tr><td>ECB</td><td><em>Electronic Codebook</em>. Modo de operação simétrico mais simples, que cifra cada bloco de forma independente.</td></tr><tr><td>HSM</td><td><em>Hardware Security Module</em>. Dispositivo dedicado, de alta segurança, para a execução de operações criptográficas e gestão de chaves.</td></tr><tr><td>IV</td><td><em>Initialization Vector</em>. Valor aleatório de partida utilizado nos modos encadeados (CBC, CFB).</td></tr><tr><td>JWT</td><td><em>JSON Web Token</em>. Formato padrão do token de autenticação emitido pelo serviço Auth0.</td></tr><tr><td>keyId</td><td>Alias armazenado no banco de dados da plataforma que aponta para uma chave criptográfica física dentro do HSM.</td></tr><tr><td>KSN</td><td><em>Key Serial Number</em>. Identificador necessário para realizar a derivação de chaves em transações DUKPT.</td></tr><tr><td>MAC</td><td><em>Message Authentication Code</em>. Código gerado para garantir a integridade e a autenticidade de uma mensagem em trânsito.</td></tr><tr><td>p_ht_data</td><td>Campo do payload para enviar dados em formato Hexadecimal ou Texto (utilizado no Encrypt e MAC).</td></tr><tr><td>p_h_data</td><td>Campo do payload exclusivo para enviar dados em formato Hexadecimal (utilizado no Decrypt e SuperDecrypt).</td></tr><tr><td>PAN</td><td><em>Primary Account Number</em>. Número principal impresso no cartão de pagamento.</td></tr><tr><td>TPK / ZPK</td><td><em>Terminal PIN Key</em> e <em>Zone PIN Key</em>. Chaves que protegem o PIN entre o terminal/host e entre instituições, respetivamente.</td></tr></tbody></table>

### Apêndice B. Referência Rápida de Endpoints

Consulte esta tabela para mapear rapidamente a operação que deseja realizar com o seu respetivo *endpoint* e campo de dados principal.

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Operação</th><th>Endpoint da API</th><th>Campo de Entrada</th><th>Suporta Lote (Batch)?</th></tr></thead><tbody><tr><td>Cifrar</td><td><code>/v4/PayShieldCrypto/EncryptData</code></td><td><code>p_ht_data</code></td><td>Não.</td></tr><tr><td>Decifrar</td><td><code>/v4/PayShieldCrypto/DecryptData</code></td><td><code>p_h_data</code></td><td>Não.</td></tr><tr><td>Decifrar Lote</td><td><code>/v4/PayShieldCrypto/SuperDecryptData</code></td><td><code>p_h_data[]</code></td><td>Sim.</td></tr><tr><td>Gerar MAC</td><td><code>/v4/PayShieldCrypto/GenerateMac</code></td><td><code>p_ht_data</code></td><td>Multi-bloco (via <code>macModeFlag</code>).</td></tr><tr><td>Validar MAC</td><td><code>/v4/PayShieldCrypto/ValidateMac</code></td><td><code>p_ht_data</code></td><td>Multi-bloco (via <code>macModeFlag</code>).</td></tr></tbody></table>


# Introdução e Fundamentos

O módulo PayShield CVV da plataforma Hop V4 expõe operações via API REST para a geração e validação de códigos de verificação de cartão. Este módulo cobre tanto os códigos estáticos (CVV1, CVV2) gravados ou impressos no cartão, quanto os códigos dinâmicos (dCVV, CVC3) utilizados em transações modernas .

Esta documentação é a referência técnica oficial para equipas de desenvolvimento e integração que vão consumir estes endpoints em sistemas de emissão, autorização e validação de cartões.

#### Pré-requisitos de Integração

Antes de iniciar o consumo dos endpoints, certifique-se de que o seu ambiente cumpre as seguintes exigências:

* Credenciais OAuth2: Client ID e Client Secret válidos para o *tenant* Auth0 da First Tech, com permissão de acesso ao módulo PayShield CVV.
* Client ID do Tenant: O `client_id` numérico atribuído pela First Tech (este identificador é distinto do Client ID utilizado no Auth0).
* Chaves Criptográficas Provisionadas: As chaves precisam estar cadastradas previamente no banco do HSM através do módulo PayShield Key Manager. Serão necessárias chaves do tipo CVK para as operações estáticas e MKAC para as operações dinâmicas.
* Ambiente de Homologação: Acesso liberado ao ambiente de testes para validação da integração antes da passagem para produção.

### O que é CVV/CVC

O CVV (*Card Verification Value*), também conhecido como CVC (*Card Verification Code*) pela MasterCard, é um código numérico curto — tipicamente de três dígitos — utilizado para verificar a posse física do cartão e a integridade dos dados durante uma transação .

O código é gerado através de uma chave criptográfica do emissor (a CVK) combinada com os dados do próprio cartão (PAN, data de expiração e *service code*). Por depender dessa chave segura, apenas o emissor possui a capacidade de validá-lo de forma autêntica .

#### Os Três Tipos de CVV na Hop V4

A API determina o tipo de CVV a ser processado através do campo `serviceCode` enviado na requisição:

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Tipo</th><th>serviceCode a enviar</th><th>Onde aparece</th><th>Característica</th></tr></thead><tbody><tr><td>CVV1 (CVC1)</td><td><em>O valor real do track</em></td><td>Tarja magnética / chip</td><td>Estático, gravado digitalmente no cartão.</td></tr><tr><td>CVV2 (CVC2)</td><td><code>000</code></td><td>Verso do plástico</td><td>Estático, impresso fisicamente.</td></tr><tr><td>dCVV (CVC3)</td><td><code>999</code></td><td>Transações <em>contactless</em> / chip</td><td>Dinâmico, recalculado a cada transação.</td></tr></tbody></table>

#### CVV Estático vs. CVV Dinâmico

Compreender esta divisão dita qual endpoint deve utilizar:

* CVV Estático (CVV1 e CVV2): É gerado uma única vez no momento da emissão. Como o valor permanece inalterado até a substituição do cartão, é vulnerável se intercetado em fraudes *card-not-present* .
  * Endpoints associados: `GenerateCV`, `SuperGenerateCV` e `ValidateCV`.
* CVV Dinâmico (dCVV/CVC3): O código é recalculado pelo cartão a cada nova transação (via chip ou aproximação) utilizando um contador interno (ATC) e dados da bandeira. Isso garante não apenas a posse do cartão, mas a unicidade daquela transação específica.
  * Endpoint associado: `VerifyDynCV`.

### Arquitetura e Autenticação

#### Base URL

Todas as requisições para o módulo CVV devem ser direcionadas à seguinte URL base : `https://apivin.first-tech.net/v4/PayShieldCVV/`

#### Autenticação Bearer (JWT)

Todos os endpoints exigem autenticação por token Bearer JWT, que deve ser enviado no cabeçalho `Authorization` da requisição HTTP :

```http
HTTP
Authorization: Bearer <TOKEN_JWT>
Content-Type: application/json
Accept: */*
```

#### Identificação do Cliente e Chave

* Campo `client_id`: Presente no corpo (*body*) de todas as requisições. É a identificação do cliente na plataforma First Tech. As chaves criptográficas utilizadas pertencem a este identificador.
* Campo `keyId`: É o *alias* da chave CVK ou MKAC no banco do HSM. O formato padrão segue a estrutura `client-{client_id}-XX-key-id-XXXX-CVK`


# Padrões de Resposta e Schemas

Os endpoints do módulo CVV partilham um conjunto de *schemas* (modelos de objetos) estruturados como heranças de uma base comum. Conhecer essa arquitetura facilita o reaproveitamento de DTOs (*Data Transfer Objects*) no código da sua aplicação .

### Padrões de Resposta (Envelopes)

Todas as respostas do módulo seguem um envelope unificado. A validação do sucesso de uma chamada deve sempre analisar primeiro o campo `retCode` (onde `0` significa sucesso e qualquer outro valor indica um código de erro proveniente do HSM).

#### ReturnSingle

Utilizado pelos endpoints `GenerateCV`, `ValidateCV` e `VerifyDynCV` (quando o retorno esperado é apenas um valor único).

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Campo</th><th>Tipo</th><th>Descrição</th></tr></thead><tbody><tr><td><code>retCode</code></td><td><code>integer</code></td><td>Código de retorno. <code>0</code> = sucesso; outros valores indicam erro.</td></tr><tr><td><code>retValue</code></td><td><code>string</code></td><td>Valor de retorno simples (o CVV gerado ou uma descrição como <code>"CVV Validated"</code>).</td></tr><tr><td><code>retMultiValue</code></td><td><code>any</code></td><td>Sempre <code>null</code> nestes endpoints.</td></tr><tr><td><code>retValid</code></td><td><code>boolean</code></td><td>Indica se a operação global foi bem-sucedida.</td></tr><tr><td><code>retDesc</code></td><td><code>string</code></td><td>Descrição textual do resultado (ex.: <code>"OK"</code> ou <code>"CVV failed verification"</code>).</td></tr></tbody></table>

#### ReturnMultiValue

Utilizado exclusivamente pelo endpoint `SuperGenerateCV` (quando o retorno é uma matriz de múltiplos valores).

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Campo</th><th>Tipo</th><th>Descrição</th></tr></thead><tbody><tr><td><code>retCode</code></td><td><code>integer</code></td><td>Código de retorno. <code>0</code> = sucesso.</td></tr><tr><td><code>retValue</code></td><td><code>string</code></td><td>Sempre <code>null</code> neste <em>schema</em>.</td></tr><tr><td><code>retMultiValue</code></td><td><code>string[]</code></td><td><em>Array</em> de <em>strings</em> contendo os CVVs gerados, apresentados exatamente na mesma ordem do <em>array</em> enviado na requisição.</td></tr><tr><td><code>retValid</code></td><td><code>boolean</code></td><td>Indica se a operação foi bem-sucedida.</td></tr><tr><td><code>retDesc</code></td><td><code>string</code></td><td>Descrição textual do resultado.</td></tr></tbody></table>

#### ReturnError

Ocorre em respostas HTTP 400, 404 e 500. Mantém o mesmo formato do `ReturnSingle`, mas com `retValid` igual a `false`, `retCode` preenchido com o código de falha do HSM e `retDesc` detalhando o erro .

### Schemas de Entrada (Requisição)

#### CvvInputBase (Campos Comuns)

*Schema* base que é herdado pelas operações de geração e validação estática.

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Campo</th><th>Tipo</th><th>Obrigatório</th><th>Descrição Técnica</th></tr></thead><tbody><tr><td><code>client_id</code></td><td><code>integer</code></td><td>Sim</td><td>Identificador numérico do cliente.</td></tr><tr><td><code>keyId</code></td><td><code>string</code></td><td>Sim</td><td>Alias da chave CVK no banco.</td></tr><tr><td><code>pan</code></td><td><code>string</code></td><td>Sim</td><td>PAN do cartão (1 a 19 dígitos numéricos).</td></tr><tr><td><code>expDate</code></td><td><code>string</code></td><td>Sim</td><td>Data de expiração no formato <code>YYMM</code> ou <code>MMYY</code>.</td></tr><tr><td><code>serviceCode</code></td><td><code>string</code></td><td>Sim</td><td><em>Service code</em> do cartão.</td></tr></tbody></table>

#### Extensões por Endpoint

`GenerateCvInput`: Idêntico ao `CvvInputBase`. Não exige campos adicionais.

`SuperGenerateCvInput`: Estende o `CvvInputBase`, mas substitui o campo de *string* `serviceCode` pelo *array* `serviceCodeArray`.

* `serviceCodeArray` (`string[]`): *Array* de *service codes*. Gera um CVV distinto por cada elemento.

`ValidateCvInput`: Estende o `CvvInputBase` adicionando o código que será submetido a validação.

* `cv` (`string`): O CVV/CVC a ser validado. Exige exatamente 3 dígitos numéricos (Regex: `^[0-9]+$`).
* `dynCv` (`string`): Usado apenas se o `serviceCode` for `"999"`.

`VerifyDynCvInput` (Validação Dinâmica): Este *schema* é completamente autónomo (não herda do base). Utiliza a chave `MKAC` e possui campos exclusivos para mapear a perspetiva dinâmica da bandeira e versão. Os campos detalhados estarão descritos na secção dedicada à validação dinâmica.


# Referência da API — CVV

Esta secção detalha os três endpoints responsáveis pelo ciclo de vida do CVV estático (o código impresso no plástico ou gravado na tarja magnética e no chip). Estas operações utilizam chaves do tipo CVK.

## Gerar CVV/CVC

> Gera o CVV/CVC (Card Verification Value/Code) para um cartão.\
> Retorna o valor gerado em \`retValue\`.\
> Em caso de erro, retorna os campos de erro (\`retCode\` e \`retDesc\`).<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield CVV API","version":"4.1.32"},"tags":[{"name":"CVV","description":"Operações de geração e validação de CVV/CVC estático e dinâmico"}],"servers":[{"url":"https://apivin.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"GenerateCvInput":{"allOf":[{"$ref":"#/components/schemas/CvvInputBase"}]},"CvvInputBase":{"type":"object","required":["client_id","keyId","pan","expDate","serviceCode"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave CVK no banco de dados"},"pan":{"type":"string","minLength":1,"maxLength":19,"description":"PAN do cartão (até 19 dígitos)"},"expDate":{"type":"string","description":"Data de expiração do cartão (formato YYMM ou MMYY conforme configuração do HSM)"},"serviceCode":{"type":"string","description":"Service Code do cartão:\n- Valor do track → CVV tipo 1 (CVV1)\n- `000` → CVV tipo 2 (CVV2)\n- `999` → CVV dinâmico (dCVV)\n"}}},"ReturnSingle":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValue":{"type":"string","nullable":true,"description":"Valor de retorno simples"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retDesc":{"type":"string","description":"Descrição do resultado"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `01`: Falha na verificação do CVV / criptograma\n- `05`: Scheme, Version ID ou Key Derivation Method não reconhecido\n- `06`: Valor YHHHHCC inválido\n- `10`: Erro de paridade na chave CVK A/B ou MK\n- `27`: CVK não é double length\n- `52`: Discretionary Data CVS inválido\n- `68`: Comando desabilitado\n- `E9`: Valor de máscara CVC3 inválido\n- `EA`: Modified PSN Flag inválido\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDesc":{"type":"string","description":"Descrição do erro"}}}}},"paths":{"/v4/PayShieldCVV/GenerateCV":{"post":{"tags":["CVV"],"summary":"Gerar CVV/CVC","description":"Gera o CVV/CVC (Card Verification Value/Code) para um cartão.\nRetorna o valor gerado em `retValue`.\nEm caso de erro, retorna os campos de erro (`retCode` e `retDesc`).\n","operationId":"generateCV","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateCvInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnSingle"}}}},"400":{"description":"Requisição inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"404":{"description":"Chave não encontrada no banco de dados","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

## Gerar múltiplos CVV/CVC

> Versão estendida do GenerateCV que aceita um array de service codes (\`serviceCodeArray\`)\
> e retorna um CVV/CVC gerado para cada service code em \`retMultiValue\`.\
> \
> Útil para gerar CVV1, CVV2 e iCVV de um mesmo cartão em uma única chamada.<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield CVV API","version":"4.1.32"},"tags":[{"name":"CVV","description":"Operações de geração e validação de CVV/CVC estático e dinâmico"}],"servers":[{"url":"https://apivin.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"SuperGenerateCvInput":{"type":"object","required":["client_id","keyId","pan","expDate","serviceCodeArray"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave CVK no banco de dados"},"pan":{"type":"string","minLength":1,"maxLength":19,"description":"PAN do cartão (até 19 dígitos)"},"expDate":{"type":"string","description":"Data de expiração do cartão"},"serviceCodeArray":{"type":"array","items":{"type":"string"},"description":"Array de service codes para geração de múltiplos CVVs em uma única chamada.\nCada elemento gera um CVV correspondente em `retMultiValue`.\n"}}},"ReturnMultiValue":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValue":{"type":"string","nullable":true},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string"},"description":"Array com os CVVs gerados — um por service code enviado"},"retValid":{"type":"boolean"},"retDesc":{"type":"string"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `01`: Falha na verificação do CVV / criptograma\n- `05`: Scheme, Version ID ou Key Derivation Method não reconhecido\n- `06`: Valor YHHHHCC inválido\n- `10`: Erro de paridade na chave CVK A/B ou MK\n- `27`: CVK não é double length\n- `52`: Discretionary Data CVS inválido\n- `68`: Comando desabilitado\n- `E9`: Valor de máscara CVC3 inválido\n- `EA`: Modified PSN Flag inválido\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDesc":{"type":"string","description":"Descrição do erro"}}}}},"paths":{"/v4/PayShieldCVV/SuperGenerateCV":{"post":{"tags":["CVV"],"summary":"Gerar múltiplos CVV/CVC","description":"Versão estendida do GenerateCV que aceita um array de service codes (`serviceCodeArray`)\ne retorna um CVV/CVC gerado para cada service code em `retMultiValue`.\n\nÚtil para gerar CVV1, CVV2 e iCVV de um mesmo cartão em uma única chamada.\n","operationId":"superGenerateCV","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuperGenerateCvInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnMultiValue"}}}},"400":{"description":"Requisição inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"404":{"description":"Chave não encontrada no banco de dados","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

## Validar CVV/CVC

> Valida o CVV/CVC de um cartão.\
> Retorna \`true\` em \`retValid\` se o CVV for válido, \`false\` caso contrário.\
> \
> O campo \`serviceCode\` define o tipo de CVV:\
> \- Valor do track → CVV tipo 1 (CVV1)\
> \- \`000\` → CVV tipo 2 (CVV2)\
> \- \`999\` → CVV dinâmico (dCVV)\
> \
> Em caso de erro, retorna os campos de erro (\`retCode\` e \`retDesc\`).<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield CVV API","version":"4.1.32"},"tags":[{"name":"CVV","description":"Operações de geração e validação de CVV/CVC estático e dinâmico"}],"servers":[{"url":"https://apivin.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"ValidateCvInput":{"allOf":[{"$ref":"#/components/schemas/CvvInputBase"},{"type":"object","required":["cv"],"properties":{"cv":{"type":"string","minLength":3,"maxLength":3,"pattern":"^[0-9]+$","description":"CVV/CVC a ser validado (exatamente 3 dígitos numéricos)"},"dynCv":{"type":"string","nullable":true,"description":"CVV dinâmico (usado apenas para serviceCode `999`)"}}}]},"CvvInputBase":{"type":"object","required":["client_id","keyId","pan","expDate","serviceCode"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave CVK no banco de dados"},"pan":{"type":"string","minLength":1,"maxLength":19,"description":"PAN do cartão (até 19 dígitos)"},"expDate":{"type":"string","description":"Data de expiração do cartão (formato YYMM ou MMYY conforme configuração do HSM)"},"serviceCode":{"type":"string","description":"Service Code do cartão:\n- Valor do track → CVV tipo 1 (CVV1)\n- `000` → CVV tipo 2 (CVV2)\n- `999` → CVV dinâmico (dCVV)\n"}}},"ReturnSingle":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValue":{"type":"string","nullable":true,"description":"Valor de retorno simples"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retDesc":{"type":"string","description":"Descrição do resultado"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `01`: Falha na verificação do CVV / criptograma\n- `05`: Scheme, Version ID ou Key Derivation Method não reconhecido\n- `06`: Valor YHHHHCC inválido\n- `10`: Erro de paridade na chave CVK A/B ou MK\n- `27`: CVK não é double length\n- `52`: Discretionary Data CVS inválido\n- `68`: Comando desabilitado\n- `E9`: Valor de máscara CVC3 inválido\n- `EA`: Modified PSN Flag inválido\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDesc":{"type":"string","description":"Descrição do erro"}}}}},"paths":{"/v4/PayShieldCVV/ValidateCV":{"post":{"tags":["CVV"],"summary":"Validar CVV/CVC","description":"Valida o CVV/CVC de um cartão.\nRetorna `true` em `retValid` se o CVV for válido, `false` caso contrário.\n\nO campo `serviceCode` define o tipo de CVV:\n- Valor do track → CVV tipo 1 (CVV1)\n- `000` → CVV tipo 2 (CVV2)\n- `999` → CVV dinâmico (dCVV)\n\nEm caso de erro, retorna os campos de erro (`retCode` e `retDesc`).\n","operationId":"validateCV","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidateCvInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnSingle"}}}},"400":{"description":"Requisição inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"404":{"description":"Chave não encontrada no banco de dados","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

## Verificar CVV/CVC dinâmico

> Verifica o CVV/CVC dinâmico (dCVV/CVC3) de um cartão para transações contactless e chip.\
> Suporta múltiplas bandeiras: Visa (DCVV), MasterCard (CVC3/PINCVC3), American Express (ExpressPay) e Discover (ZIP DCVV).\
> \
> Retorna \`true\` em \`retValid\` se o CVV dinâmico for válido.\
> Em caso de erro, retorna os campos de erro (\`retCode\` e \`retDesc\`).\
> \
> O comportamento varia conforme o campo \`brand\` e \`dynCvVers\`:\
> \- \*\*Visa\*\* (\`brand: "Visa"\`, \`dynCvVers: 0\`): requer \`expDate\`, \`serviceCode\`, \`atc\`, \`dynCv\`\
> \- \*\*MasterCard\*\* (\`brand: "MasterCard"\`): requer \`ivcvc3\` ou \`trackData\` dependendo da versão\
> \- \*\*American Express\*\* (\`brand: "American Express"\`, \`dynCvVers: 0\`): suporte básico\
> \- \*\*Discover\*\* (\`brand: "Discover"\`): suporte básico<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield CVV API","version":"4.1.32"},"tags":[{"name":"CVV","description":"Operações de geração e validação de CVV/CVC estático e dinâmico"}],"servers":[{"url":"https://apivin.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"VerifyDynCvInput":{"type":"object","required":["client_id","keyId","dynCv","pan","expDate","serviceCode","brand","dynCvVers","kdm","atc"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave MKAC no banco de dados"},"dynCv":{"type":"string","description":"CVV/CVC dinâmico a ser verificado (3N para DCVV ou 5A para CVC3/PINCVC3)"},"pan":{"type":"string","description":"PAN do cartão"},"expDate":{"type":"string","description":"Data de expiração do cartão"},"serviceCode":{"type":"string","description":"Service Code do cartão"},"brand":{"type":"string","enum":["Visa","MasterCard","American Express","Discover"],"description":"Bandeira do cartão — determina o esquema de verificação utilizado"},"dynCvVers":{"type":"integer","description":"Versão do CVV dinâmico. Varia conforme a bandeira:\n- **Visa**: `0` (DCVV)\n- **MasterCard**: `0` (CVC3 com IVCVC3), `1` (CVC3 com PSN+IVCVC3), `2` (CVC3 com track data), `3` (PINCVC3)\n- **American Express**: `0` (ExpressPay 2.0)\n- **Discover**: `0` (ZIP DCVV), `1` (ZIP DCVV Plus)\n"},"kdm":{"type":"string","description":"Método de derivação de chave:\n- `A`: EMV 4.1 Book 2 Option A\n- `B`: EMV 4.1 Book 2 Option B\n- `2`: 16-byte AUKDCVV (apenas Discover)\n- `3`: 24-byte AUKDCVV (apenas Discover)\n"},"atc":{"type":"string","description":"Application Transaction Counter (6N para Visa, 5N para MasterCard)"},"psn":{"type":"string","nullable":true,"description":"PAN Sequence Number — obrigatório para MasterCard versões 1 e 2, e American Express"},"un":{"type":"string","nullable":true,"description":"Unpredictable Number — obrigatório para MasterCard"},"ivcvc3":{"type":"string","nullable":true,"description":"Issuer proprietary static data element — obrigatório para MasterCard versões 0 e 1"},"trackDataLen":{"type":"integer","nullable":true,"description":"Comprimento dos dados de track — obrigatório para MasterCard versões 2 e 3"},"trackData":{"type":"string","nullable":true,"description":"Dados estáticos do track 1 ou 2 — obrigatório para MasterCard versões 2 e 3"}}},"ReturnSingle":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValue":{"type":"string","nullable":true,"description":"Valor de retorno simples"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retDesc":{"type":"string","description":"Descrição do resultado"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `01`: Falha na verificação do CVV / criptograma\n- `05`: Scheme, Version ID ou Key Derivation Method não reconhecido\n- `06`: Valor YHHHHCC inválido\n- `10`: Erro de paridade na chave CVK A/B ou MK\n- `27`: CVK não é double length\n- `52`: Discretionary Data CVS inválido\n- `68`: Comando desabilitado\n- `E9`: Valor de máscara CVC3 inválido\n- `EA`: Modified PSN Flag inválido\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDesc":{"type":"string","description":"Descrição do erro"}}}}},"paths":{"/v4/PayShieldCVV/VerifyDynCV":{"post":{"tags":["CVV"],"summary":"Verificar CVV/CVC dinâmico","description":"Verifica o CVV/CVC dinâmico (dCVV/CVC3) de um cartão para transações contactless e chip.\nSuporta múltiplas bandeiras: Visa (DCVV), MasterCard (CVC3/PINCVC3), American Express (ExpressPay) e Discover (ZIP DCVV).\n\nRetorna `true` em `retValid` se o CVV dinâmico for válido.\nEm caso de erro, retorna os campos de erro (`retCode` e `retDesc`).\n\nO comportamento varia conforme o campo `brand` e `dynCvVers`:\n- **Visa** (`brand: \"Visa\"`, `dynCvVers: 0`): requer `expDate`, `serviceCode`, `atc`, `dynCv`\n- **MasterCard** (`brand: \"MasterCard\"`): requer `ivcvc3` ou `trackData` dependendo da versão\n- **American Express** (`brand: \"American Express\"`, `dynCvVers: 0`): suporte básico\n- **Discover** (`brand: \"Discover\"`): suporte básico\n","operationId":"verifyDynCV","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyDynCvInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnSingle"}}}},"400":{"description":"Requisição inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"404":{"description":"Chave não encontrada no banco de dados","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

## The CvvInputBase object

```json
{"openapi":"3.0.3","info":{"title":"PayShield CVV API","version":"4.1.32"},"components":{"schemas":{"CvvInputBase":{"type":"object","required":["client_id","keyId","pan","expDate","serviceCode"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave CVK no banco de dados"},"pan":{"type":"string","minLength":1,"maxLength":19,"description":"PAN do cartão (até 19 dígitos)"},"expDate":{"type":"string","description":"Data de expiração do cartão (formato YYMM ou MMYY conforme configuração do HSM)"},"serviceCode":{"type":"string","description":"Service Code do cartão:\n- Valor do track → CVV tipo 1 (CVV1)\n- `000` → CVV tipo 2 (CVV2)\n- `999` → CVV dinâmico (dCVV)\n"}}}}}}
```

## The GenerateCvInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield CVV API","version":"4.1.32"},"components":{"schemas":{"GenerateCvInput":{"allOf":[{"$ref":"#/components/schemas/CvvInputBase"}]},"CvvInputBase":{"type":"object","required":["client_id","keyId","pan","expDate","serviceCode"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave CVK no banco de dados"},"pan":{"type":"string","minLength":1,"maxLength":19,"description":"PAN do cartão (até 19 dígitos)"},"expDate":{"type":"string","description":"Data de expiração do cartão (formato YYMM ou MMYY conforme configuração do HSM)"},"serviceCode":{"type":"string","description":"Service Code do cartão:\n- Valor do track → CVV tipo 1 (CVV1)\n- `000` → CVV tipo 2 (CVV2)\n- `999` → CVV dinâmico (dCVV)\n"}}}}}}
```

## The SuperGenerateCvInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield CVV API","version":"4.1.32"},"components":{"schemas":{"SuperGenerateCvInput":{"type":"object","required":["client_id","keyId","pan","expDate","serviceCodeArray"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave CVK no banco de dados"},"pan":{"type":"string","minLength":1,"maxLength":19,"description":"PAN do cartão (até 19 dígitos)"},"expDate":{"type":"string","description":"Data de expiração do cartão"},"serviceCodeArray":{"type":"array","items":{"type":"string"},"description":"Array de service codes para geração de múltiplos CVVs em uma única chamada.\nCada elemento gera um CVV correspondente em `retMultiValue`.\n"}}}}}}
```

## The ValidateCvInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield CVV API","version":"4.1.32"},"components":{"schemas":{"ValidateCvInput":{"allOf":[{"$ref":"#/components/schemas/CvvInputBase"},{"type":"object","required":["cv"],"properties":{"cv":{"type":"string","minLength":3,"maxLength":3,"pattern":"^[0-9]+$","description":"CVV/CVC a ser validado (exatamente 3 dígitos numéricos)"},"dynCv":{"type":"string","nullable":true,"description":"CVV dinâmico (usado apenas para serviceCode `999`)"}}}]},"CvvInputBase":{"type":"object","required":["client_id","keyId","pan","expDate","serviceCode"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave CVK no banco de dados"},"pan":{"type":"string","minLength":1,"maxLength":19,"description":"PAN do cartão (até 19 dígitos)"},"expDate":{"type":"string","description":"Data de expiração do cartão (formato YYMM ou MMYY conforme configuração do HSM)"},"serviceCode":{"type":"string","description":"Service Code do cartão:\n- Valor do track → CVV tipo 1 (CVV1)\n- `000` → CVV tipo 2 (CVV2)\n- `999` → CVV dinâmico (dCVV)\n"}}}}}}
```

## The ReturnSingle object

```json
{"openapi":"3.0.3","info":{"title":"PayShield CVV API","version":"4.1.32"},"components":{"schemas":{"ReturnSingle":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValue":{"type":"string","nullable":true,"description":"Valor de retorno simples"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retDesc":{"type":"string","description":"Descrição do resultado"}}}}}}
```

## The ReturnMultiValue object

```json
{"openapi":"3.0.3","info":{"title":"PayShield CVV API","version":"4.1.32"},"components":{"schemas":{"ReturnMultiValue":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValue":{"type":"string","nullable":true},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string"},"description":"Array com os CVVs gerados — um por service code enviado"},"retValid":{"type":"boolean"},"retDesc":{"type":"string"}}}}}}
```

## The ReturnError object

```json
{"openapi":"3.0.3","info":{"title":"PayShield CVV API","version":"4.1.32"},"components":{"schemas":{"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `01`: Falha na verificação do CVV / criptograma\n- `05`: Scheme, Version ID ou Key Derivation Method não reconhecido\n- `06`: Valor YHHHHCC inválido\n- `10`: Erro de paridade na chave CVK A/B ou MK\n- `27`: CVK não é double length\n- `52`: Discretionary Data CVS inválido\n- `68`: Comando desabilitado\n- `E9`: Valor de máscara CVC3 inválido\n- `EA`: Modified PSN Flag inválido\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDesc":{"type":"string","description":"Descrição do erro"}}}}}}
```


# Integração e Exemplos Práticos

Esta secção detalha como os endpoints do módulo CVV se encaixam na arquitetura real de um emissor ou processador de cartões, apresentando os fluxos recomendados, boas práticas de segurança e exemplos de código prontos a utilizar.

### Fluxo Típico: Emissão de Cartão

No momento da personalização e emissão de um novo cartão, o emissor necessita tipicamente de gerar os três valores de CVV de uma só vez .

O fluxo recomendado é o seguinte:

1. Autenticação: Obter o token JWT via Auth0 (utilizando o *grant* `client_credentials`), que é válido tipicamente por 24 horas.
2. Geração em Lote: Invocar o endpoint `SuperGenerateCV` enviando o *array* `["<track>", "000", "999"]` no campo `serviceCodeArray` para obter o CVV1, CVV2 e dCVV numa única chamada.
3. Persistência e Roteamento: Persistir os valores no sistema do emissor da seguinte forma:
   * O CVV1 segue para gravação na tarja/chip.
   * O CVV2 segue para a gráfica (impressão no plástico).
   * O dCVV é guardado apenas no servidor para validação em transações futuras.
4. Tratamento da Resposta: Verificar se `retCode = 0` e `retValid = true`. Em caso de falha, consultar o catálogo de erros para diagnóstico.

### Fluxo Típico: Autorização de Transação

Para transações e-commerce/MOTO (Card-Not-Present) que exigem o CVV2:

1. Autenticação: Obter ou recuperar do cache o token JWT do Auth0 .
2. Validação Estática: Invocar o `ValidateCV` enviando `serviceCode = "000"` e o `cv` preenchido no checkout pelo portador.
3. Decisão de Negócio: Avaliar o campo `retValid`:
   * `true`: Seguir com a autorização da compra.
   * `false`: Recusar a transação ou solicitar nova digitação do código .

Para transações presenciais (Chip/Contactless) com dCVV:

* Substituir o passo 2 pelo uso do endpoint `VerifyDynCV`, preenchendo os campos dependentes da bandeira (como `brand`, `dynCvVers`, `atc`, etc.) recebidos no momento da aproximação.

### Boas Práticas de Integração

Antes de colocar o código em produção, valide se a sua aplicação cumpre as seguintes diretrizes essenciais de segurança e resiliência:

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Categoria</th><th>Boas Práticas</th></tr></thead><tbody><tr><td>Autenticação</td><td>Cache do JWT: Os tokens Auth0 possuem validade longa. Não solicite um novo token a cada chamada de CVV; isso introduz latência desnecessária e pode esgotar os <em>rate limits</em> do serviço de autenticação.</td></tr><tr><td>Resiliência</td><td>Idempotência Nativa: Os endpoints <code>GenerateCV</code> e <code>SuperGenerateCV</code> são determinísticos. Para os mesmos <em>inputs</em> (PAN, <code>expDate</code>, <code>serviceCode</code> e chave), retornarão sempre o mesmo CVV. Isto permite o <em>replay</em> seguro de requisições em caso de <em>timeout</em> de rede .</td></tr><tr><td>Segurança</td><td>Higienização de Logs: Jamais registe o CVV em texto claro nos <em>logs</em> da sua aplicação. Registe apenas o <code>client_id</code>, <code>keyId</code>, <code>retCode</code> e <code>retDesc</code> para auditoria. Nunca guarde o PAN completo, o campo <code>cv</code> de entrada ou o <code>retValue</code> contendo a resposta .</td></tr><tr><td>Políticas de Retry</td><td>Como tratar erros: Erros <code>500</code> e <code>504</code> podem sofrer tentativas repetidas (<em>retry</em>) com <em>backoff</em> exponencial. Erros <code>400</code> (input inválido), <code>401</code> e <code>404</code> (chave inexistente) não devem ser retentados sem que a aplicação corrija o dado de origem .</td></tr></tbody></table>

### Exemplos de Código

Estes *snippets* demonstram a invocação prática dos endpoints.

#### cURL — Gerar CVV2 (`GenerateCV`)

```bash
Bash
curl -X POST \
  https://apivin.first-tech.net/v4/PayShieldCVV/GenerateCV \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": 42,
    "keyId": "client-42-XX-key-id-XXXX-CVK",
    "pan": "4234567890123456",
    "expDate": "825",
    "serviceCode": "000"
}'
```

#### Python — Validar CVV2 no Checkout (`ValidateCV`)

Python

<pre class="language-python"><code class="lang-python"><strong>Python
</strong>import requests

url = "https://apivin.first-tech.net/v4/PayShieldCVV/ValidateCV"
headers = {
    "Authorization": f"Bearer {token}",
    "Content-Type": "application/json",
}
payload = {
    "client_id": 42,
    "keyId": "client-42-XX-key-id-XXXX-CVK",
    "pan": "4234567890123456",
    "expDate": "825",
    "serviceCode": "000",
    "cv": "515"
}

r = requests.post(url, json=payload, headers=headers, timeout=10)
data = r.json()

if data.get("retValid"):
    print("CVV válido - seguir com autorização")
else:
    print(f"CVV inválido - código {data.get('retCode')}: {data.get('retDesc')}")
</code></pre>

#### Node.js — Gerar os 3 CVVs na Emissão (`SuperGenerateCV`)

<pre class="language-javascript"><code class="lang-javascript"><strong>JavaScript
</strong>const axios = require("axios");

async function gerarCvvsEmissao(token, pan, expDate, trackServiceCode) {
  const url = "https://apivin.first-tech.net/v4/PayShieldCVV/SuperGenerateCV";
  const payload = {
    client_id: 42,
    keyId: "client-42-XX-key-id-XXXX-CVK",
    pan,
    expDate,
    serviceCodeArray: [trackServiceCode, "000", "999"],
  };

  const { data } = await axios.post(url, payload, {
    headers: { Authorization: `Bearer ${token}` },
    timeout: 10000,
  });

  if (!data.retValid) {
    throw new Error(`HSM retCode=${data.retCode}: ${data.retDesc}`);
  }

  const [cvv1, cvv2, dcvvSeed] = data.retMultiValue;
  return { cvv1, cvv2, dcvvSeed };
}
</code></pre>


# Erros, Troubleshooting e Apêndices

Esta página consolida o material de suporte para diagnóstico rápido e consulta de referências normativas do ecossistema de pagamentos aplicadas ao módulo CVV.

### Catálogo de Códigos de Erro (`retCode`)

O campo `retCode` segue a convenção de que `0` representa sucesso. Qualquer outro valor indica uma falha criptográfica ou inconsistência de dados rejeitada diretamente pelo HSM.

A tabela abaixo lista os códigos de erro oficiais e a ação corretiva recomendada :

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Código</th><th>Significado</th><th>Origem</th><th>Ação Recomendada</th></tr></thead><tbody><tr><td><code>01</code></td><td>Falha na verificação do CVV / criptograma.</td><td>HSM</td><td>CVV inválido — recusar a transação ou solicitar nova entrada do CVV ao utilizador.</td></tr><tr><td><code>05</code></td><td>Scheme, Version ID ou Key Derivation Method não reconhecido.</td><td>HSM</td><td>Verificar os valores enviados nos campos <code>brand</code>, <code>dynCvVers</code> e <code>kdm</code> no <code>VerifyDynCV</code>.</td></tr><tr><td><code>06</code></td><td>Valor YHHHHCC inválido.</td><td>HSM</td><td>Erro interno de derivação criptográfica. Abrir chamado com o suporte técnico.</td></tr><tr><td><code>10</code></td><td>Erro de paridade na chave CVK ou MKAC.</td><td>HSM</td><td>A chave referenciada pelo <code>keyId</code> está corrompida. Recadastrar a chave via módulo Key Manager.</td></tr><tr><td><code>27</code></td><td>CVK não é <em>double length</em>.</td><td>HSM</td><td>A chave CVK tem de ter o comprimento correto (DES <em>double-length</em>). Recadastrar a chave.</td></tr><tr><td><code>52</code></td><td>CVS inválido.</td><td>HSM</td><td>Verificar os campos <em>discretionary</em> em transações específicas.</td></tr><tr><td><code>68</code></td><td>Comando desabilitado.</td><td>HSM</td><td>A operação solicitada está desabilitada na configuração do HSM. Contatar o suporte da First Tech.</td></tr><tr><td><code>E9</code></td><td>Valor de máscara CVC3 inválido.</td><td>HSM</td><td>Específico do MasterCard CVC3. Verificar a configuração de bandeira enviada.</td></tr><tr><td><code>EA</code></td><td>Modified PSN Flag inválido.</td><td>HSM</td><td>Específico do MasterCard. Verificar o valor fornecido no campo <code>psn</code>.</td></tr></tbody></table>

### Guia de Troubleshooting

A tabela a seguir cruza os sintomas mais comuns observados nas integrações iniciais com as suas prováveis causas e formas de resolução :

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Sintoma Observado</th><th>Causa Provável</th><th>Como Resolver</th></tr></thead><tbody><tr><td>HTTP 401 em todas as chamadas</td><td>Token JWT expirado ou <em>audience</em> errado.</td><td>Renovar o token via Auth0; conferir se a <em>audience</em> configurada no OAuth é a correta para a API.</td></tr><tr><td>HTTP 404 (com <code>retCode 0</code>)</td><td>O <code>keyId</code> não está cadastrado para este <code>client_id</code>, ou há um erro de digitação no <em>alias</em>.</td><td>Listar as chaves no módulo Key Manager e conferir o nome exato.</td></tr><tr><td>HTTP 400 (com <code>retCode 10</code>)</td><td>Erro de paridade na chave CVK (a chave foi importada incorretamente ou está corrompida).</td><td>Recadastrar a chave no Key Manager utilizando o KCV (Key Check Value) correto.</td></tr><tr><td>HTTP 400 (com <code>retCode 27</code>)</td><td>A CVK foi cadastrada como <em>single-length</em>, mas as operações de CVV exigem <em>double-length</em>.</td><td>Recadastrar a chave com o comprimento adequado.</td></tr><tr><td>HTTP 400 (com <code>retCode 05</code> no <code>VerifyDynCV</code>)</td><td>Combinação inválida entre <code>brand</code>, <code>dynCvVers</code> e <code>kdm</code>.</td><td>Tipicamente causado por enviar um <code>dynCvVers</code> (versão) fora dos valores aceitáveis pela bandeira.</td></tr><tr><td>O CVV gerado não bate com o impresso no plástico</td><td>O formato do <code>expDate</code> diverge entre o que foi enviado (ex: <code>YYMM</code> vs <code>MMYY</code>).</td><td>Validar a configuração do HSM para o seu <em>tenant</em> e padronizar o formato em todas as chamadas.</td></tr><tr><td><code>SuperGenerateCV</code> retorna um array com tamanho inesperado</td><td>Há <em>service codes</em> duplicados no <em>array</em> de entrada.</td><td>Garantir que o <em>array</em> enviado corresponde de forma <code>1:1</code> ao retorno; se precisar de duplicatas, faça chamadas isoladas.</td></tr><tr><td>Latência alta intermitente</td><td>Reuso excessivo de uma única conexão HTTP ou ausência de <em>keep-alive</em>.</td><td>Habilitar <em>keep-alive</em> no seu cliente HTTP. A API mantém um <em>pool</em> otimizado com o HSM, mas a conexão entre si e a API REST depende do seu código cliente.</td></tr></tbody></table>

### Apêndice A. Service Codes (ISO 7813)

O *service code* é um campo de três dígitos presente na tarja magnética e no chip, responsável por definir a tecnologia, restrições geográficas e serviços do cartão. O módulo utiliza-o como insumo criptográfico para o cálculo do CVV1 .

#### Estrutura Padrão (ISO/IEC 7813):

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Posição</th><th>Significado</th><th>Exemplos de Valor</th></tr></thead><tbody><tr><td>1º dígito</td><td>Tecnologia e uso internacional</td><td><code>1</code> = internacional, <code>2</code> = internacional (chip obrigatório), <code>5</code> = nacional, <code>6</code> = nacional (chip), <code>9</code> = teste.</td></tr><tr><td>2º dígito</td><td>Verificação de autorização</td><td><code>0</code> = normal, <code>2</code> = online via emissor, <code>4</code> = verificação obrigatória pelo emissor.</td></tr><tr><td>3º dígito</td><td>Serviços permitidos / PIN</td><td><code>0</code> = sem restrição (PIN obrigatório), <code>1</code> = sem restrição, <code>5</code> = bens e serviços (PIN obrigatório), <code>7</code> = apenas <em>cash</em>.</td></tr></tbody></table>

{% hint style="info" %}

#### Comportamento Especial na Hop V4

Independentemente da norma ISO 7813, a plataforma Hop trata os valores `"000"` e `"999"` como sinalizadores semânticos na requisição: \* `"000"`: Indica que o CVV a ser gerado/validado é o CVV2 (impresso no plástico) . \* `"999"`: Indica tratar-se de um dCVV/CVC3 dinâmico. \* Para o CVV1, deve submeter o valor *real* do *service code* do cartão.
{% endhint %}

#### Apêndice B. Glossário

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Sigla</th><th>Significado</th><th>Contexto de Uso</th></tr></thead><tbody><tr><td>ATC</td><td><em>Application Transaction Counter</em></td><td>Contador interno do cartão chip que incrementa a cada transação. Insumo vital para o cálculo do dCVV/CVC3.</td></tr><tr><td>CVK</td><td><em>Card Verification Key</em></td><td>Chave criptográfica simétrica (geralmente DES <em>double-length</em>) usada para gerar e validar CVVs estáticos (CVV1, CVV2).</td></tr><tr><td>CVV / CVC</td><td><em>Card Verification Value / Code</em></td><td>Código curto que verifica a posse do cartão. CVV é o termo da Visa; CVC é o termo da MasterCard.</td></tr><tr><td>CVV1 / CVC1</td><td>CVV gravado na tarja ou chip</td><td>Estático. Utiliza o <em>service code</em> real do cartão como insumo.</td></tr><tr><td>CVV2 / CVC2</td><td>CVV impresso no verso do cartão</td><td>Estático. Referenciado pelo <em>service code</em> <code>"000"</code> na Hop V4.</td></tr><tr><td>CVC3 / dCVV</td><td>CVV dinâmico</td><td>Recalculado a cada transação (<em>contactless</em>/chip). Referenciado pelo <em>service code</em> <code>"999"</code>.</td></tr><tr><td>HSM</td><td><em>Hardware Security Module</em></td><td>Dispositivo físico seguro que armazena as chaves criptográficas e executa as operações de cifragem sob proteção da LMK.</td></tr><tr><td>JWT</td><td><em>JSON Web Token</em></td><td>Padrão do token de autenticação emitido pelo Auth0 e utilizado no cabeçalho HTTP.</td></tr><tr><td>KCV</td><td><em>Key Check Value</em></td><td>Hash curto que comprova a integridade de uma chave após a sua importação para o HSM.</td></tr><tr><td>KDM</td><td><em>Key Derivation Method</em></td><td>Método utilizado pelo HSM para derivar a chave única da transação a partir da MKAC.</td></tr><tr><td>LMK</td><td><em>Local Master Key</em></td><td>Chave-mestra residente no HSM, responsável por proteger todas as outras chaves armazenadas na base de dados.</td></tr><tr><td>MKAC</td><td><em>Master Key for Application Cryptogram</em></td><td>Chave-mestra do emissor, usada para derivar as chaves de transação em operações de validação dinâmica (dCVV e EMV).</td></tr><tr><td>PAN</td><td><em>Primary Account Number</em></td><td>Número principal do cartão de pagamento (até 19 dígitos).</td></tr><tr><td>PSN</td><td><em>PAN Sequence Number</em></td><td>Número que diferencia múltiplos cartões associados ao mesmo PAN (ex.: titular e adicional).</td></tr><tr><td>UN</td><td><em>Unpredictable Number</em></td><td>Número pseudo-aleatório (<em>nonce</em>) gerado pelo terminal de pagamento para prevenir ataques de repetição (<em>replay</em>).</td></tr></tbody></table>


# Introdução e Fundamentos

O módulo PayShield Key Manager da plataforma Hop V4 centraliza e gere o ciclo de vida das chaves criptográficas (DES, 3DES, AES) através do HSM Thales, sempre protegidas sob a LMK (Local Master Key) .

Como o Key Manager é o módulo de base da plataforma — uma vez que todos os outros módulos (CVV, EMV, PIN, PAN, Crypto) referenciam as chaves aqui cadastradas —, este é o ponto de partida natural para qualquer integração com a Hop V4.

### Para que serve o Módulo Key Manager?

Em plataformas de pagamento, as chaves precisam de ser geradas, importadas, exportadas, rotacionadas e, por vezes, traduzidas entre ambientes. O módulo expõe via API REST as seguintes operações fundamentais :

* Generate: Gera uma nova chave aleatória diretamente no HSM, sob a proteção da LMK. O seu alias (`keyId`) e KCV (*Key Check Value*) são retornados .
* Import: Importa uma chave recebida de um parceiro, encriptada sob uma ZMK (*Zone Master Key*). O HSM decifra com a ZMK e re-cifra com a LMK para armazenamento seguro .
* ImportZMK: Importa a própria ZMK (em formato Key Block Thales), que servirá de base para proteger todas as trocas subsequentes com a contraparte .
* ExportKey: Exporta uma chave armazenada sob a LMK, encriptando-a sob a ZMK do parceiro em formatos específicos (X9.17, TR-31, TKBF).
* TranslateLMK: Traduz uma chave de um LMK antigo para o LMK atual (essencial em migrações de ambiente, como da Hop V3 para V4) .

> Princípio de Proteção Absoluta As chaves nunca aparecem em texto claro fora do HSM. Estão sempre protegidas por outra chave: pela LMK no armazenamento, pela ZMK em trânsito, ou pelo Key Block Thales (que adiciona um MAC de integridade)

### Tipos de Chave (`keyName`)

O campo `keyName` define a finalidade da chave. O HSM impõe regras estritas com base neste tipo (ex.: dita se a chave pode encriptar PIN blocks, calcular MACs ou ser exportada) .

<table data-header-hidden="false" data-header-sticky><thead><tr><th>keyName</th><th>Nome Completo</th><th>Finalidade</th></tr></thead><tbody><tr><td><code>ZMK</code></td><td>Zone Master Key</td><td>Chave-mestra partilhada. Protege outras chaves em trânsito (nunca usada diretamente em transações).</td></tr><tr><td><code>TMK</code></td><td>Terminal Master Key</td><td>Chave-mestra de terminal POS. Protege chaves de trabalho enviadas para o terminal.</td></tr><tr><td><code>ZPK</code></td><td>Zone PIN Key</td><td>Chave de trabalho para encriptar PIN blocks em transações entre zonas.</td></tr><tr><td><code>ZAK</code></td><td>Zone Authentication Key</td><td>Chave para gerar e validar MACs em mensagens entre zonas.</td></tr><tr><td><code>ZEK</code></td><td>Zone Encryption Key</td><td>Chave para encriptar dados gerais em transações.</td></tr><tr><td><code>BDK</code></td><td>Base Derivation Key</td><td>Chave-mestra DUKPT. Deriva chaves únicas de transação (UDK) nos terminais.</td></tr><tr><td><code>CVK</code></td><td>Card Verification Key</td><td>Chave usada na geração/validação de CVV/CVC.</td></tr><tr><td><code>DEK</code></td><td>Data Encryption Key</td><td>Chave genérica de criptografia de dados sensíveis (não-PIN).</td></tr><tr><td><code>KERG</code></td><td>EMV Key Encryption Key</td><td>Proteção de chaves EMV na emissão de cartões com chip.</td></tr></tbody></table>

***

### Tamanhos e Algoritmos (`keySizeType`)

O campo `keySizeType` (um único caractere) define em simultâneo o algoritmo e o tamanho da chave.

<table data-header-hidden="false" data-header-sticky><thead><tr><th>keySizeType</th><th>Algoritmo</th><th>Tamanho Efetivo</th><th>Comentário Prático</th></tr></thead><tbody><tr><td><code>S</code></td><td>DES <em>single length</em></td><td>64 bits (56 + paridade)</td><td>Legado. Vulnerável a <em>brute force</em>; não recomendado para novas chaves.</td></tr><tr><td><code>D</code></td><td>DES <em>double length</em></td><td>128 bits (112 + paridade)</td><td>Padrão tradicional (3DES). Aceite pela maioria das bandeiras.</td></tr><tr><td><code>T</code></td><td>DES <em>triple length</em></td><td>192 bits (168 + paridade)</td><td>Maior segurança em DES. Usado em chaves-mestras de longa duração.</td></tr><tr><td><code>A</code></td><td>AES-128</td><td>128 bits</td><td>Padrão moderno recomendado para novas integrações.</td></tr><tr><td><code>B</code></td><td>AES-192</td><td>192 bits</td><td>Pouco utilizado na prática comercial.</td></tr><tr><td><code>C</code></td><td>AES-256</td><td>256 bits</td><td>Maior nível de segurança AES disponível.</td></tr></tbody></table>

### Modos de Operação (`modeFlag`)

No endpoint `GenerateKey`, o campo `modeFlag` define se a chave será apenas gerada internamente, ou se será também exportada em simultâneo para uma contraparte .

<table data-header-hidden="false" data-header-sticky><thead><tr><th>modeFlag</th><th>Operação</th><th>Campos Extra Exigidos</th><th>Quando Usar</th></tr></thead><tbody><tr><td><code>0</code></td><td>Apenas gerar chave</td><td>-</td><td>Geração de chaves para uso estritamente interno (ex.: ZPK para validar PINs).</td></tr><tr><td><code>1</code></td><td>Gerar e Exportar sob ZMK/TMK</td><td><code>zmk_TMK_flag</code>, <code>zmk_TMK_keyId</code></td><td>Quando a chave será enviada de imediato a um parceiro. Evita invocar o endpoint <code>Export</code> separadamente .</td></tr><tr><td><code>A</code></td><td>Derivar chave</td><td>-</td><td>Esquemas que derivam chaves de uma chave-mãe (ex.: KSI/KSN derivado de BDK).</td></tr><tr><td><code>B</code></td><td>Derivar e Exportar</td><td><code>zmk_TMK_flag</code>, <code>zmk_TMK_keyId</code></td><td>Combinação dos cenários A e 1.</td></tr></tbody></table>

### Esquemas de Exportação (`export_scheme`)

Ao exportar chaves (no endpoint `ExportKey`), a API suporta três métodos de empacotamento. A escolha depende unicamente do formato que o sistema do seu parceiro consegue processar .

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Esquema (export_scheme)</th><th>Padrão e Algoritmo</th><th>Comentário de Integração</th></tr></thead><tbody><tr><td><code>TR31</code></td><td>ASC X9 TR-31 (DES, 3DES, AES, HMAC)</td><td>Recomendado. Inclui MAC de integridade e metadados de uso. Exigido por bandeiras em novas integrações .</td></tr><tr><td><code>X917</code></td><td>ANSI X9.17 (Apenas DES/3DES)</td><td>Esquema legado. Não suporta AES nem validação de integridade. Usar apenas se a contraparte for um sistema legado.</td></tr><tr><td><code>TKBF</code></td><td>Thales Key Block Format (DES, AES, HMAC)</td><td>Formato proprietário. Útil se a contraparte também possuir um HSM Thales.</td></tr></tbody></table>

### Chaves Efêmeras (Tempo de Vida)

A plataforma Hop suporta chaves com tempo de vida útil limitado, ativadas ao definir o campo `is_ephemeral = true` nos endpoints de geração ou importação. O tempo em minutos é estipulado no campo `key_TTL_minutes` . Após expirarem, as chaves tornam-se automaticamente inutilizáveis.

Casos de uso ideais:

* Tokens de sessão para transações específicas.
* Testes em ambiente de homologação (evitando que chaves de teste fiquem acumuladas no banco).
* Rotação de segurança programada.

Todas as respostas de geração e importação devolverão o campo `retKeyTTLmin`, indicando os minutos restantes. Para chaves permanentes (`is_ephemeral = false` ou omitido), este valor retornará `0` .


# Arquitetura, Autenticação e Modelos

Para consumir o módulo Key Manager de forma segura, a sua aplicação deve seguir os padrões de autenticação da plataforma Hop V4 e respeitar rigorosamente os *schemas* de entrada e saída.

### Arquitetura e Autenticação

#### Base URL e Autenticação Bearer (JWT)

Todas as chamadas para o módulo Key Manager utilizam a seguinte URL base : `https://apivin.first-tech.net/v4/PayShieldKeyManager/`

A autenticação é feita através de um token Bearer (JWT) emitido pelo serviço Auth0. O token deve ser transportado no cabeçalho `Authorization` de todas as requisições :

```http
HTTP
Authorization: Bearer <TOKEN_JWT>
Content-Type: application/json
Accept: */*
```

#### Segregação por `client_id` e `keyId`

* Identificação do Cliente (`client_id`): O `client_id` é o identificador numérico da sua empresa. As chaves ficam fisicamente segregadas por este ID no banco de dados do HSM — ou seja, duas chaves de clientes diferentes nunca interagem .
* Identificador da Chave (`keyId`): As respostas de geração e importação devolverão o alias da chave no campo `retValue`. Este alias deve ser guardado e utilizado nas chamadas futuras. O formato padrão segue a estrutura: `client-{client_id}-key-id-XXX-TIPO`.

### Padrões de Resposta (Envelopes de Saída)

As respostas do módulo Key Manager seguem variações de envelope consoante o endpoint acionado.

#### ReturnImpKey

Utilizado em `GenerateKey`, `ImportKey` e `ImportZMK` (onde é necessário devolver a chave, o KCV e o tempo de vida).

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Campo</th><th>Tipo</th><th>Descrição Técnica</th></tr></thead><tbody><tr><td><code>retCode</code></td><td><code>integer</code></td><td>Código de retorno. <code>0</code> = sucesso; outros valores = erro (ver catálogo).</td></tr><tr><td><code>retDescription</code></td><td><code>string</code></td><td>Descrição textual do resultado.</td></tr><tr><td><code>retMultiValue</code></td><td><code>string[]</code></td><td><em>Array</em>. A posição <code>[0]</code> contém o KCV (Key Check Value) da chave gerada/importada.</td></tr><tr><td><code>retValid</code></td><td><code>boolean</code></td><td>Indica se a operação global foi bem-sucedida.</td></tr><tr><td><code>retValue</code></td><td><code>string</code></td><td>O <code>keyId</code> gerado/importado no banco de dados (o alias da chave).</td></tr><tr><td><code>retKeyTTLmin</code></td><td><code>integer</code></td><td>Tempo de vida restante da chave em minutos. Retorna <code>0</code> se não tiver expiração.</td></tr></tbody></table>

#### ReturnMultiValue

Utilizado no `ExportKey` (onde a chave criptografada é devolvida no array).

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Campo</th><th>Tipo</th><th>Descrição Técnica</th></tr></thead><tbody><tr><td><code>retCode</code></td><td><code>integer</code></td><td><code>0</code> = sucesso.</td></tr><tr><td><code>retValue</code></td><td><code>string</code></td><td>Retorna uma <em>string</em> vazia neste endpoint.</td></tr><tr><td><code>retMultiValue</code></td><td><code>string[]</code></td><td><em>Array</em>. A posição <code>[0]</code> contém a chave exportada (encriptada sob a ZMK de destino).</td></tr><tr><td><code>retValid</code></td><td><code>boolean</code></td><td>Indica sucesso.</td></tr><tr><td><code>retDescription</code></td><td><code>string</code></td><td>Descrição textual do resultado.</td></tr></tbody></table>

#### ReturnSingle e ReturnError

* ReturnSingle: Utilizado pelo `TranslateLMK`. A chave re-encriptada sob a LMK atual é devolvida isoladamente na variável `retValue`. O campo `retMultiValue` é `null` .
* ReturnError: Ocorre em respostas HTTP 400, 404 e 500. Mantém a base do `ReturnSingle`, mas com `retValid` em `false`, o código de erro em `retCode` e a mensagem explicativa em `retDescription` .

### Schemas de Entrada (Modelos de Request)

Para simplificar a sua implementação, aqui estão os dicionários de dados exatos que cada endpoint espera receber no seu corpo (`Body`).

#### GenerateKeyInput

Para gerar novas chaves no HSM.

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Campo</th><th>Tipo</th><th>Obrigatório</th><th>Descrição</th></tr></thead><tbody><tr><td><code>client_id</code></td><td><code>integer</code></td><td>Sim</td><td>Identificador numérico do cliente.</td></tr><tr><td><code>keyName</code></td><td><code>string</code></td><td>Sim</td><td>Tipo da chave (ex.: <code>ZEK</code>, <code>ZPK</code>, <code>ZMK</code>, <code>BDK</code>).</td></tr><tr><td><code>keySizeType</code></td><td><code>string</code></td><td>Sim</td><td>Tamanho e algoritmo (ex.: <code>S</code>, <code>D</code>, <code>A</code>).</td></tr><tr><td><code>modeFlag</code></td><td><code>string</code></td><td>Sim</td><td>Modo da operação (<code>0</code>, <code>1</code>, <code>A</code>, <code>B</code>).</td></tr><tr><td><code>zmk_TMK_flag</code></td><td><code>string</code></td><td>Condicional</td><td>Obrigatório se <code>modeFlag</code> for <code>1</code> ou <code>B</code>.</td></tr><tr><td><code>zmk_TMK_keyId</code></td><td><code>string</code></td><td>Condicional</td><td>Alias da ZMK/TMK destino. Obrigatório se <code>modeFlag</code> for <code>1</code> ou <code>B</code>.</td></tr><tr><td><code>is_ephemeral</code></td><td><code>boolean</code></td><td>Não</td><td>Se <code>true</code>, define a chave como efémera.</td></tr><tr><td><code>key_TTL_minutes</code></td><td><code>integer</code></td><td>Condicional</td><td>TTL em minutos. Obrigatório se <code>is_ephemeral = true</code>.</td></tr></tbody></table>

#### ImportKeyInput

Para importar uma chave protegida por uma ZMK.

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Campo</th><th>Tipo</th><th>Obrigatório</th><th>Descrição</th></tr></thead><tbody><tr><td><code>client_id</code></td><td><code>integer</code></td><td>Sim</td><td>Identificador numérico do cliente.</td></tr><tr><td><code>keyName</code></td><td><code>string</code></td><td>Sim</td><td>Tipo da chave a importar.</td></tr><tr><td><code>keySizeType</code></td><td><code>string</code></td><td>Sim</td><td>Tamanho e algoritmo.</td></tr><tr><td><code>key_under_ZMK_to_import</code></td><td><code>string</code></td><td>Sim</td><td>Chave criptografada sob ZMK (Formato Key Block ou X9.17).</td></tr><tr><td><code>ZMK_keyId</code></td><td><code>string</code></td><td>Sim</td><td>Alias da ZMK base que decifrará o pacote.</td></tr><tr><td><em>(Campos efêmeros)</em></td><td>-</td><td>-</td><td>Aceita <code>is_ephemeral</code> e <code>key_TTL_minutes</code>.</td></tr></tbody></table>

#### ImportZMKInput

Para importar uma ZMK base em formato Key Block.

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Campo</th><th>Tipo</th><th>Obrigatório</th><th>Descrição</th></tr></thead><tbody><tr><td><code>client_id</code></td><td><code>integer</code></td><td>Sim</td><td>Identificador numérico do cliente.</td></tr><tr><td><code>kcv</code></td><td><code>string</code></td><td>Sim</td><td>KCV de validação (exatamente 6 caracteres hexadecimais).</td></tr><tr><td><code>keyZMK</code></td><td><code>string</code></td><td>Sim</td><td>A ZMK em formato Key Block Thales puro.</td></tr></tbody></table>

#### ExportKeyInput

Para exportar uma chave para um parceiro.

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Campo</th><th>Tipo</th><th>Obrigatório</th><th>Descrição</th></tr></thead><tbody><tr><td><code>client_id</code></td><td><code>integer</code></td><td>Sim</td><td>Identificador numérico do cliente.</td></tr><tr><td><code>keyId</code></td><td><code>string</code></td><td>Sim</td><td>Alias da chave que deseja exportar.</td></tr><tr><td><code>ZMK_keyId</code></td><td><code>string</code></td><td>Sim</td><td>Alias da ZMK que irá encriptar o pacote para envio.</td></tr><tr><td><code>export_scheme</code></td><td><code>string</code></td><td>Sim</td><td>Esquema de exportação (<code>X917</code>, <code>TR31</code>, <code>TKBF</code>).</td></tr></tbody></table>

#### TranslateLMKInput

Para uso em migrações (tradução de LMK).

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Campo</th><th>Tipo</th><th>Obrigatório</th><th>Descrição</th></tr></thead><tbody><tr><td><code>client_id</code></td><td><code>integer</code></td><td>Sim</td><td>Identificador numérico do cliente.</td></tr><tr><td><code>OldKey</code></td><td><code>string</code></td><td>Sim</td><td>Chave Key Block Thales encriptada sob a LMK antiga.</td></tr></tbody></table>


# Referência da API - KEY MANAGER

Esta secção detalha os três primeiros endpoints do módulo Key Manager, responsáveis por introduzir novas chaves no ambiente seguro do HSM: `GenerateKey` (criação do zero), `ImportKey` (receção de chaves de trabalho de parceiros) e `ImportZMK` (receção da chave-mestra de zona de um parceiro) .

## Gerar chave

> Gera uma nova chave criptográfica no HSM e a armazena no banco de dados.\
> Retorna o \`keyId\` gerado em \`retValue\` e o KCV (Key Check Value) em \`retMultiValue\[0]\`.\
> \
> Suporta geração simples (\`modeFlag: "0"\`) ou geração com exportação simultânea sob ZMK/TMK (\`modeFlag: "1"\`).\
> \
> Quando \`is\_ephemeral: true\`, a chave tem tempo de vida limitado definido por \`key\_TTL\_minutes\`.<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield Key Manager API","version":"4.1.32"},"tags":[{"name":"Key Manager","description":"Operações de geração, importação, exportação e tradução de chaves criptográficas"}],"servers":[{"url":"https://apivin.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"GenerateKeyInput":{"type":"object","required":["client_id","keyName","keySizeType","modeFlag"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyName":{"type":"string","description":"Nome/tipo da chave a ser gerada (ex ZEK, ZPK, ZMK, TMK, BDK)"},"keySizeType":{"type":"string","description":"Tamanho/tipo da chave:\n- S Single DES (64 bits)\n- D Double DES (128 bits)\n- T Triple DES (192 bits)\n- A AES-128\n- B AES-192\n- C AES-256\n"},"modeFlag":{"type":"string","enum":["0","1","A","B"],"description":"Modo de operacao:\n- 0 Gerar chave\n- 1 Gerar chave e exportar sob ZMK/TMK\n- A Derivar chave\n- B Derivar chave e exportar sob ZMK/TMK\n"},"zmk_TMK_flag":{"type":"string","nullable":true,"description":"Flag da ZMK/TMK, obrigatorio quando modeFlag 1 ou B"},"zmk_TMK_keyId":{"type":"string","nullable":true,"description":"Alias da ZMK/TMK, obrigatorio quando modeFlag 1 ou B"},"is_ephemeral":{"type":"boolean","description":"Se true, a chave tera tempo de vida limitado por key_TTL_minutes"},"key_TTL_minutes":{"type":"integer","nullable":true,"description":"Tempo de vida da chave em minutos, obrigatorio quando is_ephemeral true"}}},"ReturnImpKey":{"type":"object","properties":{"retCode":{"type":"integer","description":"Codigo de retorno. 0 = sucesso, outros valores indicam erro"},"retDescription":{"type":"string","description":"Descricao do resultado"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com valores adicionais, retMultiValue[0] contem o KCV da chave gerada/importada"},"retValid":{"type":"boolean","description":"Indica se a operacao foi bem-sucedida"},"retValue":{"type":"string","description":"KeyId gerado/importado no banco de dados"},"retKeyTTLmin":{"type":"integer","description":"Tempo de vida da chave em minutos (0 = sem expiracao)"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Codigo de erro:\n- -1 Erro interno\n- 01 Erro de paridade na chave (aviso)\n- 04 Tipo de chave invalido\n- 05 Flag de comprimento de chave invalido\n- 07 Tipo de ZKA Master Key invalido\n- 10 Erro de paridade na ZMK/TMK\n- 11 Erro de paridade na chave\n- 44 Migracao nao permitida (PCI HSM compliance)\n- 45 Tipo de chave de destino de migracao invalido\n- 68 Comando desabilitado\n- 137 Malformacao da requisicao\n- 155 Chave nao encontrada no banco de dados\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDescription":{"type":"string","description":"Descricao do erro"}}}}},"paths":{"/v4/PayShieldKeyManager/GenerateKey":{"post":{"tags":["Key Manager"],"summary":"Gerar chave","description":"Gera uma nova chave criptográfica no HSM e a armazena no banco de dados.\nRetorna o `keyId` gerado em `retValue` e o KCV (Key Check Value) em `retMultiValue[0]`.\n\nSuporta geração simples (`modeFlag: \"0\"`) ou geração com exportação simultânea sob ZMK/TMK (`modeFlag: \"1\"`).\n\nQuando `is_ephemeral: true`, a chave tem tempo de vida limitado definido por `key_TTL_minutes`.\n","operationId":"generateKey","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateKeyInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnImpKey"}}}},"400":{"description":"Requisição inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"404":{"description":"Chave não encontrada no banco de dados","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

> O papel crítico do KCV (Key Check Value) Observe que o valor `"6DA9EB"` é retornado no `retMultiValue[0]`. Este é o KCV: um *hash* curto de 6 dígitos hexadecimais que serve como impressão digital da chave. É utilizado para confirmar com a contraparte que ambos possuem exatamente a mesma chave, sem nunca revelar a chave em si . Registe sempre o KCV junto com o `keyId` nos seus logs de auditoria.

***

## Importar chave sob ZMK

> Importa uma chave criptográfica que está criptografada sob uma ZMK (Zone Master Key).\
> A chave é descriptografada pelo HSM e re-criptografada sob o LMK, sendo armazenada no banco de dados.\
> Retorna o \`keyId\` gerado em \`retValue\` e o KCV em \`retMultiValue\[0]\`.\
> \
> Quando \`is\_ephemeral: true\`, a chave tem tempo de vida limitado definido por \`key\_TTL\_minutes\`.<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield Key Manager API","version":"4.1.32"},"tags":[{"name":"Key Manager","description":"Operações de geração, importação, exportação e tradução de chaves criptográficas"}],"servers":[{"url":"https://apivin.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"ImportKeyInput":{"type":"object","required":["client_id","keyName","keySizeType","key_under_ZMK_to_import","ZMK_keyId"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyName":{"type":"string","description":"Nome/tipo da chave a ser importada (ex ZEK, ZPK, TMK)"},"keySizeType":{"type":"string","description":"Tamanho/tipo da chave:\n- S Single DES\n- D Double DES\n- T Triple DES\n- A AES-128\n- B AES-192\n- C AES-256\n"},"key_under_ZMK_to_import":{"type":"string","description":"Chave criptografada sob a ZMK a ser importada (formato Key Block ou X9.17)"},"ZMK_keyId":{"type":"string","description":"Alias/identificador da ZMK no banco de dados"},"is_ephemeral":{"type":"boolean","description":"Se true, a chave tera tempo de vida limitado por key_TTL_minutes"},"key_TTL_minutes":{"type":"integer","nullable":true,"description":"Tempo de vida da chave em minutos, obrigatorio quando is_ephemeral true"}}},"ReturnImpKey":{"type":"object","properties":{"retCode":{"type":"integer","description":"Codigo de retorno. 0 = sucesso, outros valores indicam erro"},"retDescription":{"type":"string","description":"Descricao do resultado"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com valores adicionais, retMultiValue[0] contem o KCV da chave gerada/importada"},"retValid":{"type":"boolean","description":"Indica se a operacao foi bem-sucedida"},"retValue":{"type":"string","description":"KeyId gerado/importado no banco de dados"},"retKeyTTLmin":{"type":"integer","description":"Tempo de vida da chave em minutos (0 = sem expiracao)"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Codigo de erro:\n- -1 Erro interno\n- 01 Erro de paridade na chave (aviso)\n- 04 Tipo de chave invalido\n- 05 Flag de comprimento de chave invalido\n- 07 Tipo de ZKA Master Key invalido\n- 10 Erro de paridade na ZMK/TMK\n- 11 Erro de paridade na chave\n- 44 Migracao nao permitida (PCI HSM compliance)\n- 45 Tipo de chave de destino de migracao invalido\n- 68 Comando desabilitado\n- 137 Malformacao da requisicao\n- 155 Chave nao encontrada no banco de dados\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDescription":{"type":"string","description":"Descricao do erro"}}}}},"paths":{"/v4/PayShieldKeyManager/ImportKey":{"post":{"tags":["Key Manager"],"summary":"Importar chave sob ZMK","description":"Importa uma chave criptográfica que está criptografada sob uma ZMK (Zone Master Key).\nA chave é descriptografada pelo HSM e re-criptografada sob o LMK, sendo armazenada no banco de dados.\nRetorna o `keyId` gerado em `retValue` e o KCV em `retMultiValue[0]`.\n\nQuando `is_ephemeral: true`, a chave tem tempo de vida limitado definido por `key_TTL_minutes`.\n","operationId":"importKey","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportKeyInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnImpKey"}}}},"400":{"description":"Requisição inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"404":{"description":"Chave não encontrada no banco de dados","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

***

## Importar ZMK (Zone Master Key)

> Importa uma ZMK (Zone Master Key) em formato Key Block Thales para o HSM.\
> A ZMK é validada pelo KCV informado e armazenada no banco de dados.\
> Retorna o \`keyId\` gerado em \`retValue\` e o KCV em \`retMultiValue\[0]\`.\
> \
> O campo \`keyZMK\` deve estar no formato Key Block Thales (ex: \`S1009652TB00S0001...\`).\
> O campo \`kcv\` deve ter exatamente 6 caracteres hexadecimais.<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield Key Manager API","version":"4.1.32"},"tags":[{"name":"Key Manager","description":"Operações de geração, importação, exportação e tradução de chaves criptográficas"}],"servers":[{"url":"https://apivin.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"ImportZMKInput":{"type":"object","required":["client_id","kcv","keyZMK"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"kcv":{"type":"string","minLength":6,"maxLength":6,"description":"Key Check Value da ZMK (exatamente 6 caracteres hexadecimais)"},"keyZMK":{"type":"string","description":"ZMK em formato Key Block Thales"}}},"ReturnImpKey":{"type":"object","properties":{"retCode":{"type":"integer","description":"Codigo de retorno. 0 = sucesso, outros valores indicam erro"},"retDescription":{"type":"string","description":"Descricao do resultado"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com valores adicionais, retMultiValue[0] contem o KCV da chave gerada/importada"},"retValid":{"type":"boolean","description":"Indica se a operacao foi bem-sucedida"},"retValue":{"type":"string","description":"KeyId gerado/importado no banco de dados"},"retKeyTTLmin":{"type":"integer","description":"Tempo de vida da chave em minutos (0 = sem expiracao)"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Codigo de erro:\n- -1 Erro interno\n- 01 Erro de paridade na chave (aviso)\n- 04 Tipo de chave invalido\n- 05 Flag de comprimento de chave invalido\n- 07 Tipo de ZKA Master Key invalido\n- 10 Erro de paridade na ZMK/TMK\n- 11 Erro de paridade na chave\n- 44 Migracao nao permitida (PCI HSM compliance)\n- 45 Tipo de chave de destino de migracao invalido\n- 68 Comando desabilitado\n- 137 Malformacao da requisicao\n- 155 Chave nao encontrada no banco de dados\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDescription":{"type":"string","description":"Descricao do erro"}}}}},"paths":{"/v4/PayShieldKeyManager/ImportZMK":{"post":{"tags":["Key Manager"],"summary":"Importar ZMK (Zone Master Key)","description":"Importa uma ZMK (Zone Master Key) em formato Key Block Thales para o HSM.\nA ZMK é validada pelo KCV informado e armazenada no banco de dados.\nRetorna o `keyId` gerado em `retValue` e o KCV em `retMultiValue[0]`.\n\nO campo `keyZMK` deve estar no formato Key Block Thales (ex: `S1009652TB00S0001...`).\nO campo `kcv` deve ter exatamente 6 caracteres hexadecimais.\n","operationId":"importZMK","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportZMKInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnImpKey"}}}},"400":{"description":"Requisição inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

#### Por que o KCV é separado

O KCV não é extraído automaticamente do Key Block — ele precisa ser informado pela contraparte e validado contra o resultado da decifração interna no HSM. Se houver divergência, o HSM rejeita a importação (tipicamente com retCode 11). Isso protege contra adulterações da ZMK em trânsito ou erros de digitação.

#### O comportamento de expiração em ZMKs

Nas respostas de sucesso deste endpoint, observará que o campo `retKeyTTLmin` retorna sempre `0` (sem expiração). Motivo: As ZMKs tipicamente NÃO são efêmeras. São chaves-mestras de longa duração que garantem trocas contínuas com um parceiro. O endpoint não expõe a flag `is_ephemeral`; caso necessite de rotacionar a ZMK, o fluxo correto é importar uma nova (obtendo um novo `keyId`) e descontinuar a antiga .

***

## Exportar chave sob ZMK

> Exporta uma chave armazenada no HSM (criptografada sob LMK) para criptografia sob uma ZMK.\
> Retorna a chave exportada em \`retMultiValue\[0]\`.\
> \
> Suporta três esquemas de exportação:\
> \- X917: Formato X9.17 (DES/3DES apenas)\
> \- TR31: Formato TR-31 Key Block\
> \- TKBF: Thales Key Block Format<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield Key Manager API","version":"4.1.32"},"tags":[{"name":"Key Manager","description":"Operações de geração, importação, exportação e tradução de chaves criptográficas"}],"servers":[{"url":"https://apivin.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"ExportKeyInput":{"type":"object","required":["client_id","keyId","ZMK_keyId","export_scheme"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave a ser exportada no banco de dados"},"ZMK_keyId":{"type":"string","description":"Alias/identificador da ZMK sob a qual a chave sera exportada"},"export_scheme":{"type":"string","enum":["X917","TR31","TKBF"],"description":"Esquema de exportacao:\n- X917 Formato X9.17 (apenas DES/3DES)\n- TR31 Formato TR-31 Key Block\n- TKBF Thales Key Block Format\n"}}},"ReturnMultiValue":{"type":"object","properties":{"retCode":{"type":"integer","description":"Codigo de retorno. 0 = sucesso, outros valores indicam erro"},"retValue":{"type":"string","nullable":true,"description":"Valor de retorno simples"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com os valores de retorno da operacao"},"retValid":{"type":"boolean","description":"Indica se a operacao foi bem-sucedida"},"retDescription":{"type":"string","description":"Descricao do resultado"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Codigo de erro:\n- -1 Erro interno\n- 01 Erro de paridade na chave (aviso)\n- 04 Tipo de chave invalido\n- 05 Flag de comprimento de chave invalido\n- 07 Tipo de ZKA Master Key invalido\n- 10 Erro de paridade na ZMK/TMK\n- 11 Erro de paridade na chave\n- 44 Migracao nao permitida (PCI HSM compliance)\n- 45 Tipo de chave de destino de migracao invalido\n- 68 Comando desabilitado\n- 137 Malformacao da requisicao\n- 155 Chave nao encontrada no banco de dados\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDescription":{"type":"string","description":"Descricao do erro"}}}}},"paths":{"/v4/PayShieldKeyManager/ExportKey":{"post":{"tags":["Key Manager"],"summary":"Exportar chave sob ZMK","description":"Exporta uma chave armazenada no HSM (criptografada sob LMK) para criptografia sob uma ZMK.\nRetorna a chave exportada em `retMultiValue[0]`.\n\nSuporta três esquemas de exportação:\n- X917: Formato X9.17 (DES/3DES apenas)\n- TR31: Formato TR-31 Key Block\n- TKBF: Thales Key Block Format\n","operationId":"exportKey","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportKeyInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnMultiValue"}}}},"400":{"description":"Requisição inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"404":{"description":"Chave não encontrada no banco de dados","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

## Traduzir chave entre LMKs

> Traduz uma chave de criptografia sob um LMK antigo para criptografia sob o LMK atual.\
> Utilizado em processos de migração de LMK.\
> Retorna a chave re-criptografada sob o novo LMK em \`retValue\` (formato Key Block Thales).\
> \
> O campo \`OldKey\` deve estar no formato Key Block Thales criptografado sob o LMK antigo.<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield Key Manager API","version":"4.1.32"},"tags":[{"name":"Key Manager","description":"Operações de geração, importação, exportação e tradução de chaves criptográficas"}],"servers":[{"url":"https://apivin.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"TranslateLMKInput":{"type":"object","required":["client_id","OldKey"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"OldKey":{"type":"string","description":"Chave em formato Key Block Thales criptografada sob o LMK antigo"}}},"ReturnSingle":{"type":"object","properties":{"retCode":{"type":"integer"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDescription":{"type":"string"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Codigo de erro:\n- -1 Erro interno\n- 01 Erro de paridade na chave (aviso)\n- 04 Tipo de chave invalido\n- 05 Flag de comprimento de chave invalido\n- 07 Tipo de ZKA Master Key invalido\n- 10 Erro de paridade na ZMK/TMK\n- 11 Erro de paridade na chave\n- 44 Migracao nao permitida (PCI HSM compliance)\n- 45 Tipo de chave de destino de migracao invalido\n- 68 Comando desabilitado\n- 137 Malformacao da requisicao\n- 155 Chave nao encontrada no banco de dados\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDescription":{"type":"string","description":"Descricao do erro"}}}}},"paths":{"/v4/PayShieldKeyManager/TranslateLMK":{"post":{"tags":["Key Manager"],"summary":"Traduzir chave entre LMKs","description":"Traduz uma chave de criptografia sob um LMK antigo para criptografia sob o LMK atual.\nUtilizado em processos de migração de LMK.\nRetorna a chave re-criptografada sob o novo LMK em `retValue` (formato Key Block Thales).\n\nO campo `OldKey` deve estar no formato Key Block Thales criptografado sob o LMK antigo.\n","operationId":"translateLMK","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranslateLMKInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnSingle"}}}},"400":{"description":"Requisição inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

## The GenerateKeyInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield Key Manager API","version":"4.1.32"},"components":{"schemas":{"GenerateKeyInput":{"type":"object","required":["client_id","keyName","keySizeType","modeFlag"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyName":{"type":"string","description":"Nome/tipo da chave a ser gerada (ex ZEK, ZPK, ZMK, TMK, BDK)"},"keySizeType":{"type":"string","description":"Tamanho/tipo da chave:\n- S Single DES (64 bits)\n- D Double DES (128 bits)\n- T Triple DES (192 bits)\n- A AES-128\n- B AES-192\n- C AES-256\n"},"modeFlag":{"type":"string","enum":["0","1","A","B"],"description":"Modo de operacao:\n- 0 Gerar chave\n- 1 Gerar chave e exportar sob ZMK/TMK\n- A Derivar chave\n- B Derivar chave e exportar sob ZMK/TMK\n"},"zmk_TMK_flag":{"type":"string","nullable":true,"description":"Flag da ZMK/TMK, obrigatorio quando modeFlag 1 ou B"},"zmk_TMK_keyId":{"type":"string","nullable":true,"description":"Alias da ZMK/TMK, obrigatorio quando modeFlag 1 ou B"},"is_ephemeral":{"type":"boolean","description":"Se true, a chave tera tempo de vida limitado por key_TTL_minutes"},"key_TTL_minutes":{"type":"integer","nullable":true,"description":"Tempo de vida da chave em minutos, obrigatorio quando is_ephemeral true"}}}}}}
```

## The ImportKeyInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield Key Manager API","version":"4.1.32"},"components":{"schemas":{"ImportKeyInput":{"type":"object","required":["client_id","keyName","keySizeType","key_under_ZMK_to_import","ZMK_keyId"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyName":{"type":"string","description":"Nome/tipo da chave a ser importada (ex ZEK, ZPK, TMK)"},"keySizeType":{"type":"string","description":"Tamanho/tipo da chave:\n- S Single DES\n- D Double DES\n- T Triple DES\n- A AES-128\n- B AES-192\n- C AES-256\n"},"key_under_ZMK_to_import":{"type":"string","description":"Chave criptografada sob a ZMK a ser importada (formato Key Block ou X9.17)"},"ZMK_keyId":{"type":"string","description":"Alias/identificador da ZMK no banco de dados"},"is_ephemeral":{"type":"boolean","description":"Se true, a chave tera tempo de vida limitado por key_TTL_minutes"},"key_TTL_minutes":{"type":"integer","nullable":true,"description":"Tempo de vida da chave em minutos, obrigatorio quando is_ephemeral true"}}}}}}
```

## The ImportZMKInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield Key Manager API","version":"4.1.32"},"components":{"schemas":{"ImportZMKInput":{"type":"object","required":["client_id","kcv","keyZMK"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"kcv":{"type":"string","minLength":6,"maxLength":6,"description":"Key Check Value da ZMK (exatamente 6 caracteres hexadecimais)"},"keyZMK":{"type":"string","description":"ZMK em formato Key Block Thales"}}}}}}
```

## The ExportKeyInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield Key Manager API","version":"4.1.32"},"components":{"schemas":{"ExportKeyInput":{"type":"object","required":["client_id","keyId","ZMK_keyId","export_scheme"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave a ser exportada no banco de dados"},"ZMK_keyId":{"type":"string","description":"Alias/identificador da ZMK sob a qual a chave sera exportada"},"export_scheme":{"type":"string","enum":["X917","TR31","TKBF"],"description":"Esquema de exportacao:\n- X917 Formato X9.17 (apenas DES/3DES)\n- TR31 Formato TR-31 Key Block\n- TKBF Thales Key Block Format\n"}}}}}}
```

## The TranslateLMKInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield Key Manager API","version":"4.1.32"},"components":{"schemas":{"TranslateLMKInput":{"type":"object","required":["client_id","OldKey"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"OldKey":{"type":"string","description":"Chave em formato Key Block Thales criptografada sob o LMK antigo"}}}}}}
```

## The ReturnImpKey object

```json
{"openapi":"3.0.3","info":{"title":"PayShield Key Manager API","version":"4.1.32"},"components":{"schemas":{"ReturnImpKey":{"type":"object","properties":{"retCode":{"type":"integer","description":"Codigo de retorno. 0 = sucesso, outros valores indicam erro"},"retDescription":{"type":"string","description":"Descricao do resultado"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com valores adicionais, retMultiValue[0] contem o KCV da chave gerada/importada"},"retValid":{"type":"boolean","description":"Indica se a operacao foi bem-sucedida"},"retValue":{"type":"string","description":"KeyId gerado/importado no banco de dados"},"retKeyTTLmin":{"type":"integer","description":"Tempo de vida da chave em minutos (0 = sem expiracao)"}}}}}}
```

## The ReturnMultiValue object

```json
{"openapi":"3.0.3","info":{"title":"PayShield Key Manager API","version":"4.1.32"},"components":{"schemas":{"ReturnMultiValue":{"type":"object","properties":{"retCode":{"type":"integer","description":"Codigo de retorno. 0 = sucesso, outros valores indicam erro"},"retValue":{"type":"string","nullable":true,"description":"Valor de retorno simples"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com os valores de retorno da operacao"},"retValid":{"type":"boolean","description":"Indica se a operacao foi bem-sucedida"},"retDescription":{"type":"string","description":"Descricao do resultado"}}}}}}
```

## The ReturnSingle object

```json
{"openapi":"3.0.3","info":{"title":"PayShield Key Manager API","version":"4.1.32"},"components":{"schemas":{"ReturnSingle":{"type":"object","properties":{"retCode":{"type":"integer"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDescription":{"type":"string"}}}}}}
```

## The ReturnError object

```json
{"openapi":"3.0.3","info":{"title":"PayShield Key Manager API","version":"4.1.32"},"components":{"schemas":{"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Codigo de erro:\n- -1 Erro interno\n- 01 Erro de paridade na chave (aviso)\n- 04 Tipo de chave invalido\n- 05 Flag de comprimento de chave invalido\n- 07 Tipo de ZKA Master Key invalido\n- 10 Erro de paridade na ZMK/TMK\n- 11 Erro de paridade na chave\n- 44 Migracao nao permitida (PCI HSM compliance)\n- 45 Tipo de chave de destino de migracao invalido\n- 68 Comando desabilitado\n- 137 Malformacao da requisicao\n- 155 Chave nao encontrada no banco de dados\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDescription":{"type":"string","description":"Descricao do erro"}}}}}}
```


# Integração e Exemplos Práticos

## Integração e Exemplos Práticos

Para garantir uma implementação segura e fluida, esta secção detalha os três fluxos operacionais mais comuns na gestão de chaves criptográficas com parceiros, acompanhados de *snippets* de código nas linguagens mais utilizadas.

### Cenários de Integração (Fluxos)

#### Cenário 1: Onboarding Interno (Gerar Nova Chave)

Este é o cenário mais simples. O cliente integrador necessita de gerar uma nova chave para uso estritamente interno (ex.: uma ZPK que será usada no módulo PayShield PIN para validar PIN blocks recebidos do *front-end*) .

Sequência:

1. Obter o token JWT via Auth0.
2. Invocar o `GenerateKey` com `keyName = "ZPK"`, `keySizeType = "D"` (DES *double-length*, padrão em PIN) e `modeFlag = "0"` .
3. Capturar o `retValue` (`keyId`) retornado e registá-lo na base de dados do cliente, associado a este contexto de uso.
4. Capturar o `retMultiValue[0]` (KCV) e registá-lo para fins de auditoria e reconciliação futura.
5. A partir deste momento, o `keyId` pode ser consumido em chamadas aos restantes módulos da Hop V4.

***

#### Cenário 2: Receção de Chave de Parceiro

Cenário típico de integração: o cliente necessita de receber uma chave ZPK gerada por um adquirente parceiro. Esta chave é enviada encriptada sob uma ZMK que ambas as partes partilham .

Sequência:

1. Key Ceremony: Acordo prévio documentado com o parceiro para definir tipos de chave, tamanhos e esquema de troca.
2. Receber do parceiro a ZMK no formato Key Block Thales e o respetivo KCV.
3. Invocar o `ImportZMK` utilizando os dados do passo anterior. Registar o `keyId` retornado.
4. Receber do parceiro a ZPK (encriptada sob a ZMK partilhada).
5. Invocar o `ImportKey` passando a chave encriptada (`key_under_ZMK_to_import`) e o alias da ZMK (`ZMK_keyId`). Registar o novo `keyId` da ZPK .
6. Validação Crítica: Comparar o KCV retornado no `retMultiValue[0]` com o KCV informado pelo parceiro. Têm de coincidir obrigatoriamente; caso contrário, aborte a operação e investigue .

***

#### Cenário 3: Envio de Chave para Parceiro

Cenário inverso: o cliente necessita de enviar uma ZPK para um parceiro. Existem duas abordagens possíveis .

Abordagem A: Geração com Exportação Simultânea Ideal quando já se sabe de antemão qual o parceiro que vai receber a chave.

1. Importar a ZMK do parceiro via `ImportZMK` (se ainda não existir no banco).
2. Invocar o `GenerateKey` com `modeFlag = "1"`, apontando para a ZMK do parceiro no campo `zmk_TMK_keyId`. A API gera a chave e, na mesma chamada, devolve a chave já encriptada sob a ZMK de destino .
3. Enviar o resultado e o KCV para o parceiro através do canal seguro acordado.

Abordagem B: Geração e Exportação Separadas Ideal quando a ZPK é criada para uso interno primeiro, ou precisa de ser distribuída a múltiplos parceiros .

1. Invocar o `GenerateKey` com `modeFlag = "0"` para criar a ZPK no banco.
2. Para cada parceiro destino: invocar o `ExportKey` utilizando o `keyId` da ZPK e a `ZMK_keyId` do parceiro em questão. Recomenda-se selecionar `"TR31"` no `export_scheme` .
3. Enviar o `retMultiValue[0]` resultante a cada parceiro, acompanhado do KCV correspondente.

***

### Exemplos de Código (Snippets)

#### cURL — Gerar uma ZEK Efémera (`GenerateKey`)

Bash

```bash
curl -X POST \
  https://apivin.first-tech.net/v4/PayShieldKeyManager/GenerateKey \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": 42,
    "keyName": "ZEK",
    "keySizeType": "S",
    "modeFlag": "0",
    "is_ephemeral": true,
    "key_TTL_minutes": 1440
}'
```

#### Python — Pipeline de Onboarding de Parceiro

Este script demonstra a importação da ZMK e, de seguida, a importação da ZPK protegida por ela.

Python

```python
import requests

BASE = "https://apivin.first-tech.net/v4/PayShieldKeyManager"

def onboard_partner(token, client_id, partner_zmk, partner_zmk_kcv, partner_zpk_under_zmk):
    headers = {"Authorization": f"Bearer {token}"}

    # 1) Importa a ZMK
    r1 = requests.post(f"{BASE}/ImportZMK", headers=headers, json={
        "client_id": client_id,
        "kcv": partner_zmk_kcv,
        "keyZMK": partner_zmk,
    }, timeout=15)
    
    d1 = r1.json()
    if not d1.get("retValid"):
        raise RuntimeError(f"ImportZMK falhou: {d1}")
        
    zmk_alias = d1["retValue"]
    print(f"ZMK cadastrada: {zmk_alias} (KCV={d1['retMultiValue'][0]})")

    # 2) Importa a ZPK sob a ZMK
    r2 = requests.post(f"{BASE}/ImportKey", headers=headers, json={
        "client_id": client_id,
        "keyName": "ZPK",
        "keySizeType": "D",
        "key_under_ZMK_to_import": partner_zpk_under_zmk,
        "ZMK_keyId": zmk_alias,
    }, timeout=15)
    
    d2 = r2.json()
    if not d2.get("retValid"):
        raise RuntimeError(f"ImportKey falhou: {d2}")
        
    return {
        "zmk_keyId": zmk_alias,
        "zpk_keyId": d2["retValue"],
        "zpk_kcv": d2["retMultiValue"][0]
    }
```

#### Node.js — Geração com Exportação Simultânea (`modeFlag = 1`)

JavaScript

```javascript
const axios = require("axios");

async function generateAndExportZpkToPartner(token, clientId, partnerZmkAlias) {
  const url = "https://apivin.first-tech.net/v4/PayShieldKeyManager/GenerateKey";
  const payload = {
    client_id: clientId,
    keyName: "ZPK",
    keySizeType: "D",
    modeFlag: "1",
    zmk_TMK_flag: "ZMK",
    zmk_TMK_keyId: partnerZmkAlias,
  };

  const { data } = await axios.post(url, payload, {
    headers: { Authorization: `Bearer ${token}` },
    timeout: 15000,
  });

  if (!data.retValid) {
    throw new Error(`HSM retCode=${data.retCode}: ${data.retDescription}`);
  }

  return {
    keyId: data.retValue,
    kcv: data.retMultiValue[0],
    keyUnderZmk: data.retMultiValue[1] || null
  };
}
```


# Troubleshooting, Erros e Apêndices

### Troubleshooting, Erros e Apêndices

Esta secção serve como o guia de referência operacional e de diagnóstico para a integração com o módulo Key Manager.

#### Catálogo de Códigos de Erro (`retCode`)

O catálogo de erros é partilhado entre todos os endpoints do módulo. A coluna "Origem" indica se o erro foi detetado pela camada de validação da API ou diretamente pelo HSM Thales.

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Código</th><th>Significado</th><th>Origem</th><th>Ação Recomendada</th></tr></thead><tbody><tr><td><code>-1</code></td><td>Erro interno</td><td>API</td><td>Erro genérico. O <code>retDescription</code> traz tipicamente <code>"Internal error: &#x3C;mensagem>"</code>. Abrir chamado com a First Tech.</td></tr><tr><td><code>01</code></td><td>Erro de paridade na chave (Aviso)</td><td>HSM</td><td>A chave gerada/importada tem um byte de paridade incorreto. Tipicamente é um <em>warning</em> (aviso).</td></tr><tr><td><code>04</code></td><td>Tipo de chave inválido</td><td>HSM</td><td>O valor enviado em <code>keyName</code> não é reconhecido. Verifique a lista de tipos suportados.</td></tr><tr><td><code>05</code></td><td>Flag de comprimento inválido</td><td>API</td><td>O <code>keySizeType</code> está fora dos valores aceites (S/D/T/A/B/C).</td></tr><tr><td><code>07</code></td><td>Tipo de ZKA Master Key inválido</td><td>HSM</td><td>O tipo da ZMK referenciada não corresponde ao esperado. Verifique <code>zmk_TMK_keyId</code> ou <code>ZMK_keyId</code>.</td></tr><tr><td><code>10</code></td><td>Erro de paridade na ZMK/TMK</td><td>HSM</td><td>A chave-mestra referenciada está corrompida no banco. Recadastrar via <code>ImportZMK</code>.</td></tr><tr><td><code>11</code></td><td>Erro de paridade na chave</td><td>HSM</td><td>A chave referenciada está corrompida. Em <code>ImportZMK</code>, indica KCV divergente (validar com a contraparte).</td></tr><tr><td><code>44</code></td><td>Migração não permitida</td><td>HSM</td><td>A operação (<code>TranslateLMK</code>) viola regras de Compliance PCI HSM V3. Contatar o suporte.</td></tr><tr><td><code>45</code></td><td>Tipo de chave de destino inválido</td><td>HSM</td><td>Em <code>TranslateLMK</code>: a chave de destino tem tipo incompatível.</td></tr><tr><td><code>68</code></td><td>Comando desabilitado</td><td>HSM</td><td>Operação desabilitada no HSM. Contatar o suporte.</td></tr><tr><td><code>137</code></td><td>Malformação da requisição</td><td>API</td><td>JSON malformado, tipo de dado errado ou combinação inválida (ex.: <code>is_ephemeral = true</code> sem <code>key_TTL_minutes</code>) .</td></tr><tr><td><code>155</code></td><td>Chave não encontrada</td><td>API</td><td>O <code>keyId</code> não existe ou pertence a outro <code>client_id</code> .</td></tr></tbody></table>

***

### Guia de Troubleshooting

Sintomas comuns e resoluções para integrações iniciais :

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Sintoma Observado</th><th>Causa Provável</th><th>Como Resolver</th></tr></thead><tbody><tr><td>HTTP 400 com <code>retCode = 137</code></td><td>JSON malformado ou combinação inválida.</td><td>Validar o <em>body</em> contra o <em>schema</em>; conferir tipos numéricos vs <em>strings</em>.</td></tr><tr><td>HTTP 404 com <code>retCode = 155</code> em Export/Import</td><td>O <code>ZMK_keyId</code> ou o <code>keyId</code> não existem.</td><td>Listar as chaves no banco para confirmar os aliases exatos.</td></tr><tr><td>HTTP 400 com <code>retCode = 11</code> no <code>ImportZMK</code></td><td>O KCV informado não bate com o KCV calculado pelo HSM após decifrar o Key Block.</td><td>Confirmar com a contraparte o KCV correto; verificar erro de transcrição.</td></tr><tr><td>HTTP 400 com <code>retCode = 07</code> no <code>GenerateKey</code> (<code>modeFlag=1</code>)</td><td>O <code>zmk_TMK_keyId</code> aponta para uma chave que não é do tipo ZMK ou TMK.</td><td>Confirmar que o alias passado corresponde realmente a uma ZMK/TMK no banco.</td></tr><tr><td>Em <code>ExportKey</code> (scheme=X917), <code>retCode = 04</code></td><td>Tentativa de exportar chave AES com esquema X9.17.</td><td>Trocar o <code>export_scheme</code> para <code>TR31</code> ou <code>TKBF</code> (X9.17 só suporta DES).</td></tr><tr><td>Chave deixou de funcionar após horas</td><td>A chave foi gerada com <code>is_ephemeral = true</code> e expirou.</td><td>Se precisa de chave permanente, gere com <code>is_ephemeral = false</code>.</td></tr><tr><td>KCV difere do informado pela contraparte</td><td>Diferença na convenção de cálculo de KCV (ex.: Thales usa os primeiros 3 bytes de zeros encriptados).</td><td>Confirmar o algoritmo de KCV utilizado pela contraparte.</td></tr></tbody></table>

***

### Apêndice A - `TranslateLMK` e a Migração Hop V3 → V4

O endpoint `TranslateLMK` re-criptografa chaves entre ambientes (V3 para V4) . Abaixo estão os comportamentos técnicos esperados após uma tradução bem-sucedida:

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Aspecto</th><th>Comportamento Esperado</th></tr></thead><tbody><tr><td><code>keyId</code></td><td>Mantém o mesmo alias. O que muda é apenas o LMK interno que protege a chave.</td></tr><tr><td><code>KCV</code></td><td>Mantém o mesmo valor. O KCV é calculado sobre o material da chave em si, e não sobre a proteção LMK.</td></tr><tr><td>Consumo em Módulos</td><td>Continuam 100% funcionais imediatamente após a tradução (CVV, EMV, PIN, etc.).</td></tr><tr><td>Reversibilidade</td><td>A operação é tipicamente irreversível. Voltar ao LMK antigo exigiria nova chamada inversa, reforçando a importância da validação pós-migração.</td></tr></tbody></table>

***

### Apêndice B - Matrizes de Combinações Válidas

#### B.1 `keyName` x `keySizeType`

A matriz abaixo indica os tamanhos e algoritmos suportados por cada tipo de chave .

<table data-header-hidden="false" data-header-sticky><thead><tr><th>keyName</th><th>S (DES)</th><th>D (3DES)</th><th>T (3DES T)</th><th>A (AES-128)</th><th>B (AES-192)</th><th>C (AES-256)</th></tr></thead><tbody><tr><td>ZMK / TMK</td><td>-</td><td>Sim</td><td>Sim</td><td>Sim</td><td>-</td><td>Sim</td></tr><tr><td>ZPK / ZAK</td><td>-</td><td>Sim</td><td>-</td><td>Sim</td><td>-</td><td>Sim</td></tr><tr><td>ZEK / DEK</td><td>Sim</td><td>Sim</td><td>Sim</td><td>Sim</td><td>-</td><td>Sim</td></tr><tr><td>BDK</td><td>-</td><td>Sim</td><td>Sim</td><td>Sim</td><td>-</td><td>Sim</td></tr><tr><td>CVK / KERG</td><td>-</td><td>Sim</td><td>-</td><td>Sim</td><td>-</td><td>-</td></tr></tbody></table>

#### B.2 `export_scheme` x `keySizeType`

Compatibilidade entre os formatos de exportação e os algoritmos :

<table data-header-hidden="false" data-header-sticky><thead><tr><th>export_scheme</th><th>DES / 3DES (S, D, T)</th><th>AES (A, B, C)</th></tr></thead><tbody><tr><td>X917</td><td>Sim</td><td><p>Não (Esquema exclusivamente DES)</p><p><a class="button secondary"></a></p></td></tr><tr><td>TR31</td><td>Sim</td><td>Sim</td></tr><tr><td>TKBF</td><td>Sim</td><td>Sim</td></tr></tbody></table>

***

### Apêndice C - Glossário

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Sigla</th><th>Significado</th><th>Contexto</th></tr></thead><tbody><tr><td>AES / DES</td><td>Advanced / Data Encryption Standard</td><td>Algoritmos de criptografia simétrica.</td></tr><tr><td>BDK / UDK</td><td>Base Derivation Key / Unique Derived Key</td><td>Chaves do esquema DUKPT para terminais POS.</td></tr><tr><td>HSM</td><td>Hardware Security Module</td><td>Dispositivo de alta segurança (Thales) que executa a criptografia.</td></tr><tr><td>KCV</td><td>Key Check Value</td><td>Hash curto (6 caracteres hex) que atua como impressão digital da chave.</td></tr><tr><td>Key Block</td><td>-</td><td>Estrutura proprietária (ou TR-31) que embrulha a chave com um MAC sob LMK.</td></tr><tr><td>LMK</td><td>Local Master Key</td><td>A chave-mestra interna do HSM.</td></tr><tr><td>ZMK / ZPK</td><td>Zone Master / PIN Key</td><td>Chaves-mestras e de trabalho para comunicação segura entre instituições.</td></tr></tbody></table>


# Introdução e Fundamentos

### Introdução

O módulo PayShield Pan da plataforma Hop V4 constitui o núcleo de gestão criptográfica de PIN e PAN da First Tech. A API expõe operações para geração, tradução entre chaves de diferentes algoritmos (3DES e AES) e domínios (LMK e ZPK), além da validação e re-cifragem de PIN sob mudança de PAN.

Embora o módulo se denomine "Pan", a maioria dos seus *endpoints* opera sobre o PIN — sendo que apenas o `TranslatePan` e o `TranslatePinPan` envolvem a alteração efetiva do PAN. Este documento serve como referência técnica completa, detalhando os modelos de dados, a taxonomia de erros e os fluxos de integração para o ciclo de vida do PIN.

#### Público-alvo

* Desenvolvedores encarregues da integração de aplicações ou *hosts* ao Hop V4 para operações de PIN e PAN.
* Arquitetos de sistemas para avaliação de criptografia como serviço.
* Equipas de segurança da informação e de operações responsáveis pela migração e ciclo de vida de cartões.

#### Pré-requisitos

* Cliente devidamente provisionado na plataforma Hop V4 com `client_id` atribuído.
* Chaves criptográficas (LMK, ZPK do emissor e ZPK do adquirente) cadastradas e associadas ao `client_id`.
* Credenciais Auth0 (token JWT) válidas e conectividade autorizada para o *endpoint* `apivin.first-tech.net`.

***

### Fundamentos

#### Conceitos-chave

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Termo</th><th>Significado</th></tr></thead><tbody><tr><td>LMK</td><td><em>Local Master Key</em>. Chave-mestra do HSM da First Tech, utilizada para proteger PINs em repouso e como ponto de entrada/saída para traduções. Tipicamente AES.</td></tr><tr><td>ZPK</td><td><em>Zone PIN Key</em>. Chave partilhada entre instituições (zona de confiança) entre adquirente, emissor, bandeira ou gráfica. Pode ser 3DES ou AES.</td></tr><tr><td>TPK</td><td><em>Terminal PIN Key</em>. Chave que protege o PIN entre o terminal (POS, ATM) e o adquirente. Tratada como uma ZPK específica de canal.</td></tr><tr><td>PinBlock</td><td>Bloco padronizado que encapsula o PIN para transmissão segura. Suporta múltiplos formatos ISO e proprietários.</td></tr><tr><td>Embossing</td><td>Refere-se à tradução de LMK para ZPK destinada a um canal externo (gráfica, terminal).</td></tr><tr><td>Internalization</td><td>Tradução inversa: traz o PIN de uma ZPK externa para a LMK interna do emissor.</td></tr></tbody></table>

#### Princípio Operacional

Toda a operação de PIN no Hop V4 referencia as chaves através do seu *alias* (`keyId`), garantindo que o material criptográfico real nunca saia do HSM. Da mesma forma, os PINs em claro nunca trafegam pela rede; estão sempre encapsulados num PinBlock cifrado.

O HoP atua como um tradutor entre domínios: recebe um PinBlock cifrado por uma chave de origem, realiza a decifragem e a re-cifragem com a chave de destino dentro do ambiente seguro, e devolve o novo PinBlock ao solicitante.

***

### Matriz de Operações

O módulo PAN suporta as traduções entre os domínios LMK e ZPK utilizando algoritmos AES e 3DES.

#### Tradução de PIN

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Origem</th><th>Destino</th><th>Algoritmos</th><th>Endpoint</th></tr></thead><tbody><tr><td>LMK</td><td>ZPK</td><td>AES → 3DES</td><td><code>PinEmbossing</code></td></tr><tr><td>LMK</td><td>ZPK</td><td>AES → AES</td><td><code>TranslatePinLmkToZpk</code></td></tr><tr><td>ZPK</td><td>LMK</td><td>3DES → AES</td><td><code>PinInternalization</code></td></tr><tr><td>ZPK</td><td>LMK</td><td>AES → AES</td><td><code>TranslatePinZpkToLmk</code></td></tr></tbody></table>

#### Geração, Tradução de PAN e Validação

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Operação</th><th>Endpoint</th><th>Observação</th></tr></thead><tbody><tr><td>Gerar PIN sob LMK</td><td><code>GeneratePin</code></td><td>Destinado a uso interno.</td></tr><tr><td>Gerar PIN sob ZPK</td><td><code>GeneratePinIssuerKey</code></td><td>Para envio à gráfica ou personalização.</td></tr><tr><td>Trocar PAN (Preservar PIN)</td><td><code>TranslatePan</code></td><td>Re-cifra o PIN para o novo PAN (reemissão).</td></tr><tr><td>Trocar PAN + Traduzir PIN</td><td><code>TranslatePinPan</code></td><td>Combina a troca de PAN com a tradução de chave.</td></tr><tr><td>Validar PIN</td><td><code>ValidatePinIssuerKey</code></td><td>Traduz e valida o PIN para autorização.</td></tr></tbody></table>

#### Flowchart de Decisão

O diagrama seguinte auxilia na escolha do *endpoint* adequado com base na operação e nas chaves envolvidas:

***

### Formatos de PinBlock

A API utiliza duas convenções para identificar o formato do PinBlock, dependendo do *endpoint* acionado.

#### Códigos Thales (`pinBlockFmt`)

Utilizada nos *endpoints* `PinEmbossing` e `PinInternalization`.

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Código</th><th>Padrão</th><th>Notas</th></tr></thead><tbody><tr><td>01</td><td>ISO 9564-1 Format 0</td><td>Formato mais comum em transações ISO 8583.</td></tr><tr><td>02</td><td>ISO 9564-1 Format 1</td><td>Sem PAN no bloco.</td></tr><tr><td>03/04/05</td><td>ISO Format 2 / Proprietário</td><td>Formatos para cartões com chip ou variantes Thales.</td></tr><tr><td>47/48</td><td>ISO 9564-1 Format 4</td><td>O Formato 48 é exclusivo para algoritmos AES.</td></tr></tbody></table>

#### Índices Abreviados (`formatCode`)

Utilizada nos *endpoints* `TranslatePinLmkToZpk`, `TranslatePinZpkToLmk`, `TranslatePan` e `TranslatePinPan`.

<table data-header-hidden="false" data-header-sticky><thead><tr><th>formatCode</th><th>Código Thales</th><th>Padrão Equivalente</th></tr></thead><tbody><tr><td>0</td><td>01</td><td>ISO 9564-1 Format 0.</td></tr><tr><td>1</td><td>05</td><td>Proprietário Thales.</td></tr><tr><td>3</td><td>47</td><td>ISO 9564-1 Format 4 (variante).</td></tr><tr><td>4</td><td>48</td><td>ISO 9564-1 Format 4 (padrão default).</td></tr></tbody></table>

#### Matriz de Compatibilidade

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Formato</th><th>Suporte AES</th><th>Suporte 3DES</th></tr></thead><tbody><tr><td>01-47</td><td>Sim</td><td>Sim</td></tr><tr><td>48</td><td>Sim</td><td>Não</td></tr></tbody></table>

O Formato 48 (ISO Format 4) requer obrigatoriamente chaves AES. Consequentemente, não é suportado como destino em operações que envolvam chaves 3DES, como no caso do `PinEmbossing`.

***

### Modelo de Retorno

| `retCode`        | `integer` | `0` indica sucesso; outros valores indicam erro. |
| ---------------- | --------- | ------------------------------------------------ |
| `retValue`       | `string`  | Texto informativo (ex.: `"PIN Generated"`).      |
| `retMultiValue`  | `any`     | Resultado estruturado (ex.: o PinBlock gerado).  |
| `retValid`       | `boolean` | Sucesso da operação ou validade do PIN.          |
| `retDescription` | `string`  | Descrição textual do resultado.                  |


# Referência API - PAN

### Autenticação

Todas as chamadas à API exigem o cabeçalho `Authorization` preenchido com um token Bearer JWT válido .

HTTP

```
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ii4uLiJ9...
```

***

## Gerar PIN aleatório

> Gera um PIN aleatório e retorna o PIN criptografado sob a LMK em \`retMultiValue\[0]\`.\
> Em caso de erro, retorna os campos de erro (\`retCode\` e \`retDescription\`).<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield PAN API","version":"4.1.32"},"tags":[{"name":"PIN","description":"Operações de geração, validação e tradução de PIN"}],"servers":[{"url":"https://apivin.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"GeneratePinInput":{"type":"object","required":["client_id","pan","pinLength"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"pan":{"type":"string","minLength":12,"maxLength":19,"description":"PAN do cartão (12 a 19 dígitos)"},"pinLength":{"type":"integer","minimum":4,"maximum":12,"description":"Comprimento do PIN a ser gerado (4 a 12 dígitos)"}}},"ReturnMultiValue":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValue":{"type":"string","nullable":true,"description":"Valor de retorno simples"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com os valores de retorno da operação"},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retDescription":{"type":"string","description":"Descrição do resultado"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `-1`: Erro interno\n- `01`: Falha na verificação do PIN\n- `10`: Erro de paridade na chave ZPK de origem\n- `11`: Erro de paridade na chave ZPK de destino\n- `17`: Tradução de PIN desabilitada\n- `68`: Comando desabilitado\n- `69`: Formato do PinBlock desabilitado\n- `81`: Tamanho do PIN incompatível\n- `88`: Aviso — PinBlock contém PIN de tamanho zero\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDescription":{"type":"string","description":"Descrição do erro"}}}}},"paths":{"/v4/PayShieldPan/GeneratePin":{"post":{"tags":["PIN"],"summary":"Gerar PIN aleatório","description":"Gera um PIN aleatório e retorna o PIN criptografado sob a LMK em `retMultiValue[0]`.\nEm caso de erro, retorna os campos de erro (`retCode` e `retDescription`).\n","operationId":"generatePin","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeneratePinInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnMultiValue"}}}},"400":{"description":"Requisição inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

***

## Gerar PIN com chave do emissor

> Gera um novo PIN e o criptografa com a chave do emissor (\`keyIdDb\`).\
> Retorna o PIN gerado em \`retMultiValue.generatedPin\`.\
> Em caso de erro, retorna os campos de erro (\`retCode\` e \`retDescription\`).<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield PAN API","version":"4.1.32"},"tags":[{"name":"PIN","description":"Operações de geração, validação e tradução de PIN"}],"servers":[{"url":"https://apivin.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"GeneratePinIssuerKeyInput":{"type":"object","required":["client_id","pan","pinLength","keyIdDb"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"pan":{"type":"string","description":"PAN do cartão"},"pinLength":{"type":"integer","minimum":4,"maximum":12,"description":"Comprimento do PIN a ser gerado"},"keyIdDb":{"type":"string","description":"Alias/identificador da chave ZPK do emissor no banco de dados"}}},"ReturnGenericObj":{"type":"object","properties":{"retCode":{"type":"integer"},"retValue":{"type":"string"},"retMultiValue":{"type":"object","nullable":true,"description":"Objeto com os valores de retorno (estrutura varia por operação)"},"retValid":{"type":"boolean"},"retDescription":{"type":"string"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `-1`: Erro interno\n- `01`: Falha na verificação do PIN\n- `10`: Erro de paridade na chave ZPK de origem\n- `11`: Erro de paridade na chave ZPK de destino\n- `17`: Tradução de PIN desabilitada\n- `68`: Comando desabilitado\n- `69`: Formato do PinBlock desabilitado\n- `81`: Tamanho do PIN incompatível\n- `88`: Aviso — PinBlock contém PIN de tamanho zero\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDescription":{"type":"string","description":"Descrição do erro"}}}}},"paths":{"/v4/PayShieldPan/GeneratePinIssuerKey":{"post":{"tags":["PIN"],"summary":"Gerar PIN com chave do emissor","description":"Gera um novo PIN e o criptografa com a chave do emissor (`keyIdDb`).\nRetorna o PIN gerado em `retMultiValue.generatedPin`.\nEm caso de erro, retorna os campos de erro (`retCode` e `retDescription`).\n","operationId":"generatePinIssuerKey","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeneratePinIssuerKeyInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnGenericObj"}}}},"400":{"description":"Requisição inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

***

## PIN Embossing — LMK (AES) para ZPK (3DES)

> Traduz o PIN de criptografia sob a LMK (AES) para criptografia sob uma ZPK (3DES).\
> Retorna o PinBlock traduzido em \`retMultiValue\[0]\`.\
> \
> Chaves de criptografia AES só podem ser usadas com o formato de PinBlock \`48\` (ISO PIN Block Format 4).<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield PAN API","version":"4.1.32"},"tags":[{"name":"PIN","description":"Operações de geração, validação e tradução de PIN"}],"servers":[{"url":"https://apivin.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"PinEmbossingInput":{"type":"object","required":["client_id","zpkKeyIdSrc","zpkKeyIdDst","pinBlockSrc","pan","pinBlockFmtDst"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"zpkKeyIdSrc":{"type":"string","description":"Alias da chave de origem AES (LMK)"},"zpkKeyIdDst":{"type":"string","description":"Alias da chave de destino 3DES (ZPK)"},"pinBlockSrc":{"type":"string","minLength":4,"maxLength":33,"description":"PinBlock de origem criptografado sob a chave AES"},"pan":{"type":"string","minLength":16,"maxLength":16,"description":"PAN do cartão (exatamente 16 dígitos)"},"pinBlockFmtDst":{"type":"string","minLength":2,"maxLength":2,"description":"Formato do PinBlock de destino. Valores válidos:\n`01`, `02`, `03`, `04`, `05`, `34`, `35`, `41`, `42`, `47`, `48`\n"}}},"ReturnMultiValue":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValue":{"type":"string","nullable":true,"description":"Valor de retorno simples"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com os valores de retorno da operação"},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retDescription":{"type":"string","description":"Descrição do resultado"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `-1`: Erro interno\n- `01`: Falha na verificação do PIN\n- `10`: Erro de paridade na chave ZPK de origem\n- `11`: Erro de paridade na chave ZPK de destino\n- `17`: Tradução de PIN desabilitada\n- `68`: Comando desabilitado\n- `69`: Formato do PinBlock desabilitado\n- `81`: Tamanho do PIN incompatível\n- `88`: Aviso — PinBlock contém PIN de tamanho zero\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDescription":{"type":"string","description":"Descrição do erro"}}}}},"paths":{"/v4/PayShieldPan/PinEmbossing":{"post":{"tags":["PIN"],"summary":"PIN Embossing — LMK (AES) para ZPK (3DES)","description":"Traduz o PIN de criptografia sob a LMK (AES) para criptografia sob uma ZPK (3DES).\nRetorna o PinBlock traduzido em `retMultiValue[0]`.\n\nChaves de criptografia AES só podem ser usadas com o formato de PinBlock `48` (ISO PIN Block Format 4).\n","operationId":"pinEmbossing","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PinEmbossingInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnMultiValue"}}}},"400":{"description":"Requisição inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

***

## PIN Internalization — ZPK (3DES) para LMK (AES)

> Traduz o PIN de criptografia sob uma ZPK (3DES) para criptografia sob a LMK (AES).\
> Retorna o PinBlock traduzido em \`retMultiValue\[0]\`.\
> \
> Chaves 3DES não podem ser usadas com o formato de PinBlock \`48\` (ISO PIN Block Format 4).<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield PAN API","version":"4.1.32"},"tags":[{"name":"PIN","description":"Operações de geração, validação e tradução de PIN"}],"servers":[{"url":"https://apivin.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"PinInternalizationInput":{"type":"object","required":["client_id","zpkKeyIdSrc","zpkKeyIdDst","pinBlockSrc","pinBlockFmtSrc","pan"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"zpkKeyIdSrc":{"type":"string","description":"Alias da chave de origem 3DES (ZPK)"},"zpkKeyIdDst":{"type":"string","description":"Alias da chave de destino AES (LMK)"},"pinBlockSrc":{"type":"string","minLength":4,"maxLength":33,"description":"PinBlock de origem criptografado sob a chave 3DES"},"pinBlockFmtSrc":{"type":"string","description":"Formato do PinBlock de origem. Valores válidos:\n`01`, `02`, `03`, `04`, `05`, `34`, `35`, `41`, `42`, `47`\n(formato `48` não é suportado para chaves 3DES)\n"},"pan":{"type":"string","minLength":16,"maxLength":16,"description":"PAN do cartão (exatamente 16 dígitos)"}}},"ReturnMultiValue":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValue":{"type":"string","nullable":true,"description":"Valor de retorno simples"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com os valores de retorno da operação"},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retDescription":{"type":"string","description":"Descrição do resultado"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `-1`: Erro interno\n- `01`: Falha na verificação do PIN\n- `10`: Erro de paridade na chave ZPK de origem\n- `11`: Erro de paridade na chave ZPK de destino\n- `17`: Tradução de PIN desabilitada\n- `68`: Comando desabilitado\n- `69`: Formato do PinBlock desabilitado\n- `81`: Tamanho do PIN incompatível\n- `88`: Aviso — PinBlock contém PIN de tamanho zero\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDescription":{"type":"string","description":"Descrição do erro"}}}}},"paths":{"/v4/PayShieldPan/PinInternalization":{"post":{"tags":["PIN"],"summary":"PIN Internalization — ZPK (3DES) para LMK (AES)","description":"Traduz o PIN de criptografia sob uma ZPK (3DES) para criptografia sob a LMK (AES).\nRetorna o PinBlock traduzido em `retMultiValue[0]`.\n\nChaves 3DES não podem ser usadas com o formato de PinBlock `48` (ISO PIN Block Format 4).\n","operationId":"pinInternalization","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PinInternalizationInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnMultiValue"}}}},"400":{"description":"Requisição inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

## Traduzir PAN

> Traduz o PIN criptografado sob a LMK de um PAN antigo para um PAN novo.\
> O PIN do cliente permanece inalterado.\
> Retorna o PIN re-criptografado com o novo PAN em \`retMultiValue\[0]\`.\
> \
> Quando usando AES Key Block LMK, o PIN criptografado sob a LMK usa o formato Thales \`48\` (ISO PIN Block format 4).<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield PAN API","version":"4.1.32"},"tags":[{"name":"PAN","description":"Operações de tradução de PAN"}],"servers":[{"url":"https://apivin.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"TranslatePanInput":{"type":"object","required":["client_id","pin","oldPan","newPan"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"pin":{"type":"string","maxLength":33,"description":"PIN criptografado sob a LMK"},"oldPan":{"type":"string","minLength":12,"maxLength":19,"description":"PAN antigo do cartão (12 a 19 dígitos)"},"newPan":{"type":"string","minLength":12,"maxLength":19,"description":"Novo PAN do cartão (12 a 19 dígitos)"}}},"ReturnMultiValue":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValue":{"type":"string","nullable":true,"description":"Valor de retorno simples"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com os valores de retorno da operação"},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retDescription":{"type":"string","description":"Descrição do resultado"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `-1`: Erro interno\n- `01`: Falha na verificação do PIN\n- `10`: Erro de paridade na chave ZPK de origem\n- `11`: Erro de paridade na chave ZPK de destino\n- `17`: Tradução de PIN desabilitada\n- `68`: Comando desabilitado\n- `69`: Formato do PinBlock desabilitado\n- `81`: Tamanho do PIN incompatível\n- `88`: Aviso — PinBlock contém PIN de tamanho zero\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDescription":{"type":"string","description":"Descrição do erro"}}}}},"paths":{"/v4/PayShieldPan/TranslatePan":{"post":{"tags":["PAN"],"summary":"Traduzir PAN","description":"Traduz o PIN criptografado sob a LMK de um PAN antigo para um PAN novo.\nO PIN do cliente permanece inalterado.\nRetorna o PIN re-criptografado com o novo PAN em `retMultiValue[0]`.\n\nQuando usando AES Key Block LMK, o PIN criptografado sob a LMK usa o formato Thales `48` (ISO PIN Block format 4).\n","operationId":"translatePan","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranslatePanInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnMultiValue"}}}},"400":{"description":"Requisição inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

***

## Traduzir PIN — LMK (AES) para ZPK (AES)

> Traduz o PIN de criptografia sob a LMK (AES) para criptografia sob uma ZPK (AES).\
> Retorna o PinBlock traduzido em \`retMultiValue\[0]\`.\
> \
> Quando usado com Variant LMK ou 3DES Key Block LMK, o PIN criptografado sob a LMK sempre usará formato não-ISO.<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield PAN API","version":"4.1.32"},"tags":[{"name":"PIN","description":"Operações de geração, validação e tradução de PIN"}],"servers":[{"url":"https://apivin.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"TranslatePinLmkToZpkInput":{"type":"object","required":["client_id","keyId","pin","pan","formatCode"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave ZPK de destino"},"pin":{"type":"string","maxLength":33,"description":"PIN criptografado sob a LMK"},"pan":{"type":"string","description":"PAN do cartão"},"formatCode":{"type":"integer","minimum":0,"maximum":4,"description":"Código de formato do PinBlock de destino:\n- `0` → formato Thales `01`\n- `1` → formato Thales `05`\n- `3` → formato Thales `47`\n- `4` (padrão) → formato Thales `48`\n"}}},"ReturnMultiValue":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValue":{"type":"string","nullable":true,"description":"Valor de retorno simples"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com os valores de retorno da operação"},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retDescription":{"type":"string","description":"Descrição do resultado"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `-1`: Erro interno\n- `01`: Falha na verificação do PIN\n- `10`: Erro de paridade na chave ZPK de origem\n- `11`: Erro de paridade na chave ZPK de destino\n- `17`: Tradução de PIN desabilitada\n- `68`: Comando desabilitado\n- `69`: Formato do PinBlock desabilitado\n- `81`: Tamanho do PIN incompatível\n- `88`: Aviso — PinBlock contém PIN de tamanho zero\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDescription":{"type":"string","description":"Descrição do erro"}}}}},"paths":{"/v4/PayShieldPan/TranslatePinLmkToZpk":{"post":{"tags":["PIN"],"summary":"Traduzir PIN — LMK (AES) para ZPK (AES)","description":"Traduz o PIN de criptografia sob a LMK (AES) para criptografia sob uma ZPK (AES).\nRetorna o PinBlock traduzido em `retMultiValue[0]`.\n\nQuando usado com Variant LMK ou 3DES Key Block LMK, o PIN criptografado sob a LMK sempre usará formato não-ISO.\n","operationId":"translatePinLmkToZpk","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranslatePinLmkToZpkInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnMultiValue"}}}},"400":{"description":"Requisição inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

***

## Traduzir PIN — ZPK (AES) para LMK (AES)

> Traduz o PIN de criptografia sob uma ZPK (AES) para criptografia sob a LMK (AES).\
> Retorna o PinBlock traduzido em \`retMultiValue\[0]\`.\
> \
> Quando usado com Variant LMK ou 3DES Key Block LMK, o PIN criptografado sob a LMK sempre usará formato não-ISO.<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield PAN API","version":"4.1.32"},"tags":[{"name":"PIN","description":"Operações de geração, validação e tradução de PIN"}],"servers":[{"url":"https://apivin.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"TranslatePinZpkToLmkInput":{"type":"object","required":["client_id","keyId","pin","pan","formatCode"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave ZPK de origem"},"pin":{"type":"string","minLength":16,"maxLength":16,"description":"PinBlock criptografado sob a ZPK (exatamente 16 dígitos)"},"pan":{"type":"string","minLength":16,"maxLength":16,"description":"PAN do cartão (exatamente 16 dígitos)"},"formatCode":{"type":"integer","minimum":0,"maximum":4,"description":"Código de formato do PinBlock de origem:\n- `0` → formato Thales `01`\n- `1` → formato Thales `05`\n- `3` → formato Thales `47`\n- `4` (padrão) → formato Thales `48`\n"}}},"ReturnMultiValue":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValue":{"type":"string","nullable":true,"description":"Valor de retorno simples"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com os valores de retorno da operação"},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retDescription":{"type":"string","description":"Descrição do resultado"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `-1`: Erro interno\n- `01`: Falha na verificação do PIN\n- `10`: Erro de paridade na chave ZPK de origem\n- `11`: Erro de paridade na chave ZPK de destino\n- `17`: Tradução de PIN desabilitada\n- `68`: Comando desabilitado\n- `69`: Formato do PinBlock desabilitado\n- `81`: Tamanho do PIN incompatível\n- `88`: Aviso — PinBlock contém PIN de tamanho zero\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDescription":{"type":"string","description":"Descrição do erro"}}}}},"paths":{"/v4/PayShieldPan/TranslatePinZpkToLmk":{"post":{"tags":["PIN"],"summary":"Traduzir PIN — ZPK (AES) para LMK (AES)","description":"Traduz o PIN de criptografia sob uma ZPK (AES) para criptografia sob a LMK (AES).\nRetorna o PinBlock traduzido em `retMultiValue[0]`.\n\nQuando usado com Variant LMK ou 3DES Key Block LMK, o PIN criptografado sob a LMK sempre usará formato não-ISO.\n","operationId":"translatePinZpkToLmk","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranslatePinZpkToLmkInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnMultiValue"}}}},"400":{"description":"Requisição inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

***

## Traduzir PIN e PAN combinados

> Combina a tradução de PAN com a tradução de PIN (LMK para ZPK).\
> Retorna o PinBlock traduzido com o PAN correto em \`retMultiValue\[0]\`.\
> \
> O PIN do cliente permanece inalterado durante a tradução do PAN.\
> \
> Quando usando AES Key Block LMK, o PIN criptografado sob a LMK usa o formato Thales \`48\` (ISO PIN Block format 4).<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield PAN API","version":"4.1.32"},"tags":[{"name":"PIN","description":"Operações de geração, validação e tradução de PIN"}],"servers":[{"url":"https://apivin.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"TranslatePinPanInput":{"type":"object","required":["client_id","pin","pan","keyId","formatCode"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"pin":{"type":"string","description":"PIN criptografado sob a LMK"},"pan":{"type":"string","description":"PAN do cartão"},"keyId":{"type":"string","description":"Alias/identificador da chave ZPK de destino"},"formatCode":{"type":"integer","minimum":0,"maximum":4,"description":"Código de formato do PinBlock:\n- `0` → formato Thales `01`\n- `1` → formato Thales `05`\n- `3` → formato Thales `47`\n- `4` (padrão) → formato Thales `48`\n"}}},"ReturnMultiValue":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValue":{"type":"string","nullable":true,"description":"Valor de retorno simples"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com os valores de retorno da operação"},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retDescription":{"type":"string","description":"Descrição do resultado"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `-1`: Erro interno\n- `01`: Falha na verificação do PIN\n- `10`: Erro de paridade na chave ZPK de origem\n- `11`: Erro de paridade na chave ZPK de destino\n- `17`: Tradução de PIN desabilitada\n- `68`: Comando desabilitado\n- `69`: Formato do PinBlock desabilitado\n- `81`: Tamanho do PIN incompatível\n- `88`: Aviso — PinBlock contém PIN de tamanho zero\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDescription":{"type":"string","description":"Descrição do erro"}}}}},"paths":{"/v4/PayShieldPan/TranslatePinPan":{"post":{"tags":["PIN"],"summary":"Traduzir PIN e PAN combinados","description":"Combina a tradução de PAN com a tradução de PIN (LMK para ZPK).\nRetorna o PinBlock traduzido com o PAN correto em `retMultiValue[0]`.\n\nO PIN do cliente permanece inalterado durante a tradução do PAN.\n\nQuando usando AES Key Block LMK, o PIN criptografado sob a LMK usa o formato Thales `48` (ISO PIN Block format 4).\n","operationId":"translatePinPan","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranslatePinPanInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnMultiValue"}}}},"400":{"description":"Requisição inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

***

## Validar PIN com chave do emissor

> Combina a tradução de PIN (ZPK para LMK) com a validação do PIN.\
> Retorna \`true\` em \`retValid\` se o PIN for válido.\
> Em caso de erro, retorna os campos de erro (\`retCode\` e \`retDescription\`).<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield PAN API","version":"4.1.32"},"tags":[{"name":"PIN","description":"Operações de geração, validação e tradução de PIN"}],"servers":[{"url":"https://apivin.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"ValidatePinIssuerKeyInput":{"type":"object","required":["client_id","keyId","keyIdDb","pin","pinDb","formatCode","formatCodeDb","pan"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias da chave ZPK 3DES usada para criptografar o PIN recebido"},"keyIdDb":{"type":"string","description":"Alias da chave ZPK AES usada para criptografar o PIN armazenado"},"pin":{"type":"string","description":"PIN recebido (criptografado sob `keyId`)"},"pinDb":{"type":"string","description":"PIN armazenado no banco (criptografado sob `keyIdDb`)"},"formatCode":{"type":"integer","minimum":0,"maximum":4,"description":"Código de formato do PIN recebido"},"formatCodeDb":{"type":"integer","minimum":0,"maximum":4,"description":"Código de formato do PIN armazenado"},"pan":{"type":"string","description":"PAN do cartão"}}},"ReturnSingle":{"type":"object","properties":{"retCode":{"type":"integer"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDescription":{"type":"string"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `-1`: Erro interno\n- `01`: Falha na verificação do PIN\n- `10`: Erro de paridade na chave ZPK de origem\n- `11`: Erro de paridade na chave ZPK de destino\n- `17`: Tradução de PIN desabilitada\n- `68`: Comando desabilitado\n- `69`: Formato do PinBlock desabilitado\n- `81`: Tamanho do PIN incompatível\n- `88`: Aviso — PinBlock contém PIN de tamanho zero\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDescription":{"type":"string","description":"Descrição do erro"}}}}},"paths":{"/v4/PayShieldPan/ValidatePinIssuerKey":{"post":{"tags":["PIN"],"summary":"Validar PIN com chave do emissor","description":"Combina a tradução de PIN (ZPK para LMK) com a validação do PIN.\nRetorna `true` em `retValid` se o PIN for válido.\nEm caso de erro, retorna os campos de erro (`retCode` e `retDescription`).\n","operationId":"validatePinIssuerKey","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidatePinIssuerKeyInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnSingle"}}}},"400":{"description":"Requisição inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

***

## The GeneratePinInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield PAN API","version":"4.1.32"},"components":{"schemas":{"GeneratePinInput":{"type":"object","required":["client_id","pan","pinLength"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"pan":{"type":"string","minLength":12,"maxLength":19,"description":"PAN do cartão (12 a 19 dígitos)"},"pinLength":{"type":"integer","minimum":4,"maximum":12,"description":"Comprimento do PIN a ser gerado (4 a 12 dígitos)"}}}}}}
```

## The GeneratePinIssuerKeyInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield PAN API","version":"4.1.32"},"components":{"schemas":{"GeneratePinIssuerKeyInput":{"type":"object","required":["client_id","pan","pinLength","keyIdDb"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"pan":{"type":"string","description":"PAN do cartão"},"pinLength":{"type":"integer","minimum":4,"maximum":12,"description":"Comprimento do PIN a ser gerado"},"keyIdDb":{"type":"string","description":"Alias/identificador da chave ZPK do emissor no banco de dados"}}}}}}
```

## The PinEmbossingInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield PAN API","version":"4.1.32"},"components":{"schemas":{"PinEmbossingInput":{"type":"object","required":["client_id","zpkKeyIdSrc","zpkKeyIdDst","pinBlockSrc","pan","pinBlockFmtDst"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"zpkKeyIdSrc":{"type":"string","description":"Alias da chave de origem AES (LMK)"},"zpkKeyIdDst":{"type":"string","description":"Alias da chave de destino 3DES (ZPK)"},"pinBlockSrc":{"type":"string","minLength":4,"maxLength":33,"description":"PinBlock de origem criptografado sob a chave AES"},"pan":{"type":"string","minLength":16,"maxLength":16,"description":"PAN do cartão (exatamente 16 dígitos)"},"pinBlockFmtDst":{"type":"string","minLength":2,"maxLength":2,"description":"Formato do PinBlock de destino. Valores válidos:\n`01`, `02`, `03`, `04`, `05`, `34`, `35`, `41`, `42`, `47`, `48`\n"}}}}}}
```

## The PinInternalizationInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield PAN API","version":"4.1.32"},"components":{"schemas":{"PinInternalizationInput":{"type":"object","required":["client_id","zpkKeyIdSrc","zpkKeyIdDst","pinBlockSrc","pinBlockFmtSrc","pan"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"zpkKeyIdSrc":{"type":"string","description":"Alias da chave de origem 3DES (ZPK)"},"zpkKeyIdDst":{"type":"string","description":"Alias da chave de destino AES (LMK)"},"pinBlockSrc":{"type":"string","minLength":4,"maxLength":33,"description":"PinBlock de origem criptografado sob a chave 3DES"},"pinBlockFmtSrc":{"type":"string","description":"Formato do PinBlock de origem. Valores válidos:\n`01`, `02`, `03`, `04`, `05`, `34`, `35`, `41`, `42`, `47`\n(formato `48` não é suportado para chaves 3DES)\n"},"pan":{"type":"string","minLength":16,"maxLength":16,"description":"PAN do cartão (exatamente 16 dígitos)"}}}}}}
```

## The TranslatePanInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield PAN API","version":"4.1.32"},"components":{"schemas":{"TranslatePanInput":{"type":"object","required":["client_id","pin","oldPan","newPan"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"pin":{"type":"string","maxLength":33,"description":"PIN criptografado sob a LMK"},"oldPan":{"type":"string","minLength":12,"maxLength":19,"description":"PAN antigo do cartão (12 a 19 dígitos)"},"newPan":{"type":"string","minLength":12,"maxLength":19,"description":"Novo PAN do cartão (12 a 19 dígitos)"}}}}}}
```

## The TranslatePinLmkToZpkInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield PAN API","version":"4.1.32"},"components":{"schemas":{"TranslatePinLmkToZpkInput":{"type":"object","required":["client_id","keyId","pin","pan","formatCode"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave ZPK de destino"},"pin":{"type":"string","maxLength":33,"description":"PIN criptografado sob a LMK"},"pan":{"type":"string","description":"PAN do cartão"},"formatCode":{"type":"integer","minimum":0,"maximum":4,"description":"Código de formato do PinBlock de destino:\n- `0` → formato Thales `01`\n- `1` → formato Thales `05`\n- `3` → formato Thales `47`\n- `4` (padrão) → formato Thales `48`\n"}}}}}}
```

## The TranslatePinZpkToLmkInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield PAN API","version":"4.1.32"},"components":{"schemas":{"TranslatePinZpkToLmkInput":{"type":"object","required":["client_id","keyId","pin","pan","formatCode"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave ZPK de origem"},"pin":{"type":"string","minLength":16,"maxLength":16,"description":"PinBlock criptografado sob a ZPK (exatamente 16 dígitos)"},"pan":{"type":"string","minLength":16,"maxLength":16,"description":"PAN do cartão (exatamente 16 dígitos)"},"formatCode":{"type":"integer","minimum":0,"maximum":4,"description":"Código de formato do PinBlock de origem:\n- `0` → formato Thales `01`\n- `1` → formato Thales `05`\n- `3` → formato Thales `47`\n- `4` (padrão) → formato Thales `48`\n"}}}}}}
```

## The TranslatePinPanInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield PAN API","version":"4.1.32"},"components":{"schemas":{"TranslatePinPanInput":{"type":"object","required":["client_id","pin","pan","keyId","formatCode"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"pin":{"type":"string","description":"PIN criptografado sob a LMK"},"pan":{"type":"string","description":"PAN do cartão"},"keyId":{"type":"string","description":"Alias/identificador da chave ZPK de destino"},"formatCode":{"type":"integer","minimum":0,"maximum":4,"description":"Código de formato do PinBlock:\n- `0` → formato Thales `01`\n- `1` → formato Thales `05`\n- `3` → formato Thales `47`\n- `4` (padrão) → formato Thales `48`\n"}}}}}}
```

## The ValidatePinIssuerKeyInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield PAN API","version":"4.1.32"},"components":{"schemas":{"ValidatePinIssuerKeyInput":{"type":"object","required":["client_id","keyId","keyIdDb","pin","pinDb","formatCode","formatCodeDb","pan"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias da chave ZPK 3DES usada para criptografar o PIN recebido"},"keyIdDb":{"type":"string","description":"Alias da chave ZPK AES usada para criptografar o PIN armazenado"},"pin":{"type":"string","description":"PIN recebido (criptografado sob `keyId`)"},"pinDb":{"type":"string","description":"PIN armazenado no banco (criptografado sob `keyIdDb`)"},"formatCode":{"type":"integer","minimum":0,"maximum":4,"description":"Código de formato do PIN recebido"},"formatCodeDb":{"type":"integer","minimum":0,"maximum":4,"description":"Código de formato do PIN armazenado"},"pan":{"type":"string","description":"PAN do cartão"}}}}}}
```

## The ReturnMultiValue object

```json
{"openapi":"3.0.3","info":{"title":"PayShield PAN API","version":"4.1.32"},"components":{"schemas":{"ReturnMultiValue":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValue":{"type":"string","nullable":true,"description":"Valor de retorno simples"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com os valores de retorno da operação"},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retDescription":{"type":"string","description":"Descrição do resultado"}}}}}}
```

## The ReturnSingle object

```json
{"openapi":"3.0.3","info":{"title":"PayShield PAN API","version":"4.1.32"},"components":{"schemas":{"ReturnSingle":{"type":"object","properties":{"retCode":{"type":"integer"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDescription":{"type":"string"}}}}}}
```

## The ReturnGenericObj object

```json
{"openapi":"3.0.3","info":{"title":"PayShield PAN API","version":"4.1.32"},"components":{"schemas":{"ReturnGenericObj":{"type":"object","properties":{"retCode":{"type":"integer"},"retValue":{"type":"string"},"retMultiValue":{"type":"object","nullable":true,"description":"Objeto com os valores de retorno (estrutura varia por operação)"},"retValid":{"type":"boolean"},"retDescription":{"type":"string"}}}}}}
```

## The ReturnError object

```json
{"openapi":"3.0.3","info":{"title":"PayShield PAN API","version":"4.1.32"},"components":{"schemas":{"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `-1`: Erro interno\n- `01`: Falha na verificação do PIN\n- `10`: Erro de paridade na chave ZPK de origem\n- `11`: Erro de paridade na chave ZPK de destino\n- `17`: Tradução de PIN desabilitada\n- `68`: Comando desabilitado\n- `69`: Formato do PinBlock desabilitado\n- `81`: Tamanho do PIN incompatível\n- `88`: Aviso — PinBlock contém PIN de tamanho zero\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDescription":{"type":"string","description":"Descrição do erro"}}}}}}
```


# Casos de Uso: Cenários 1 a 3

### Cenário 1 - Emissão de PIN para Novo Cartão

O emissor produz um cartão novo e necessita de gerar um PIN aleatório, persisti-lo cifrado na sua base de dados e enviá-lo cifrado à gráfica de personalização para impressão num *PIN mailer* ou exibição num PIN pad seguro ao titular .

#### Sequência de Etapas

1. Solicitação do PIN: O sistema do emissor invoca o endpoint `GeneratePinIssuerKey` passando o `pan` do novo cartão, o `pinLength` desejado e o `keyIdDb` da ZPK do emissor que protegerá o PIN durante o trânsito .
2. Geração do PIN: O HoP gera um PIN aleatório no HSM, cifra-o sob a ZPK do emissor e devolve-o no campo `retMultiValue.generatedPin`. O PIN em claro nunca sai do HSM .
3. Persistência: O sistema do emissor persiste o PIN cifrado vinculado ao PAN na Base de Cartões. O `keyIdDb` utilizado é armazenado em conjunto para suportar futuras rotações de chave .
4. Envio à gráfica: O sistema envia o PIN cifrado para a gráfica/personalização através de um canal seguro (TLS + chave partilhada). A gráfica necessita de ter a ZPK correspondente disponível no seu próprio HSM .
5. Impressão segura: A gráfica decifra o PIN dentro do seu PIN pad seguro e imprime o *PIN mailer* físico (ou exibe-o num canal eletrónico controlado). O PIN nunca é manipulado em claro fora do hardware seguro .

***

### Cenário 2 - Validação de PIN em Compra com Cartão

O titular insere o cartão num POS e digita o PIN para autorizar uma compra. A transação percorre o ecossistema clássico de quatro partes (POS → adquirente → bandeira → emissor) até chegar ao HoP do emissor para validação criptográfica do PIN .

#### Sequência de Etapas

1. Inserção do cartão e PIN: O titular insere o cartão na máquina (POS) e digita o PIN. O POS cifra o PIN imediatamente sob a TPK (chave do terminal) .
2. Envio ao adquirente: O POS envia ao adquirente uma mensagem ISO 8583 com o PIN cifrado e os dados da transação .
3. Encaminhamento à bandeira: O adquirente encaminha a transação (após eventualmente traduzir o PIN para a ZPK partilhada com a bandeira) .
4. Encaminhamento ao emissor: A bandeira encaminha a transação ao emissor do cartão, incluindo o PIN cifrado pela ZPK partilhada entre a bandeira e o emissor.
5. Validação no HoP: O emissor invoca o endpoint `ValidatePinIssuerKey` passando o PIN recebido (`pin` sob `keyId`), o PIN armazenado na sua base (`pinDb` sob `keyIdDb`), e o PAN. O HoP traduz o PIN recebido para a LMK, decifra ambos dentro do HSM e compara os valores .
6. Resultado da validação: O HoP retorna `retValid = true` se o PIN for válido, ou `false` caso contrário. O emissor verifica então as restantes variáveis de negócio (saldo, limite, fraude) para decidir a autorização .
7. Resposta à cadeia: O emissor envia a resposta de autorização (aprovação ou recusa) à bandeira . A bandeira repassa a resposta ao adquirente , que a transmite de volta ao POS .
8. Notificação ao titular: O POS informa o titular sobre a aprovação ou recusa, finalizando a transação .

***

### Cenário 3 - Reset de PIN via Canal Digital

O titular esqueceu o PIN e solicita um novo através da aplicação móvel ou *internet banking*. O emissor gera um PIN novo, persiste o dado e exibe-o ao titular através de um componente seguro (PIN pad virtual na app ou canal homologado) .

#### Sequência de Etapas

1. Solicitação do reset: O cliente, após autenticação multifator, solicita o reset de PIN na aplicação. O backend valida a elegibilidade e dispara o processo .
2. Geração do novo PIN: O backend invoca o endpoint `GeneratePinIssuerKey` passando o PAN e o `keyIdDb` da ZPK do emissor .
3. Retorno do PIN cifrado: O HoP retorna o PIN gerado no campo `retMultiValue.generatedPin`, devidamente cifrado sob a ZPK do emissor .
4. Atualização da base: O backend atualiza o PIN cifrado no cadastro do cartão na Base de PINs. O PIN antigo é invalidado .
5. Tradução para o canal de exibição: O backend invoca o endpoint `PinEmbossing` (ou `TranslatePinLmkToZpk` se o PIN pad for AES) para traduzir o PIN da ZPK do emissor para a ZPK do componente seguro de exibição .
6. Retorno do PIN sob chave do PIN pad: O HoP devolve o PinBlock cifrado sob a chave de destino .
7. Envio ao componente seguro: O backend envia o PinBlock cifrado ao componente, que o decifra dentro do seu próprio enclave seguro (HSM ou *secure element* local) .
8. Exibição ao cliente: O componente exibe o PIN ao cliente em modo de leitura única (sem permissão de *screenshot* e sem persistência local). O cliente memoriza o PIN .


# Casos de Uso: Cenários 4 a 6

### Cenário 4 - Reissuance de Cartão Preservando PIN

Um cartão é reemitido (devido a perda, roubo, vencimento ou programa de fidelidade) e ganha um PAN novo. O cliente não deve precisar de memorizar um novo PIN . O *endpoint* `TranslatePan` re-cifra o PIN existente para o novo PAN sem que o PIN em claro seja exposto em momento algum.

#### Sequência de Etapas

1. Acionamento do processo: Um evento (perda reportada, roubo, vencimento programado ou novo programa) aciona o fluxo de *reissuance* no sistema do emissor .
2. Leitura do PIN antigo: O sistema lê o PIN cifrado vinculado ao PAN antigo no cadastro. O PIN ainda está cifrado sob LMK (ou ZPK do emissor, conforme a arquitetura) .
3. Tradução para o novo PAN: O sistema invoca o `TranslatePan` passando o `pin`, o `oldPan` e o `newPan`. O HoP decifra o PIN com referência ao PAN antigo, calcula a nova cifragem com referência ao PAN novo e retorna o resultado .
4. Retorno do PIN re-cifrado: O HoP devolve em `retMultiValue[0]` o PIN que se encontra agora vinculado criptograficamente ao novo PAN .
5. Persistência no novo cadastro: O sistema cria o cadastro do novo cartão com o PAN novo e o PIN re-cifrado. O cadastro antigo é marcado para descomissionamento .
6. Personalização do cartão: A gráfica imprime o cartão novo com o PAN novo. Não é necessário reimprimir o *PIN mailer*, uma vez que o cliente continua a usar a mesma senha .

***

### Cenário 5 - Saque em ATM com Tradução de PIN

Um cliente realiza um levantamento de dinheiro num ATM. O PIN passa por múltiplas traduções de chave durante o seu trajeto: TPK (terminal) → LMK (adquirente) → ZPK (emissor) . Cada tradução acontece de forma segura dentro do HSM do ator correspondente.

#### Sequência de Etapas

1. Inserção do cartão e PIN: O titular insere o cartão e digita o PIN no teclado (PIN pad) do ATM. O PIN é imediatamente cifrado sob a TPK (chave do terminal) .
2. Envio ao adquirente: O ATM envia ao adquirente o PIN cifrado sob TPK. Para o adquirente, esta TPK atua como uma ZPK específica do canal terminal .
3. Internalização no adquirente: O adquirente invoca o `PinInternalization` no seu HoP para trazer o PIN da TPK (3DES) para a LMK interna (AES). Isto permite a manipulação subsequente sob o domínio interno .
4. Retorno do PIN sob LMK: O HoP devolve o PIN cifrado sob a LMK do adquirente .
5. Tradução para o emissor: O adquirente invoca o `PinEmbossing` (LMK AES → ZPK 3DES, se a chave partilhada com o emissor for 3DES) ou o `TranslatePinLmkToZpk` (se for AES) para preparar o PIN para o envio ao emissor .
6. Retorno do PIN sob ZPK do emissor: O HoP devolve o PIN cifrado pela ZPK partilhada entre o adquirente e o emissor .
7. Encaminhamento da transação: O adquirente envia ao emissor a transação ISO 8583 (saque, MTI 0200) com o PIN cifrado sob a ZPK e os dados do levantamento .
8. Autorização: O emissor valida o PIN através do `ValidatePinIssuerKey` e verifica os critérios de negócio (saldo, limite), retornando a autorização ou a recusa .
9. Repasse ao ATM: O adquirente repassa a resposta ao ATM .
10. Dispensação ou recusa: O ATM dispensa as cédulas (se aprovada) ou exibe a recusa ao titular, finalizando a transação .

***

### Cenário 6 - Migração de Chaves Criptográficas

Este cenário ilustra uma operação programada de modernização criptográfica. A base de dados existente está sob ZPK 3DES (legado) e precisa de ser migrada para ZPK AES (devido ao programa PCI DSS ou a uma política interna). O *job* lê os PINs antigos, traduz o domínio e o algoritmo, e persiste sob a nova chave .

#### Sequência de Etapas

1. Leitura da base antiga: O *job* de migração lê em lote os registos (PIN cifrado + PAN) da base antiga sob ZPK 3DES .
2. Internalização (3DES → AES sob LMK): Para cada registo, o *job* invoca o `PinInternalization` passando o `zpkKeyIdSrc` (ZPK 3DES antiga), o `zpkKeyIdDst` (LMK AES interna), o `pinBlockSrc` e o `pinBlockFmtSrc` .
3. Retorno sob LMK AES: O HoP retorna o PIN cifrado sob a LMK AES .
4. Tradução para a nova ZPK: O *job* invoca o `TranslatePinLmkToZpk` passando o `keyId` (ZPK AES nova) e o PIN sob LMK AES, garantindo o envio do `formatCode = 4` (formato 48, o padrão para AES) .
5. Retorno sob nova ZPK: O HoP devolve o PIN cifrado sob a nova ZPK AES .
6. Persistência: O *job* grava o registo na nova base de dados com o `keyId` novo. A base antiga é marcada para descomissionamento apenas após a reconciliação completa do lote processado .


# Integração, Boas Práticas e Apêndices

### Fluxo de Integração Recomendado

As cinco etapas abaixo cobrem a integração ponta-a-ponta de uma aplicação cliente ao módulo PayShield Pan .

#### Provisionamento

* Solicite à First Tech a criação do `client_id` e o registo das chaves criptográficas necessárias (LMK do *tenant* e as ZPKs por canal: emissor, adquirente, terminais, gráfica) .
* Mapeie cada caso de uso a um par origem/destino e ao endpoint correspondente, conforme a matriz de operações (Secção 3).
* Documente internamente os `keyIds` e os seus algoritmos (AES vs 3DES), uma vez que o algoritmo não é exposto pela API e tem de ser conhecido pelo integrador.

#### Autenticação

* Obtenha o token Bearer junto ao Auth0 da First Tech .
* Implemente um sistema de *cache* do token, respeitando o TTL (*Time-To-Live*) fornecido pelo provedor.
* Implemente a renovação proativa antes da expiração para evitar erros `401` em transações críticas.

#### Operação

* Construa o *body* de acordo com o endpoint alvo. Tenha especial atenção às convenções de nome de campo (ex.: `zpkKeyIdSrc/Dst` em `PinEmbossing`/`PinInternalization`, versus `keyId` em `TranslatePin*`) .
* Valide a compatibilidade formato × algoritmo antes de enviar (Secção 4.3).
* Trate a resposta inspecionando primeiro o `retCode` antes de avaliar a flag `retValid`.

#### Tratamento de Erros

* O `retCode 01` no `ValidatePinIssuerKey` é a resposta esperada quando o PIN está incorreto; não se trata de um erro técnico .
* Os `retCode 10` ou `11` (paridade de chave) indicam que a chave está corrompida e precisa de ser reprovisionada (abra um chamado com a First Tech).
* O `retCode 17` indica que a tradução para o par origem/destino está bloqueada pelas políticas do HSM.
* O `retCode 69` (formato desabilitado) indica uma violação da matriz de compatibilidade (ex.: formato 48 em 3DES).
* Os erros `5xx` podem ser transitórios. Implemente um mecanismo de *retry* com *backoff* exponencial e *jitter*, mas NUNCA registe o PIN nos *logs* durante este processo.

#### Observabilidade

* Métricas Mínimas: Monitorize a taxa de chamadas por endpoint, a latência nos percentis `p50`/`p95`/`p99`, e a taxa de erro agrupada por `retCode` .
* Alertas: Configure alarmes em caso de desvio de SLA, num incremento súbito de `retCode 01` (que pode indicar um ataque de força bruta), em erros `401` persistentes, e em quaisquer `retCodes` de paridade.
* Regra de Ouro (Logs): É estritamente PROIBIDO registar em *log* os campos `pin`, `pinDb`, `pinBlockSrc`, `generatedPin` ou qualquer conteúdo do `retMultiValue`. Registe apenas o `client_id`, o endpoint, o `retCode` e a duração da chamada.

***

### Boas Práticas

#### Segurança

* O PIN em claro NUNCA deve ser visto pela aplicação. Toda a manipulação acontece sob cifragem (LMK, ZPK, TPK). Se o desenho arquitetural exigir o PIN em claro, o desenho está incorreto .
* Restrinja o acesso ao endpoint `apivin.first-tech.net` através de uma *allowlist* de IPs, sempre que possível.
* Implemente *rate limits* por `client_id` na sua infraestrutura para evitar enumeração de PINs (ex.: um máximo de `N` tentativas por PAN por hora).
* Em fluxos de `ValidatePinIssuerKey`, propague apenas o valor booleano do `retValid` para a camada de negócio; nunca exponha o `retDescription` ao cliente final.

#### Performance

* Reaproveite as conexões HTTP (*keep-alive*). O serviço Hop V4 já mantém uma conexão persistente e otimizada com o HSM .
* Em *jobs* de migração, dimensione lotes pequenos (50 a 200 registos) para não saturar a fila de processamento do HSM.
* Distribua os *jobs* de migração durante as janelas de menor movimento (*off-peak*) para preservar a capacidade de processamento das transações *online*.

#### Guia de Troubleshooting Rápido

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Sintoma Observado</th><th>Causa Provável</th><th>Ação Corretiva</th></tr></thead><tbody><tr><td>HTTP 401 em todas as chamadas</td><td>Token expirado ou ausente.</td><td>Renovar token no Auth0; verificar <em>header</em> <code>Authorization</code>.</td></tr><tr><td><code>retCode 17</code> em PinEmbossing</td><td>Tradução LMK → ZPK desabilitada para o par de chaves.</td><td>Verificar as políticas do HSM aplicadas ao seu <em>tenant</em>.</td></tr><tr><td><code>retCode 69</code> em PinEmbossing com formato 48</td><td>Formato 48 não suportado em ZPK 3DES (destino).</td><td>Usar formatos <code>01-47</code> no <code>pinBlockFmtDst</code>.</td></tr><tr><td><code>retCode 81</code> com pinLength informado</td><td>Tamanho real do PIN no PinBlock difere do declarado.</td><td>Validar a rotina de geração do PinBlock na origem.</td></tr><tr><td><code>retCode 88</code></td><td>PinBlock com PIN de tamanho zero (alerta).</td><td>Revisar processo de geração na origem.</td></tr><tr><td><code>retCode 10</code> ou <code>11</code></td><td>Erro de paridade na chave.</td><td>Solicitar reprovisionamento da chave à First Tech.</td></tr><tr><td><code>ValidatePinIssuerKey</code> sempre retorna <code>retValid false</code></td><td><code>formatCode</code> / <code>formatCodeDb</code> invertidos ou <code>keyIds</code> trocados.</td><td>Validar o <em>payload</em> rigorosamente contra o exemplo da Secção 15.3.</td></tr><tr><td><code>TranslatePan</code> retorna formato inesperado</td><td>AES Key Block LMK força nativamente o formato 48 no resultado.</td><td>Documentar esta regra nas integrações <em>downstream</em> que processam a resposta.</td></tr></tbody></table>

***

### Apêndices

#### Apêndice A - Glossário

| AES                    | *Advanced Encryption Standard*. Algoritmo simétrico padrão (128, 192 e 256 bits). |
| ---------------------- | --------------------------------------------------------------------------------- |
| AES Key Block LMK      | Modelo de armazenamento de chaves AES no HSM em formato Key Block (TR-31).        |
| 3DES Key Block LMK     | Modelo de armazenamento de chaves 3DES no HSM em formato Key Block.               |
| BDK                    | *Base Derivation Key*. Chave-mãe DUKPT.                                           |
| DUKPT                  | *Derived Unique Key Per Transaction*. Esquema de derivação por transação.         |
| formatCode             | Índice abreviado de formato de PinBlock (0/1/3/4).                                |
| ISO PIN Block Format 4 | Formato moderno de PinBlock (Thales 48), exclusivo para chaves AES.               |
| LMK                    | *Local Master Key*. Chave-mestra AES interna do HSM da First Tech.                |
| pinBlockFmt            | Código direto Thales de formato de PinBlock (01, 02... 48).                       |
| TPK / ZPK              | *Terminal PIN Key* / *Zone PIN Key*. Chaves partilhadas entre zonas ou terminais. |
| Variant LMK            | Modelo legado de armazenamento de chaves no HSM (anterior ao Key Block).          |

#### Apêndice B - Referência Rápida de Endpoints

| Gerar PIN sob LMK            | `/v4/PayShieldPan/GeneratePin`          | LMK                            |
| ---------------------------- | --------------------------------------- | ------------------------------ |
| Gerar PIN sob ZPK do emissor | `/v4/PayShieldPan/GeneratePinIssuerKey` | ZPK                            |
| LMK AES → ZPK 3DES           | `/v4/PayShieldPan/PinEmbossing`         | AES → 3DES                     |
| ZPK 3DES → LMK AES           | `/v4/PayShieldPan/PinInternalization`   | 3DES → AES                     |
| LMK AES → ZPK AES            | `/v4/PayShieldPan/TranslatePinLmkToZpk` | AES → AES                      |
| ZPK AES → LMK AES            | `/v4/PayShieldPan/TranslatePinZpkToLmk` | AES → AES                      |
| Trocar PAN preservando PIN   | `/v4/PayShieldPan/TranslatePan`         | LMK → LMK                      |
| Trocar PAN + traduzir PIN    | `/v4/PayShieldPan/TranslatePinPan`      | LMK → ZPK                      |
| Validar PIN recebido         | `/v4/PayShieldPan/ValidatePinIssuerKey` | ZPK 3DES → LMK AES (validação) |


# Fundamentos e Criptografia

O módulo PIN da plataforma Hop V4 expõe operações REST seguras para a validação de PINs de portadores e para a tradução de PinBlocks entre diferentes chaves criptográficas. Toda operação ocorre em ambiente de Hardware Security Module (HSM) certificado PCI PIN, garantindo que o PIN nunca seja exposto em claro .

### Regras de Ouro (PCI PIN)

Ao integrar com os endpoints deste módulo, as seguintes premissas arquiteturais são inegociáveis:

* Nunca exponha o PIN em claro: Os endpoints não retornam e não devem retornar o PIN decifrado.
* Cifragem de Ponta a Ponta: Chaves de PIN (TPK, ZPK, BDK, PVK) jamais circulam em claro.
* Não armazene PinBlocks em cache: O reaproveitamento de PinBlocks entre transações viola o padrão PCI PIN e falhará tecnicamente em esquemas de chaves dinâmicas (DUKPT) .
* Mascaramento de Logs: É estritamente proibido registrar os campos `hPibBlock`, `hPinHost` ou o PAN completo nos logs da sua aplicação .

***

### Tipos de Chaves Suportadas

O módulo suporta operações em uma cadeia completa de aquisição, atuando como tradutor de chaves para adquirentes e como validador final para emissores .

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Tipo</th><th>Nome Completo</th><th>Descrição e Uso</th></tr></thead><tbody><tr><td>TPK</td><td><em>Terminal PIN Key</em></td><td>Chave injetada no terminal (maquininha). Cifra o PinBlock no momento em que o portador digita a senha.</td></tr><tr><td>ZPK</td><td><em>Zone PIN Key</em></td><td>Chave compartilhada entre zonas de segurança (ex: adquirente ↔ bandeira ↔ emissor). O PinBlock é traduzido entre ZPKs a cada fronteira de rede.</td></tr><tr><td>BDK</td><td><em>Base Derivation Key</em></td><td>Chave-mestra utilizada em ambientes DUKPT (<em>Derived Unique Key Per Transaction</em>). O HSM utiliza o BDK em conjunto com o KSN para derivar uma chave de sessão única por transação.</td></tr><tr><td>PVK</td><td><em>PIN Verification Key</em></td><td>Utilizada pelo emissor para gerar e validar o PVV (<em>PIN Verification Value</em>). O PIN é validado no HSM sem a necessidade de ser armazenado.</td></tr></tbody></table>

***

### Formatos de PinBlock

O campo que recebe o código de formato no payload da API é grafado como `pibBlockFmt`. Certifique-se de manter esta grafia exata na sua integração; o uso de "pinBlockFmt" resultará em erro de requisição (HTTP 400).

Os seguintes valores de formato são aceitos pela API:

#### Formatos ISO 9564-1

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Código (pibBlockFmt)</th><th>Norma e Formato</th><th>Características</th></tr></thead><tbody><tr><td><code>01</code></td><td>ISO 9564-1 Formato 0</td><td>Bloco de 8 bytes. Padrão mais comum em transações com cartão. Construído com operação XOR entre o PIN e os últimos 12 dígitos do PAN.</td></tr><tr><td><code>02</code></td><td>ISO 9564-1 Formato 1</td><td>Bloco de 8 bytes com <em>padding</em> aleatório. Utilizado em cenários onde não há PAN disponível (ex: ATM offline).</td></tr><tr><td><code>03</code></td><td>ISO 9564-1 Formato 2</td><td>Bloco de 8 bytes sem operação XOR com o PAN. Uso restrito e tipicamente offline.</td></tr><tr><td><code>04</code></td><td>ISO 9564-1 Formato 3</td><td>Bloco de 8 bytes. Variação do formato 0, mas contendo <em>padding</em> aleatório adicional.</td></tr><tr><td><code>05</code></td><td>ISO 9564-1 Formato 4</td><td>Bloco de 16 bytes (128 bits) criptografado sob AES. Formato obrigatório em esquemas EMV modernos.</td></tr></tbody></table>

#### Formatos Proprietários

O módulo também oferece suporte nativo à validação e tradução de variantes proprietárias utilizadas na indústria:

* `34`: Variante Proprietária `0x34`.
* `35`: Variante Proprietária `0x35`.
* `41`: Variante Proprietária `0x41`.
* `42`: Variante Proprietária `0x42`.
* `47`: Variante Proprietária `0x47`.
* `48`: Variante Proprietária `0x48`.

> Atenção à consistência do PAN: Nos formatos baseados em operação XOR (`01`, `04`, `05`), se o PAN enviado na requisição da API divergir do PAN utilizado pelo terminal no momento da criação do PinBlock, o PIN resultante será corrompido, gerando erro de "tamanho zero" (Código 88) ou recusa indevida da senha.


# Referência API - PIN

## Validar PIN

> Valida o PIN do portador do cartão comparando o PinBlock recebido com o PIN armazenado no HSM.\
> Retorna \`true\` em \`retValid\` se o PIN for válido, \`false\` caso contrário.\
> Em caso de erro, retorna os campos de erro (\`retCode\` e \`retDescription\`).<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield PIN API","version":"4.1.32"},"tags":[{"name":"PIN","description":"Operações de tradução e validação de PIN"}],"servers":[{"url":"https://apivin.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"ValidatePinInput":{"type":"object","required":["client_id","keyId","hPibBlock","pibBlockFmt","pan"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave TPK ou ZPK no banco de dados"},"hPibBlock":{"type":"string","description":"PinBlock em formato Hexadecimal"},"pibBlockFmt":{"type":"string","description":"Formato do PinBlock. Valores válidos:\n`01`, `02`, `03`, `04`, `05`, `34`, `35`, `41`, `42`, `47`, `48`\n"},"hPinHost":{"type":"string","nullable":true,"description":"PIN Host em formato Hexadecimal (usado para validação contra PIN armazenado)"},"pan":{"type":"string","description":"PAN do cartão (16 a 19 dígitos)"}}},"ReturnSingle":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValue":{"type":"string","description":"Valor de retorno simples"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retDesc":{"type":"string","description":"Descrição do resultado"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `-1`: Erro interno\n- `01`: Falha na verificação do PIN\n- `10`: Erro de paridade na chave TPK de origem\n- `11`: Erro de paridade na chave ZPK de destino\n- `17`: Tradução de PIN desabilitada\n- `68`: Comando desabilitado\n- `69`: Formato do PinBlock desabilitado\n- `88`: Aviso — PinBlock contém PIN de tamanho zero\n- `137`: Malformação da requisição\n- `155`: Chave não encontrada no banco de dados\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDesc":{"type":"string","description":"Descrição do erro"}}}}},"paths":{"/v4/PayShieldPin/ValidatePin":{"post":{"tags":["PIN"],"summary":"Validar PIN","description":"Valida o PIN do portador do cartão comparando o PinBlock recebido com o PIN armazenado no HSM.\nRetorna `true` em `retValid` se o PIN for válido, `false` caso contrário.\nEm caso de erro, retorna os campos de erro (`retCode` e `retDescription`).\n","operationId":"validatePin","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidatePinInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnSingle"}}}},"400":{"description":"Requisição inválida — campo obrigatório ausente ou formato incorreto","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"404":{"description":"Chave não encontrada no banco de dados","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

***

## Traduzir PIN

> Traduz um PinBlock de uma chave de origem (\`keyIdSrc\`) para uma chave de destino (\`keyIdDst\`).\
> Suporta chaves do tipo TPK, ZPK e BDK (DUKPT).\
> \
> Retorna em \`retMultiValue\`:\
> \- \`retMultiValue\[0]\` = formato do PinBlock de destino\
> \- \`retMultiValue\[1]\` = PinBlock traduzido (sob a chave de destino)\
> \- \`retMultiValue\[2]\` = formato do PinBlock de origem\
> \
> Em caso de erro, retorna os campos de erro (\`retCode\` e \`retDescription\`).<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield PIN API","version":"4.1.32"},"tags":[{"name":"PIN","description":"Operações de tradução e validação de PIN"}],"servers":[{"url":"https://apivin.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"TranslatePinInput":{"type":"object","required":["client_id","keyIdSrc","hPibBlockSrc","pibBlockFmtSrc","keyIdDst","pibBlockFmtDst","pan"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyIdSrc":{"type":"string","description":"Alias/identificador da chave de origem (TPK, ZPK ou BDK)"},"hPibBlockSrc":{"type":"string","description":"PinBlock de origem em formato alfanumérico (a-z, A-Z, 0-9)"},"pibBlockFmtSrc":{"type":"string","description":"Formato do PinBlock de origem. Valores válidos:\n`01`, `02`, `03`, `04`, `05`, `34`, `35`, `41`, `42`, `47`, `48`\n"},"hPinHost":{"type":"string","nullable":true,"description":"PIN Host em formato Hexadecimal (opcional)"},"keyIdDst":{"type":"string","description":"Alias/identificador da chave de destino (TPK, ZPK ou BDK)"},"pibBlockFmtDst":{"type":"string","description":"Formato do PinBlock de destino. Valores válidos:\n`01`, `02`, `03`, `04`, `05`, `34`, `35`, `41`, `42`, `47`, `48`\n"},"pan":{"type":"string","description":"PAN do cartão de origem (16 a 19 dígitos)"},"ksn_desc":{"type":"string","nullable":true,"description":"Descritor KSN da chave de origem — necessário apenas se `keyIdSrc` for do tipo BDK (DUKPT)"},"ksn":{"type":"string","nullable":true,"description":"KSN da chave de origem — necessário apenas se `keyIdSrc` for do tipo BDK (DUKPT)"},"pan_dst":{"type":"string","nullable":true,"description":"PAN do cartão de destino (16 a 19 dígitos) — necessário quando o PAN de destino difere do de origem"},"ksn_desc_dst":{"type":"string","nullable":true,"description":"Descritor KSN da chave de destino — necessário apenas se `keyIdDst` for do tipo BDK (DUKPT)"},"ksn_dst":{"type":"string","nullable":true,"description":"KSN da chave de destino — necessário apenas se `keyIdDst` for do tipo BDK (DUKPT)"}}},"ReturnMultiValue":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValue":{"type":"string","description":"Valor de retorno simples (geralmente vazio em sucesso)"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com os valores de retorno da operação TranslatePin:\n- `[0]` = formato do PinBlock de destino\n- `[1]` = PinBlock traduzido (sob a chave de destino)\n- `[2]` = formato do PinBlock de origem\n"},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retDesc":{"type":"string","description":"Descrição do resultado"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `-1`: Erro interno\n- `01`: Falha na verificação do PIN\n- `10`: Erro de paridade na chave TPK de origem\n- `11`: Erro de paridade na chave ZPK de destino\n- `17`: Tradução de PIN desabilitada\n- `68`: Comando desabilitado\n- `69`: Formato do PinBlock desabilitado\n- `88`: Aviso — PinBlock contém PIN de tamanho zero\n- `137`: Malformação da requisição\n- `155`: Chave não encontrada no banco de dados\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDesc":{"type":"string","description":"Descrição do erro"}}}}},"paths":{"/v4/PayShieldPin/TranslatePin":{"post":{"tags":["PIN"],"summary":"Traduzir PIN","description":"Traduz um PinBlock de uma chave de origem (`keyIdSrc`) para uma chave de destino (`keyIdDst`).\nSuporta chaves do tipo TPK, ZPK e BDK (DUKPT).\n\nRetorna em `retMultiValue`:\n- `retMultiValue[0]` = formato do PinBlock de destino\n- `retMultiValue[1]` = PinBlock traduzido (sob a chave de destino)\n- `retMultiValue[2]` = formato do PinBlock de origem\n\nEm caso de erro, retorna os campos de erro (`retCode` e `retDescription`).\n","operationId":"translatePin","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranslatePinInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnMultiValue"}}}},"400":{"description":"Requisição inválida — campo obrigatório ausente ou formato incorreto","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"404":{"description":"Chave não encontrada no banco de dados","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```


# Tratamento de Erros e Operação

### Códigos de Erro (Taxonomia Completa)

Nas respostas de erro (HTTP 400, 404, 500), o campo `retCode` indica a categoria da falha ocorrida no processamento da API ou na validação criptográfica do HSM .

<table data-header-hidden="false" data-header-sticky><thead><tr><th>retCode</th><th>HTTP Típico</th><th>Significado</th><th>Ação Sugerida</th></tr></thead><tbody><tr><td><code>-1</code></td><td>400/500</td><td>Erro interno genérico</td><td>Falha do serviço criptográfico. Aplicar <em>retry</em> com <em>backoff</em>. Se persistir, escalar para o suporte técnico.</td></tr><tr><td><code>01</code></td><td>400</td><td>Falha na verificação do PIN</td><td>Indica inconsistência de formato/chave ou, dependendo da integração, falha de validação.</td></tr><tr><td><code>10</code></td><td>400/500</td><td>Erro de paridade (Chave Origem)</td><td>Problema criptográfico grave na chave. A chave está corrompida. Requer intervenção do suporte técnico.</td></tr><tr><td><code>11</code></td><td>400/500</td><td>Erro de paridade (Chave Destino)</td><td>Análogo ao código 10, aplicado à chave de destino.</td></tr><tr><td><code>17</code></td><td>400</td><td>Tradução de PIN desabilitada</td><td>O comando <code>TranslatePin</code> não está habilitado no contrato ou perfil associado ao seu <code>client_id</code>.</td></tr><tr><td><code>68</code></td><td>400</td><td>Comando desabilitado</td><td>O comando PIN em questão está desabilitado comercialmente para o cliente.</td></tr><tr><td><code>69</code></td><td>400</td><td>Formato do PinBlock desabilitado</td><td>O <code>pibBlockFmt</code> informado é válido no HSM, mas encontra-se desabilitado para o seu <em>tenant</em>.</td></tr><tr><td><code>88</code></td><td>400</td><td>PinBlock contém PIN de tamanho zero</td><td>O bloco foi decifrado, mas o PIN extraído tem 0 dígitos. Sinaliza problema na geração do bloco na origem (terminal) ou PAN inconsistente.</td></tr><tr><td><code>137</code></td><td>400</td><td>Malformação da requisição</td><td><em>Payload</em> JSON inválido, campo obrigatório ausente ou nome de campo incorreto (ex: <code>pinBlockFmt</code> em vez de <code>pibBlockFmt</code>).</td></tr><tr><td><code>155</code></td><td>404</td><td>Chave não encontrada</td><td>O alias informado em <code>keyId</code>, <code>keyIdSrc</code> ou <code>keyIdDst</code> não existe ou não pertence ao seu cliente.</td></tr></tbody></table>

***

### Boas Práticas e Armadilhas Comuns

#### Boas Práticas

* Mascaramento de Logs (Obrigatório): Auditorias de PCI PIN reprovam integrações que registam dados sensíveis. O PAN completo e os campos `hPibBlock` e `hPinHost` NUNCA devem constar nos *logs* da sua aplicação (ex: mascare o PAN como `111122******4444` e suprima os PinBlocks) .
* Diferenciar Falha Técnica de Recusa: Um `HTTP 200` com `retValid: false` (PIN incorreto) é uma decisão de negócio e não um erro técnico. Instrumente métricas separadas; misturá-las com falhas 400/500 dificultará o rastreio de incidentes reais .
* Token JWT Unificado: O mesmo token Bearer atende a todos os módulos (EMV, PIN, Key Manager, Crypto, CVV, PAN, RSA). Mantenha um *cache* partilhado na sua arquitetura .
* Validação de KCV: Ao provisionar chaves com o suporte, valide o KCV (*Key Check Value*) no ambiente de homologação. KCVs incorretos são a principal causa dos erros `10` e `11` em produção .

#### Armadilhas Comuns na Integração

1. Grafia do campo `pibBlockFmt`: Como mencionado, a API exige a grafia com "pib". Tentar utilizar "pinBlockFmt" gerará imediatamente o erro `137` .
2. Incompatibilidade Algoritmo/Formato: Formatos como o `05` (ISO 4) exigem obrigatoriamente chaves AES. Tentativas de decifrar o formato `05` com chaves 3DES causarão o erro `69` ou falhas de paridade .
3. PAN Inconsistente: Se o PAN enviado no *request* divergir do PAN efetivamente utilizado pelo terminal para gerar o PinBlock, a operação de extração do PIN falhará, resultando frequentemente no erro `88` (PIN de tamanho zero).
4. Ausência de KSN no DUKPT: Quando o `keyIdSrc` for um BDK, a ausência dos campos `ksn` ou `ksn_desc` invalidará a requisição, pois o HSM não terá como derivar a chave de sessão.

***

### Troubleshooting

Guia de triagem rápida para anomalias observadas durante a fase de integração e produção :

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Sintoma</th><th>Causa Provável</th><th>Ação Sugerida</th></tr></thead><tbody><tr><td>HTTP 200 / <code>retValid: false</code> sempre</td><td>Chave errada ou PAN inconsistente.</td><td>Validar rigorosamente se o PAN do <em>request</em> corresponde ao PAN utilizado no cálculo no terminal.</td></tr><tr><td>HTTP 400 (<code>retCode 137</code>)</td><td>Erro estrutural no <em>payload</em>.</td><td>Inspecionar a sintaxe JSON e garantir o uso correto de <code>pibBlockFmt</code>.</td></tr><tr><td>HTTP 400 (<code>retCode 88</code>)</td><td>PIN decifrado com tamanho zero.</td><td>Verificar integridade do PAN e, em cenários DUKPT, confirmar se o KSN não sofreu mutação.</td></tr><tr><td>HTTP 404 (<code>retCode 155</code>)</td><td>Chave não localizada.</td><td>O erro não distingue entre Origem e Destino; verifique ambos os <em>aliases</em> no Key Manager.</td></tr><tr><td>HTTP 400/500 (<code>retCode 10</code> ou <code>11</code>)</td><td>Paridade de chave corrompida.</td><td>Escalar para o suporte técnico para reprovisionamento do <em>alias</em>.</td></tr><tr><td>HTTP 401 intermitente</td><td>Token expirado.</td><td>Implementar <em>cache</em> com renovação proativa (<em>pre-fetch</em>).</td></tr></tbody></table>


# Fundamentos e Arquitetura

O módulo PayShield RSA da plataforma Hop V4 disponibiliza operações REST para a importação de chaves públicas (RSA e ECC) e a exportação segura de chaves simétricas (DES, AES, HMAC) protegidas por essas chaves públicas.

Este módulo é fundamental para fluxos de troca de chaves entre instituições, como em cerimónias de troca inicial de chaves entre adquirentes, emissores e bandeiras, ou na integração com parceiros que exijam o transporte seguro de chaves simétricas através de criptografia de chave pública.

### Funcionamento do Módulo

O transporte de chaves sob chave pública permite que a instituição destinatária gere um par de chaves RSA, envie a parte pública e receba a chave simétrica criptografada, garantindo que apenas o detentor da chave privada correspondente consiga decifrá-la.

O fluxo implementado no Hop V4 ocorre em duas etapas obrigatórias:

1. Import: Recebe a chave pública em formato DER ASN.1, gera um MAC sobre ela utilizando a LMK do HSM e devolve a chave encapsulada num Key Block Thales. Este formato protege a chave pública contra adulterações após a importação.
2. Export: Recebe a referência (`keyId`) de uma chave simétrica e o Key Block Thales obtido no passo anterior, retornando a chave simétrica criptografada sob a chave pública.

> ⚠️ Sequência Obrigatória: Import → Export A chave pública utilizada como entrada no endpoint `Export` NÃO deve ser a chave bruta DER recebida da contraparte. Deve ser obrigatoriamente o resultado da operação `Import` (o Key Block Thales com MAC). O uso direto da chave DER resultará em erros de validação (código 02 ou 83).

***

### Modos de Padding (RSA)

A criptografia RSA exige um esquema de preenchimento (*padding*) para garantir a segurança da operação. O Hop V4 suporta os dois esquemas padrão da indústria através do parâmetro `padModeId`:

<table data-header-hidden="false" data-header-sticky><thead><tr><th>padModeId</th><th>Esquema</th><th>Aplicação</th><th>Requer MGF?</th></tr></thead><tbody><tr><td>1</td><td>PKCS#1 v1.5</td><td>Compatibilidade com sistemas legados ou parceiros que ainda não migraram para OAEP.</td><td>Não</td></tr><tr><td>2</td><td>PKCS#1 v2.2 OAEP</td><td>Padrão moderno recomendado. Mais resistente a ataques de oráculo de padding.</td><td>Sim</td></tr></tbody></table>

#### Funções Hash MGF (Apenas OAEP)

Ao utilizar o modo OAEP (`padModeId = 2`), o campo `mgfHashFunction` torna-se obrigatório para indicar a função hash utilizada no MGF1 (*Mask Generation Function*):

<table data-header-hidden="false" data-header-sticky><thead><tr><th>mgfHashFunction</th><th>Função Hash</th><th>Recomendação</th></tr></thead><tbody><tr><td>1</td><td>SHA-1</td><td><p>Apenas para compatibilidade legada.</p><p><a class="button secondary"></a></p></td></tr><tr><td>5</td><td>SHA-224</td><td><p>Pouco utilizada na prática.</p><p><a class="button secondary"></a></p></td></tr><tr><td>6</td><td>SHA-256</td><td><p>Padrão recomendado para novas integrações.</p><p><a class="button secondary"></a></p></td></tr><tr><td>7 / 8</td><td>SHA-384 / SHA-512</td><td><p>Níveis superiores de segurança (verificar compatibilidade).</p><p><a class="button secondary"></a></p></td></tr></tbody></table>

***

### Formatos de Chave Pública e Bloco de Saída

#### Codificação na Importação (`publicKeyEncoding`)

O parâmetro `publicKeyEncoding` no endpoint `Import` define a estrutura da chave pública DER ASN.1 recebida:

<table data-header-hidden="false" data-header-sticky><thead><tr><th>publicKeyEncoding</th><th>Formato</th><th>Tipo de Chave</th></tr></thead><tbody><tr><td>1</td><td>DER ASN.1 RSA (INTEGER unsigned)</td><td>RSA (PKCS#1 ou X.509).</td></tr><tr><td>2</td><td>DER ASN.1 RSA (INTEGER 2's complement)</td><td>RSA (variação de codificação de módulo).</td></tr><tr><td>3</td><td>DER ASN.1 ECC X9.62 uncompressed</td><td>ECC (formato de ponto uncompressed, prefixo <code>0x04</code>).</td></tr></tbody></table>

#### Tipo de Bloco na Exportação (`keyBlockType`)

O parâmetro `keyBlockType` define o formato do bloco de chave produzido. Atualmente, o único valor suportado em produção é o 3 (*Unformatted Key Data Block*).

***

### Arquitetura e Padrão de Resposta

* Base URL: `https://apivin.first-tech.net/v4/PayShieldRsa/`.
* Autenticação: Exige token Bearer JWT enviado no cabeçalho `Authorization` de cada requisição.
* Identificação do Cliente: O campo `client_id` identifica o cliente, garantindo a segregação de chaves e histórico no HSM.
* Identificação da Chave (`keyId`): Referencia o alias da chave simétrica (DES, AES ou HMAC) previamente cadastrada no módulo Key Manager. O formato padrão é `client-{client_id}-key-id-XXX-TIPO`.

#### Estrutura de Resposta (`ReturnSingle`)

Todas as respostas do módulo RSA utilizam o envelope `ReturnSingle`, processando uma única chave por chamada:

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Campo</th><th>Tipo</th><th>Descrição</th></tr></thead><tbody><tr><td><code>retCode</code></td><td><code>integer</code></td><td>Código de retorno (<code>0</code> para sucesso).</td></tr><tr><td><code>retValid</code></td><td><code>boolean</code></td><td>Indica o sucesso da operação.</td></tr><tr><td><code>retValue</code></td><td><code>string</code></td><td>Valor em hexadecimal (Key Block no Import; Chave criptografada no Export).</td></tr><tr><td><code>retDescription</code></td><td><code>string</code></td><td>Descrição textual do resultado (Ex.: "OK").</td></tr></tbody></table>


# Referência da API — RSA

Esta seção descreve os dois endpoints expostos pelo módulo PayShield RSA: `Import` e `Export`. Eles são utilizados sequencialmente para garantir a transferência segura de chaves simétricas .

## Exportar chave sob chave pública RSA

> Traduz uma chave DES, AES ou HMAC de criptografia sob o LMK para criptografia sob uma chave pública RSA.\
> Retorna a chave exportada (criptografada sob a chave pública) em \`retValue\` em formato Hex.\
> \
> Suporta dois modos de padding:\
> \- \*\*PKCS#1 v1.5\*\* (\`padModeId: 1\`): método clássico, não requer \`mgfHashFunction\`\
> \- \*\*OAEP\*\* (\`padModeId: 2\`): método moderno, requer \`mgfHashFunction\`\
> \
> Atualmente apenas \`keyBlockType: 3\` (Unformatted Key Data Block) é suportado.<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield RSA API","version":"4.1.32"},"tags":[{"name":"RSA","description":"Operações de exportação e importação de chaves RSA/ECC"}],"servers":[{"url":"https://apivin.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"ExportKeyInput":{"type":"object","required":["client_id","keyId","padModeId","publicKey","keyBlockType"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave a ser exportada no banco de dados"},"padModeId":{"type":"integer","enum":[1,2],"description":"Identificador do modo de padding usado na criptografia:\n- `1`: PKCS#1 v1.5 (EME-PKCS1-v1_5)\n- `2`: PKCS#1 v2.2 OAEP (EME-OAEP-ENCODE) — requer `mgfHashFunction`\n"},"mgfHashFunction":{"type":"integer","enum":[1,5,6,7,8],"nullable":true,"description":"Identificador da função hash MGF — obrigatório apenas quando `padModeId: 2` (OAEP):\n- `1`: SHA-1\n- `5`: SHA-224\n- `6`: SHA-256\n- `7`: SHA-384\n- `8`: SHA-512\n"},"publicKey":{"type":"string","description":"Chave pública RSA em formato Key Block Thales (Hex).\nGerada pelo endpoint `Import` deste mesmo serviço.\n"},"keyBlockType":{"type":"integer","enum":[3],"description":"Tipo do Key Data Block:\n- `3`: Unformatted Key Data Block (único valor suportado atualmente)\n"}}},"ReturnSingle":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retValue":{"type":"string","description":"Valor de retorno — chave exportada/importada em Hex"},"retDescription":{"type":"string","description":"Descrição do resultado"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro (Export):\n- `01`: Falha na verificação do MAC\n- `02`: Falha na verificação do check value\n- `03`: Tipo de chave privada inválido / Tipo de codificação de chave pública inválido\n- `04`: Flag de chave privada inválido / Chave pública não conforme com as regras de codificação\n- `05`: Tipo de chave DES/AES inválido\n- `06`: Identificador de criptografia inválido\n- `07`: Identificador de modo de padding inválido\n- `08`: Erro no Key Block HMAC\n- `10`: Erro de paridade na chave DES\n- `34`: Valor de identificador hash HMAC inválido\n- `47`: Algoritmo não licenciado\n- `50`: Chave pública não conforme com as regras de codificação\n- `68`: Comando desabilitado\n- `76`: Erro no comprimento do Key Data Block\n- `81`: Tipo de Key Data Block inválido\n- `83`: Erro no formato do Key Block\n- `84`: Erro no check value do Key Block\n- `85`: Função MGF OAEP inválida\n- `86`: Função hash MGF OAEP inválida\n- `87`: Erro no parâmetro OAEP\n- `88`: Erro OAEP\n- `D3`: Erro na chave / Critérios de equivalência PCI HSM V3 não atendidos\n- `D4`: Chave pública ECC inválida\n"},"retValid":{"type":"boolean"},"retValue":{"type":"string"},"retDescription":{"type":"string","description":"Descrição do erro"}}}}},"paths":{"/v4/PayShieldRsa/Export":{"post":{"tags":["RSA"],"summary":"Exportar chave sob chave pública RSA","description":"Traduz uma chave DES, AES ou HMAC de criptografia sob o LMK para criptografia sob uma chave pública RSA.\nRetorna a chave exportada (criptografada sob a chave pública) em `retValue` em formato Hex.\n\nSuporta dois modos de padding:\n- **PKCS#1 v1.5** (`padModeId: 1`): método clássico, não requer `mgfHashFunction`\n- **OAEP** (`padModeId: 2`): método moderno, requer `mgfHashFunction`\n\nAtualmente apenas `keyBlockType: 3` (Unformatted Key Data Block) é suportado.\n","operationId":"exportKey","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportKeyInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnSingle"}}}},"400":{"description":"Requisição inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"404":{"description":"Chave não encontrada no banco de dados","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

***

## Importar chave pública RSA/ECC

> Importa uma chave pública RSA ou ECC gerando um MAC sobre ela.\
> Retorna a chave pública importada com o MAC gerado em \`retValue\` (formato Key Block Thales).\
> \
> O campo \`publicKey\` deve ser a chave pública em formato DER encoded ASN.1 em Hex.\
> O \`publicKeyEncoding\` define o formato de codificação da chave.<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield RSA API","version":"4.1.32"},"tags":[{"name":"RSA","description":"Operações de exportação e importação de chaves RSA/ECC"}],"servers":[{"url":"https://apivin.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"ImportPublicKeyInput":{"type":"object","required":["client_id","publicKeyEncoding","publicKey"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"publicKeyEncoding":{"type":"integer","enum":[1,2,3],"description":"Regras de codificação da chave pública:\n- `1`: DER encoded ASN.1 RSA Public Key (INTEGER com representação unsigned)\n- `2`: DER encoded ASN.1 RSA Public Key (INTEGER com representação 2's complement)\n- `3`: DER encoded ASN.1 ECC X9.62 format uncompressed key\n"},"publicKey":{"type":"string","description":"Chave pública RSA ou ECC em formato DER encoded ASN.1 em Hex.\nPara RSA: SubjectPublicKeyInfo ou RSAPublicKey.\nPara ECC: X9.62 uncompressed point format.\n"}}},"ReturnSingle":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retValue":{"type":"string","description":"Valor de retorno — chave exportada/importada em Hex"},"retDescription":{"type":"string","description":"Descrição do resultado"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro (Export):\n- `01`: Falha na verificação do MAC\n- `02`: Falha na verificação do check value\n- `03`: Tipo de chave privada inválido / Tipo de codificação de chave pública inválido\n- `04`: Flag de chave privada inválido / Chave pública não conforme com as regras de codificação\n- `05`: Tipo de chave DES/AES inválido\n- `06`: Identificador de criptografia inválido\n- `07`: Identificador de modo de padding inválido\n- `08`: Erro no Key Block HMAC\n- `10`: Erro de paridade na chave DES\n- `34`: Valor de identificador hash HMAC inválido\n- `47`: Algoritmo não licenciado\n- `50`: Chave pública não conforme com as regras de codificação\n- `68`: Comando desabilitado\n- `76`: Erro no comprimento do Key Data Block\n- `81`: Tipo de Key Data Block inválido\n- `83`: Erro no formato do Key Block\n- `84`: Erro no check value do Key Block\n- `85`: Função MGF OAEP inválida\n- `86`: Função hash MGF OAEP inválida\n- `87`: Erro no parâmetro OAEP\n- `88`: Erro OAEP\n- `D3`: Erro na chave / Critérios de equivalência PCI HSM V3 não atendidos\n- `D4`: Chave pública ECC inválida\n"},"retValid":{"type":"boolean"},"retValue":{"type":"string"},"retDescription":{"type":"string","description":"Descrição do erro"}}}}},"paths":{"/v4/PayShieldRsa/Import":{"post":{"tags":["RSA"],"summary":"Importar chave pública RSA/ECC","description":"Importa uma chave pública RSA ou ECC gerando um MAC sobre ela.\nRetorna a chave pública importada com o MAC gerado em `retValue` (formato Key Block Thales).\n\nO campo `publicKey` deve ser a chave pública em formato DER encoded ASN.1 em Hex.\nO `publicKeyEncoding` define o formato de codificação da chave.\n","operationId":"importKey","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportPublicKeyInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnSingle"}}}},"400":{"description":"Requisição inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

***

## The ExportKeyInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield RSA API","version":"4.1.32"},"components":{"schemas":{"ExportKeyInput":{"type":"object","required":["client_id","keyId","padModeId","publicKey","keyBlockType"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave a ser exportada no banco de dados"},"padModeId":{"type":"integer","enum":[1,2],"description":"Identificador do modo de padding usado na criptografia:\n- `1`: PKCS#1 v1.5 (EME-PKCS1-v1_5)\n- `2`: PKCS#1 v2.2 OAEP (EME-OAEP-ENCODE) — requer `mgfHashFunction`\n"},"mgfHashFunction":{"type":"integer","enum":[1,5,6,7,8],"nullable":true,"description":"Identificador da função hash MGF — obrigatório apenas quando `padModeId: 2` (OAEP):\n- `1`: SHA-1\n- `5`: SHA-224\n- `6`: SHA-256\n- `7`: SHA-384\n- `8`: SHA-512\n"},"publicKey":{"type":"string","description":"Chave pública RSA em formato Key Block Thales (Hex).\nGerada pelo endpoint `Import` deste mesmo serviço.\n"},"keyBlockType":{"type":"integer","enum":[3],"description":"Tipo do Key Data Block:\n- `3`: Unformatted Key Data Block (único valor suportado atualmente)\n"}}}}}}
```

## The ImportPublicKeyInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield RSA API","version":"4.1.32"},"components":{"schemas":{"ImportPublicKeyInput":{"type":"object","required":["client_id","publicKeyEncoding","publicKey"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"publicKeyEncoding":{"type":"integer","enum":[1,2,3],"description":"Regras de codificação da chave pública:\n- `1`: DER encoded ASN.1 RSA Public Key (INTEGER com representação unsigned)\n- `2`: DER encoded ASN.1 RSA Public Key (INTEGER com representação 2's complement)\n- `3`: DER encoded ASN.1 ECC X9.62 format uncompressed key\n"},"publicKey":{"type":"string","description":"Chave pública RSA ou ECC em formato DER encoded ASN.1 em Hex.\nPara RSA: SubjectPublicKeyInfo ou RSAPublicKey.\nPara ECC: X9.62 uncompressed point format.\n"}}}}}}
```

## The ReturnSingle object

```json
{"openapi":"3.0.3","info":{"title":"PayShield RSA API","version":"4.1.32"},"components":{"schemas":{"ReturnSingle":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retValue":{"type":"string","description":"Valor de retorno — chave exportada/importada em Hex"},"retDescription":{"type":"string","description":"Descrição do resultado"}}}}}}
```

## The ReturnError object

```json
{"openapi":"3.0.3","info":{"title":"PayShield RSA API","version":"4.1.32"},"components":{"schemas":{"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro (Export):\n- `01`: Falha na verificação do MAC\n- `02`: Falha na verificação do check value\n- `03`: Tipo de chave privada inválido / Tipo de codificação de chave pública inválido\n- `04`: Flag de chave privada inválido / Chave pública não conforme com as regras de codificação\n- `05`: Tipo de chave DES/AES inválido\n- `06`: Identificador de criptografia inválido\n- `07`: Identificador de modo de padding inválido\n- `08`: Erro no Key Block HMAC\n- `10`: Erro de paridade na chave DES\n- `34`: Valor de identificador hash HMAC inválido\n- `47`: Algoritmo não licenciado\n- `50`: Chave pública não conforme com as regras de codificação\n- `68`: Comando desabilitado\n- `76`: Erro no comprimento do Key Data Block\n- `81`: Tipo de Key Data Block inválido\n- `83`: Erro no formato do Key Block\n- `84`: Erro no check value do Key Block\n- `85`: Função MGF OAEP inválida\n- `86`: Função hash MGF OAEP inválida\n- `87`: Erro no parâmetro OAEP\n- `88`: Erro OAEP\n- `D3`: Erro na chave / Critérios de equivalência PCI HSM V3 não atendidos\n- `D4`: Chave pública ECC inválida\n"},"retValid":{"type":"boolean"},"retValue":{"type":"string"},"retDescription":{"type":"string","description":"Descrição do erro"}}}}}}
```


# Schemas e Códigos de Erro

Esta secção detalha os modelos de objeto (*schemas*) utilizados para o envio de requisições e processamento de respostas, bem como a taxonomia completa dos erros técnicos que podem ser retornados pelo HSM ou pela camada de validação da API.

### Modelos de Dados (Schemas)

#### Schemas de Entrada

Estes são os objetos JSON esperados no corpo (*body*) das requisições para cada *endpoint*.

`ImportPublicKeyInput` (Utilizado no *endpoint* `Import`):

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Campo</th><th>Tipo</th><th>Obrigatório</th><th>Descrição</th></tr></thead><tbody><tr><td><code>client_id</code></td><td><code>integer</code></td><td>Sim</td><td>Identificador numérico do cliente. Mínimo: 1.</td></tr><tr><td><code>publicKeyEncoding</code></td><td><code>integer</code></td><td>Sim</td><td>Regra de codificação da chave pública (1, 2 ou 3).</td></tr><tr><td><code>publicKey</code></td><td><code>string</code></td><td>Sim</td><td>Chave pública DER ASN.1 em hexadecimal.</td></tr></tbody></table>

`ExportKeyInput` (Utilizado no *endpoint* `Export`):

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Campo</th><th>Tipo</th><th>Obrigatório</th><th>Descrição</th></tr></thead><tbody><tr><td><code>client_id</code></td><td><code>integer</code></td><td>Sim</td><td>Identificador numérico do cliente.</td></tr><tr><td><code>keyId</code></td><td><code>string</code></td><td>Sim</td><td>Alias da chave simétrica DES/AES/HMAC a ser exportada.</td></tr><tr><td><code>padModeId</code></td><td><code>integer</code></td><td>Sim</td><td>Modo de <em>padding</em> (<code>1</code> = PKCS#1 v1.5, <code>2</code> = OAEP).</td></tr><tr><td><code>mgfHashFunction</code></td><td><code>integer</code></td><td>Não</td><td>Função hash MGF. Obrigatório apenas se <code>padModeId = 2</code>.</td></tr><tr><td><code>publicKey</code></td><td><code>string</code></td><td>Sim</td><td>Chave pública em formato Key Block Thales (resultado do <code>Import</code>).</td></tr><tr><td><code>keyBlockType</code></td><td><code>integer</code></td><td>Sim</td><td>Tipo do Key Data Block (apenas <code>3</code> suportado).</td></tr></tbody></table>

#### Schemas de Saída

`ReturnSingle` (Resposta de Sucesso): Utilizado tanto no `Import` quanto no `Export`. O módulo RSA retorna sempre um único valor criptográfico por chamada .

| **Campo**        | **Tipo**  | **Obrigatório** | **Descrição**                                        |
| ---------------- | --------- | --------------- | ---------------------------------------------------- |
| `retCode`        | `integer` | Não             | `0` para sucesso. Outros valores indicam erro.       |
| `retValid`       | `boolean` | Não             | Indica sucesso da operação.                          |
| `retValue`       | `string`  | Não             | Chave importada ou exportada em formato hexadecimal. |
| `retDescription` | `string`  | Não             | Descrição textual do resultado.                      |

`ReturnError` (Respostas HTTP 400, 404 e 500): Possui o mesmo formato do `ReturnSingle`, mas com a flag `retValid` definida como `false` e o `retCode` preenchido com o código específico da falha do HSM ou da API. A mensagem de detalhe é enviada no campo `retDescription` .

***

### Catálogo de Códigos de Erro (`retCode`)

O módulo PayShield RSA possui um catálogo de erros extenso, refletindo o rigor das validações criptográficas e de formatação exigidas pelos padrões PCI HSM V3 . A coluna "Origem" ajuda a identificar se a recusa partiu da validação da API ou do próprio *Hardware Security Module* (HSM) .

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Código</th><th>Significado</th><th>Origem</th><th>Ação Recomendada</th></tr></thead><tbody><tr><td><code>01</code></td><td>Falha na verificação do MAC</td><td>HSM</td><td>Key Block Thales corrompido ou alterado após o <code>Import</code>. Refazer o <code>Import</code> e tentar novamente com o novo valor.</td></tr><tr><td><code>02</code></td><td>Falha na verificação do <em>check value</em></td><td>HSM</td><td>A chave simétrica referenciada por <code>keyId</code> está corrompida na base de dados. Recadastrar a chave.</td></tr><tr><td><code>03</code></td><td>Tipo de codificação de chave pública inválido</td><td>HSM</td><td>Verificar se o <code>publicKeyEncoding</code> corresponde ao tipo real da chave enviada.</td></tr><tr><td><code>04</code> / <code>50</code></td><td>Estrutura DER ASN.1 mal formada</td><td>HSM</td><td>A estrutura de dados está incorreta. Reverificar o processo de geração da chave pública na origem.</td></tr><tr><td><code>05</code></td><td>Tipo de chave DES/AES inválido</td><td>HSM</td><td>A chave <code>keyId</code> não é do tipo suportado. Apenas chaves DES, AES ou HMAC são exportáveis.</td></tr><tr><td><code>06</code></td><td>Identificador de criptografia inválido</td><td>HSM</td><td>Combinação inválida de parâmetros criptográficos. Revisar o <code>padModeId</code>.</td></tr><tr><td><code>07</code></td><td>Identificador de modo de <em>padding</em> inválido</td><td>API</td><td>O <code>padModeId</code> está fora dos valores aceites (deve ser <code>1</code> ou <code>2</code>).</td></tr><tr><td><code>08</code></td><td>Erro no Key Block HMAC</td><td>HSM</td><td>Falha ao tentar exportar chave HMAC devido a bloco interno inválido. Recadastrar a chave.</td></tr><tr><td><code>10</code></td><td>Erro de paridade na chave DES</td><td>HSM</td><td>A chave simétrica DES referenciada está corrompida. Recadastrar a chave.</td></tr><tr><td><code>34</code></td><td>Valor de identificador hash HMAC inválido</td><td>HSM</td><td>O identificador hash da chave HMAC não é reconhecido. Recadastrar a chave.</td></tr><tr><td><code>47</code></td><td>Algoritmo não licenciado</td><td>HSM</td><td>O HSM não possui a licença ativa para o algoritmo solicitado. Acionar suporte.</td></tr><tr><td><code>68</code></td><td>Comando desabilitado</td><td>HSM</td><td>A operação está bloqueada na configuração do HSM. Acionar suporte.</td></tr><tr><td><code>76</code></td><td>Erro no comprimento do Key Data Block</td><td>HSM</td><td>O tamanho do bloco da chave pública (<code>publicKey</code>) está incorreto.</td></tr><tr><td><code>81</code></td><td>Tipo de Key Data Block inválido</td><td>API</td><td>O <code>keyBlockType</code> está fora dos valores aceites (apenas <code>3</code> é suportado).</td></tr><tr><td><code>83</code></td><td>Erro no formato do Key Block</td><td>HSM</td><td>O <code>publicKey</code> enviado no <code>Export</code> NÃO está no formato Key Block Thales. Use o <code>retValue</code> retornado pelo <code>Import</code>.</td></tr><tr><td><code>84</code></td><td>Erro no <em>check value</em> do Key Block</td><td>HSM</td><td>O Key Block foi adulterado em trânsito. Refazer o <code>Import</code>.</td></tr><tr><td><code>85</code></td><td>Função MGF OAEP inválida</td><td>API</td><td>O <code>mgfHashFunction</code> foi enviado incorretamente num contexto PKCS#1 v1.5, ou o valor está fora do <em>range</em> aceite.</td></tr><tr><td><code>86</code></td><td>Função hash MGF OAEP inválida</td><td>API</td><td>O valor do <code>mgfHashFunction</code> não consta na lista aceita (<code>1</code>, <code>5</code>, <code>6</code>, <code>7</code>, <code>8</code>).</td></tr><tr><td><code>87</code> / <code>88</code></td><td>Erro no parâmetro OAEP</td><td>HSM</td><td>Parâmetros OAEP incompatíveis ou erro genérico. Validar acordo prévio de <em>padding</em>.</td></tr><tr><td><code>D3</code></td><td>Critérios PCI HSM V3 não atendidos</td><td>HSM</td><td>A chave não atende às regras de segurança PCI HSM V3 (ex: tamanho, uso ou algoritmo).</td></tr><tr><td><code>D4</code></td><td>Chave pública ECC inválida</td><td>HSM</td><td>A chave ECC não está no formato X9.62 <em>uncompressed</em> válido (aplicável quando <code>publicKeyEncoding = 3</code>).</td></tr></tbody></table>


# Integração, Exemplos e Troubleshooting

### Fluxo de Integração

#### Pré-requisitos

Antes de consumir os *endpoints* do módulo RSA, o integrador deve garantir os seguintes itens :

* Credenciais Auth0: *Client ID* e *Client Secret* com escopo de acesso ao módulo RSA.
* Identificador do Cliente: O seu `client_id` numérico.
* Chave Simétrica Cadastrada: A chave (DES/AES/HMAC) a ser exportada deve estar previamente cadastrada via módulo Key Manager .
* Chave Pública da Contraparte: Recebida em formato DER ASN.1 (codificada em hexadecimal) .
* Acordo de Key Ceremony: Definição mútua sobre os parâmetros de *padding* (`padModeId`) e MGF (`mgfHashFunction`).

#### Fluxo Típico — Exportar uma ZMK para um Parceiro

Neste cenário, a instituição envia uma *Zone Master Key* (ZMK) para um parceiro adquirente de forma segura :

1. Receber a chave pública RSA do parceiro (formato DER ASN.1 em hexadecimal) através de um canal seguro.
2. Obter o token JWT de autenticação.
3. Invocar o *endpoint* `Import` utilizando o `publicKeyEncoding` adequado à chave recebida. O retorno (`retValue`) será o Key Block Thales .
4. Invocar o *endpoint* `Export` referenciando o `keyId` da ZMK, os parâmetros de *padding* acordados, e injetando o Key Block Thales no campo `publicKey`.
5. Enviar a chave criptografada (o `retValue` do `Export`) para a contraparte através do canal acordado.

> Aviso Arquitetural: O módulo PayShield RSA efetua apenas a EXPORTAÇÃO da chave. A operação inversa (decifragem da chave simétrica utilizando a chave privada RSA) ocorre no HSM da contraparte e está fora do escopo do Hop V4 .

#### Boas Práticas

* OAEP por Padrão: Priorize sempre a utilização do `padModeId = 2` (OAEP) combinado com `mgfHashFunction = 6` (SHA-256). Utilize PKCS#1 v1.5 apenas em integrações legadas.
* Não armazene o Key Block em Cache: O retorno do `Import` (Key Block) contém um MAC com *timestamp* implícito. Refaça a importação a cada nova operação; não armazene este bloco para uso futuro .
* Auditoria: Registe nos *logs* de segurança os parâmetros da operação (`client_id`, `keyId`, *padding*, *fingerprint* SHA-256 da chave pública). NUNCA registe o `retValue` do *Export*, pois é o próprio material criptográfico .
* Validação Prévia: Antes de chamar a API, valide o tamanho e a estrutura da chave pública recebida utilizando o OpenSSL.
* Política de Retry: Efetue *retry* automático apenas em erros `500`. Erros `400` (ex: `01`, `02`, `04`, `83`) indicam anomalias nos dados ou nos parâmetros e requerem correção antes de nova tentativa .

***

### Exemplos Práticos

#### Preparação (Geração de Chaves via OpenSSL)

Para simular a contraparte em ambiente de testes :

Bash

```bash
# 1. Gera chave privada RSA de 2048 bits
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out private_key.pem

# 2. Extrai a chave pública
openssl rsa -in private_key.pem -pubout -out public_key.pem

# 3. Converte para DER e obtém o hexadecimal (input para a API)
openssl rsa -in public_key.pem -pubin -outform DER -out public_key.der
xxd -p -c 9999 public_key.der
```

#### Fluxo Completo via cURL

Bash

```bash
# Passo 1 - Import
curl -X POST https://apivin.first-tech.net/v4/PayShieldRsa/Import \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": 42,
    "publicKeyEncoding": 1,
    "publicKey": "3082020A0282020100A069D9C3..."
  }'

# Passo 2 - Export (utilizando o retValue retornado no passo 1)
KEY_BLOCK="S1056002RN00S00013082020A..."

curl -X POST https://apivin.first-tech.net/v4/PayShieldRsa/Export \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d "{
    \"client_id\": 42,
    \"keyId\": \"client-42-key-id-XXXX-ZMK\",
    \"padModeId\": 2,
    \"mgfHashFunction\": 6,
    \"publicKey\": \"$KEY_BLOCK\",
    \"keyBlockType\": 3
  }"
```

#### Snippet em Python

Python

```python
import requests
BASE = "https://apivin.first-tech.net/v4/PayShieldRsa"

def exportar_chave_para_parceiro(token, client_id, key_id, public_key_hex, encoding=1, pad_mode=2, mgf_hash=6):
    headers = {"Authorization": f"Bearer {token}"}
    
    # Passo 1: Import
    r1 = requests.post(f"{BASE}/Import", headers=headers, json={
        "client_id": client_id,
        "publicKeyEncoding": encoding,
        "publicKey": public_key_hex,
    }, timeout=15)
    d1 = r1.json()
    if not d1.get("retValid"):
        raise RuntimeError(f"Import falhou: {d1}")
        
    key_block = d1["retValue"]
    
    # Passo 2: Export
    payload = {
        "client_id": client_id,
        "keyId": key_id,
        "padModeId": pad_mode,
        "publicKey": key_block,
        "keyBlockType": 3,
    }
    if pad_mode == 2:
        payload["mgfHashFunction"] = mgf_hash
        
    r2 = requests.post(f"{BASE}/Export", headers=headers, json=payload, timeout=15)
    d2 = r2.json()
    if not d2.get("retValid"):
        raise RuntimeError(f"Export falhou: {d2}")
        
    return d2["retValue"]
```

***

### Troubleshooting

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Sintoma</th><th>Causa Provável</th><th>Solução</th></tr></thead><tbody><tr><td>HTTP 400 (<code>retCode 04</code> ou <code>50</code>) no Import</td><td>Chave pública em formato errado (ex: PKCS#1 vs X.509).</td><td>Confirmar com a contraparte o formato e ajustar o parâmetro <code>publicKeyEncoding</code>.</td></tr><tr><td>HTTP 400 (<code>retCode 83</code>) no Export</td><td>O <code>publicKey</code> enviado é a chave DER bruta.</td><td>Enviar estritamente o Key Block Thales obtido no retorno do <code>Import</code>.</td></tr><tr><td>HTTP 400 (<code>retCode 07</code>) no Export</td><td>O <code>padModeId</code> está incorreto.</td><td>Utilizar apenas os valores <code>1</code> ou <code>2</code>.</td></tr><tr><td>HTTP 400 (<code>retCode 85</code> ou <code>86</code>) no Export</td><td>O <code>mgfHashFunction</code> foi enviado de forma inválida.</td><td>OAEP exige função MGF explícita. O modo PKCS#1 v1.5 exige a omissão deste campo.</td></tr><tr><td>HTTP 400 (<code>retCode 10</code> ou <code>47</code>) no Export</td><td>Erro de paridade na chave simétrica ou algoritmo não licenciado no HSM.</td><td>Recadastrar a chave no módulo Key Manager ou acionar o suporte técnico para questões de licenciamento.</td></tr><tr><td>HTTP 404 no Export</td><td><code>keyId</code> não cadastrado.</td><td>Confirmar a sintaxe e a existência do alias no Key Manager.</td></tr><tr><td>HTTP 400 (<code>retCode D3</code>) no Export</td><td>Violação dos critérios PCI HSM V3.</td><td>O algoritmo ou o tamanho da chave não cumprem os requisitos mínimos de segurança parametrizados.</td></tr><tr><td>Contraparte falha na decifragem</td><td>Divergência de parâmetros criptográficos.</td><td>Reverificar o acordo formal (<em>Key Ceremony</em>) em relação ao <em>Padding</em> e à Função Hash.</td></tr></tbody></table>

***

### Apêndices

#### Apêndice A. Acordo de Key Ceremony (Itens Obrigatórios)

Qualquer troca de chaves via módulo RSA requer um alinhamento prévio:

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Parâmetro</th><th>Descrição</th></tr></thead><tbody><tr><td>Partes Envolvidas</td><td>Razão social, CNPJ e responsáveis de ambas as instituições.</td></tr><tr><td>Tipo de Chave e Finalidade</td><td>Ex: ZMK, ZPK, BDK (e o seu propósito específico).</td></tr><tr><td>Algoritmos Simétricos e Assimétricos</td><td>Ex: AES-256 (simétrica) e RSA 2048 / ECC P-256 (assimétrica).</td></tr><tr><td>Codificação (<code>publicKeyEncoding</code>)</td><td>Formato exato da chave DER ASN.1 (<code>1</code>, <code>2</code> ou <code>3</code>).</td></tr><tr><td>Modo de Preenchimento e MGF</td><td><code>padModeId</code> (PKCS#1 v1.5 ou OAEP) e a respetiva função hash (ex: SHA-256).</td></tr><tr><td>Canal e Validade</td><td>Canal de partilha e o ciclo de vida/rotação da chave partilhada.</td></tr></tbody></table>

#### Apêndice B. Identificação Visual de Formatos

Se o parceiro não especificar o formato da chave, o cabeçalho hexadecimal fornece indícios cruciais:

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Início do Hexadecimal</th><th>Formato Provável</th><th>publicKeyEncoding Aplicável</th></tr></thead><tbody><tr><td><code>3082...</code></td><td>DER ASN.1 SEQUENCE longo (X.509 <code>SubjectPublicKeyInfo</code>).</td><td><code>1</code> (RSA unsigned)</td></tr><tr><td><code>3081...</code></td><td>DER ASN.1 SEQUENCE médio (<code>RSAPublicKey</code> PKCS#1).</td><td><code>1</code> ou <code>2</code></td></tr><tr><td><code>04...</code></td><td>X9.62 ECC uncompressed point.</td><td><code>3</code> (ECC X9.62)</td></tr><tr><td><code>02...</code> / <code>03...</code></td><td>X9.62 ECC compressed.</td><td>Não suportado</td></tr></tbody></table>

#### Apêndice C. Glossário Resumido

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Sigla</th><th>Significado</th><th>Contexto</th></tr></thead><tbody><tr><td>ASN.1 / DER</td><td><em>Abstract Syntax Notation One</em> / <em>Distinguished Encoding Rules</em></td><td>Padrão e codificação binária das estruturas de chaves públicas.</td></tr><tr><td>BDK / ZMK / ZPK</td><td><em>Base Derivation Key</em> / <em>Zone Master Key</em> / <em>Zone PIN Key</em></td><td>Chaves simétricas protegidas e geridas pelo ecossistema de pagamentos.</td></tr><tr><td>ECC / RSA</td><td><em>Elliptic Curve Cryptography</em> / <em>Rivest-Shamir-Adleman</em></td><td>Algoritmos de criptografia assimétrica.</td></tr><tr><td>Key Block</td><td>Bloco Seguro (Thales)</td><td>Estrutura que encapsula o material criptográfico juntamente com um MAC (integridade).</td></tr><tr><td>OAEP / MGF</td><td><em>Optimal Asymmetric Encryption Padding</em> / <em>Mask Generation Function</em></td><td>Esquemas modernos e avançados de preenchimento matemático para chaves RSA.</td></tr></tbody></table>


# HoP V4 - Documentação endpoints

Bem vindo a página de documentação dos endpoints da API HoP V4. \
Escolha um dos serviços abaixo e acesse a documentação de cada endpoint.

### Serviços

<table data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><h4><i class="fa-binary-lock">:binary-lock:</i></h4></td><td><h2>Crypto</h2></td><td>ws-hop-api-crypto</td><td></td><td></td><td><a href="/pages/EHNQyP4sSdr2azX2lklY">/pages/EHNQyP4sSdr2azX2lklY</a></td></tr><tr><td><h4><i class="fa-key">:key:</i></h4></td><td><h2>PIN</h2></td><td>ws-hop-api-pin</td><td></td><td></td><td><a href="/pages/tHBKOD49SCSEbzpnLL3O">/pages/tHBKOD49SCSEbzpnLL3O</a></td></tr><tr><td><h4><i class="fa-credit-card">:credit-card:</i></h4></td><td><h2>PAN</h2></td><td>ws-hop-api-pan</td><td></td><td></td><td><a href="/pages/7QmJb1G9e2qzYIyeh9rG">/pages/7QmJb1G9e2qzYIyeh9rG</a></td></tr><tr><td><h4><i class="fa-input-password">:input-password:</i></h4></td><td><h2>CVV</h2></td><td>ws-hop-api-cvv</td><td></td><td></td><td><a href="/pages/j1ngfApFPj117PXNdHZI">/pages/j1ngfApFPj117PXNdHZI</a></td></tr><tr><td><h4><i class="fa-credit-card-front">:credit-card-front:</i></h4></td><td><h2>EMV</h2></td><td>ws-hop-api-emv</td><td></td><td></td><td><a href="/pages/NyP38E7LyfNSkf87MzBC">/pages/NyP38E7LyfNSkf87MzBC</a></td></tr><tr><td><h4><i class="fa-user-key">:user-key:</i></h4></td><td><h2>Key Manager</h2></td><td>ws-hop-api-keymanager</td><td></td><td></td><td><a href="/pages/bi00OT4X3ODkUYvqWbim">/pages/bi00OT4X3ODkUYvqWbim</a></td></tr><tr><td><h4><i class="fa-dice-three">:dice-three:</i></h4></td><td><h2>RSA</h2></td><td>ws-hop-api-rsa</td><td></td><td></td><td><a href="/pages/taSmopm7ygwc1mlxtc5I">/pages/taSmopm7ygwc1mlxtc5I</a></td></tr><tr><td><h4><i class="fa-address-card">:address-card:</i></h4></td><td><h2>Autenticação</h2></td><td>OAuth2</td><td></td><td></td><td><a href="/pages/52270BkwRadJJnIQR1f7">/pages/52270BkwRadJJnIQR1f7</a></td></tr></tbody></table>


# Crypto

Endpoints do serviço ws-hop-api-crypto

## Data Encryption Module

> Returns encrypted data and IV (if applicable) (in retMultiValue), always in Hex format, in case of error, it returns details in the Error fields (retCode and RetDescription). Returns the following in retMultiValue:\
> &#x20; in retMultiValue:\<br>\<br> \<blockquote> retMultiValue\[0] = msgRespEncrypted\
> &#x20; -> Encrypted message (open)\<br> retMultiValue\[1] = ivResp - > IV for the\
> &#x20; next call to decrypt only in case of modeEncFlag 01, 02, 03, otherwise this\
> &#x20; field will be null\</blockquote>.<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield Crypto API","version":"4.1.32"},"tags":[{"name":"Crypto","description":"Operações de criptografia e descriptografia de dados"}],"servers":[{"url":"https://api-hext.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"EncryptDataInput":{"allOf":[{"$ref":"#/components/schemas/CryptoInputBase"},{"type":"object","required":["p_ht_data"],"properties":{"p_ht_data":{"type":"string","description":"Dados a serem criptografados em formato H (Hex) ou T (Texto)"},"b_data":{"type":"string","nullable":true,"description":"Dados em formato binário (uso reservado)"}}}]},"CryptoInputBase":{"type":"object","required":["client_id","keyId","modeEncFlag","data_fmt"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave no banco de dados"},"modeEncFlag":{"type":"string","description":"Modo de operação da cifra:\n- `00`: ECB (padrão se null ou valor não listado)\n- `01`: CBC (requer IV)\n- `02`: CFB8 (requer IV)\n- `03`: CFB64 (requer IV)\n"},"ksn_desc":{"type":"string","nullable":true,"description":"Descritor KSN — necessário apenas se o keyId for do tipo BDK (DUKPT)"},"ksn":{"type":"string","nullable":true,"description":"KSN — necessário apenas se o keyId for do tipo BDK (DUKPT)"},"iv":{"type":"string","nullable":true,"description":"Vetor de inicialização em Hex — obrigatório nos modos 01, 02, 03"},"data_fmt":{"type":"string","enum":["H","T"],"description":"Formato dos dados de entrada:\n- `H`: Hexadecimal\n- `T`: Texto\n"}}},"ReturnMultiValue":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValue":{"type":"string","description":"Valor de retorno simples (geralmente vazio em sucesso)"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com os valores de retorno da operação"},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retDescription":{"type":"string","description":"Descrição do resultado"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `500`: Erro interno\n- `4097`: Formato inválido\n- `155`: Chave não encontrada no banco de dados\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDescription":{"type":"string","description":"Descrição do erro"}}}}},"paths":{"/v4/PayShieldCrypto/EncryptData":{"post":{"tags":["Crypto"],"summary":"Data Encryption Module","description":"Returns encrypted data and IV (if applicable) (in retMultiValue), always in Hex format, in case of error, it returns details in the Error fields (retCode and RetDescription). Returns the following in retMultiValue:\n  in retMultiValue:<br><br> <blockquote> retMultiValue[0] = msgRespEncrypted\n  -> Encrypted message (open)<br> retMultiValue[1] = ivResp - > IV for the\n  next call to decrypt only in case of modeEncFlag 01, 02, 03, otherwise this\n  field will be null</blockquote>.\n","operationId":"encryptData","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EncryptDataInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnMultiValue"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"404":{"description":"Chave não encontrada no banco de dados","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

## Data Decryption Module

> Returns decrypted data and IV (if applicable) (retMultiValue), always in Hex format, in case of error, it returns details in the Error fields (retCode and RetDescription).\
> Returns the following in retMultiValue:\<br> Returns the following\
> &#x20; in retMultiValue:\<br>\<br> \<blockquote> retMultiValue\[0] = msgRespDecrypted\
> &#x20; -> Decrypted message (open)\<br> retMultiValue\[1] = ivResp - > IV for the\
> &#x20; next call to encrypt only in case of modeEncFlag 01, 02, 03, otherwise this\
> &#x20; field will be null\</blockquote>.<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield Crypto API","version":"4.1.32"},"tags":[{"name":"Crypto","description":"Operações de criptografia e descriptografia de dados"}],"servers":[{"url":"https://api-hext.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"DecryptDataInput":{"allOf":[{"$ref":"#/components/schemas/CryptoInputBase"},{"type":"object","required":["p_h_data"],"properties":{"p_h_data":{"type":"string","description":"Dados criptografados a serem descriptografados em formato Hex"}}}]},"CryptoInputBase":{"type":"object","required":["client_id","keyId","modeEncFlag","data_fmt"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave no banco de dados"},"modeEncFlag":{"type":"string","description":"Modo de operação da cifra:\n- `00`: ECB (padrão se null ou valor não listado)\n- `01`: CBC (requer IV)\n- `02`: CFB8 (requer IV)\n- `03`: CFB64 (requer IV)\n"},"ksn_desc":{"type":"string","nullable":true,"description":"Descritor KSN — necessário apenas se o keyId for do tipo BDK (DUKPT)"},"ksn":{"type":"string","nullable":true,"description":"KSN — necessário apenas se o keyId for do tipo BDK (DUKPT)"},"iv":{"type":"string","nullable":true,"description":"Vetor de inicialização em Hex — obrigatório nos modos 01, 02, 03"},"data_fmt":{"type":"string","enum":["H","T"],"description":"Formato dos dados de entrada:\n- `H`: Hexadecimal\n- `T`: Texto\n"}}},"ReturnMultiValue":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValue":{"type":"string","description":"Valor de retorno simples (geralmente vazio em sucesso)"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com os valores de retorno da operação"},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retDescription":{"type":"string","description":"Descrição do resultado"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `500`: Erro interno\n- `4097`: Formato inválido\n- `155`: Chave não encontrada no banco de dados\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDescription":{"type":"string","description":"Descrição do erro"}}}}},"paths":{"/v4/PayShieldCrypto/DecryptData":{"post":{"tags":["Crypto"],"summary":"Data Decryption Module","description":"Returns decrypted data and IV (if applicable) (retMultiValue), always in Hex format, in case of error, it returns details in the Error fields (retCode and RetDescription).\nReturns the following in retMultiValue:<br> Returns the following\n  in retMultiValue:<br><br> <blockquote> retMultiValue[0] = msgRespDecrypted\n  -> Decrypted message (open)<br> retMultiValue[1] = ivResp - > IV for the\n  next call to encrypt only in case of modeEncFlag 01, 02, 03, otherwise this\n  field will be null</blockquote>.\n","operationId":"decryptData","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecryptDataInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnMultiValue"}}}},"400":{"description":"Formato de data_fmt inválido — use 'H' (Hexadecimal) ou 'T' (Texto)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"404":{"description":"Chave não encontrada no banco de dados","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

## The CryptoInputBase object

```json
{"openapi":"3.0.3","info":{"title":"PayShield Crypto API","version":"4.1.32"},"components":{"schemas":{"CryptoInputBase":{"type":"object","required":["client_id","keyId","modeEncFlag","data_fmt"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave no banco de dados"},"modeEncFlag":{"type":"string","description":"Modo de operação da cifra:\n- `00`: ECB (padrão se null ou valor não listado)\n- `01`: CBC (requer IV)\n- `02`: CFB8 (requer IV)\n- `03`: CFB64 (requer IV)\n"},"ksn_desc":{"type":"string","nullable":true,"description":"Descritor KSN — necessário apenas se o keyId for do tipo BDK (DUKPT)"},"ksn":{"type":"string","nullable":true,"description":"KSN — necessário apenas se o keyId for do tipo BDK (DUKPT)"},"iv":{"type":"string","nullable":true,"description":"Vetor de inicialização em Hex — obrigatório nos modos 01, 02, 03"},"data_fmt":{"type":"string","enum":["H","T"],"description":"Formato dos dados de entrada:\n- `H`: Hexadecimal\n- `T`: Texto\n"}}}}}}
```

## The EncryptDataInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield Crypto API","version":"4.1.32"},"components":{"schemas":{"EncryptDataInput":{"allOf":[{"$ref":"#/components/schemas/CryptoInputBase"},{"type":"object","required":["p_ht_data"],"properties":{"p_ht_data":{"type":"string","description":"Dados a serem criptografados em formato H (Hex) ou T (Texto)"},"b_data":{"type":"string","nullable":true,"description":"Dados em formato binário (uso reservado)"}}}]},"CryptoInputBase":{"type":"object","required":["client_id","keyId","modeEncFlag","data_fmt"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave no banco de dados"},"modeEncFlag":{"type":"string","description":"Modo de operação da cifra:\n- `00`: ECB (padrão se null ou valor não listado)\n- `01`: CBC (requer IV)\n- `02`: CFB8 (requer IV)\n- `03`: CFB64 (requer IV)\n"},"ksn_desc":{"type":"string","nullable":true,"description":"Descritor KSN — necessário apenas se o keyId for do tipo BDK (DUKPT)"},"ksn":{"type":"string","nullable":true,"description":"KSN — necessário apenas se o keyId for do tipo BDK (DUKPT)"},"iv":{"type":"string","nullable":true,"description":"Vetor de inicialização em Hex — obrigatório nos modos 01, 02, 03"},"data_fmt":{"type":"string","enum":["H","T"],"description":"Formato dos dados de entrada:\n- `H`: Hexadecimal\n- `T`: Texto\n"}}}}}}
```

## The DecryptDataInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield Crypto API","version":"4.1.32"},"components":{"schemas":{"DecryptDataInput":{"allOf":[{"$ref":"#/components/schemas/CryptoInputBase"},{"type":"object","required":["p_h_data"],"properties":{"p_h_data":{"type":"string","description":"Dados criptografados a serem descriptografados em formato Hex"}}}]},"CryptoInputBase":{"type":"object","required":["client_id","keyId","modeEncFlag","data_fmt"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave no banco de dados"},"modeEncFlag":{"type":"string","description":"Modo de operação da cifra:\n- `00`: ECB (padrão se null ou valor não listado)\n- `01`: CBC (requer IV)\n- `02`: CFB8 (requer IV)\n- `03`: CFB64 (requer IV)\n"},"ksn_desc":{"type":"string","nullable":true,"description":"Descritor KSN — necessário apenas se o keyId for do tipo BDK (DUKPT)"},"ksn":{"type":"string","nullable":true,"description":"KSN — necessário apenas se o keyId for do tipo BDK (DUKPT)"},"iv":{"type":"string","nullable":true,"description":"Vetor de inicialização em Hex — obrigatório nos modos 01, 02, 03"},"data_fmt":{"type":"string","enum":["H","T"],"description":"Formato dos dados de entrada:\n- `H`: Hexadecimal\n- `T`: Texto\n"}}}}}}
```

## The ReturnMultiValue object

```json
{"openapi":"3.0.3","info":{"title":"PayShield Crypto API","version":"4.1.32"},"components":{"schemas":{"ReturnMultiValue":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValue":{"type":"string","description":"Valor de retorno simples (geralmente vazio em sucesso)"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com os valores de retorno da operação"},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retDescription":{"type":"string","description":"Descrição do resultado"}}}}}}
```

## The ReturnError object

```json
{"openapi":"3.0.3","info":{"title":"PayShield Crypto API","version":"4.1.32"},"components":{"schemas":{"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `500`: Erro interno\n- `4097`: Formato inválido\n- `155`: Chave não encontrada no banco de dados\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDescription":{"type":"string","description":"Descrição do erro"}}}}}}
```


# PIN

Endpoints do serviço ws-hop-api-pin

## Validar PIN

> Returns the OK(true) / Not Ok (false) in (retValid), in case of error returns the Error fields (retCode and RetDescription).<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield PIN API","version":"4.1.32"},"tags":[{"name":"PIN","description":"Operações de tradução e validação de PIN"}],"servers":[{"url":"https://api-hext.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"ValidatePinInput":{"type":"object","required":["client_id","keyId","hPinBlock","pinBlockFmt","pan"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave TPK ou ZPK no banco de dados"},"hPinBlock":{"type":"string","description":"PinBlock em formato Hexadecimal"},"pinBlockFmt":{"type":"string","description":"Formato do PinBlock. Valores válidos:\n`01`, `02`, `03`, `04`, `05`, `34`, `35`, `41`, `42`, `47`, `48`\n"},"hPinHost":{"type":"string","nullable":true,"description":"PIN Host em formato Hexadecimal (usado para validação contra PIN armazenado)"},"pan":{"type":"string","description":"PAN do cartão (16 a 19 dígitos)"}}},"ReturnSingle":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retValue":{"type":"string","description":"Valor de retorno simples"},"retDescription":{"type":"string","description":"Descrição do resultado"},"retMultiValue":{"nullable":true}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `500`: Erro interno do servidor\n- `400`: Requisição inválida\n- `155`: Chave não encontrada no banco de dados\n"},"retValid":{"type":"boolean"},"retValue":{"type":"string","nullable":true},"retDescription":{"type":"string","description":"Descrição do erro"},"retMultiValue":{"nullable":true}}}}},"paths":{"/v4/PayShieldPin/ValidatePin":{"post":{"tags":["PIN"],"summary":"Validar PIN","description":"Returns the OK(true) / Not Ok (false) in (retValid), in case of error returns the Error fields (retCode and RetDescription).\n","operationId":"validatePin","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidatePinInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnSingle"}}}},"400":{"description":"Requisição inválida — campo obrigatório ausente ou formato incorreto","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"404":{"description":"Chave não encontrada no banco de dados","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

## Traduzir PIN

> Returns the PibBlock protected by the KeyIdDst key (in retMultiValue), in case of error it returns the Error fields (retCode and RetDescription).<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield PIN API","version":"4.1.32"},"tags":[{"name":"PIN","description":"Operações de tradução e validação de PIN"}],"servers":[{"url":"https://api-hext.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"TranslatePinInput":{"type":"object","required":["client_id","keyIdSrc","hPinBlockSrc","pinBlockFmtSrc","keyIdDst","pinBlockFmtDst","pan"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyIdSrc":{"type":"string","description":"Alias/identificador da chave de origem (TPK, ZPK ou BDK)"},"hPinBlockSrc":{"type":"string","description":"PinBlock de origem em formato alfanumérico (a-z, A-Z, 0-9)"},"pinBlockFmtSrc":{"type":"string","description":"Formato do PinBlock de origem. Valores válidos:\n`01`, `02`, `03`, `04`, `05`, `34`, `35`, `41`, `42`, `47`, `48`\n"},"hPinHost":{"type":"string","nullable":true,"description":"PIN Host em formato Hexadecimal (opcional)"},"keyIdDst":{"type":"string","description":"Alias/identificador da chave de destino (TPK, ZPK ou BDK)"},"pinBlockFmtDst":{"type":"string","description":"Formato do PinBlock de destino. Valores válidos:\n`01`, `02`, `03`, `04`, `05`, `34`, `35`, `41`, `42`, `47`, `48`\n"},"pan":{"type":"string","description":"PAN do cartão de origem (16 a 19 dígitos)"},"ksn_desc":{"type":"string","nullable":true,"description":"Descritor KSN da chave de origem — necessário apenas se `keyIdSrc` for do tipo BDK (DUKPT)"},"ksn":{"type":"string","nullable":true,"description":"KSN da chave de origem — necessário apenas se `keyIdSrc` for do tipo BDK (DUKPT)"},"pan_dst":{"type":"string","nullable":true,"description":"PAN do cartão de destino (16 a 19 dígitos) — necessário quando o PAN de destino difere do de origem"},"ksn_desc_dst":{"type":"string","nullable":true,"description":"Descritor KSN da chave de destino — necessário apenas se `keyIdDst` for do tipo BDK (DUKPT)"},"ksn_dst":{"type":"string","nullable":true,"description":"KSN da chave de destino — necessário apenas se `keyIdDst` for do tipo BDK (DUKPT)"}}},"ReturnMultiValue":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retValue":{"type":"string","description":"Valor de retorno simples (geralmente vazio em sucesso)"},"retDescription":{"type":"string","description":"Descrição do resultado"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com os valores de retorno da operação TranslatePin:\n- `[0]` = PINLength (ex: \"04\")\n- `[1]` = destPINBlock (ex: \"AFA6E4F1FA93CB9F\")\n- `[2]` = destPBFormat (ex: \"01\")\n"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `500`: Erro interno do servidor\n- `400`: Requisição inválida\n- `155`: Chave não encontrada no banco de dados\n"},"retValid":{"type":"boolean"},"retValue":{"type":"string","nullable":true},"retDescription":{"type":"string","description":"Descrição do erro"},"retMultiValue":{"nullable":true}}}}},"paths":{"/v4/PayShieldPin/TranslatePin":{"post":{"tags":["PIN"],"summary":"Traduzir PIN","description":"Returns the PibBlock protected by the KeyIdDst key (in retMultiValue), in case of error it returns the Error fields (retCode and RetDescription).\n","operationId":"translatePin","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranslatePinInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnMultiValue"}}}},"400":{"description":"Requisição inválida — campo obrigatório ausente ou formato incorreto","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"404":{"description":"Chave não encontrada no banco de dados","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

## The ValidatePinInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield PIN API","version":"4.1.32"},"components":{"schemas":{"ValidatePinInput":{"type":"object","required":["client_id","keyId","hPinBlock","pinBlockFmt","pan"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave TPK ou ZPK no banco de dados"},"hPinBlock":{"type":"string","description":"PinBlock em formato Hexadecimal"},"pinBlockFmt":{"type":"string","description":"Formato do PinBlock. Valores válidos:\n`01`, `02`, `03`, `04`, `05`, `34`, `35`, `41`, `42`, `47`, `48`\n"},"hPinHost":{"type":"string","nullable":true,"description":"PIN Host em formato Hexadecimal (usado para validação contra PIN armazenado)"},"pan":{"type":"string","description":"PAN do cartão (16 a 19 dígitos)"}}}}}}
```

## The TranslatePinInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield PIN API","version":"4.1.32"},"components":{"schemas":{"TranslatePinInput":{"type":"object","required":["client_id","keyIdSrc","hPinBlockSrc","pinBlockFmtSrc","keyIdDst","pinBlockFmtDst","pan"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyIdSrc":{"type":"string","description":"Alias/identificador da chave de origem (TPK, ZPK ou BDK)"},"hPinBlockSrc":{"type":"string","description":"PinBlock de origem em formato alfanumérico (a-z, A-Z, 0-9)"},"pinBlockFmtSrc":{"type":"string","description":"Formato do PinBlock de origem. Valores válidos:\n`01`, `02`, `03`, `04`, `05`, `34`, `35`, `41`, `42`, `47`, `48`\n"},"hPinHost":{"type":"string","nullable":true,"description":"PIN Host em formato Hexadecimal (opcional)"},"keyIdDst":{"type":"string","description":"Alias/identificador da chave de destino (TPK, ZPK ou BDK)"},"pinBlockFmtDst":{"type":"string","description":"Formato do PinBlock de destino. Valores válidos:\n`01`, `02`, `03`, `04`, `05`, `34`, `35`, `41`, `42`, `47`, `48`\n"},"pan":{"type":"string","description":"PAN do cartão de origem (16 a 19 dígitos)"},"ksn_desc":{"type":"string","nullable":true,"description":"Descritor KSN da chave de origem — necessário apenas se `keyIdSrc` for do tipo BDK (DUKPT)"},"ksn":{"type":"string","nullable":true,"description":"KSN da chave de origem — necessário apenas se `keyIdSrc` for do tipo BDK (DUKPT)"},"pan_dst":{"type":"string","nullable":true,"description":"PAN do cartão de destino (16 a 19 dígitos) — necessário quando o PAN de destino difere do de origem"},"ksn_desc_dst":{"type":"string","nullable":true,"description":"Descritor KSN da chave de destino — necessário apenas se `keyIdDst` for do tipo BDK (DUKPT)"},"ksn_dst":{"type":"string","nullable":true,"description":"KSN da chave de destino — necessário apenas se `keyIdDst` for do tipo BDK (DUKPT)"}}}}}}
```

## The ReturnSingle object

```json
{"openapi":"3.0.3","info":{"title":"PayShield PIN API","version":"4.1.32"},"components":{"schemas":{"ReturnSingle":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retValue":{"type":"string","description":"Valor de retorno simples"},"retDescription":{"type":"string","description":"Descrição do resultado"},"retMultiValue":{"nullable":true}}}}}}
```

## The ReturnMultiValue object

```json
{"openapi":"3.0.3","info":{"title":"PayShield PIN API","version":"4.1.32"},"components":{"schemas":{"ReturnMultiValue":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retValue":{"type":"string","description":"Valor de retorno simples (geralmente vazio em sucesso)"},"retDescription":{"type":"string","description":"Descrição do resultado"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com os valores de retorno da operação TranslatePin:\n- `[0]` = PINLength (ex: \"04\")\n- `[1]` = destPINBlock (ex: \"AFA6E4F1FA93CB9F\")\n- `[2]` = destPBFormat (ex: \"01\")\n"}}}}}}
```

## The ReturnError object

```json
{"openapi":"3.0.3","info":{"title":"PayShield PIN API","version":"4.1.32"},"components":{"schemas":{"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `500`: Erro interno do servidor\n- `400`: Requisição inválida\n- `155`: Chave não encontrada no banco de dados\n"},"retValid":{"type":"boolean"},"retValue":{"type":"string","nullable":true},"retDescription":{"type":"string","description":"Descrição do erro"},"retMultiValue":{"nullable":true}}}}}}
```


# PAN

Endpoints do serviço ws-hop-api-pan

## PayShield Pan Service

> Generate a Random PIN\
> Returns the new PIN encrypted under the LMK in retMultiValue\[0] with retCode 0 and retDescription Ok. In case of error returns the Error fields (retCode and RetDescription):<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield PAN API","version":"4.1.32"},"tags":[{"name":"PIN","description":"Operações de geração, validação e tradução de PIN"}],"servers":[{"url":"https://api-hext.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"GeneratePinInput":{"type":"object","required":["client_id","pan","pinLength"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"pan":{"type":"string","minLength":12,"maxLength":19,"description":"PAN do cartão (12 a 19 dígitos)"},"pinLength":{"type":"integer","minimum":4,"maximum":12,"description":"Comprimento do PIN a ser gerado (4 a 12 dígitos)"}}},"ReturnMultiValue":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retValue":{"type":"string","nullable":true,"description":"Valor de retorno simples"},"retDescription":{"type":"string","description":"Descrição do resultado"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com os valores de retorno da operação"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `500`: Erro interno do servidor\n- `400`: Requisição inválida\n- `155`: Chave não encontrada no banco de dados\n"},"retValid":{"type":"boolean"},"retValue":{"type":"string","nullable":true},"retDescription":{"type":"string","description":"Descrição do erro"},"retMultiValue":{"nullable":true}}}}},"paths":{"/v4/PayShieldPan/GeneratePin":{"post":{"tags":["PIN"],"summary":"PayShield Pan Service","description":"Generate a Random PIN\nReturns the new PIN encrypted under the LMK in retMultiValue[0] with retCode 0 and retDescription Ok. In case of error returns the Error fields (retCode and RetDescription):\n","operationId":"generatePin","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeneratePinInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnMultiValue"}}}},"400":{"description":"Requisição inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

## Translate Pan

> Returns the account number for a PIN encrypted under LMK 02-03 from an old account number to a new account number in retMultiValue\[0] with retCode 0 and retDescription OK. In case of error, it returns details in the Error fields (retCode and RetDescription).\
> \
> The customer PIN itself remains unchanged.\
> \
> When using an AES Key Block LMK, the LMK-encrypted PIN is the result of encrypting the PIN under the LMK using Thales PIN Block format 48 (ISO PIN Block format 4).<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield PAN API","version":"4.1.32"},"tags":[{"name":"PAN","description":"Operações de tradução de PAN"}],"servers":[{"url":"https://api-hext.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"TranslatePanInput":{"type":"object","required":["client_id","pin","oldPan","newPan"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"pin":{"type":"string","maxLength":33,"description":"PIN criptografado sob a LMK"},"oldPan":{"type":"string","minLength":12,"maxLength":19,"description":"PAN antigo do cartão (12 a 19 dígitos)"},"newPan":{"type":"string","minLength":12,"maxLength":19,"description":"Novo PAN do cartão (12 a 19 dígitos)"}}},"ReturnMultiValue":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retValue":{"type":"string","nullable":true,"description":"Valor de retorno simples"},"retDescription":{"type":"string","description":"Descrição do resultado"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com os valores de retorno da operação"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `500`: Erro interno do servidor\n- `400`: Requisição inválida\n- `155`: Chave não encontrada no banco de dados\n"},"retValid":{"type":"boolean"},"retValue":{"type":"string","nullable":true},"retDescription":{"type":"string","description":"Descrição do erro"},"retMultiValue":{"nullable":true}}}}},"paths":{"/v4/PayShieldPan/TranslatePan":{"post":{"tags":["PAN"],"summary":"Translate Pan","description":"Returns the account number for a PIN encrypted under LMK 02-03 from an old account number to a new account number in retMultiValue[0] with retCode 0 and retDescription OK. In case of error, it returns details in the Error fields (retCode and RetDescription).\n\nThe customer PIN itself remains unchanged.\n\nWhen using an AES Key Block LMK, the LMK-encrypted PIN is the result of encrypting the PIN under the LMK using Thales PIN Block format 48 (ISO PIN Block format 4).\n","operationId":"translatePan","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranslatePanInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnMultiValue"}}}},"400":{"description":"Requisição inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

## Translate PIN LMK (AES) To ZPK (AES)

> Translate PIN LMK (AES) To ZPK (AES)\
> \
> Returns the translated PIN from encryption under the LMK (AES) to encryption under a ZPK (AES) in retMultiValue\[0] with retCode 0 and retDescription OK. In case of error, it returns details in the Error fields (retCode and RetDescription)\
> \
> When used with a Variant LMK or 3DES Key Block LMK, the PIN encrypted under the LMK will always be using a non-ISO format<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield PAN API","version":"4.1.32"},"tags":[{"name":"PIN","description":"Operações de geração, validação e tradução de PIN"}],"servers":[{"url":"https://api-hext.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"TranslatePinLmkToZpkInput":{"type":"object","required":["client_id","keyId","pin","pan","formatCode"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave ZPK de destino"},"pin":{"type":"string","maxLength":33,"description":"PIN criptografado sob a LMK"},"pan":{"type":"string","description":"PAN do cartão"},"formatCode":{"type":"integer","minimum":0,"maximum":4,"description":"Código de formato do PinBlock de destino:\n- `0` → formato Thales `01`\n- `1` → formato Thales `05`\n- `3` → formato Thales `47`\n- `4` (padrão) → formato Thales `48`\n"}}},"ReturnMultiValue":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retValue":{"type":"string","nullable":true,"description":"Valor de retorno simples"},"retDescription":{"type":"string","description":"Descrição do resultado"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com os valores de retorno da operação"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `500`: Erro interno do servidor\n- `400`: Requisição inválida\n- `155`: Chave não encontrada no banco de dados\n"},"retValid":{"type":"boolean"},"retValue":{"type":"string","nullable":true},"retDescription":{"type":"string","description":"Descrição do erro"},"retMultiValue":{"nullable":true}}}}},"paths":{"/v4/PayShieldPan/TranslatePinLmkToZpk":{"post":{"tags":["PIN"],"summary":"Translate PIN LMK (AES) To ZPK (AES)","description":"Translate PIN LMK (AES) To ZPK (AES)\n\nReturns the translated PIN from encryption under the LMK (AES) to encryption under a ZPK (AES) in retMultiValue[0] with retCode 0 and retDescription OK. In case of error, it returns details in the Error fields (retCode and RetDescription)\n\nWhen used with a Variant LMK or 3DES Key Block LMK, the PIN encrypted under the LMK will always be using a non-ISO format\n","operationId":"translatePinLmkToZpk","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranslatePinLmkToZpkInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnMultiValue"}}}},"400":{"description":"Requisição inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

## Translate PIN ZPK (AES) to LMK (AES)

> Returns the translated PIN from encryption under the ZPK (AES) to encryption under a LMK (AES) in retMultiValue\[0] with retCode 0 and retDescription Ok. In case of error, it returns details in the Error fields (retCode and RetDescription)\
> \
> When used with a Variant LMK or 3DES Key Block LMK, the PIN encrypted under the LMK will always be using a non-ISO format<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield PAN API","version":"4.1.32"},"tags":[{"name":"PIN","description":"Operações de geração, validação e tradução de PIN"}],"servers":[{"url":"https://api-hext.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"TranslatePinZpkToLmkInput":{"type":"object","required":["client_id","keyId","pin","pan","formatCode"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave ZPK de origem"},"pin":{"type":"string","minLength":16,"maxLength":16,"description":"PinBlock criptografado sob a ZPK (exatamente 16 dígitos)"},"pan":{"type":"string","minLength":16,"maxLength":16,"description":"PAN do cartão (exatamente 16 dígitos)"},"formatCode":{"type":"integer","minimum":0,"maximum":4,"description":"Código de formato do PinBlock de origem:\n- `0` → formato Thales `01`\n- `1` → formato Thales `05`\n- `3` → formato Thales `47`\n- `4` (padrão) → formato Thales `48`\n"}}},"ReturnMultiValue":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retValue":{"type":"string","nullable":true,"description":"Valor de retorno simples"},"retDescription":{"type":"string","description":"Descrição do resultado"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com os valores de retorno da operação"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `500`: Erro interno do servidor\n- `400`: Requisição inválida\n- `155`: Chave não encontrada no banco de dados\n"},"retValid":{"type":"boolean"},"retValue":{"type":"string","nullable":true},"retDescription":{"type":"string","description":"Descrição do erro"},"retMultiValue":{"nullable":true}}}}},"paths":{"/v4/PayShieldPan/TranslatePinZpkToLmk":{"post":{"tags":["PIN"],"summary":"Translate PIN ZPK (AES) to LMK (AES)","description":"Returns the translated PIN from encryption under the ZPK (AES) to encryption under a LMK (AES) in retMultiValue[0] with retCode 0 and retDescription Ok. In case of error, it returns details in the Error fields (retCode and RetDescription)\n\nWhen used with a Variant LMK or 3DES Key Block LMK, the PIN encrypted under the LMK will always be using a non-ISO format\n","operationId":"translatePinZpkToLmk","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranslatePinZpkToLmkInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnMultiValue"}}}},"400":{"description":"Requisição inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

## The GeneratePinInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield PAN API","version":"4.1.32"},"components":{"schemas":{"GeneratePinInput":{"type":"object","required":["client_id","pan","pinLength"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"pan":{"type":"string","minLength":12,"maxLength":19,"description":"PAN do cartão (12 a 19 dígitos)"},"pinLength":{"type":"integer","minimum":4,"maximum":12,"description":"Comprimento do PIN a ser gerado (4 a 12 dígitos)"}}}}}}
```

## The TranslatePanInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield PAN API","version":"4.1.32"},"components":{"schemas":{"TranslatePanInput":{"type":"object","required":["client_id","pin","oldPan","newPan"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"pin":{"type":"string","maxLength":33,"description":"PIN criptografado sob a LMK"},"oldPan":{"type":"string","minLength":12,"maxLength":19,"description":"PAN antigo do cartão (12 a 19 dígitos)"},"newPan":{"type":"string","minLength":12,"maxLength":19,"description":"Novo PAN do cartão (12 a 19 dígitos)"}}}}}}
```

## The TranslatePinLmkToZpkInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield PAN API","version":"4.1.32"},"components":{"schemas":{"TranslatePinLmkToZpkInput":{"type":"object","required":["client_id","keyId","pin","pan","formatCode"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave ZPK de destino"},"pin":{"type":"string","maxLength":33,"description":"PIN criptografado sob a LMK"},"pan":{"type":"string","description":"PAN do cartão"},"formatCode":{"type":"integer","minimum":0,"maximum":4,"description":"Código de formato do PinBlock de destino:\n- `0` → formato Thales `01`\n- `1` → formato Thales `05`\n- `3` → formato Thales `47`\n- `4` (padrão) → formato Thales `48`\n"}}}}}}
```

## The TranslatePinZpkToLmkInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield PAN API","version":"4.1.32"},"components":{"schemas":{"TranslatePinZpkToLmkInput":{"type":"object","required":["client_id","keyId","pin","pan","formatCode"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave ZPK de origem"},"pin":{"type":"string","minLength":16,"maxLength":16,"description":"PinBlock criptografado sob a ZPK (exatamente 16 dígitos)"},"pan":{"type":"string","minLength":16,"maxLength":16,"description":"PAN do cartão (exatamente 16 dígitos)"},"formatCode":{"type":"integer","minimum":0,"maximum":4,"description":"Código de formato do PinBlock de origem:\n- `0` → formato Thales `01`\n- `1` → formato Thales `05`\n- `3` → formato Thales `47`\n- `4` (padrão) → formato Thales `48`\n"}}}}}}
```

## The ReturnMultiValue object

```json
{"openapi":"3.0.3","info":{"title":"PayShield PAN API","version":"4.1.32"},"components":{"schemas":{"ReturnMultiValue":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retValue":{"type":"string","nullable":true,"description":"Valor de retorno simples"},"retDescription":{"type":"string","description":"Descrição do resultado"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com os valores de retorno da operação"}}}}}}
```

## The ReturnError object

```json
{"openapi":"3.0.3","info":{"title":"PayShield PAN API","version":"4.1.32"},"components":{"schemas":{"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `500`: Erro interno do servidor\n- `400`: Requisição inválida\n- `155`: Chave não encontrada no banco de dados\n"},"retValid":{"type":"boolean"},"retValue":{"type":"string","nullable":true},"retDescription":{"type":"string","description":"Descrição do erro"},"retMultiValue":{"nullable":true}}}}}}
```


# CVV

Endpoints do serviço ws-hop-api-cvv

## CVV Generate CV Module

> Returns the CV (Card Validation Value / Code) in (retValue).<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield CVV API","version":"4.1.32"},"tags":[{"name":"CVV","description":"Operações de geração e validação de CVV/CVC estático e dinâmico"}],"servers":[{"url":"https://api-hext.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"GenerateCvInput":{"allOf":[{"$ref":"#/components/schemas/CvvInputBase"}]},"CvvInputBase":{"type":"object","required":["client_id","keyId","pan","expDate","serviceCode"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave CVK no banco de dados"},"pan":{"type":"string","minLength":1,"maxLength":19,"description":"PAN do cartão (até 19 dígitos)"},"expDate":{"type":"string","description":"Data de expiração do cartão (formato YYMM ou MMYY conforme configuração do HSM)"},"serviceCode":{"type":"string","description":"Service Code do cartão:\n- Valor do track → CVV tipo 1 (CVV1)\n- `000` → CVV tipo 2 (CVV2)\n- `999` → CVV dinâmico (dCVV)\n"}}},"ReturnSingle":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValue":{"type":"string","nullable":true,"description":"Valor de retorno simples"},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retDescription":{"type":"string","description":"Descrição do resultado"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `500`: Erro interno\n- `400`: Requisição inválida\n- `155`: Chave não encontrada no banco de dados\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDescription":{"type":"string","description":"Descrição do erro"}}}}},"paths":{"/v4/PayShieldCVV/GenerateCV":{"post":{"tags":["CVV"],"summary":"CVV Generate CV Module","description":"Returns the CV (Card Validation Value / Code) in (retValue).\n","operationId":"generateCV","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateCvInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnSingle"}}}},"400":{"description":"Requisição inválida — campo obrigatório ausente ou formato incorreto","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"404":{"description":"Chave não encontrada no banco de dados","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

## CVV Generate CV Module

> Returns the CVs (Card Validation Value / Code) in (retMultiValue).<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield CVV API","version":"4.1.32"},"tags":[{"name":"CVV","description":"Operações de geração e validação de CVV/CVC estático e dinâmico"}],"servers":[{"url":"https://api-hext.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"SuperGenerateCvInput":{"type":"object","required":["client_id","keyId","pan","expDate","serviceCodeArray"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave CVK no banco de dados"},"pan":{"type":"string","minLength":1,"maxLength":19,"description":"PAN do cartão (até 19 dígitos)"},"expDate":{"type":"string","description":"Data de expiração do cartão"},"serviceCodeArray":{"type":"array","items":{"type":"string"},"description":"Array de service codes para geração de múltiplos CVVs em uma única chamada.\nCada elemento gera um CVV correspondente em `retMultiValue`.\n"}}},"ReturnMultiValue":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValue":{"type":"string","nullable":true},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string"},"description":"Array com os CVVs gerados — um por service code enviado"},"retValid":{"type":"boolean"},"retDescription":{"type":"string"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `500`: Erro interno\n- `400`: Requisição inválida\n- `155`: Chave não encontrada no banco de dados\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDescription":{"type":"string","description":"Descrição do erro"}}}}},"paths":{"/v4/PayShieldCVV/SuperGenerateCV":{"post":{"tags":["CVV"],"summary":"CVV Generate CV Module","description":"Returns the CVs (Card Validation Value / Code) in (retMultiValue).\n","operationId":"superGenerateCV","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuperGenerateCvInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnMultiValue"}}}},"400":{"description":"Requisição inválida — campo obrigatório ausente ou formato incorreto","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"404":{"description":"Chave não encontrada no banco de dados","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

## CVV Dynamic Module

> Returns OK(true) or Not-Ok(false) in (retValid), in case of error, it returns details in the Error fields (retCode and RetDescription).<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield CVV API","version":"4.1.32"},"tags":[{"name":"CVV","description":"Operações de geração e validação de CVV/CVC estático e dinâmico"}],"servers":[{"url":"https://api-hext.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"ValidateCvInput":{"allOf":[{"$ref":"#/components/schemas/CvvInputBase"},{"type":"object","required":["cv"],"properties":{"cv":{"type":"string","minLength":3,"maxLength":3,"pattern":"^[0-9]+$","description":"CVV/CVC a ser validado (exatamente 3 dígitos numéricos)"},"dynCv":{"type":"string","nullable":true,"description":"CVV dinâmico (usado apenas para serviceCode `999`)"}}}]},"CvvInputBase":{"type":"object","required":["client_id","keyId","pan","expDate","serviceCode"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave CVK no banco de dados"},"pan":{"type":"string","minLength":1,"maxLength":19,"description":"PAN do cartão (até 19 dígitos)"},"expDate":{"type":"string","description":"Data de expiração do cartão (formato YYMM ou MMYY conforme configuração do HSM)"},"serviceCode":{"type":"string","description":"Service Code do cartão:\n- Valor do track → CVV tipo 1 (CVV1)\n- `000` → CVV tipo 2 (CVV2)\n- `999` → CVV dinâmico (dCVV)\n"}}},"ReturnSingle":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValue":{"type":"string","nullable":true,"description":"Valor de retorno simples"},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retDescription":{"type":"string","description":"Descrição do resultado"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `500`: Erro interno\n- `400`: Requisição inválida\n- `155`: Chave não encontrada no banco de dados\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDescription":{"type":"string","description":"Descrição do erro"}}}}},"paths":{"/v4/PayShieldCVV/ValidateCV":{"post":{"tags":["CVV"],"summary":"CVV Dynamic Module","description":"Returns OK(true) or Not-Ok(false) in (retValid), in case of error, it returns details in the Error fields (retCode and RetDescription).\n","operationId":"validateCV","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidateCvInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnSingle"}}}},"400":{"description":"Requisição inválida — campo obrigatório ausente ou formato incorreto","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"404":{"description":"Chave não encontrada no banco de dados","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

## The CvvInputBase object

```json
{"openapi":"3.0.3","info":{"title":"PayShield CVV API","version":"4.1.32"},"components":{"schemas":{"CvvInputBase":{"type":"object","required":["client_id","keyId","pan","expDate","serviceCode"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave CVK no banco de dados"},"pan":{"type":"string","minLength":1,"maxLength":19,"description":"PAN do cartão (até 19 dígitos)"},"expDate":{"type":"string","description":"Data de expiração do cartão (formato YYMM ou MMYY conforme configuração do HSM)"},"serviceCode":{"type":"string","description":"Service Code do cartão:\n- Valor do track → CVV tipo 1 (CVV1)\n- `000` → CVV tipo 2 (CVV2)\n- `999` → CVV dinâmico (dCVV)\n"}}}}}}
```

## The GenerateCvInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield CVV API","version":"4.1.32"},"components":{"schemas":{"GenerateCvInput":{"allOf":[{"$ref":"#/components/schemas/CvvInputBase"}]},"CvvInputBase":{"type":"object","required":["client_id","keyId","pan","expDate","serviceCode"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave CVK no banco de dados"},"pan":{"type":"string","minLength":1,"maxLength":19,"description":"PAN do cartão (até 19 dígitos)"},"expDate":{"type":"string","description":"Data de expiração do cartão (formato YYMM ou MMYY conforme configuração do HSM)"},"serviceCode":{"type":"string","description":"Service Code do cartão:\n- Valor do track → CVV tipo 1 (CVV1)\n- `000` → CVV tipo 2 (CVV2)\n- `999` → CVV dinâmico (dCVV)\n"}}}}}}
```

## The SuperGenerateCvInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield CVV API","version":"4.1.32"},"components":{"schemas":{"SuperGenerateCvInput":{"type":"object","required":["client_id","keyId","pan","expDate","serviceCodeArray"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave CVK no banco de dados"},"pan":{"type":"string","minLength":1,"maxLength":19,"description":"PAN do cartão (até 19 dígitos)"},"expDate":{"type":"string","description":"Data de expiração do cartão"},"serviceCodeArray":{"type":"array","items":{"type":"string"},"description":"Array de service codes para geração de múltiplos CVVs em uma única chamada.\nCada elemento gera um CVV correspondente em `retMultiValue`.\n"}}}}}}
```

## The ValidateCvInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield CVV API","version":"4.1.32"},"components":{"schemas":{"ValidateCvInput":{"allOf":[{"$ref":"#/components/schemas/CvvInputBase"},{"type":"object","required":["cv"],"properties":{"cv":{"type":"string","minLength":3,"maxLength":3,"pattern":"^[0-9]+$","description":"CVV/CVC a ser validado (exatamente 3 dígitos numéricos)"},"dynCv":{"type":"string","nullable":true,"description":"CVV dinâmico (usado apenas para serviceCode `999`)"}}}]},"CvvInputBase":{"type":"object","required":["client_id","keyId","pan","expDate","serviceCode"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave CVK no banco de dados"},"pan":{"type":"string","minLength":1,"maxLength":19,"description":"PAN do cartão (até 19 dígitos)"},"expDate":{"type":"string","description":"Data de expiração do cartão (formato YYMM ou MMYY conforme configuração do HSM)"},"serviceCode":{"type":"string","description":"Service Code do cartão:\n- Valor do track → CVV tipo 1 (CVV1)\n- `000` → CVV tipo 2 (CVV2)\n- `999` → CVV dinâmico (dCVV)\n"}}}}}}
```

## The ReturnSingle object

```json
{"openapi":"3.0.3","info":{"title":"PayShield CVV API","version":"4.1.32"},"components":{"schemas":{"ReturnSingle":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValue":{"type":"string","nullable":true,"description":"Valor de retorno simples"},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retDescription":{"type":"string","description":"Descrição do resultado"}}}}}}
```

## The ReturnMultiValue object

```json
{"openapi":"3.0.3","info":{"title":"PayShield CVV API","version":"4.1.32"},"components":{"schemas":{"ReturnMultiValue":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValue":{"type":"string","nullable":true},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string"},"description":"Array com os CVVs gerados — um por service code enviado"},"retValid":{"type":"boolean"},"retDescription":{"type":"string"}}}}}}
```

## The ReturnError object

```json
{"openapi":"3.0.3","info":{"title":"PayShield CVV API","version":"4.1.32"},"components":{"schemas":{"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `500`: Erro interno\n- `400`: Requisição inválida\n- `155`: Chave não encontrada no banco de dados\n"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retValid":{"type":"boolean"},"retDescription":{"type":"string","description":"Descrição do erro"}}}}}}
```


# EMV

Endpoints do serviço ws-hop-api-emv

## EMV Validate ARPC 4.x Module

> Returns True or False according to the validation of the ARQC (Request Cryptogram) if it is valid or not, in retValid.<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield EMV API","version":"4.1.32"},"tags":[{"name":"PayShield EMV","description":"Operações de validação de criptogramas EMV (ARPC/ARQC)"}],"servers":[{"url":"https://api-hext.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"ArpcInput":{"type":"object","required":["client_id","brand","mode","schemeId","mkacKeyId","pan","panSeqNr","field55EmvTags"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"brand":{"type":"string","enum":["MASTERCARD","VISA","AMEX"],"description":"Bandeira do cartão"},"mode":{"type":"string","description":"Modo de operação do comando EMV:\n- `0`: Validar ARQC\n- `1`: Validar ARQC e gerar ARPC método 1 (ARC)\n- `2`: Gerar ARPC método 1 (ARC) sem validar ARQC\n- `3`: Validar ARQC e gerar ARPC método 2 (CSU)\n- `4`: Gerar ARPC método 2 (CSU) sem validar ARQC\n- `5`: Validar ARQC e gerar ARPC métodos 1 e 2\n- `6`: Gerar ARPC métodos 1 e 2 sem validar ARQC\n- `8`: Validar TC/AAC\n- `9`: Validar TC/AAC e gerar ARPC método 1\n"},"schemeId":{"type":"string","description":"Identificador do esquema EMV:\n- `0`: Visa VIS (CVN 10 ou 17)\n- `1`: Mastercard M/Chip (CVN 10 ou 11)\n- `2`: American Express AEIPS\n- `3`: Mastercard M/Chip com PAN length\n- `5`: Visa VIS com PAN length\n- `6`: JCB\n- `7`: Discover\n- `9`: Visa qVSDC\n- `A`: Mastercard PayPass\n- `B`: Mastercard PayPass com PAN length\n- `C`: Mastercard PayPass com padding flag\n"},"iv_ac":{"type":"string","nullable":true,"description":"IV para derivação de chave de sessão EMV 2000.\nObrigatório apenas para `schemeId` = `0` ou `1`.\n"},"branch_height_params":{"type":"string","nullable":true,"description":"Parâmetros de branch/height para derivação de chave de sessão EMV 2000.\nObrigatório apenas para `schemeId` = `0` ou `1`.\n- `0`: Branch factor 2, Tree Height 16\n- `1`: Branch factor 4, Tree Height 8\n"},"mkacKeyId":{"type":"string","description":"Alias/identificador da chave MKAC no banco de dados"},"pan":{"type":"string","description":"PAN do cartão"},"panSeqNr":{"type":"string","description":"Número de sequência do PAN (PSN) — usar `00` se não disponível"},"field55EmvTags":{"type":"string","description":"Dados EMV da transação em formato TLV hexadecimal (campo 55 da ISO 8583).\nO ARQC é extraído automaticamente da tag `9F26`.\nTags relevantes utilizadas: `9F26` (ARQC), `9F36` (ATC), `9F10` (Issuer Application Data), `8C` (CDOL1).\n"},"arc":{"type":"string","nullable":true,"description":"Authorization Response Code — obrigatório para `mode` = `1`, `2`, `5`, `6` ou `9`.\nValor em Hex (ex: `00` = aprovado, `01` = negado).\n"},"arqc":{"type":"string","nullable":true,"description":"ARQC (Authorization Request Cryptogram) em Hex.\nQuando informado, sobrescreve o valor extraído automaticamente da tag `9F26` do `field55EmvTags`.\nUtilizado principalmente no endpoint `ValidateARQC4x`.\n"},"csu":{"type":"string","nullable":true,"description":"Card Status Update — obrigatório para `mode` = `3`, `4`, `5` ou `6`.\n4 bytes em Hex.\n"}}},"ReturnSingle":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValid":{"type":"boolean","description":"Indica se o ARQC foi validado com sucesso"},"retValue":{"type":"string","nullable":true,"description":"ARPC gerado em Hex (quando aplicável)"},"retDescription":{"type":"string","description":"Descrição do resultado"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `500`: Erro interno\n- `400`: Requisição inválida\n- `155`: Chave não encontrada no banco de dados\n"},"retValid":{"type":"boolean"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retDescription":{"type":"string","description":"Descrição do erro"}}}}},"paths":{"/v4/PayShieldEMV/ValidateARQC4x":{"post":{"tags":["PayShield EMV"],"summary":"EMV Validate ARPC 4.x Module","description":"Returns True or False according to the validation of the ARQC (Request Cryptogram) if it is valid or not, in retValid.\n","operationId":"validateARQC4x","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArpcInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnSingle"}}}},"400":{"description":"Requisição inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"404":{"description":"Chave não encontrada no banco de dados","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

## The ArpcInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield EMV API","version":"4.1.32"},"components":{"schemas":{"ArpcInput":{"type":"object","required":["client_id","brand","mode","schemeId","mkacKeyId","pan","panSeqNr","field55EmvTags"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"brand":{"type":"string","enum":["MASTERCARD","VISA","AMEX"],"description":"Bandeira do cartão"},"mode":{"type":"string","description":"Modo de operação do comando EMV:\n- `0`: Validar ARQC\n- `1`: Validar ARQC e gerar ARPC método 1 (ARC)\n- `2`: Gerar ARPC método 1 (ARC) sem validar ARQC\n- `3`: Validar ARQC e gerar ARPC método 2 (CSU)\n- `4`: Gerar ARPC método 2 (CSU) sem validar ARQC\n- `5`: Validar ARQC e gerar ARPC métodos 1 e 2\n- `6`: Gerar ARPC métodos 1 e 2 sem validar ARQC\n- `8`: Validar TC/AAC\n- `9`: Validar TC/AAC e gerar ARPC método 1\n"},"schemeId":{"type":"string","description":"Identificador do esquema EMV:\n- `0`: Visa VIS (CVN 10 ou 17)\n- `1`: Mastercard M/Chip (CVN 10 ou 11)\n- `2`: American Express AEIPS\n- `3`: Mastercard M/Chip com PAN length\n- `5`: Visa VIS com PAN length\n- `6`: JCB\n- `7`: Discover\n- `9`: Visa qVSDC\n- `A`: Mastercard PayPass\n- `B`: Mastercard PayPass com PAN length\n- `C`: Mastercard PayPass com padding flag\n"},"iv_ac":{"type":"string","nullable":true,"description":"IV para derivação de chave de sessão EMV 2000.\nObrigatório apenas para `schemeId` = `0` ou `1`.\n"},"branch_height_params":{"type":"string","nullable":true,"description":"Parâmetros de branch/height para derivação de chave de sessão EMV 2000.\nObrigatório apenas para `schemeId` = `0` ou `1`.\n- `0`: Branch factor 2, Tree Height 16\n- `1`: Branch factor 4, Tree Height 8\n"},"mkacKeyId":{"type":"string","description":"Alias/identificador da chave MKAC no banco de dados"},"pan":{"type":"string","description":"PAN do cartão"},"panSeqNr":{"type":"string","description":"Número de sequência do PAN (PSN) — usar `00` se não disponível"},"field55EmvTags":{"type":"string","description":"Dados EMV da transação em formato TLV hexadecimal (campo 55 da ISO 8583).\nO ARQC é extraído automaticamente da tag `9F26`.\nTags relevantes utilizadas: `9F26` (ARQC), `9F36` (ATC), `9F10` (Issuer Application Data), `8C` (CDOL1).\n"},"arc":{"type":"string","nullable":true,"description":"Authorization Response Code — obrigatório para `mode` = `1`, `2`, `5`, `6` ou `9`.\nValor em Hex (ex: `00` = aprovado, `01` = negado).\n"},"arqc":{"type":"string","nullable":true,"description":"ARQC (Authorization Request Cryptogram) em Hex.\nQuando informado, sobrescreve o valor extraído automaticamente da tag `9F26` do `field55EmvTags`.\nUtilizado principalmente no endpoint `ValidateARQC4x`.\n"},"csu":{"type":"string","nullable":true,"description":"Card Status Update — obrigatório para `mode` = `3`, `4`, `5` ou `6`.\n4 bytes em Hex.\n"}}}}}}
```

## The ReturnSingle object

```json
{"openapi":"3.0.3","info":{"title":"PayShield EMV API","version":"4.1.32"},"components":{"schemas":{"ReturnSingle":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValid":{"type":"boolean","description":"Indica se o ARQC foi validado com sucesso"},"retValue":{"type":"string","nullable":true,"description":"ARPC gerado em Hex (quando aplicável)"},"retDescription":{"type":"string","description":"Descrição do resultado"}}}}}}
```

## The ReturnError object

```json
{"openapi":"3.0.3","info":{"title":"PayShield EMV API","version":"4.1.32"},"components":{"schemas":{"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `500`: Erro interno\n- `400`: Requisição inválida\n- `155`: Chave não encontrada no banco de dados\n"},"retValid":{"type":"boolean"},"retValue":{"type":"string"},"retMultiValue":{"nullable":true},"retDescription":{"type":"string","description":"Descrição do erro"}}}}}}
```


# Key Manager

Endpoints do serviço ws-hop-api-keymanager

## Key Manager Generate Key Module

> Returns the KeyId generated by the HSM.<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield Key Manager API","version":"4.1.32"},"tags":[{"name":"Key Manager","description":"Operações de geração, importação, exportação e tradução de chaves criptográficas"}],"servers":[{"url":"https://api-hext.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"GenerateKeyInput":{"type":"object","required":["client_id","keyName","keySizeType","modeFlag"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyName":{"type":"string","description":"Nome/tipo da chave a ser gerada (ex ZEK, ZPK, ZMK, TMK, BDK)"},"keySizeType":{"type":"string","description":"Tamanho/tipo da chave:\n- S Single DES (64 bits)\n- D Double DES (128 bits)\n- T Triple DES (192 bits)\n- A AES-128\n- B AES-192\n- C AES-256\n"},"modeFlag":{"type":"string","enum":["0","1","A","B"],"description":"Modo de operacao:\n- 0 Gerar chave\n- 1 Gerar chave e exportar sob ZMK/TMK\n- A Derivar chave\n- B Derivar chave e exportar sob ZMK/TMK\n"},"zmk_TMK_flag":{"type":"string","nullable":true,"description":"Flag da ZMK/TMK, obrigatorio quando modeFlag 1 ou B"},"zmk_TMK_keyId":{"type":"string","nullable":true,"description":"Alias da ZMK/TMK, obrigatorio quando modeFlag 1 ou B"},"is_ephemeral":{"type":"boolean","description":"Se true, a chave tera tempo de vida limitado por key_TTL_minutes"},"key_TTL_minutes":{"type":"integer","nullable":true,"description":"Tempo de vida da chave em minutos, obrigatorio quando is_ephemeral true"}}},"ReturnImpKey":{"type":"object","properties":{"retCode":{"type":"integer","description":"Codigo de retorno. 0 = sucesso, outros valores indicam erro"},"retValid":{"type":"boolean","description":"Indica se a operacao foi bem-sucedida"},"retValue":{"type":"string","description":"KeyId gerado/importado no banco de dados"},"retDescription":{"type":"string","description":"Descricao do resultado"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com valores adicionais, retMultiValue[0] contem o KCV da chave gerada/importada"},"retKeyTTLmin":{"type":"integer","description":"Tempo de vida da chave em minutos (0 = sem expiracao)"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Codigo de erro:\n- 500 Erro interno do servidor\n- 400 Requisicao invalida\n- 155 Chave nao encontrada no banco de dados\n"},"retValid":{"type":"boolean"},"retValue":{"type":"string","nullable":true},"retDescription":{"type":"string","description":"Descricao do erro"},"retMultiValue":{"nullable":true}}}}},"paths":{"/v4/PayShieldKeyManager/GenerateKey":{"post":{"tags":["Key Manager"],"summary":"Key Manager Generate Key Module","description":"Returns the KeyId generated by the HSM.\n","operationId":"generateKey","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateKeyInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnImpKey"}}}},"400":{"description":"Requisição inválida — campo obrigatório ausente ou formato incorreto","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"404":{"description":"Chave não encontrada no banco de dados","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

## Key Manager Import Key Module

> Returns the KeyId generated from the imported key.<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield Key Manager API","version":"4.1.32"},"tags":[{"name":"Key Manager","description":"Operações de geração, importação, exportação e tradução de chaves criptográficas"}],"servers":[{"url":"https://api-hext.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"ImportKeyInput":{"type":"object","required":["client_id","keyName","keySizeType","key_under_ZMK_to_import","ZMK_keyId"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyName":{"type":"string","description":"Nome/tipo da chave a ser importada (ex ZEK, ZPK, TMK)"},"keySizeType":{"type":"string","description":"Tamanho/tipo da chave:\n- S Single DES\n- D Double DES\n- T Triple DES\n- A AES-128\n- B AES-192\n- C AES-256\n"},"key_under_ZMK_to_import":{"type":"string","description":"Chave criptografada sob a ZMK a ser importada (formato Key Block ou X9.17)"},"ZMK_keyId":{"type":"string","description":"Alias/identificador da ZMK no banco de dados"},"is_ephemeral":{"type":"boolean","description":"Se true, a chave tera tempo de vida limitado por key_TTL_minutes"},"key_TTL_minutes":{"type":"integer","nullable":true,"description":"Tempo de vida da chave em minutos, obrigatorio quando is_ephemeral true"}}},"ReturnImpKey":{"type":"object","properties":{"retCode":{"type":"integer","description":"Codigo de retorno. 0 = sucesso, outros valores indicam erro"},"retValid":{"type":"boolean","description":"Indica se a operacao foi bem-sucedida"},"retValue":{"type":"string","description":"KeyId gerado/importado no banco de dados"},"retDescription":{"type":"string","description":"Descricao do resultado"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com valores adicionais, retMultiValue[0] contem o KCV da chave gerada/importada"},"retKeyTTLmin":{"type":"integer","description":"Tempo de vida da chave em minutos (0 = sem expiracao)"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Codigo de erro:\n- 500 Erro interno do servidor\n- 400 Requisicao invalida\n- 155 Chave nao encontrada no banco de dados\n"},"retValid":{"type":"boolean"},"retValue":{"type":"string","nullable":true},"retDescription":{"type":"string","description":"Descricao do erro"},"retMultiValue":{"nullable":true}}}}},"paths":{"/v4/PayShieldKeyManager/ImportKey":{"post":{"tags":["Key Manager"],"summary":"Key Manager Import Key Module","description":"Returns the KeyId generated from the imported key.\n","operationId":"importKey","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportKeyInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnImpKey"}}}},"400":{"description":"Requisição inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"404":{"description":"Chave não encontrada no banco de dados","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

## POST /v4/PayShieldKeyManager/ImportZMK

> Key Manager Import ZMK Module

```json
{"openapi":"3.0.3","info":{"title":"PayShield Key Manager API","version":"4.1.32"},"tags":[{"name":"Key Manager","description":"Operações de geração, importação, exportação e tradução de chaves criptográficas"}],"servers":[{"url":"https://api-hext.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"ImportZMKInput":{"type":"object","required":["client_id","kcv","keyZMK"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"kcv":{"type":"string","minLength":6,"maxLength":6,"description":"Key Check Value da ZMK (exatamente 6 caracteres hexadecimais)"},"keyZMK":{"type":"string","description":"ZMK em formato Key Block Thales"}}},"ReturnImpKey":{"type":"object","properties":{"retCode":{"type":"integer","description":"Codigo de retorno. 0 = sucesso, outros valores indicam erro"},"retValid":{"type":"boolean","description":"Indica se a operacao foi bem-sucedida"},"retValue":{"type":"string","description":"KeyId gerado/importado no banco de dados"},"retDescription":{"type":"string","description":"Descricao do resultado"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com valores adicionais, retMultiValue[0] contem o KCV da chave gerada/importada"},"retKeyTTLmin":{"type":"integer","description":"Tempo de vida da chave em minutos (0 = sem expiracao)"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Codigo de erro:\n- 500 Erro interno do servidor\n- 400 Requisicao invalida\n- 155 Chave nao encontrada no banco de dados\n"},"retValid":{"type":"boolean"},"retValue":{"type":"string","nullable":true},"retDescription":{"type":"string","description":"Descricao do erro"},"retMultiValue":{"nullable":true}}}}},"paths":{"/v4/PayShieldKeyManager/ImportZMK":{"post":{"tags":["Key Manager"],"summary":"Key Manager Import ZMK Module","description":"","operationId":"importZMK","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportZMKInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnImpKey"}}}},"400":{"description":"Requisição inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

## POST /v4/PayShieldKeyManager/ExportKey

> Key Manager Export Key Module

```json
{"openapi":"3.0.3","info":{"title":"PayShield Key Manager API","version":"4.1.32"},"tags":[{"name":"Key Manager","description":"Operações de geração, importação, exportação e tradução de chaves criptográficas"}],"servers":[{"url":"https://api-hext.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"ExportKeyInput":{"type":"object","required":["client_id","keyId","ZMK_keyId","export_scheme"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave a ser exportada no banco de dados"},"ZMK_keyId":{"type":"string","description":"Alias/identificador da ZMK sob a qual a chave sera exportada"},"export_scheme":{"type":"string","enum":["X917","TR31","TKBF"],"description":"Esquema de exportacao:\n- X917 Formato X9.17 (apenas DES/3DES)\n- TR31 Formato TR-31 Key Block\n- TKBF Thales Key Block Format\n"}}},"ReturnMultiValue":{"type":"object","properties":{"retCode":{"type":"integer","description":"Codigo de retorno. 0 = sucesso, outros valores indicam erro"},"retValid":{"type":"boolean","description":"Indica se a operacao foi bem-sucedida"},"retValue":{"type":"string","nullable":true,"description":"Valor de retorno simples"},"retDescription":{"type":"string","description":"Descricao do resultado"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com os valores de retorno da operacao"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Codigo de erro:\n- 500 Erro interno do servidor\n- 400 Requisicao invalida\n- 155 Chave nao encontrada no banco de dados\n"},"retValid":{"type":"boolean"},"retValue":{"type":"string","nullable":true},"retDescription":{"type":"string","description":"Descricao do erro"},"retMultiValue":{"nullable":true}}}}},"paths":{"/v4/PayShieldKeyManager/ExportKey":{"post":{"tags":["Key Manager"],"summary":"Key Manager Export Key Module","description":"","operationId":"exportKey","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportKeyInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnMultiValue"}}}},"400":{"description":"Requisição inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"404":{"description":"Chave não encontrada no banco de dados","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

## The GenerateKeyInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield Key Manager API","version":"4.1.32"},"components":{"schemas":{"GenerateKeyInput":{"type":"object","required":["client_id","keyName","keySizeType","modeFlag"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyName":{"type":"string","description":"Nome/tipo da chave a ser gerada (ex ZEK, ZPK, ZMK, TMK, BDK)"},"keySizeType":{"type":"string","description":"Tamanho/tipo da chave:\n- S Single DES (64 bits)\n- D Double DES (128 bits)\n- T Triple DES (192 bits)\n- A AES-128\n- B AES-192\n- C AES-256\n"},"modeFlag":{"type":"string","enum":["0","1","A","B"],"description":"Modo de operacao:\n- 0 Gerar chave\n- 1 Gerar chave e exportar sob ZMK/TMK\n- A Derivar chave\n- B Derivar chave e exportar sob ZMK/TMK\n"},"zmk_TMK_flag":{"type":"string","nullable":true,"description":"Flag da ZMK/TMK, obrigatorio quando modeFlag 1 ou B"},"zmk_TMK_keyId":{"type":"string","nullable":true,"description":"Alias da ZMK/TMK, obrigatorio quando modeFlag 1 ou B"},"is_ephemeral":{"type":"boolean","description":"Se true, a chave tera tempo de vida limitado por key_TTL_minutes"},"key_TTL_minutes":{"type":"integer","nullable":true,"description":"Tempo de vida da chave em minutos, obrigatorio quando is_ephemeral true"}}}}}}
```

## The ImportKeyInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield Key Manager API","version":"4.1.32"},"components":{"schemas":{"ImportKeyInput":{"type":"object","required":["client_id","keyName","keySizeType","key_under_ZMK_to_import","ZMK_keyId"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyName":{"type":"string","description":"Nome/tipo da chave a ser importada (ex ZEK, ZPK, TMK)"},"keySizeType":{"type":"string","description":"Tamanho/tipo da chave:\n- S Single DES\n- D Double DES\n- T Triple DES\n- A AES-128\n- B AES-192\n- C AES-256\n"},"key_under_ZMK_to_import":{"type":"string","description":"Chave criptografada sob a ZMK a ser importada (formato Key Block ou X9.17)"},"ZMK_keyId":{"type":"string","description":"Alias/identificador da ZMK no banco de dados"},"is_ephemeral":{"type":"boolean","description":"Se true, a chave tera tempo de vida limitado por key_TTL_minutes"},"key_TTL_minutes":{"type":"integer","nullable":true,"description":"Tempo de vida da chave em minutos, obrigatorio quando is_ephemeral true"}}}}}}
```

## The ImportZMKInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield Key Manager API","version":"4.1.32"},"components":{"schemas":{"ImportZMKInput":{"type":"object","required":["client_id","kcv","keyZMK"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"kcv":{"type":"string","minLength":6,"maxLength":6,"description":"Key Check Value da ZMK (exatamente 6 caracteres hexadecimais)"},"keyZMK":{"type":"string","description":"ZMK em formato Key Block Thales"}}}}}}
```

## The ExportKeyInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield Key Manager API","version":"4.1.32"},"components":{"schemas":{"ExportKeyInput":{"type":"object","required":["client_id","keyId","ZMK_keyId","export_scheme"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave a ser exportada no banco de dados"},"ZMK_keyId":{"type":"string","description":"Alias/identificador da ZMK sob a qual a chave sera exportada"},"export_scheme":{"type":"string","enum":["X917","TR31","TKBF"],"description":"Esquema de exportacao:\n- X917 Formato X9.17 (apenas DES/3DES)\n- TR31 Formato TR-31 Key Block\n- TKBF Thales Key Block Format\n"}}}}}}
```

## The ReturnImpKey object

```json
{"openapi":"3.0.3","info":{"title":"PayShield Key Manager API","version":"4.1.32"},"components":{"schemas":{"ReturnImpKey":{"type":"object","properties":{"retCode":{"type":"integer","description":"Codigo de retorno. 0 = sucesso, outros valores indicam erro"},"retValid":{"type":"boolean","description":"Indica se a operacao foi bem-sucedida"},"retValue":{"type":"string","description":"KeyId gerado/importado no banco de dados"},"retDescription":{"type":"string","description":"Descricao do resultado"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com valores adicionais, retMultiValue[0] contem o KCV da chave gerada/importada"},"retKeyTTLmin":{"type":"integer","description":"Tempo de vida da chave em minutos (0 = sem expiracao)"}}}}}}
```

## The ReturnMultiValue object

```json
{"openapi":"3.0.3","info":{"title":"PayShield Key Manager API","version":"4.1.32"},"components":{"schemas":{"ReturnMultiValue":{"type":"object","properties":{"retCode":{"type":"integer","description":"Codigo de retorno. 0 = sucesso, outros valores indicam erro"},"retValid":{"type":"boolean","description":"Indica se a operacao foi bem-sucedida"},"retValue":{"type":"string","nullable":true,"description":"Valor de retorno simples"},"retDescription":{"type":"string","description":"Descricao do resultado"},"retMultiValue":{"type":"array","nullable":true,"items":{"type":"string","nullable":true},"description":"Array com os valores de retorno da operacao"}}}}}}
```

## The ReturnError object

```json
{"openapi":"3.0.3","info":{"title":"PayShield Key Manager API","version":"4.1.32"},"components":{"schemas":{"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Codigo de erro:\n- 500 Erro interno do servidor\n- 400 Requisicao invalida\n- 155 Chave nao encontrada no banco de dados\n"},"retValid":{"type":"boolean"},"retValue":{"type":"string","nullable":true},"retDescription":{"type":"string","description":"Descricao do erro"},"retMultiValue":{"nullable":true}}}}}}
```


# RSA

ws-hop-api-rsa

## Import RSA / ECC Key Module

> Imports an RSA or ECC Public Key by generating a MAC on it.<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield RSA API","version":"4.1.32"},"tags":[{"name":"RSA","description":"Operações de importação e exportação de chaves RSA/ECC"}],"servers":[{"url":"https://api-hext.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"ImportPublicKeyInput":{"type":"object","required":["client_id","publicKeyEncoding","publicKey"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"publicKeyEncoding":{"type":"integer","enum":[1,2,3],"description":"Regras de codificação da chave pública:\n- `1`: DER encoded ASN.1 RSA Public Key (INTEGER com representação unsigned)\n- `2`: DER encoded ASN.1 RSA Public Key (INTEGER com representação 2's complement)\n- `3`: DER encoded ASN.1 ECC X9.62 format uncompressed key\n"},"publicKey":{"type":"string","description":"Chave pública RSA ou ECC em formato DER encoded ASN.1 em Hex.\nPara RSA: SubjectPublicKeyInfo ou RSAPublicKey.\nPara ECC: X9.62 uncompressed point format.\n"}}},"ReturnSingle":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retValue":{"type":"string","description":"Valor de retorno — chave exportada/importada em Hex"},"retDescription":{"type":"string","description":"Descrição do resultado"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `500`: Erro interno do servidor\n- `400`: Requisição inválida\n- `155`: Chave não encontrada no banco de dados\n"},"retValid":{"type":"boolean"},"retValue":{"type":"string","nullable":true},"retDescription":{"type":"string","description":"Descrição do erro"},"retMultiValue":{"nullable":true}}}}},"paths":{"/v4/PayShieldRsa/Import":{"post":{"tags":["RSA"],"summary":"Import RSA / ECC Key Module","description":"Imports an RSA or ECC Public Key by generating a MAC on it.\n","operationId":"importKey","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportPublicKeyInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnSingle"}}}},"400":{"description":"Requisição inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

## Export Key under an RSA Public Key Module

> Translate a DES, AES or HMAC key from encryption under an LMK pair to encryption under a\
> public key.<br>

```json
{"openapi":"3.0.3","info":{"title":"PayShield RSA API","version":"4.1.32"},"tags":[{"name":"RSA","description":"Operações de importação e exportação de chaves RSA/ECC"}],"servers":[{"url":"https://api-hext.first-tech.net","description":"Homologação (OKE)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Token JWT obtido via Auth0"}},"schemas":{"ExportKeyInput":{"type":"object","required":["client_id","keyId","padModeId","publicKey","keyBlockType"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave a ser exportada no banco de dados"},"padModeId":{"type":"integer","enum":[1,2],"description":"Identificador do modo de padding usado na criptografia:\n- `1`: PKCS#1 v1.5 (EME-PKCS1-v1_5)\n- `2`: PKCS#1 v2.2 OAEP (EME-OAEP-ENCODE) — requer `mgfHashFunction`\n"},"mgfHashFunction":{"type":"integer","enum":[1,5,6,7,8],"nullable":true,"description":"Identificador da função hash MGF — obrigatório apenas quando `padModeId: 2` (OAEP):\n- `1`: SHA-1\n- `5`: SHA-224\n- `6`: SHA-256\n- `7`: SHA-384\n- `8`: SHA-512\n"},"publicKey":{"type":"string","description":"Chave pública RSA em formato Key Block Thales (Hex).\nGerada pelo endpoint `Import` deste mesmo serviço.\n"},"keyBlockType":{"type":"integer","enum":[3],"description":"Tipo do Key Data Block:\n- `3`: Unformatted Key Data Block (único valor suportado atualmente)\n"}}},"ReturnSingle":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retValue":{"type":"string","description":"Valor de retorno — chave exportada/importada em Hex"},"retDescription":{"type":"string","description":"Descrição do resultado"}}},"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `500`: Erro interno do servidor\n- `400`: Requisição inválida\n- `155`: Chave não encontrada no banco de dados\n"},"retValid":{"type":"boolean"},"retValue":{"type":"string","nullable":true},"retDescription":{"type":"string","description":"Descrição do erro"},"retMultiValue":{"nullable":true}}}}},"paths":{"/v4/PayShieldRsa/Export":{"post":{"tags":["RSA"],"summary":"Export Key under an RSA Public Key Module","description":"Translate a DES, AES or HMAC key from encryption under an LMK pair to encryption under a\npublic key.\n","operationId":"exportKey","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportKeyInput"}}}},"responses":{"200":{"description":"Operação realizada com sucesso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnSingle"}}}},"400":{"description":"Requisição inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"401":{"description":"Não autorizado — token Bearer ausente ou inválido"},"404":{"description":"Chave não encontrada no banco de dados","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}},"500":{"description":"Erro interno do servidor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnError"}}}}}}}}}
```

## The ExportKeyInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield RSA API","version":"4.1.32"},"components":{"schemas":{"ExportKeyInput":{"type":"object","required":["client_id","keyId","padModeId","publicKey","keyBlockType"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"keyId":{"type":"string","description":"Alias/identificador da chave a ser exportada no banco de dados"},"padModeId":{"type":"integer","enum":[1,2],"description":"Identificador do modo de padding usado na criptografia:\n- `1`: PKCS#1 v1.5 (EME-PKCS1-v1_5)\n- `2`: PKCS#1 v2.2 OAEP (EME-OAEP-ENCODE) — requer `mgfHashFunction`\n"},"mgfHashFunction":{"type":"integer","enum":[1,5,6,7,8],"nullable":true,"description":"Identificador da função hash MGF — obrigatório apenas quando `padModeId: 2` (OAEP):\n- `1`: SHA-1\n- `5`: SHA-224\n- `6`: SHA-256\n- `7`: SHA-384\n- `8`: SHA-512\n"},"publicKey":{"type":"string","description":"Chave pública RSA em formato Key Block Thales (Hex).\nGerada pelo endpoint `Import` deste mesmo serviço.\n"},"keyBlockType":{"type":"integer","enum":[3],"description":"Tipo do Key Data Block:\n- `3`: Unformatted Key Data Block (único valor suportado atualmente)\n"}}}}}}
```

## The ImportPublicKeyInput object

```json
{"openapi":"3.0.3","info":{"title":"PayShield RSA API","version":"4.1.32"},"components":{"schemas":{"ImportPublicKeyInput":{"type":"object","required":["client_id","publicKeyEncoding","publicKey"],"properties":{"client_id":{"type":"integer","format":"int64","minimum":1,"description":"Identificador do cliente"},"publicKeyEncoding":{"type":"integer","enum":[1,2,3],"description":"Regras de codificação da chave pública:\n- `1`: DER encoded ASN.1 RSA Public Key (INTEGER com representação unsigned)\n- `2`: DER encoded ASN.1 RSA Public Key (INTEGER com representação 2's complement)\n- `3`: DER encoded ASN.1 ECC X9.62 format uncompressed key\n"},"publicKey":{"type":"string","description":"Chave pública RSA ou ECC em formato DER encoded ASN.1 em Hex.\nPara RSA: SubjectPublicKeyInfo ou RSAPublicKey.\nPara ECC: X9.62 uncompressed point format.\n"}}}}}}
```

## The ReturnSingle object

```json
{"openapi":"3.0.3","info":{"title":"PayShield RSA API","version":"4.1.32"},"components":{"schemas":{"ReturnSingle":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de retorno. 0 = sucesso, outros valores indicam erro"},"retValid":{"type":"boolean","description":"Indica se a operação foi bem-sucedida"},"retValue":{"type":"string","description":"Valor de retorno — chave exportada/importada em Hex"},"retDescription":{"type":"string","description":"Descrição do resultado"}}}}}}
```

## The ReturnError object

```json
{"openapi":"3.0.3","info":{"title":"PayShield RSA API","version":"4.1.32"},"components":{"schemas":{"ReturnError":{"type":"object","properties":{"retCode":{"type":"integer","description":"Código de erro:\n- `500`: Erro interno do servidor\n- `400`: Requisição inválida\n- `155`: Chave não encontrada no banco de dados\n"},"retValid":{"type":"boolean"},"retValue":{"type":"string","nullable":true},"retDescription":{"type":"string","description":"Descrição do erro"},"retMultiValue":{"nullable":true}}}}}}
```


# Visão geral

### 1. Visão Geral: O que é o HoP GO?

O **HoP GO (HSM off Premises)** é um serviço de infraestrutura criptográfica em nuvem projetado para atender às demandas críticas de segurança em ambientes de produção, com foco especial no setor de meios de pagamento.

Ele oferece às empresas acesso remoto a funcionalidades avançadas de um **HSM (Hardware Security Module)**, eliminando a necessidade de aquisição, instalação ou manutenção de equipamentos físicos dedicados.

#### Como funciona na prática?

O HoP GO permite que as organizações realizem operações criptográficas essenciais diretamente em uma infraestrutura altamente segura, resiliente e escalável, hospedada fora do ambiente local (off-premises). Essas operações incluem:

* Geração, armazenamento e gerenciamento seguro de chaves.
* Criptografia e descriptografia de dados sensíveis.
* Assinatura digital.
* Validação de transações.

#### Para quem é indicado?

Esse modelo é especialmente relevante para o ecossistema de pagamentos eletrônicos, incluindo:

* Adquirentes e Subadquirentes
* Fintechs
* Emissores de cartões
* Gateways de pagamento

A adoção do HoP GO garante conformidade com padrões rigorosos de segurança do setor (como **PCI DSS** e **PCI PIN**) e reduz significativamente a complexidade operacional dessas empresas.

#### Detalhes Técnicos e Operacionais

Para garantir a máxima segurança e disponibilidade, a infraestrutura do HoP GO conta com as seguintes características:

* **Hardware**: Utiliza o *Thales payShield 10K*, considerado o padrão ouro em segurança de HSM para pagamentos.
* **Datacenter**: Hospedado em infraestrutura Tier 3, garantindo redundância elétrica, de refrigeração e de conectividade, com disponibilidade mínima de 99,982%.
* **Modelo de Consumo**: Substitui o CapEx (investimento em hardware físico) pelo OpEx (assinatura mensal flexível).
* **Segurança e Compliance**: Todo o ambiente é certificado nas normas PCI DSS v4.0 e PCI PIN, contando com logs de auditoria centralizados e criptografia ponta a ponta.
* **Suporte Integrado**: A *First Tech* gerencia toda a infraestrutura, incluindo atualizações de firmware, rotinas de backup e planos de contingência.

#### Principais Benefícios

Ao adotar o HoP GO, as organizações ganham vantagens competitivas e operacionais:

* 💰 **Redução de custos**: Evita altos investimentos iniciais na compra de servidores HSM dedicados e em sua manutenção contínua.
* 📈 **Escalabilidade**: Permite o ajuste do poder de processamento (TPS - *Transactions Per Second*) conforme a demanda real de transações do negócio.
* ⚙️ **Simplicidade**: Reduz a complexidade operacional da equipe de TI, permitindo maior foco no *core business*.
* 🛡️ **Compliance**: Garante de forma simplificada o atendimento às certificações exigidas pelo setor financeiro.

***

### 2. Gestão e Migração de Chaves (Key Migration)

A migração para o HoP GO exige um processo de transporte seguro e uma governança rigorosa das chaves criptográficas. Para garantir o sucesso e a segurança dessa transição, as seguintes etapas e controles são aplicados:

* **Planejamento Estratégico**: Avaliação do HSM existente, identificação minuciosa das chaves a serem migradas, análise de compatibilidade de *smartcards* e definição de janelas de migração.
* **Uso de Key Blocks (TR-31)**: É obrigatório o uso de métodos estruturados em blocos seguros (como o TR-31) para garantir a integridade e a confidencialidade das chaves durante o transporte e o armazenamento.
* **Cerimonial de Chaves**: Um evento formal e rigorosamente documentado para a geração de novas chaves, incluindo a assinatura por *custodians* e o registro completo para fins de auditoria.
* **Custodiantes Designados**: Pessoas de confiança indicadas especificamente para inserir componentes de chave, autorizar operações críticas e manter os logs de ações.
* **Compatibilidade de Smartcards e LMK:** Validação técnica dos cartões LMK (*Local Master Key*) existentes com o ambiente em nuvem, garantindo a continuidade operacional sem qualquer perda de dados.
* **Logs e Auditoria**: Registro contínuo e completo de todas as operações de chave, acompanhado de monitoramento em tempo real para identificar e bloquear qualquer tentativa de acesso não autorizado.

***

### 3. Requisitos de Integração e Conectividade

Para garantir uma comunicação fluida e totalmente segura entre a aplicação do cliente e o ambiente do HoP GO, é necessário atender aos seguintes requisitos técnicos, divididos entre configurações de infraestrutura e da própria aplicação:

#### Infraestrutura: Rede e Segurança

* **Túnel Seguro**: Estabelecimento de VPN IPsec ou Direct Link conectando o datacenter ou cloud do cliente (AWS, Azure, Google Cloud, Oracle) ao ambiente HoP GO.
* **Autenticação mTLS**: Utilização de certificados digitais emitidos por uma Autoridade Certificadora confiável para garantir a autenticação mútua dos servidores.
* **Regras de Firewall**: Liberação prévia de portas TCP/IP específicas, necessárias para o tráfego dos comandos de *host* do payShield 10K.
* **Segurança de Transporte**: Aplicação de criptografia TLS 1.3 (ou superior), aliada a sistemas de detecção de intrusão e monitoramento de tráfego em tempo real.

#### Configurações da Aplicação

* **Comandos Thales**: A aplicação deve suportar os comandos de *host* compatíveis com o Thales payShield 10K, incluindo *PIN translation*, *key injection* e geração de chaves de sessão.
* **Endereçamento Virtual (VIP)**: Configuração da aplicação para apontar para o *Virtual IP* fornecido pelo HoP GO, garantindo um processo de *failover* transparente em caso de instabilidades.
* **Gestão de Sessões TCP**: Implementação de sessões persistentes com o objetivo de reduzir a latência e evitar *timeouts* durante transações críticas.
* **Monitoramento e Alertas**: Integração com os sistemas de monitoramento próprios do cliente, permitindo o disparo de alertas imediatos em casos de falhas de comunicação ou indisponibilidade do HSM.

***

### 4. Estrutura da Solução e Homologação

Para garantir uma implantação segura e eficiente, a First Tech organiza a solução em dois módulos principais, cobrindo de ponta a ponta o ciclo de vida do cliente:

| Módulo                       | Finalidade        | Público-Alvo                               | Detalhes Adicionais |
| ---------------------------- | ----------------- | ------------------------------------------ | ------------------- |
| Hop Lab                      | Ambiente de Teste | <p>Desenvolvedores e</p><p>QA</p>          | <p>Simulação de     |
| <br>transações,              |                   |                                            |                     |
| <br>validação de             |                   |                                            |                     |
| <br>comandos Thales,         |                   |                                            |                     |
| <br>integração com APIs      |                   |                                            |                     |
| <br>antes da produção.</p>   |                   |                                            |                     |
| Hop Go                       | Produção Real     | <p>Fintechs,</p><p>Adquirentes, Bancos</p> | <p>Processamento    |
| <br>seguro de                |                   |                                            |                     |
| <br>transações reais,        |                   |                                            |                     |
| <br>alta disponibilidade e   |                   |                                            |                     |
| <br>failover automático.</p> |                   |                                            |                     |

#### Documentação e Homologação

Antes de ir para a produção, o ambiente passa por um processo rigoroso de validação técnica, que inclui:

* **Matriz de Fluxo de Dados**: Mapeamento detalhado do tráfego entre a aplicação e o HSM, identificando claramente todos os comandos, portas e protocolos utilizados.
* **Plano de Homologação**: Execução de um *checklist* abrangente de comandos no ambiente de testes (HoP LAB). Isso garante a validação prévia de operações críticas, como *PIN translation* (ex: EE0600), *key injection* e geração de chaves (ex: A0).
* **Auditoria e Logs**: Geração e armazenamento de logs detalhados durante toda a fase de homologação, assegurando total rastreabilidade e facilitando auditorias de conformidade.

***

### 5. Público-Alvo e Casos de Uso

O HoP GO é a solução ideal para instituições que operam no mercado financeiro e exigem altos níveis de segurança, agilidade e escalabilidade.

#### Perfis e Aplicações Práticas

* **Fintechs e Bancos Digitais**: Viabiliza uma entrada rápida no mercado (*time-to-market*) e um *onboarding* ágil de clientes, eliminando a necessidade de altos investimentos iniciais em hardware (CapEx).
* **Adquirentes e Processadoras**: Garante a autorização segura de cartões, validação de segurança (PIN/CVV) e oferece capacidade para suportar transações PIX em alto volume.
* **Gateways de Pagamento**: Processamento robusto para grandes volumes transacionais, contando com alta disponibilidade, mecanismo de *failover* automático e baixa latência.
* **Instituições Reguladas**: Assegura o atendimento estrito às normas de segurança e auditoria exigidas pelos órgãos financeiros e entidades regulatórias (como o Bacen e o PCI SSC).

#### Benefícios Operacionais Resumidos

* **Eficiência Financeira**: Redução drástica dos custos com infraestrutura física própria e manutenção contínua.
* **Escalabilidade Dinâmica**: Ajuste do poder de processamento (TPS) de forma flexível, acompanhando os picos e a demanda real do negócio.
* **Visibilidade e Controle**: Monitoramento centralizado e trilhas de auditoria completas, cobrindo tanto as transações diárias quanto as operações críticas de gestão de chaves.


# 👋 Bem-vindo - HoP KMS

Esta página contém a introdução para a documentação HoP KMS da First Tech

Bem-vindo à central de desenvolvedores e documentação técnica do HoP KMS (Key Management Service) da First Tech.

O HoP KMS é uma plataforma corporativa de alta segurança, disponibilidade e desempenho, projetada para simplificar o gerenciamento do ciclo de vida, transporte, geração e custódia segura de chaves criptográficas. Utilizando os recursos mais avançados de Hardware Security Modules (HSM), a solução garante a proteção contra ameaças físicas e lógicas, assegurando a integridade e a confidencialidade das operações mais críticas do seu negócio.

### Os Três Pilares do HoP KMS

Para atender de forma especializada a diferentes cenários de segurança, o HoP KMS é dividido em dois módulos funcionais independentes e complementares:

#### 1. Módulo Key Management (Administrativo)

Focado na governança corporativa de chaves e certificados de infraestrutura para servidores, bancos de dados e aplicações parceiras.

* Armazenamento Criptografado no HSM: Todas as chaves e certificados enviados via upload são imediatamente cifrados pelo HSM sob chaves mestras geradas em Cerimônia de Chaves (Safe Room) com algoritmos simétricos robustos como AES-256.
* Segurança sob Dupla Custódia: O download de ativos criptográficos do repositório exige um fluxo rigoroso de aprovação mútua (*Four-Eyes Principle*), onde múltiplos custodiantes aprovam a operação através de canais temporários e seguros.
* Logs de Auditoria: Rastreabilidade completa de todas as operações administrativas (geração, exportação, revogação e acessos).

#### 2. Módulo MPoC (Dispositivos de Captura)

Focado no ecossistema de meios de pagamento e transações móveis em dispositivos comerciais comuns, como smartphones e tablets (COTS - *Commercial Off-The-Shelf*).

* Adequação PCI: Permite a captura segura de transações por aproximação (NFC) sem PIN ou com inserção de PIN via software.
* Esquema de Chaves Dinâmicas: Implementação rigorosa do padrão DUKPT (Derived Unique Key Per Transaction) para garantir uma chave exclusiva por transação.
* Segurança de Transporte: Acordos de chaves baseados em curvas elípticas (ECC/ECDH) para transporte seguro de sementes criptográficas para os terminais móveis.

#### Módulo Nonce Generator (Geração de Aleatoriedade)

Projetado para fornecer números aleatórios de altíssima segurança (criptograficamente fortes) para sistemas distribuídos que exigem alta entropia.

* Alta Entropia Física: Diferente de geradores de software comuns (que utilizam pseudo-aleatoriedade), as sementes do HoP KMS são obtidas diretamente do gerador físico do HSM, certificado por padrões globais de segurança.
* Flexibilidade de Tamanho: Capacidade de gerar valores aleatórios (nonces, salts, vetores de inicialização - IV) sob demanda com tamanho de até 256 bytes configuráveis.
* Mitigação de Ataques: Essencial para alimentar protocolos de desafio-resposta (Challenge-Response) e evitar ataques de repetição (*replay attacks*) no ecossistema transacional.

### Conformidade e Padrões Suportados

O HoP KMS foi construído em conformidade com as principais regulamentações da indústria de cartões de pagamento e segurança cibernética global:

{% columns %}
{% column %}
**Padrão / Norma**
{% endcolumn %}

{% column %}
**Escopo de Aplicação no HoP KMS**
{% endcolumn %}
{% endcolumns %}

{% columns %}
{% column %}
PCI MPoC
{% endcolumn %}

{% column %}
Segurança em transações financeiras capturadas em dispositivos móveis (*COTS*).
{% endcolumn %}
{% endcolumns %}

{% columns %}
{% column %}
FIPS (Federal Information Processing Standards)
{% endcolumn %}

{% column %}
Certificação internacional de segurança que valida a integridade do módulo gerador de números aleatórios do HSM.
{% endcolumn %}
{% endcolumns %}

{% columns %}
{% column %}
ANSI X9.24-3-2017
{% endcolumn %}

{% column %}
Especificação técnica para gerenciamento de chaves DUKPT (AES e TDES).
{% endcolumn %}
{% endcolumns %}

{% columns %}
{% column %}
TR-31 (ANSI X9.143)
{% endcolumn %}

{% column %}
Formato de Key Blocks utilizado para transporte seguro de chaves com metadados de uso.
{% endcolumn %}
{% endcolumns %}

{% columns %}
{% column %}
ISO 9564
{% endcolumn %}

{% column %}
Requisitos de segurança e gerenciamento para proteção e processamento de blocos de PIN.
{% endcolumn %}
{% endcolumns %}

{% columns %}
{% column %}
AES & ECC
{% endcolumn %}

{% column %}
Algoritmos nativos escaláveis de alta entropia para criptografia simétrica e acordo de chaves.
{% endcolumn %}
{% endcolumns %}

### Como Navegar por esta Documentação?

Para facilitar sua jornada de integração, estruturamos este portal de forma progressiva. Recomendamos seguir a ordem abaixo para realizar o provisionamento do seu ambiente:

* HoP KMS - v1 > v2: Entenda as mudanças de arquitetura da nova versão e por que a v2 é muito mais segura e aderente às regras do PCI.
* Introdução e Fundamentos: Conceitos essenciais sobre criptografia de curvas elípticas, DUKPT, KSN e blocos TR-31.
* Fluxo DUKPT: O passo a passo visual e descritivo de como sua aplicação e o dispositivo final interagem com o HoP KMS.
* Referência da API - Key Derivation: O contrato técnico completo do endpoint de derivação, incluindo payloads de requisição e resposta.
* Erros e Troubleshooting: Guia de apoio para depuração de erros e testes de integração.


# HoP KMS - v1 > v2

Esta página detalha a evolução da nossa arquitetura de gerenciamento de chaves da versão v1 para a v2, os motivos de segurança que impulsionaram essa mudança e o impacto direto na integração do seu sistema.

### 1. Visão Geral da Mudança

Até a versão v1, o processo de derivação de chaves do HoP KMS entregava ao cliente final as chaves de transação prontas (*Working Keys* como a *PIN Encryption Key*, *Data Decryption Key*, entre outras).

Na versão v2, o HoP KMS adota o padrão estrito de segurança DUKPT (AES) em conformidade com as normas do PCI. Em vez de expor chaves de sessão individuais, a API da v2 agora entrega exclusivamente a IKEY (Initial Key) protegida por um envelope criptográfico seguro no formato TR-31 Key Block.

### 2. Comparativo de Arquitetura

Para entender o impacto prático dessa transição, veja abaixo como as duas versões se comportam em relação à entrega e ao ciclo de vida das chaves:

#### 2.1 Fluxo na v1 (Modelo Anterior)

Na v1, o servidor de chaves calculava toda a árvore de derivação e entregava à sua aplicação um conjunto de chaves de sessão específicas para aquela transação:

<figure><img src="/files/nzD8H9b183NMtvPgGcDF" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Vulnerabilidade: Trafegar e armazenar chaves de sessão prontas (principalmente chaves de PIN e de dados sensíveis) no servidor da aplicação aumenta significativamente a superfície de ataque e viola diretamente as regras de segurança do PCI-DSS e PCI-PIN, mesmo cifradas.
{% endhint %}

#### 2.2 Fluxo na v2 (Modelo Atual)

Na v2, o HoP KMS atua como um distribuidor de chaves de partida seguras. Ele gera e entrega apenas a IKEY protegida por um Key Block. A partir dela, o terminal ou o sistema de destino realiza a derivação das chaves de trabalho localmente:

<figure><img src="/files/tpnM84MOFwYvg5nahmA3" alt=""><figcaption></figcaption></figure>

### 3. Matriz de Diferenças Técnicas

| **Métrica**              | **Versão v1 (Legada)**                       | **Versão v2 (Atual)**                                                                 |
| ------------------------ | -------------------------------------------- | ------------------------------------------------------------------------------------- |
| Chave Entregue           | Múltiplas chaves de sessão (*Working Keys*). | Apenas a IKEY (Initial Key / IPEK).                                                   |
| Formato de Entrega       | String Hexadecimal proprietária.             | TR-31 Key Block (Criptografia AES padrão internacional).                              |
| Cálculo de Derivação     | Executado inteiramente no servidor KMS.      | Executado no dispositivo final (mPOS/COTS) a partir da IKEY conforme regras PCI MPoC. |
| Conformidade Regulatório | Parcialmente aderente ao PCI MPoC.           | 100% aderente ao PCI MPoC e ANSI X9.24-3.                                             |
| Segurança de Tráfego     | Chaves de uso sensível expostas no payload.  | Chave inicial envelopada com metadados e restrição de uso.                            |

### 4. Por que essa mudança é obrigatória para o seu negócio?

Se o seu produto lida com captura de transações em dispositivos móveis (smartphones, tablets ou POS), a adequação à v2 é essencial pelos seguintes fatores:

1. Adequação aos requisitos MPoC: Os normativos do PCI estabelecem que dispositivos comerciais (COTS) precisam isolar as chaves de transação. A entrega da IKEY permite que o seu aplicativo móvel utilize as APIs nativas do dispositivo seguro para derivar chaves dinâmicas sem nunca expor a chave mestre (BDK).
2. Uso de Key Blocks TR-31: O formato TR-31 não é apenas um algoritmo de criptografia, mas um mecanismo de blindagem. Ele impede o ataque de substituição de chaves, garantindo que uma chave destinada à decifragem de dados nunca possa ser usada, por exemplo, para decifrar uma senha (PIN).
3. Redução do Escopo de Auditoria (QSA): Ao remover o armazenamento e o tráfego de chaves de transação descriptografadas do seu servidor back-end, o escopo da auditoria PCI-DSS da sua empresa é drasticamente reduzido, economizando tempo e recursos de infraestrutura.


# Autenticação (OAuth2)

A segurança é a base do **HoP KMS**. Como lidamos com operações criptográficas e dados sensíveis, todas as requisições aos nossos serviços devem ser obrigatoriamente autenticadas.

Para facilitar sua integração e garantir o mais alto nível de segurança, utilizamos o padrão de mercado **OAuth2** (gerenciado via Auth0).

Nesta seção, você aprenderá como obter suas credenciais, gerar um token de acesso (`access_token`) e como enviá-lo corretamente no cabeçalho das suas requisições.

{% hint style="warning" %}
Atenção: Suas credenciais (`client_secret`) e seus tokens de acesso dão poder total sobre o seu ambiente criptográfico. Nunca exponha esses dados no front-end (navegadores ou aplicativos móveis) ou em repositórios públicos (como o GitHub).
{% endhint %}

***

### O Protocolo OAuth2 (M2M)

A HoP KMS utiliza o padrão **OAuth2** através do fluxo de **Client Credentials** (Credenciais de Cliente).

Como a nossa infraestrutura foi desenhada para operações de backend (comunicação de servidor para servidor), este é o fluxo ideal para interações **Máquina-a-Máquina (M2M)**. Ele permite que a sua aplicação se autentique de forma autônoma e contínua, sem a necessidade de intervenção humana (como telas de login de usuários).

Essa abordagem garante o isolamento total da sua aplicação e a proteção dos dados durante operações criptográficas críticas, mantendo a sua integração em total conformidade com as normas de segurança do mercado.

### Obtenção de Credenciais (Webadmin)

Para se comunicar com o HoP KMS, sua aplicação precisará de duas chaves exclusivas: um **`Client_Id`** e um **`Client_Secret`**.

Por questões de segurança e controle de acesso, essas credenciais **não são geradas dinamicamente via API.**

{% hint style="warning" %}
**Pré-requisito Obrigatório:**\
Antes de prosseguir com qualquer teste ou integração, acesse a plataforma Webadmin (nosso portal de gestão de chaves) para provisionar e validar as suas credenciais. A geração do token de acesso não funcionará sem este passo.
{% endhint %}

### Endpoints de Autenticação (Auth0)

Para gerar o seu token de acesso, você fará uma requisição <mark style="color:green;">**`POST`**</mark> para o nosso servidor de autorização.

Lembre-se da regra de ouro: as credenciais geradas no **Webadmin no Ambiente de Testes** só funcionam na URL de Homologação, e as credenciais do **Webadmin de Produção** só funcionam na URL de Produção.

Utilize o endpoint correspondente ao seu ambiente:

{% tabs %}
{% tab title="🧪 Ambiente de Homologação" %}

```http
https://first-tech-teste.us.auth0.com/oauth/token
```

{% endtab %}

{% tab title="🚀 Ambiente de Produção" %}

```http
https://auth.first-tech.net/oauth/token
```

{% endtab %}
{% endtabs %}

### Parâmetros da Requisição (Payload)

A solicitação do token deve ser enviada via método <mark style="color:green;">**`POST`**</mark>. O corpo da requisição (body) deve conter os seguintes parâmetros no formato JSON:

`client_id` · *<mark style="color:blue;">string</mark>* · **Obrigatório** &#x20;

O identificador único da sua aplicação. Você deve obter este valor no painel do Webadmin.

`client_secret` · *<mark style="color:blue;">string</mark>* · **Obrigatório** &#x20;

A chave secreta da sua aplicação, também obtida no Webadmin. Nunca exponha este valor.

`audience`  · *<mark style="color:blue;">string</mark>* · **Obrigatório** &#x20;

O identificador único do recurso (API) que você deseja acessar.

*Homologação:* "audience": "<https://auth0-jwt-authorizer>",

*Produção:* "audience": "<https://auth-jwt-authorize-prd-first-tech>",

{% hint style="warning" %}
**Atenção ao campo** `audience`

O valor deste campo muda de acordo com o ambiente. Se você usar o `audience` de Sandbox apontando para a URL de Produção (ou vice-versa), o Auth0 emitirá um token inválido e suas chamadas ao HoP API serão rejeitadas. Confirme o valor correto no Webadmin.
{% endhint %}

`grant_type`  · *<mark style="color:blue;">string</mark>* · **Obrigatório** &#x20;

Define o fluxo de autenticação. Para interações máquina-a-máquina, deve ser estritamente: *client\_credentials*

### Exemplo de Requisição

Abaixo, apresentamos a estrutura da chamada. Lembre-se de configurar o cabeçalho `Content-Type` como `application/json` e substituir os valores de exemplo pelas suas credenciais reais obtidas no painel do Webadmin.

{% tabs %}
{% tab title="cURL" %}

```bash
curl --request POST \
  --url https://first-tech-teste.us.auth0.com/oauth/token \
  --header 'Content-Type: application/json' \
  --data '{
    "client_id": "SEU_CLIENT_ID_AQUI",
    "client_secret": "SEU_CLIENT_SECRET_AQUI",
    "audience": "https://auth0-jwt-authorizer",
    "grant_type": "client_credentials"
  }'
```

{% endtab %}

{% tab title="HTTP (Raw)" %}

```http
POST /oauth/token HTTP/1.1
Host: first-tech-teste.us.auth0.com
Content-Type: application/json

{
  "client_id": "SEU_CLIENT_ID_AQUI",
  "client_secret": "SEU_CLIENT_SECRET_AQUI",
  "audience": "https://auth0-jwt-authorizer",
  "grant_type": "client_credentials"
}
```

{% endtab %}
{% endtabs %}

### Resposta de Sucesso

Se as credenciais estiverem corretas, o servidor retornará um status <mark style="color:$success;">**`200 OK`**</mark>. O corpo da resposta conterá o seu token de acesso (JWT) e o tempo de validade dele em segundos.

```json
{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6...",
  "token_type": "Bearer",
  "expires_in": 86400
}
```

{% hint style="success" %}
**Melhor Prática: Faça cache do seu Token**

Para garantir altíssimo desempenho e evitar latência nas suas transações, **não gere um novo token a cada requisição.**

O valor retornado em `expires_in` (ex: 86400 segundos = 24 horas) indica quanto tempo essa chave é válida. A estratégia correta é salvar o `access_token` na memória da sua aplicação (cache) e reutilizá-lo em todas as chamadas ao HSM, solicitando um token novo apenas quando o atual estiver a poucos minutos de expirar. Isso também evita que você seja bloqueado por excesso de chamadas (*Rate Limiting*).
{% endhint %}


# Introdução e Fundamentos

Esta página apresenta os conceitos de criptografia e gerenciamento de chaves que fundamentam o funcionamento do HoP KMS v2. Compreender esses pilares é essencial para garantir uma integração segura e em conformidade com as exigências do PCI (como o PCI-MPoC).

### 1. O Padrão DUKPT (AES)

O DUKPT (*Derived Unique Key Per Transaction*) é o padrão ouro na indústria de meios de pagamento para a proteção de transações financeiras. O seu principal objetivo é mitigar o impacto de vazamentos: se um invasor conseguir comprometer a chave de uma transação específica, ele não terá acesso às transações anteriores nem às futuras.

No HoP KMS v2, utilizamos a especificação AES DUKPT conforme a norma ANSI X9.24-3-2017.

#### Componentes Principais do DUKPT

* **BDK (Base Derivation Key):** Chave simétrica mestra custodiada com segurança máxima dentro do HSM do HoP KMS. Criada através de cerimonial de chaves, nunca é exposta fora do ambiente seguro e serve como raiz de confiança para a derivação de chaves filhas.<br>
* **IKEY / IPEK (Initial Key / Initial PIN Encryption Key)**: Chave inicial do terminal, derivada diretamente da BDK a partir do KSI do dispositivo. O HoP KMS v2 retorna esta chave para que a aplicação realize o provisionamento seguro do mPOS/PINpad.<br>
* **KSI (Key Set Identifier)**: Identificador estático do dispositivo e da família de chaves. No padrão AES / Key Block (ANSI X9.143 / TR-31), possui 16 caracteres hexadecimais (8 bytes / 64 bits) e é estruturado como:\
  \
  $$\text{KSI} = \text{BDK ID} \parallel \text{Device ID}$$<br>
  * **BDK ID** (4 bytes / 8 hex): Identifica a BDK mestre no HSM para roteamento da transação e segmentação de segurança por cliente ou produto.
  * **Device ID** (4 bytes / 8 hex): Identifica univocamente o terminal físico (TRSM) ou aplicação móvel.<br>
* **KSN (Key Serial Number)**: Identificador único enviado a cada transação para indicar ao HSM qual chave individual utilizar no desacoplamento da mensagem. No padrão AES DUKPT, possui 24 caracteres hexadecimais (12 bytes / 96 bits) e é formado pela junção do KSI estático ao contador dinâmico:

  \
  $$\text{KSN} = \text{KSI} \parallel \text{Transaction Counter}$$<br>

  * **KSI** (8 bytes / 16 hex): Bloco estático de identificação da BDK e do dispositivo.
  * **Transaction Counter** (4 bytes / 8 hex): Contador incremental que muda a cada operação, garantindo o princípio DUKPT (*Derived Unique Key Per Transaction*).

### 2. O Papel da IKEY (Initial Key)

Diferente do modelo v1 (onde o servidor KMS entregava chaves de sessão prontas para a aplicação), a versão v2 foca no fornecimento seguro da IKEY.

> 💡 Por que a IKEY é suficiente?
>
> A partir do momento em que o terminal mPOS (ou o seu ecossistema seguro de destino) recebe a IKEY e o KSN inicial, ele possui capacidade matemática de calcular de forma autônoma e offline todas as chaves de transação futuras (*Working Keys*).

Sempre que uma nova transação é realizada, o terminal incrementa o seu *Transaction Counter* (presente no KSN) e utiliza o algoritmo DUKPT local para derivar uma chave de uso específico para aquela operação, seja para criptografia de PIN, criptografia de dados confidenciais ou autenticação de mensagens (MAC).

### 3. Envelopamento com TR-31 Key Blocks

Para que a IKEY seja transmitida pela rede sem o risco de interceptação ou manipulação de finalidade, o HoP KMS v2 adota o formato de Key Blocks TR-31 (definido pela norma ANSI X9.143).

O TR-31 é uma estrutura que envolve a chave criptográfica em um envelope seguro composto por três partes:

<figure><img src="/files/P7U9g5dyJCub9Uxgavl5" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/qPOdeXq1nf2DQLF8REtT" alt=""><figcaption></figcaption></figure>

### 4. Acordo de Chaves Híbrido (ECDH P-521)

A transmissão segura do TR-31 contendo a sua IKEY exige uma chave de criptografia de transporte exclusiva e dinâmica. Para isso, o HoP KMS implementa o algoritmo Elliptic Curve Diffie-Hellman (ECDH) sob as curva de alta segurança P-256, P-384 ou P-521.

O fluxo matemático para estabelecer o canal seguro ocorre da seguinte forma:

1. Sua aplicação gera um par de chaves efêmeras ECC (Privada $$d\_A$$ e Pública $$Q\_A$$).
2. Ao chamar a API, você envia sua chave pública $$Q\_A$$ no parâmetro `keyPublic`.
3. O HoP KMS gera seu próprio par efêmero (Privada $$d\_B$$ e Pública $$Q\_B$$).
4. Ambos os lados calculam independentemente o ponto compartilhado secreto $$S$$ através da multiplicação de pontos na curva elíptica:

<p align="center"><span class="math">S = d_A \cdot Q_B = d_B \cdot Q_A</span></p>

5. Esse ponto secreto $$S$$ passa por uma Função de Derivação de Chave (KDF) para gerar a ZMK efêmera (uma chave simétrica AES-256 temporária).
6. O HoP KMS cifra a IKEY dentro do TR-31 utilizando esta ZMK efêmera e envia o resultado no payload.
7. Sua aplicação, tendo calculado o mesmo segredo $$S$$, decifra o TR-31 localmente e recupera a IKEY com segurança absoluta.


# Fluxo transacional - DUKPT

Esta página detalha o fluxo completo de ponta a ponta da nossa arquitetura. O ciclo de vida do gerenciamento de chaves no HoP KMS v4 é dividido em duas fases distintas: Fase 1: Provisionamento (Inicialização do Dispositivo) e Fase 2: Transacional (Operação do Dispositivo).

### 1. Visão Geral das Fases

Para garantir a máxima proteção dos dados transacionais, dividimos a responsabilidade criptográfica entre o servidor seguro (KMS) e o dispositivo final de captura (mPOS/COTS)

1. FASE 1: PROVISIONAMENTO (Ocorre uma única vez): O HoP KMS gera e entrega a IKEY de forma segura ao cliente.
2. FASE 2: TRANSACIONAL (Ocorre a cada transação): O dispositivo deriva suas próprias chaves para cifrar dados e o servidor as re-deriva internamente para decifrar.

### 2. Fase 1: Provisionamento (Carga da IKEY)

Esta fase é executada quando o dispositivo de captura precisa ser inicializado ou quando o seu contador de transações do KSN atinge o limite máximo e uma nova semente criptográfica precisa ser injetada.

#### Diagrama de Sequência: Provisionamento Seguro

<figure><img src="/files/KwmSXRhbjFulTa5UA7ka" alt=""><figcaption></figcaption></figure>

#### Detalhamento dos Passos:

1. Solicitação do Terminal: O dispositivo de captura (mPOS) solicita sua semente criptográfica ao back-end da sua aplicação.
2. Preparação do Back-end: O seu back-end gera um par de chaves efêmeras ECC sob a curva P-521 (Privada $$d\_A$$ e Pública $$Q\_A$$).
3. Chamada ao KMS: O seu back-end envia uma requisição `POST` para o endpoint `/v4/keyDerivation` contendo a sua chave pública $$Q\_A$$, o KSN de inicialização do terminal e o alias da BDK a ser utilizada.
4. Segurança no KMS:
   * O KMS realiza o cálculo do acordo de chaves Diffie-Hellman (ECDH) para gerar a chave de criptografia de transporte (ZMK efêmera).
   * O KMS deriva a IKEY a partir da BDK e do KSN informados.
   * A IKEY é encapsulada em um Key Block TR-31 e cifrada com a ZMK efêmera.
   * O KMS gera uma assinatura digital (ECDSA) sobre o pacote para garantir que a resposta não seja alterada.
5. Decifração no Back-end: Seu back-end recebe a resposta, valida a assinatura do KMS, realiza o acordo ECDH localmente para obter a mesma ZMK efêmera, decifra o Key Block TR-31 e obtém a IKEY limpa.
6. Injeção no Dispositivo: Seu back-end transfere a IKEY e o KSN inicial para o dispositivo de captura através de um canal seguro local de injeção.

### 3. Fase 2: Fluxo Transacional (Operação Offline)

Uma vez provisionado com a IKEY e o KSN inicial, o dispositivo de captura (mPOS) não precisa mais consultar o HoP KMS para realizar transações. Ele é capaz de operar de forma autônoma. o HoP API é capaz de reconstruir a IKEY e validar o PIN/dado gerado pelo dispositivo mPOS - <https://ftcoders.first-tech.com/hop-api/modulo-pin/referencia-api-pin>

#### Diagrama de Sequência: Autorização de Transação

<figure><img src="/files/xzXmWCzicOmclFZy162O" alt=""><figcaption></figcaption></figure>

#### Detalhamento dos Passos:

1. Derivação no Terminal: No momento da transação, o dispositivo utiliza o algoritmo DUKPT interno para calcular a chave de transação específica (*Working Key*) usando a semente IKEY e o contador atual do KSN.
2. Criptografia do Payload: O dispositivo cifra o PIN ou os dados confidenciais do cartão com a chave recém-derivada e, em seguida, incrementa o contador do KSN, inutilizando a chave utilizada.
3. Envio ao Back-end: O dispositivo envia para o seu back-end os dados criptografados junto com o KSN utilizado naquela transação.
4. Descriptografia Segura: Ao receber a transação, o seu back-end envia o payload criptografado e o KSN para o HoP API.
5. Processamento no Hardware Seguro (HSM): O HSM do HoP API utiliza a BDK (que nunca saiu de lá) e o KSN recebido para recalcular exatamente a mesma chave usada pelo terminal naquela transação. O HSM decifra o payload ou valida o PIN dentro de sua memória segura e retorna apenas o resultado para o seu back-end.

> 📌 A Regra de Ouro do DUKPT Note que as chaves de transação (*Working Keys*) são geradas pelo terminal de um lado, reconstruídas pelo HSM do outro, e nunca trafegam em canais abertos nem são expostas ao servidor de aplicação. Isso garante a conformidade absoluta com as normas internacionais de segurança de pagamentos.


# Referência da API - Key Derivation


# Erros, Troubleshooting e Apêndices


# Introdução e Fundamentos

Esta página apresenta os conceitos fundamentais de aleatoriedade criptográfica, entropia e conformidade de segurança que sustentam o funcionamento do Módulo Nonce Generator do HoP KMS.

### 1. O que é um Nonce?

Na criptografia, um Nonce (*Number used once*) é um número aleatório ou pseudoaleatório que deve ser utilizado apenas uma única vez em um processo de comunicação segura.

Sua principal finalidade é garantir a unicidade e impedir ataques de repetição (replay attacks), onde um atacante intercepta um pacote legítimo e tenta reenviá-lo ao servidor para replicar uma ação (como uma transação financeira).

### 2. A Importância da Alta Entropia

A força de qualquer algoritmo de segurança depende diretamente da imprevisibilidade dos seus segredos gerados.

* Geradores de Software (PRNG): A maioria dos servidores comuns utiliza geradores de números pseudoaleatórios por software. Eles dependem de algoritmos determinísticos e de sementes baseadas em variáveis do sistema (como relógios). Sob análise matemática pesada ou estresse de carga, esses geradores podem se tornar previsíveis.
* Geradores de Hardware (TRNG): O HoP KMS utiliza o hardware físico do HSM (Hardware Security Module) para coletar ruído térmico e fenômenos físicos imprevisíveis. Isso garante uma entropia máxima (aleatoriedade real), tornando impossível prever o próximo número gerado, mesmo conhecendo-se as saídas anteriores.

### 3. Certificação FIPS: O Padrão de Ouro

O módulo de geração de números aleatórios do HoP KMS opera dentro do núcleo criptográfico do HSM, que é rigorosamente certificado sob os padrões FIPS (Federal Information Processing Standards).

Essa certificação internacional garante que o hardware passou por testes de estresse matemático e físico extremos, validando que os números gerados não possuem padrões lógicos e são verdadeiramente aleatórios.

### 4. Casos de Uso Comuns

O gerador de nonces do HoP KMS foi desenhado para apoiar o seu sistema nos seguintes cenários:

* Sais Criptográficos (Salts): Geração de valores aleatórios para serem concatenados a senhas antes do processo de hash, impedindo ataques de dicionário e tabelas de arco-íris (*rainbow tables*).
* Vetores de Inicialização (IV): Valores necessários para iniciar processos de criptografia simétrica (como AES em modo CBC ou GCM) de forma segura.
* Desafios (Challenges): Criação de tokens únicos para fluxos de autenticação de dois fatores ou assinaturas de mensagens transacionais.


# Referência da API - Nonce Generator


# Erros, Troubleshooting e Apêndices


# Welcome to First Code

This page contains the introduction for the First Tech TTP SDK

The First Tech Tap to Phone SDK, or simply the SDK, is an Android library designed to securely access the operating system and memory structures, enabling the reading of credit and debit card data—whether from physical cards or digital wallets using contactless technology. By handling the technical complexities of the payments ecosystem, the SDK allows developers to focus on creating a smooth, secure, and efficient checkout experience, with fast integration and lower costs.

Currently, the SDK supports **VISA**, **Mastercard**, and **Elo**, and can be used to develop dedicated payment capture apps or integrate directly into business applications that benefit from open payment networks.

This document is here to help developers troubleshoot errors and issues that may arise when using the SDK. It provides detailed explanations and step-by-step solutions for each identified error. While we've covered most cases, some edge scenarios may still emerge. As new issues are reported by customers and become relevant to the product, they will be added to this documentation.

### Who is this page for?

This page is intended for developers and support teams handling customer-reported issues during coding, deployment, or operation of the product.

### Jump right in

<table data-view="cards"><thead><tr><th></th></tr></thead><tbody><tr><td>Specifications &#x26; Capabilities</td></tr><tr><td>Best Practices &#x26; Requirements for Secure Integration</td></tr><tr><td>Prerequisites &#x26; Requirements</td></tr><tr><td>End-to-End Flow</td></tr><tr><td>Distinguishing Environments: Staging vs. Production</td></tr><tr><td>For Developers: Setting Up the Environment to Get Started</td></tr><tr><td>SDK Calls &#x26; Integration Guide</td></tr><tr><td>Capturing Errors in the Application</td></tr><tr><td>Instructions for Deploying the App to Production</td></tr><tr><td>Glossary of Payment Industry Terms</td></tr><tr><td>Resolving Issues in Testing and Production</td></tr><tr><td>Device Handling Best Practices</td></tr></tbody></table>


# Specifications & Capabilities

This page describe all the features and capabilities for the First Tech TTP SDK

### Product Features

Below are the key features of the product, covering hardware, software, certifications, and applicable business use cases:

<details>

<summary>Hardware</summary>

* **Supported Devices**: No restrictions, as long as the device has an active NFC chip.
* **Operating Systems**: Android (iOS support available upon request).
* **NFC Requirement**: NFC must be enabled for reading and transmitting payment data. Any smartphone with an active NFC chip can use the product, regardless of the manufacturer.
* **TEE or Secure Element**: The smartphone must have a dedicated processor or a security chip for cryptographic key management. This is required to use Android Keystore and Key Attestation APIs. Any Android device running version 10 or later with Google Play Store access meets these requirements.
* **Chip & Magnetic Stripe Reading**: The SDK does not support chip or magnetic stripe card readers. Only contactless-enabled cards can be used.
* **Network Connectivity**: Requires Wi-Fi or mobile data with at least 3G coverage for terminal activation and transaction processing.

</details>

<details>

<summary>Software</summary>

* **Programming Languages**: The SDK is developed in Java but can be used with hybrid technologies such as React Native, Flutter, or any language that supports native library bridging.
* **Mandatory permissions for the apps builded with SDK**:&#x20;
  * **(NFC)** android.Manifest.permission.NFC
  * **(Vibrate)** android.Manifest.permission.VIBRATE
  * **(Internet)** android.permission.INTERNET
  * **(Network State)** android.permission.ACCESS\_NETWORK\_STATE
  * **(Notification Policy)** android.permission.ACCESS\_NOTIFICATION\_POLICY
* **Minimum Android Version**: Android 10 or later.
* **Android API:** Level 29 or later.
* **Google Play Services Version**: Play Services 11 or later.

</details>

<details>

<summary>Permissions</summary>

Required permissions

```
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.NFC"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

```

</details>

<details>

<summary>Certifications</summary>

**Security & Compliance**: PCI HSM, PCI PIN, PCI DSS, PIN on Glass, Visa Security 1.8.1, MPOC 1.1, ISO 27001.

</details>

<details>

<summary><strong>Usage Restrictions in Production</strong></summary>

The SDK will not function on smartphones that:

* Have **jailbreak/root mode enabled**.
* Have **developer options enabled** (debug mode).
* Have **malicious apps installed**.
* Have **any debugger connected**.
* Have **manual date and time settings** (must be set to automatic).
* Have the app **installed from sources outside Google Play**.

</details>

<details>

<summary>SDK Capabilities</summary>

* **Terminal Creation**: The terminal is automatically created when a transaction request is initiated. A security check is performed to ensure system integrity before terminal creation.
* **Session Creation**: A session is automatically created upon a new transaction request. The terminal runs a full security validation with the central server before processing any transaction.
* **Transaction Processing**: Supports **credit (single and installment payments) and debit** transactions.
* **Prepayment Support**: **Not provided** by the SDK.
* **Instant Refunds (D0)**: **Not provided** by the SDK.
* **Refunds (D+1 or later)**: Can be processed via API or through the acquiring bank.

</details>

<details>

<summary>Use Cases</summary>

* **Mobile POS**: A new application must be developed using the SDK. User control, business logic, CNPJ context switching, additional payment method integrations, UI customization, and other specific functionalities must be implemented by the company using the SDK.
* **Online-to-Offline Transaction Transfers (E-commerce)**: The application must be developed with approval from the participating card networks under the Tap to Everything / Tap to Own Device program. Merchants’ reports must be submitted monthly, and adjustments to ISO 8583 messaging must be made to properly flag transactions that originated online but were processed offline.
* **Prepayment Support**: If embedded within an app, the SDK can capture prepayments. The **prepayment mode must be communicated to the payment gateway**, and the acquiring bank must provide methods for modifying, canceling, or converting prepayments into standard payments.
* **User Identification via Card**: NFC-captured data can be used to create a **fingerprint of the credit card** and link it to a customer database. This enables the SDK to **identify users** beyond just payment collection, facilitating loyalty program integration and improving login flows where traditional authentication is ineffective.
* **Tap to Fill & Digital Wallet Enrollment**: In digital wallet or e-commerce apps, NFC technology can automatically capture the **card number and expiration date**, simplifying the checkout process and eliminating manual entry—similar to scanning a credit card using a camera.

</details>


# Key Questions for Customer Onboarding

This contains a list of questions that is important to be asked about the App usage

Below is a list of essential questions that should be discussed with the client during the onboarding and credentialing process. These questions help establish a clear understanding of the project requirements before development begins, making them an excellent starting point for aligning expectations and defining the development scope:

<details>

<summary>Question: What is the operating system and the minimum Android version supported by your TTP application?</summary>

The security certifications of the devices, in compliance with card networks and PCI regulatory bodies, certify the SDK to operate only on Android versions 10 or higher.

</details>

<details>

<summary>Question: Do the devices have an NFC chip?</summary>

To use applications that enable contactless payments, the mobile device must support **NFC Technology**. This technology allows communication between the device and credit/debit cards or digital wallets that also have NFC capabilities.

To check if a mobile device has NFC functionality, refer to the **technical specifications** on the manufacturer’s website or the product manual. If you have the device in hand, go to the **Settings app** and search for "NFC." If the option appears, the feature is installed and ready for use.

</details>

<details>

<summary>Question: Does the App require physical reading of the card's chip or magstripe?</summary>

This SDK reads data exclusively via contactless (NFC) and is not compatible with chip or magnetic stripe reading. For these functionalities, you can combine this SDK with other payment industry SDKs that integrate with Android, such as those from TecToy or Gertec. In this case, the external SDK is responsible for handling communication with the chip or magstripe.

</details>

<details>

<summary>Question: What type of network connectivity is available in the region where these applications will be used? (Wi-Fi/Cellular)</summary>

Although Android manages both Wi-Fi and mobile data connections, this SDK has been designed and tested for 3G or higher networks. Performance on slower networks (2G/EDGE) should be evaluated and tested by the developer based on the application's requirements.

</details>

<details>

<summary>Question: What programming language is used in the app that will integrate the TTP SDK?</summary>

The SDK was developed in Java/Kotlin but is also compatible with hybrid languages like React Native, which, through a feature called 'bridge,' allows communication with code written in other languages. It is important to note that using languages without this 'bridge' functionality or newly released ones, such as .NET MAUI, may lead to unexpected behavior in the SDK. We recommend informing the client about this potential issue at the beginning of the negotiation.

To facilitate integration, we provide example applications that demonstrate how the SDK works in different scenarios. These examples are available at the start of the onboarding process, along with implementation guidelines.

</details>

<details>

<summary>Question: Will the application run on devices with root access, alongside apps installed from external sources (outside Google Play), or with apps in debugger mode?</summary>

To ensure transaction security, the SDK will not function on smartphones that:

* **Have Jailbreak/Root access enabled**: This compromises system security and increases the risk of malicious apps gaining access.
* **Have developer tools enabled**: Debug mode can expose the device to vulnerabilities.
* **Have malicious apps installed**: Such apps may interfere with the SDK’s operation and attempt to steal data.
* **Have any debugger connected**: Debuggers can be used to manipulate the application and the SDK.
* **Have manually set date and time**: Correct date and time settings are crucial for transaction validation.
* **Have the app installed or downloaded from sources outside Google Play**: Apps from external sources may not be secure.

In these cases, the SDK will **not** be activated, as the device integrity verification process will detect security risks.

</details>

<details>

<summary>Question: Which card brand will you process? What payment methods will be accepted?</summary>

The SDK processes **credit (single payment and installments) and debit transactions** for **Visa, Mastercard, and Elo** card networks. Transactions via **digital wallets** (Google Pay, Apple Pay, and Samsung Pay) are also supported, as long as the linked cards belong to these networks.

To integrate **Pix** and other payment methods (such as bank slips and wire transfers), use the **acquirer’s API**. This direct integration provides greater flexibility for implementation and allows the acquirer to customize payment flows.

</details>

<details>

<summary>Question: Does the app have any restrictions regarding being instantiated from the Application class in Android?</summary>

* **Following MPOC security standards (PCI regulation for this product), the SDK cannot be integrated with other applications or SDKs**—it must remain isolated.
* **This restriction prevents unauthorized instantiation**, ensuring that other classes cannot initialize the SDK partially, incompletely, or without authorization. This maintains the principle of isolation, prevents security vulnerabilities, and preserves the product's existing certification (ensuring compliance with the certified flow).
* **By being instantiated in the main application class, the SDK benefits from a longer lifecycle compared to other Activities and Fragments**. This guarantees that initialization occurs only once, encryption processes are not lost between screens or activities, and application integrity monitoring covers the entire application scope.

</details>


# Best Practices & Requirements for Secure Integration

Developing applications with the **Tap to Phone SDK** requires a **strategic and meticulous approach**, as it is directly tied to the **payments industry**—a sector known for its strict regulations, high security standards, and certifications. These requirements are essential to **ensure reliability against fraud and system failures**. It is therefore crucial for developers to **carefully follow the provided recommendations**, ensuring that the development process **complies with both technical and regulatory requirements**. Managing the mobile computing environment plays a key role in **preventing vulnerabilities and protecting the integrity of each transaction**.

To support this process, this documentation provides **detailed guidelines on using the SDK**, along with best practices and mandatory requirements that must be followed. These elements help **minimize risks while maximizing the security and efficiency** of the application. Adhering to these guidelines ensures a **secure and reliable payment experience**, adding value to the market by delivering a **high-quality and compliant product**.

Developing a payment app that meets **Visa Tap to Phone** and **Mastercard Tap on Phone** certifications **goes beyond standard development concerns**, requiring heightened attention to security standards. These certifications include compliance with **EMVCo rules for encryption, key management, and contactless communication**, as well as adherence to **PCI DSS regulations**. Each card network imposes **specific security, transaction processing, and user interface requirements**, making it essential for developers to understand these demands **before starting the project**. **Incorporating security from the start helps avoid rework and potential certification issues**.

Even when using a certified SDK, developers must ensure:

* **Correct SDK integration**: Follow the implementation instructions without modifications and always use the latest SDK versions.
* **Application security**: Implement additional protections such as **code obfuscation, requesting configuration files or parameters via API (instead of using hardcoded values that can be intercepted or modified)**, follow **secure development practices (OWASP)**, and adopt other security measures to **prevent malicious application tampering**.
* **Transaction processing**: Implement **anti-fraud mechanisms and audit logs**, as well as monitoring services to detect **exceptions, transaction delays, conversion rate drops, and activation tracking of deployed applications**.
* **User interface**: Ensure an **intuitive, secure, and transparent** payment experience.
* **Security testing**: Perform **rigorous security tests** to identify and fix vulnerabilities in business processes. **Under no circumstances should the SDK be updated without extensive testing to ensure that the app’s core functionalities remain intact**. The **final responsibility for delivering a high-quality user experience lies with the developers maintaining the application**.
* **Regular updates**: To provide the **best experience and security for users**, we continuously update our applications to **comply with new regulations, laws, and security standards**. It is **essential to update the SDK at least every six months** to **keep fraud levels under control and access new features**. The **development company is responsible for managing version deprecation and device deactivation**, ensuring that outdated and potentially vulnerable versions remain **under control**.
* **Clear communication**: Inform users about **security measures** and maintain an **accessible privacy policy**.


# End-to-End Flow

The SDK operates in **five key stages**. Understanding each stage is essential to ensure **a smooth integration, efficient troubleshooting, and a seamless payment experience**:

### The SDK Steps

{% stepper %}
{% step %}

### Terminal Initialization

The SDK performs a series of security checks to prepare the mobile device for a transaction. Errors at this stage are typically related to **device security**, with comprehensive verifications covering the **operating system status and hardware components**.\
\
**Responsible Parties:** Solution Developer and Product User.
{% endstep %}

{% step %}

### Session Initialization

After verifying the device's integrity, the application is validated through the **Google Play Integrity service**. This step ensures that the app remains **trusted** and was **downloaded from an authorized store** to process payments using our **Tap to Phone SDK**. Errors at this stage indicate **discrepancies between the declared information and the actual running code**. Once validated, the **transaction preparation process begins**.

**Responsible Parties:** Solution Developer and First Tech.
{% endstep %}

{% step %}

### Card Tap & Data Reading

The SDK is ready and waiting for the customer to **tap the card** and optionally **enter the PIN**. Potential errors at this stage may be related to:

* **Timeouts** when reading the card or digital wallet.
* **Security violations** in rendering the PIN entry screen.
* **Incorrect EMV tag configuration** for card data reading and transmission to the acquirer.

**Responsible Parties:** Solution Developer, SDK User, and First Tech.
{% endstep %}

{% step %}

### PIN Entry Device Generation

During card reading, with the transaction data already available, the SDK communicates with the **card chip** to determine whether **PIN entry is required**. If necessary, an **encrypted process** is triggered to generate a **secure digital PIN entry interface**, allowing the user to safely input their PIN.

It is important to note that this step is **optional** and depends on both the **transaction amount and the issuer's rules**. There is **no possibility of configuring parameters to force PIN entry**.

**Responsible Parties:** First Tech.
{% endstep %}

{% step %}

### Transaction Submission & Autorization

The transaction is sent to **backend services (outside the SDK)** and then forwarded to the **acquirer**, which is responsible for authorization.

Issues at this stage typically arise from:

* **Configuration mismatches** with the acquirer's authorization system.
* **Restrictions within the acquirer's ecosystem**.

In most cases, troubleshooting at this stage is the **acquirer's responsibility**. Once processing is complete, the SDK receives the **transaction response (approved or declined)** and forwards it to the application for display to the customer.

**Responsible Parties:** Acquirer and First Tech.
{% endstep %}
{% endstepper %}

### SDK Scopes

1. **The Device**

   The SDK is included as a dependency within the application, which, during its operation, initiates a **contactless financial transaction**, either via a physical card or a digital wallet. In this context, the objectives are:

   1. **Ensure that the application processes payments only in a secure environment**, free from security vulnerabilities, malicious software, or practices that compromise system integrity.
   2. **Collect transaction data**, including the **amount, payment type (credit or debit), number of installments (if applicable), and metadata** for the backend. This metadata consists of **information that the application wishes to send along with the transaction and receive back as part of the approval or cancellation response**.
   3. **Maintain a list of accepted products** and other **essential information** required to correctly interpret card data and relay it appropriately to the **acquirer**.

2. **Cloud-Based Contactless Kernel**

   After ensuring the **operating system's security at the device level**, the SDK requests a series of instructions from the **Cloud Contactless Kernel** to:

   1. **Verify if the application was downloaded from the Google Play Store**, ensuring it is **valid and authorized by the developer to operate with the First Tech TTP SDK**.
   2. **Provide the SDK authentication credentials** to the **cloud-based contactless kernel**, ensuring that the SDK is **running a valid and active version**.
   3. **Process transactions by encrypting card data and PINs** according to the security standards defined by **Visa Security 1.8.1 and MPOC**.

3. **First Tech Cloud**

   This layer acts as the **processing core of the TTP SDK**, responsible for:

   1. &#x20;**Updating and providing the SDK with a unified acquirer-specific table**, containing the necessary **card reading parameters** and the appropriate **data exchange interpretations for both physical cards and digital wallets**.
   2. **Receiving encrypted transactions and re-encrypting them in a secure environment**, following standards accepted by acquirers. In **Brazil**, these standards often differ from international **TTP technology protocols**, covering both **card data (number and expiration date) and PIN data**.
   3. **Routing transactions to the acquirer's native authorization environment**, performing **necessary field conversions and providing external feedback** to the SDK on the transaction status. This layer also enables **transaction recovery** in cases of **power or network failure**, restoring the **device state** when needed.

4. **Authorizer**

   This is the **acquirer's environment**, responsible for **receiving the transaction from the First Tech Cloud layer, executing the necessary operations to approve or decline the transaction, and returning the response**. This information is then sent **back to the First Tech Cloud layer, which forwards it to the contactless kernel layer, and finally, to the device layer**.

   This layer has the following responsibilities:<br>

   1. **Processing the transaction request** based on **anti-fraud rules, card network policies, and issuer requirements**, utilizing its **product and service ecosystem**.
   2. **Returning the final transaction status**, along with the **receipt and any additional details**, allowing the SDK to **relay this information to the application and manage the transaction lifecycle**.

### Roles & Stakeholders

The process involves **multiple participants**, each with specific responsibilities to ensure the **proper operation of the payment flow**:

* **Solution Developer**

  Responsible for **integrating the First Tech SDK** into their applications. This role includes:

  * **Registering the company with acquirers** and **developing the software** according to **security guidelines and First Tech documentation**.
  * **Ensuring the application remains updated** with the latest SDK versions and other technical requirements.
  * **Providing a seamless and reliable user experience**.
  * **Conducting extensive testing** to guarantee **security and performance**.
  * **Implementing logging and auditing mechanisms** for **business and payment transaction tracking.**

* **First Tech**

  Responsible for the **development, maintenance, and continuous updates** of the SDK, ensuring that it remains **certified and compliant** with industry **security and regulatory standards**. First Tech also:

  * **Incorporates new features** into the SDK.
  * **Maintains cloud services with high availability**.
  * **Performs proactive monitoring** to prevent failures.
  * **Provides technical support** to both developers and acquirers.
  * **Delivers educational materials**, such as tutorials and manuals, to assist in the efficient use of the solution.

* **Acquirer**

  The **company that processes and authorizes transactions**. In some cases, the acquirer also **redistributes the SDK** as a **white-label** solution for other companies. Its responsibilities include:

  * **Providing Level 1 support** to developers when redistributing the SDK.
  * **Ensuring transactions are processed in a resilient environment**.
  * **Investing in advanced anti-fraud solutions**.
  * **Managing integrations** with other players in the ecosystem, such as **issuers and card networks**, ensuring regulatory compliance.

* **Merchant (Business/Store)**

  The **point of sale or business** that **uses the solution** to accept payments. Their responsibilities include:

  * **Operating the application correctly**.
  * **Ensuring that devices are properly configured** according to technical requirements.
  * **Providing support to end users** during the payment process.
  * **Training staff** to use the system properly.
  * **Regularly checking** the condition of mobile devices.

* **Solution User (Customer)**

  These are the **customers making payments** using **cards or digital wallets**. They are responsible for:

  * **Correctly positioning their cards and NFC-enabled devices** on the readers at the right time and place.
  * **Entering the PIN correctly**, if required.
  * **Ensuring their cards are valid** and have **sufficient balance or credit limit**.


# Distinguishing Environments: Staging vs. Production

Are you supporting an application being developed in a **staging (testing) or production environment**? This distinction is **crucial**, as each environment has **different characteristics** and requires **specific strategies**. It impacts everything from **how the application handles errors** to **how logs are generated and retrieved**.

* **Staging Environment:** Ideal for **testing**, with a **lower security level** to facilitate **log analysis**. Additionally, it **does not require synchronization with Google Play**, allowing the application to be **installed directly from any .apk (Android installation package)**.
* **Production Environment:** **Mission-critical**, enforcing **additional rules and restrictions** to ensure **security and stability**.

When troubleshooting application issues, the **first step is identifying which environment the issue should be addressed in**.

### First Tech SDK Library Dependencies Behavior

First Tech provides **two library dependencies** within the same repository. To integrate them correctly, it is essential to **properly configure the group, library name, and version** in the project's package manager.

This applies regardless of the programming language (e.g., in Java, this would be within the **`build.gradle`** file). Proper configuration ensures that the package manager references the **appropriate library**.

The **reference below** serves as a **useful tool for correctly setting up both environments**.

<details>

<summary>Environment: Testing/Staging</summary>

Group Organization: com.first-tech

Library Name: taponphone-sdk-v2-hml

Version: 1.0.0 (20) or higher

Device Integrity Check: ✅ Yes

App Store Verification: ❌ No\
\
Logs: Detailed via **Android Studio** with the device connected to a computer\
\
Transaction Behavior: Reads card data **but does not send the transaction for acquirer authorization**. Instead, it returns an **emulated receipt**. Customer identification parameters in the request are **not validated**.

</details>

<details>

<summary>Environment: Production/Release</summary>

Group Organization: com.first-tech

Library Name: taponphone-sdk-v2-release

Version: 1.0.0 (20) or higher

Device Integrity Check: ✅ Yes

App Store Verification: ✅ Yes\
\
Logs: Via **redactable logs** using `logcat`\
\
Transaction Behavior: Reads card data **and submits it for acquirer authorization**. **Deducts funds** from the account or **reduces the available credit limit**. Returns a **real transaction receipt**. Customer identification parameters are **validated during authorization**.

</details>

Next, **search for or request** the following strings in the **dependency management settings** within the code or in the **log files**, looking for something similar to the examples below:

#### Example Reference in the Testing/Staging Environment:

```
com.first-tech:taponphone-sdk-v2-hml
```

#### Example Reference in the Production/Release Environment:

```
com.first-tech:taponphone-sdk-v2-release
```

### How to Identify

There are **different ways** to identify **which environment** the application is running in:

#### Method 1: Check the Dependency Manager Configuration File

Verify the **dependency manager configuration file** used in the programming language chosen for implementation.

For example, if the customer is using **Java or Kotlin DSL**, simply open the **`build.gradle`** file and check the **notations** (directives responsible for locating and including library dependencies during the application build process).

<pre><code><strong>dependencies {
</strong>    hmlImplementation(libs.taponphone.sdk.v2.hml)
    releaseImplementation(libs.taponphone.sdk.v2.release)
}
</code></pre>

Another example with Kotlin and Gradle Groovy DSL

```
dependencies {
    hmlImplementation libs.taponphone.sdk.v2.hml
    releaseImplementation libs.taponphone.sdk.v2.release
}
```

Another example using different approach:

```
dependencies {
    add("hmlImplementation", libs.taponphone.sdk.v2.hml)
    add("releaseImplementation", libs.taponphone.sdk.v2.release)
}
```

For other programming languages, ask the developer to check or show where to locate, within the **library and dependency manager configuration file**, the references corresponding to these addresses.

#### Method 2: Analyze the Application Log Output

Ask the developer to do the following:

{% stepper %}
{% step %}

### Setup Build Variant to 'Debug'

When using our **staging (hml) SDK**, configure the **build variants** in **Android Studio** to debug
{% endstep %}

{% step %}

### Open Console Window in Android Studio

With the project open, access the **console window** (press **Alt + F12** to open it)

<figure><img src="/files/U7Q2nzdKJBlCvpmZpK8z" alt=""><figcaption><p>Console Window Open in an Example Android Project</p></figcaption></figure>
{% endstep %}

{% step %}

### Connect the Device

The **mobile device** must be **connected to the computer**. This allows logs to be displayed **directly on the screen** or saved **to a file**
{% endstep %}

{% step %}

### Call 'adb' to Start your Log Process

Inside command line window referencing your project file folder,use the commands bellow:

```
adb logcat
```

this command will show the logs in your console window

```
adb logcat > logs.txt
```

this command will send all the logs to saved text file. It is very usefull if you need to send to support department or attach in opened a tickets
{% endstep %}
{% endstepper %}

After the developer runs the application and attempts to send a transaction, the environment being used can be identified by **checking the SDK’s request URL for each backend**.

The developer should look for the corresponding string:

* **`gwpay-hml.first-tech.net`** → **Staging Environment**
* **`gwpay-prod.first-tech.net`** → **Production Environment**

#### Example for Testing/Staging Environment

```
01-13 15:41:30.503 26564  3470 I okhttp.OkHttpClient: --> POST https://gwpay-hml.first-tech.net/v3/bff/pos/initialize
```

#### Example for Production/Release Environment

```
01-13 15:41:30.503 26564  3470 I okhttp.OkHttpClient: --> POST https://gwpay-prod.first-tech.net/v3/bff/pos/initialize
```


# For Developers: Setting Up the Environment to Get Started

You can start the project in **two ways**:

1. **Creating a new project from scratch** in your IDE.
2. **Using our prebuilt sample projects**, which are already set up for testing and compilation.

In this page, we will focus on **creating the project from the ground up**.

Below, we highlight the **essential points** to ensure the correct functionality of our **Tap On Phone SDK**.

### Creating a New Android Project

{% stepper %}
{% step %}

### Restoring the Development Mobile Device Factory Mode

It is **strongly recommended** that the developer **starts the project using a factory-reset mobile device**.

This practice prevents contamination from **previous device usage**, ensuring a **clean and reliable environment** for **development and testing**. Additionally, it helps **avoid unnecessary troubleshooting processes**, which can be **time-consuming**.
{% endstep %}

{% step %}

### Starting Android Project

We understand that there are various approaches to **creating a new project**, whether through a **graphical user interface (GUI)** or the **command line**.

We will follow the GUI path here:

In **Android Studio**, start a new project by selecting the **'Phone and Tablet'** template and choosing the **'Empty Activity'** model.

<figure><img src="/files/I65ldVMbtcgqdnNXgpoO" alt=""><figcaption><p>New Android Project Creation Screen in [Android Studio]</p></figcaption></figure>

Click **Next** to proceed to the configuration step for two of the most important project elements: the **application name** and the **package name**.

<figure><img src="/files/MoR9OAgXnSbHP2awA32u" alt=""><figcaption><p>New Android Project Information Screen in [Android Studio]</p></figcaption></figure>

These details are **essential** for **credential generation**, troubleshooting, and ensuring the **SDK functions correctly** within the application.

#### **Field Descriptions:**

* **Name:** Enter the project name (e.g., *My Application*).
* **Package Name:** Define a **unique and meaningful package name** (e.g., *com.companyname.payments.myapp*).

{% hint style="info" %}
The **Package Name** is a critical piece of information required to authorize the application during deployment. If you change this field after the app has been deployed to production, you **must notify First Tech** to have it reauthorized. Otherwise, **session activation errors may occur during Tap to Phone transactions.**
{% endhint %}

* **Save Location:** Choose the directory where the project will be saved (e.g., *E:\Dev\FirstTech\AppNative\MyApplication*).
* **Minimum SDK:** Select the **minimum Android SDK version** that the application should support.

{% hint style="info" %}
**Minimum Android SDK version supported by the Tap On Phone SDK:**\
**\[Android 10 - API Level 29]**
{% endhint %}

● **Language:** Choose the programming language (e.g., **Kotlin \[recommended]** or **Java**).

After filling in these details, click **Finish** to create the project.

Wait until the **Gradle synchronization** is fully completed and the project is ready for editing.

Once everything is loaded and set up, your **Android Studio file structure** should resemble the one shown bellow:

<figure><img src="/files/1SbpAmlYk64PF4nu54bH" alt=""><figcaption><p>Android Studio IDE Loaded and Ready for Development</p></figcaption></figure>
{% endstep %}

{% step %}

### First Build & Testing

At this point, you can already perform the **Build** process for the project and validate that everything is set up correctly before proceeding to the next steps. To do this, you need a **configured device or emulator** in your development environment.

To list the **devices/emulators** connected to your development environment, open the **Android Studio terminal** (**\[ALT + F12]**) and enter the following command:

```
adb devices
```

<figure><img src="/files/E7sqmYLwFRUEkr1BzcaY" alt=""><figcaption><p>Android Studio IDE Terminal Listing Devices Ready for Use in the Development Environment.</p></figcaption></figure>
{% endstep %}
{% endstepper %}


# SDK Calls & Integration Guide

Access to the Nexus repository must be configured in the `build.gradle` file so that the Tap to Phone SDK is correctly imported into the project. The Nexus repository contains the staging and production versions of the SDK. Follow the steps below to complete the configuration:

{% stepper %}
{% step %}

### Locate the `build.gradle` file:

Access the `build.gradle` file at the project level (project root).
{% endstep %}

{% step %}

### Add the Nexus repository to the project's `build.gradle`:

It is recommended to add the Nexus repository in the root `build.gradle` file. This ensures that the repository is globally available for all modules, avoiding unnecessary repetitions.
{% endstep %}

{% step %}

### Configure the Nexus repository with credentials:

In the `repositories` block, add the Nexus configuration with the provided credentials.
{% endstep %}
{% endstepper %}

Example: Adding Nexus Repository

```

buildscript {
    repositories {
        maven {
            url = uri("https://nexus.first-tech.net/repository/taponphone-dock/")
            credentials {
                username = "XXX"
                password = "YYY"
            }
        }
    }
}
​
allprojects {
    repositories {
        maven {
            url = uri("https://nexus.first-tech.net/repository/taponphone-dock/")
            credentials {
                username = "XXX"
                password =  "YYY"
            }
        }
    }
}

```

Consider that the **username** and **password** will be provided during the onboarding process by the repository provider, which may be First Tech or the company that purchased the product under the white-label model.

<figure><img src="/files/PXXfg0YcutUB71lmhJL9" alt=""><figcaption></figcaption></figure>

### Configure the SDK in the `build.gradle` file of the app module

* Open the `build.gradle` file at the app module level.
* Add the SDK dependency in the `dependencies` block.

Example:

```
debugImplementation(libs.taponphone.sdk.v2.hml)
releaseImplementation(libs.taponphone.sdk.v2.release)
```

<figure><img src="/files/faR2xpM1GvOPz6ikKouJ" alt=""><figcaption></figcaption></figure>

As a best programming practice, the path of these variables is configured to be retrieved from the `libs.versions.toml` file.

<figure><img src="/files/DR2HMipqcNb4xSzeq9Fw" alt=""><figcaption></figcaption></figure>

At this point, you can execute the '**Sync Project with Gradle Files**' command to synchronize the project.

If an error occurs during 'Sync Project with Gradle Files':

```
If an error occurs during 'Sync Project with Gradle Files':
```

Remove the following snippet from the `settings.gradle.kts` file:

```
dependencyResolutionManagement {
   repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
   repositories {
       google()
       mavenCentral()
   }
}
```

And run the command again.

`[CTRL + Shift + o]`

The expected output in the console should be: `BUILD SUCCESSFUL`.

<figure><img src="/files/3liq5Oddn4Dyh7sm1Lq5" alt=""><figcaption></figcaption></figure>

### Implementing the use of the SDK

In your project's initialization class (`Application`), you must "extend"  `Application`

In this class, it is necessary to replace the `terminalConfig` variable, which is instantiated from the `TerminalConfigEntity` entity, considering the parameters provided during onboarding with First Tech, which are:

```
class Application : Application() {
​
    override fun onCreate() {
        super.onCreate()
​
        if (!TapOnPhoneInitializer.isApplicationInitAllowed(this)) return
​
        TapOnPhoneInitializer.initializeTerminal(this)
​
        TapOnPhoneInitializer.setTerminalConfig(
            TerminalConfigEntity(
                companyDocument = BuildConfig.COMPANY_DOCUMENT,
                companyName = BuildConfig.COMPANY_NAME,
                merchantId = UUID.fromString(BuildConfig.MERCHANT_ID),
                terminalNumber = BuildConfig.TERMINAL_NUMBER,
                clientId = BuildConfig.CLIENT_ID,
                clientSecret = BuildConfig.CLIENT_SECRET,
                sdkScope = BuildConfig.SDK_SCOPE,
                sdkClientId = BuildConfig.SKD_CLIENT_ID,
                sdkClientSecret = BuildConfig.SDK_CLIENT_SECRET,
                appVersion = "1.0.0",
                packageName = applicationContext.packageName,
                sdkOrganization = "Organization 123",
                versionCode = (if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                    packageManager.getPackageInfo(packageName, 0).longVersionCode
                } else {
                    packageManager.getPackageInfo(packageName, 0).versionCode.toLong()
                }).toString()
            )
        )
    }
}
```

* `companyDocument` → Your company's CNPJ document without special characters.
* `companyName` → Your company's trade name.
* `merchantId` → UUID provided by First Tech during the onboarding process. *(Note: This field is the Java UUID object.)*
* `terminalNumber` → Terminal number provided by First Tech during the onboarding process.
* `clientId` → Client ID provided by First Tech during the onboarding process.
* `clientSecret` → Client key provided by First Tech during the onboarding process.
* `sdkScope`  -> Client Secret for auth, given by FirstTech team, but, submitted by the consummer of this SDK
* `sdkClientId` -> Client ID for SDK, given by FirstTech team, but, submitted by the consummer of this SDK
* `sdkClientSecret`  -> Client Secret for SDK, given by FirstTech team, but, submitted by the consummer of this SDK
* `appVersion`   -> Version number of the client application.
* `packageName`   -> Name of the package where the client application is running
* `sdkOrganization`   -> This figure is provided by First Tech.
* `versionCode`   -> Value of the application's versionCode.

All SDK manipulation operations are performed through the `ViewModel`, which receives `TapOnPhoneApplication` as a parameter during its creation.

```
private val mppProviderViewModel by lazy { MPPPProviderViewModel(application as TapOnPhoneApplication) }
```

<figure><img src="/files/irlcnziLgaKzN9aMp8Yt" alt=""><figcaption></figcaption></figure>

### Starting a payment

Execute the `startPaymentFlow()` function, provided by `MPPProviderViewModel`. To do this, you need to pass the `TransactionInfoEntity` class as a parameter, which receives the following values in its constructor:

* `installments`: An integer containing the number of installments.
* `paymentType`: One of the options from the `PaymentType` ENUM, which can be either `PaymentType.DEBIT` or `PaymentType.CREDIT`.
* `amount`: The total transaction amount, expressed as a `Long`.

| Value R$ | Long |
| -------- | ---- |
| R$ 23,34 | 2334 |
| R$ 15,00 | 1500 |
| R$ 0,15  | 15   |
| R$0,01   | 1    |

```
    private fun startPayment() {
        mppProviderViewModel.startPaymentFlow(
            TransactionInfoEntity(
                paymentType.DEBIT, //IT COULD BE paymentType.CREDIT
                100, //For example, this 100 means R$ 1.00, 
                2 //Number of installments, in this case, two installments
            )
        )
    }
```

After this step, simply react to the events published in `onMessage` and capture the information from the entities of these events.

### Reacting to messages

`MPPProviderViewModel` provides the `LiveData onMessage`, which will receive an 'extended' object from the `MPPViewData` class.

{% hint style="info" %}
It is important to observe `onMessage` within the correct lifecycle, ensuring that there are no memory leaks or unexpected reactions.
{% endhint %}

In this project, we use the concept of Sealed Classes for a more efficient abstraction. Below, we list all the objects that can be returned in `onMessage` and their respective meanings.

| Class                                   | Description                                                          |
| --------------------------------------- | -------------------------------------------------------------------- |
| `TerminalInitializingViewData`          | The terminal has started the initialization process.                 |
| `TerminalInitializingErrorViewData`     | The terminal has completed the initialization process with an error. |
| `TerminalInitializingSuccessViewData`   | The terminal has successfully completed the initialization process.  |
| `TerminalNotCreatedViewData`            | The terminal instance has not yet been created.                      |
| `TerminalCreatingViewData`              | The terminal instance is being created.                              |
| `TerminalCreatedSuccessViewData`        | The terminal instance has been successfully created.                 |
| `TerminalCreatedErrorViewData`          | The terminal instance was not created.                               |
| `TerminalSessionCreatingViewData`       | The payment session is being created.                                |
| `TerminalSessionCreatedSuccessViewData` | The payment session has been successfully created.                   |
| `TerminalSessionCreatedErrorViewData`   | The payment session was not created.                                 |
| `TerminalSessionTimeoutViewData`        | The payment session has expired.                                     |
| `TerminalPaymentStartingViewData`       | The transaction process has started.                                 |
| `TerminalPaymentProcessingViewData`     | The transaction is being processed.                                  |
| `TerminalPaymentCancelledViewData`      | The transaction has been canceled.                                   |
| `TerminalPaymentSuccessViewData`        | The transaction was successfully completed.                          |
| `TerminalPaymentErrorViewData`          | The transaction was completed with an error.                         |
| `TerminalPaymentFinishedViewData`       | The entire process has been completed.                               |

Here, we obtain the reference to the `LiveData onMessage` and start observing it:

```
private fun setupObserver() {
   mppProviderViewModel.onMessage.observe(this, ::onMessage)
}
```

And we react to events as follows:

> Note: In this example, we do not list all `MPPViewData` classes, but we strongly recommend implementing all classes.

> Note: Some `MPPViewData` classes contain objects that help understand the message that should be displayed at a specific step.

```
  private fun onMessage(viewData: MPPViewData?) {
        viewData?.let {
            when (viewData) {
                MPPViewData.TerminalInitializingViewData -> {
                    showLoadingDialog("Inicializando terminal")
                    binding.tvMessage.text = "Inicializando terminal"
                }

                MPPViewData.TerminalInitializingErrorViewData -> {
                    showFeedbackDialog("Erro ao inicializar terminal")
                    progressDialog.dismiss()
                }

                MPPViewData.TerminalInitializingSuccessViewData -> {
                    progressDialog.dismiss()
                    binding.tvMessage.text = "Inicialização concluída"
                }
                
                //Mapear todos os cenários de MPPViewData

            }
        }
    }
```

Next, we will explain in more detail the messages returned in the `onMessage` interface, which are extensions of the `MPPViewData` object.

Classes not detailed below do not have internal variables. In these cases, follow the guidelines described in Table 2 – OnMessage Return List.

{% stepper %}
{% step %}

#### TerminalCreatedErrorViewData | TerminalSessionCreatedErrorViewData

* `cause` → Throwable object returned by the payment SDK, used for debugging only.
* `logMessage` → Conversion of `cause` to a String.
  {% endstep %}

{% step %}

#### TerminalPaymentProcessingViewData

`uiMessage` → Enumeration of all possible scenarios during card information processing, including:

* APPROVED
* NOT\_AUTHORISED
* PLEASE\_ENTER\_PIN
* PROCESSING\_ERROR
* PRESENT\_CARD
* CARD\_READ\_OK\_PLEASE\_REMOVE
* APPROVED\_PLEASE\_SIGN
* AUTHORISING\_PLEASE\_WAIT
* TRY\_ANOTHER\_CARD
* CLEAR\_DISPLAY
* SEE\_PHONE
* PRESENT\_CARD\_AGAIN
* HOLD\_STILL
* UNKNOWN

*A default message is provided for display on the screen, but developers have the freedom to customize it as long as they comply with ABECS regulations.*
{% endstep %}

{% step %}

#### TerminalPaymentCancelledViewData

`reason` → Enumeration of error scenarios that occur during card information reading and capture, including:

* TRANSACTION\_WAS\_TERMINATED
* USER\_CANCELLED\_PIN\_PAD
* SESSION\_DEACTIVATED
* DEVICE\_STATE\_FAILURE
* TIME\_CHECK\_ERROR
* UNKNOWN

*A default message is provided for display on the screen, but developers have the freedom to customize it as long as they comply with ABECS regulations.*
{% endstep %}

{% step %}

#### TerminalPaymentSuccessViewData

`result` → `TransactionCompleted` object containing all payment details

> **Note:** This does not guarantee that the transaction was successfully completed, as issues may have occurred with the acquirer. All fields will be explained in the following sections.

1. **cardHolder**

When available, it returns the card brand used for the transaction:

* MASTERCARD
* VISA
* AMERICAN\_EXPRESS
* DISCOVER
* EFTPOS
* UNKNOWN

2. **discretionaryTagData**

Returns EMV Tags read by the SDK. Two methods are provided for better abstraction:

* `getDiscretionaryTagDataHashMap()` → Returns a key-value array containing `EMVTag` and its value.
* `getDiscretionaryTagDataPrintable()` → Same function as above, but returns a formatted String for display.

3. **metaData**

A `ByteArray` of metadata returned by the backend. Two methods are available for better interpretation:

* `getMetaDataTranslated()` → Returns a parsed `Metadata` object with additional information.
* `getMetaDataString()` → Same as the above method but returns a JSON-formatted String.

4. **processingResult**

This object, as a `SealedClass`, can have two abstractions:

5. **TransactionApproved**

`cardScheme` → When available, returns the card brand used in the transaction:

* MASTERCARD
* VISA
* AMERICAN\_EXPRESS
* DISCOVER
* EFTPOS
* UNKNOWN

6. **TransactionNotAuthorised**

`reason` → Enumeration of authorization failure reasons, including:

* ONLINE\_DECLINED
* OFFLINE\_DECLINED
* INVALID\_AUTHORISATION\_DATA
* NO\_CARD\_APPLICATION
* NO\_CARD\_APPLICATION\_SELECTOR\_MISMATCHED
* PROCESSING\_ERROR
* CARD\_ERROR
* UNKNOWN

*A default message is provided for display on the screen, but developers have the freedom to customize it as long as they comply with ABECS regulations.*

7. **serviceTransactionId**

A unique identifier for the transaction (UUID).

8. **uiMessage**

Enumeration of all possible scenarios during card information processing:

* ONLINE\_DECLINED
* OFFLINE\_DECLINED
* INVALID\_AUTHORISATION\_DATA
* NO\_CARD\_APPLICATION
* NO\_CARD\_APPLICATION\_SELECTOR\_MISMATCHED
* PROCESSING\_ERROR
* CARD\_ERROR
* UNKNOWN

9. **subMessage**

An enumeration of sub-messages that should also be displayed when returned, following ABECS standards.
{% endstep %}

{% step %}

#### TerminalPaymentErrorViewData

Returned when a payment error is detected.

* `errorCause` → Enumeration of possible failures.
* `exception` → Throwable object returned by the payment SDK, used for debugging only.
* `discretionaryTagData` → Key-value return of EMV Tags read by the SDK.

*A default message is provided for display on the screen, but developers have the freedom to customize it as long as they comply with ABECS regulations.*
{% endstep %}
{% endstepper %}

With these instructions, we understand that there are macro guidelines for setting up the environment, downloading dependencies, and best practices for product implementation. The development team should have a more specific and comprehensive document for application creation, which is not covered here. Some excerpts have been included only to illustrate to the operations support team the steps involved in the application's development.

### Device Information

To obtain the deviceID, in order to facilitate log analysis. A method has been provided within the DeviceInformationUtils class. To use it, use the following syntax

```
DeviceInformationUtils.getDeviceIdentifier(applicationContext)
```

<figure><img src="/files/i1LBhkw0PaR0aBk4P1Cl" alt=""><figcaption></figcaption></figure>

A String value will be returned, this value can be used in some visualization on the screen, to make it easier to identify the device in any possible error analysis.

#### To obtain information about the device. A method has also been provided within the DeviceInformationUtils class.

{% hint style="info" %}
Note: this method must be used within a coroutine, as it is a suspend method
{% endhint %}

{% hint style="info" %}
To obtain this information, use the following syntax
{% endhint %}

```
  binding.btnDeviceInfo.setOnClickListener {
            lifecycleScope.launch {
                binding.tvLog.text = DeviceInformationUtils.getDeviceInfo(applicationContext)
            }
        }
```

A JSON (below) will be returned as a String, this value can be used in some visualization on the screen or some pop-up, to facilitate the identification of any configuration made on the device that is preventing its use for some transaction.

* JSON return example

```
{
  "device" : {
    "apiVersionAndroid" : 33,               //Android OS API level of the device running the app
    "batteryLevel" : 92,                    //Battery percentage 
    "brand" : "samsung",                    //Device brand 
    "deviceId" : "2c9496cabbdde392",        //Id of the application installed on the device
    "googlePlayServiceVersion" : 251633029, //Version of Google Play Service installed on the device
    "isActivatedBatteryMode" : false,       //Check if the battery saving mode is active
    "isActivatedDeveloperMode" : true,      //Check if the developer mode is active
    "isEnabledAutomaticTime" : true,        //Check if the time is set automatically
    "isEnabledNfc" : false,                 //Check if the Nfc function is active
    "isRooted" : false,                     //Check if the device is in root mode
    "manufacturer" : "samsung",             //Manufacturer of the device
    "memoryCapacity" : "3. 45",             //Device memory capacity
    "memoryInUse" : "1. 51",                //Total memory in use
    "mobileSignal" : {
    "level" : 1,                            //Mobile network signal level
    "operatorName" : "CLARO BR",            //Mobile network operator
    "typeOfSignal" : "4G"                   //Type of signal captured
    },
    "model" : "SM-A326B",                   //Device model
    "soVersionAndroid" : "13",              //Trade name of A version
    "wifiSignal" : 4                        //Level of WI-FI signal received
  },
  "securityScan" : {
    "appsInstalledOnDevice" : [ "com.sec.android.gallery3d", "com.android.chrome", "com.android.settings", "com.android.vending", "com.google.android.apps.maps", "com.google.android.apps.messaging", "com.google.android.apps.tachyon", "com.google.android.gm", "com.google.android.youtube", "com.samsung.android.app.contacts", "com.samsung.android.arzone", "com.samsung.android.calendar", "com.samsung.android.dialer", "com.samsung.android.messaging", "com.sec.android.app.camera", "com.google.android.apps.docs", "com.google.android.apps.photos", "com.google.android.apps.youtube.music", "com.google.android.videos", "com.microsoft.office.outlook", "com.samsung.android.oneconnect", "com.sec.android.app.sbrowser", "com.sec.android.app.shealth", "com.android.stk", "com.claroColombia.contenedor", "com.gameloft.android.gdc", "com.google.android.googlequicksearchbox", "com.samsung.android.app.spage", "com.samsung.android.game.gamehome", "com.sec.android.app.clockpackage", "com.sec.android.app.fm", "com.sec.android.app.myfiles", "com.sec.android.app.samsungapps", "com.sec.android.usermanual", "br.com.claropay.claropay", "com.claro.claromusica.br", "com.clarodrive.android", "com.dla.android", "com.edifier.edifierconnect", "com.example.testemicrophone", "com.facebook.katana", "com.facebook.orca", "com.firsttech.taponphone.app", "com.firsttech.taponphone.app.dev", "com.firsttech.taponphone.dev.app", "com.firsttech.taponphone.kt.app.dev", "com.google.android.apps.playconsole", "com.handmark.expressweather", "com.instagram.android", "com.microsoft.office.officehubrow", "com.nvt.cs", "com.rsupport.rs.activity.rsupport.aas2", "com.samsung.android.app.notes", "com.samsung.android.app.watchmanager", "com.samsung.android.spay", "com.samsung.android.voc", "com.samsung.sree", "com.sec.android.app.popupcalculator", "com.sec.android.app.voicenote", "com.sec.android.easyMover" ], //Apps installed on the device
    "appsMalwareList" : [ ],                //Apps found in the list of apps not recommended to run in parallel with TTP
    "appsOutsidePlaystoreList" : [ ],       //Not implemented
    "appsRunningList" : [ ]                 //Not implemented
  }
}
```


# Capturing Errors in the Application

Before collecting data, it is important to recall some key characteristics of the SDK's behavior in the staging and production environments, as discussed in sections 3 and 6 of this document.

<details>

<summary>Staging Environment</summary>

* **Errors in the Terminal Creation Step**
  * Only the status *'Jailbreak/Root Mode Enabled'* prevents usage.
* **Errors in the Session Creation Step**
  * There are no session errors, as internal credentials are not verified.
* **Errors in the Card Reading and Transaction Submission Steps**
  * Errors follow the descriptions provided in *Section 6 - Instructions for Deploying the App in Production* of this document and can be captured in the logs as usual.<br>

</details>

<details>

<summary>Production Environment</summary>

* **Errors in the Terminal Creation Step**
  * Permission checks for the device, malicious applications, enabled developer mode, apps installed outside Google Play, and other extensive verifications mentioned in *Section 6 - Instructions for Deploying the App in Production* of this document must be observed.
* **Session Errors**
  * Credentials are verified according to the details provided in *Section 6 - Instructions for Deploying the App in Production* of this document.
* **Errors in the Card Reading and Transaction Submission Steps**
  * Errors follow the descriptions provided in *Section 6 - Instructions for Deploying the App in Production* of this document and can be captured in the logs as usual.

</details>

### Types of logs

**Redactable Log**

These logs appear only in the production environment and are encrypted by the SDK, intended exclusively for interpretation by **First Tech**. They are essential for understanding errors and must always be sent.

Example of a Redactable Log

{% code overflow="wrap" %}

```
2025-01-09 13:37:57.009 19993-20669 TapOnPhoneLogger br.com.app D r.110002 : #0.0.1 #1.1. #2.1. #3.1. #4.1. #5.1. #6.1. #7.1. #8.1. #9.1. #10.1. #11.1. #12.0.1
```

{% endcode %}

**Public SDK Error Logs**

These logs are displayed as exceptions are generated within the *viewData* and shown on the screen. Essentially, they correspond to the exception classes described in *Section 6 - Instructions for Deploying the App in Production* of this document, containing guidelines for issue resolution.

They must be sent to **First Tech**, along with the **Redactable Logs**, when opening a support ticket.

Example of a Public SDK Error Log:

{% code overflow="wrap" %}

```
2025-01-09 13:37:57.042 19993-19993 TapOnPhoneModule br.com.app E Terminal created error: java.lang.Exception: Terminal creation failed: DEVICE_STATE_FAILURE
```

{% endcode %}

**Application Logs**

Logs created by the application developer to monitor their own business processes and problem indicators. These logs are typically not analyzed by First Tech during inspections.

{% code overflow="wrap" %}

```
01-20 13:56:13.429  1724  1814 I NSLocationMonitor: getGPSUsingApps() called
01-20 13:56:13.447  2984 28852 I NSLocationManager_FLP: getGPSUsingApps, NO_FREEZE={5013} / FREEZE={10207}
01-20 13:56:13.861  1559  2237 I bauth_FPBAuthService: pcf : 0x1012, 0 ,1 ,0 ,0 ,0 ,0, 7.0.0.1

```

{% endcode %}

Logs can be extremely extensive; therefore, filtering and organizing them before submitting a ticket significantly accelerates the problem resolution process. For an effective analysis, the collected log should be limited to a maximum of 100 lines and focus exclusively on the transaction that caused the issue, removing any irrelevant records or entries related to other aspects of the application.

***

### **Collecting Logs with the Staging SDK**

Ask the developer to configure the build variants in Android Studio for the staging environment (**hml**) when using our staging SDK. With the project open, access the console window by pressing **Alt + F12**.

If the developer is not familiar with build variants, guide them to refer to **Section 4: Environment Preparation to Get Started** for more information.

Don't forget to request that **developer mode** is enabled on the device.

<figure><img src="/files/W2VUl2n5V8BO8Pn5qIsI" alt=""><figcaption><p><strong>Figure 17: Console Screen Open in a Sample Android Project</strong></p></figcaption></figure>

The mobile device must be connected to the computer. This allows you to run the following command in the console to display only encrypted error logs and save them to a file containing only encrypted and public logs:

```
adb logcat -c
```

The command above will clear any ADB buffer, preventing logs from previous tests from being included. Then, proceed with recording the application log using the next command in the console:

```
adb logcat -s TapOnPhoneLogger > logs.txt
```

The command will generate a file named **logs.txt** in the folder specified by the path in the console.

The next step is to repeat the operation, collecting all errors and generating a second file containing the complete set of application errors during the process.

```
adb logcat > logs2.txt
```

The command will generate a file named **logs2.txt** in the folder specified by the path in the console.

The difference between the two logs will allow for a more accurate analysis, separating the **Tap to Phone SDK** context from the **public logs** and **application logs**.

Analyze both files, and if no public error covered by this document has an effective resolution procedure (refer to **Section 6: Instructions for Releasing the App to Production**), proceed with opening a ticket with **First Tech**, including these two log files.

***

### **Collecting Logs with the Production SDK**

The process follows the same steps as described in **Section 5.1: Collecting Logs with the Staging SDK**, but special attention must be given to **turning developer mode off and on** at the correct time.

Ask the developer to configure the build variants in **Android Studio** for the **staging environment (hml)** when using our **staging SDK**. With the project open, access the console window by pressing **Alt + F12**.

If the developer is not familiar with build variants, guide them to refer to **Section 4: Environment Preparation to Get Started** for more information.

<figure><img src="/files/5KBnHR92GbNJG60BCgPL" alt=""><figcaption><p><strong>Figure 18: Console Screen Open in a Sample Android Project</strong></p></figcaption></figure>

The mobile device must be connected to the computer. This allows you to run the following command in the console to display only **encrypted error logs** and save them to a file containing only **encrypted and public logs**:

```
adb logcat -c
```

The command above will clear any **ADB buffer**, preventing logs from previous tests from being included. Now, proceed with your test normally until the desired error occurs.

Once the desired error has been triggered, you can **enable developer mode again** to continue log collection. With developer mode reactivated, follow the next commands as if you were in the **staging environment** (**Section 5.1: Collecting Logs with the Staging SDK**).

```
adb logcat -s TapOnPhoneLogger > logs.txt
```

The command will generate a file named **logs.txt** in the folder specified by the path in the console.

The next step is to repeat the operation, collecting all errors and generating a **second file** containing the **complete set of application errors** during the process.

```
adb logcat > logs2.txt
```

The command will generate a file named **logs2.txt** in the folder specified by the path in the console.

The difference between the two logs will allow for a **more accurate analysis**, separating the **Tap to Phone SDK** context from the **public logs** and **application logs**.

It is important to perform this task in **production quickly**, as the log buffer may be overwritten, potentially losing the test data that was just recorded.

Analyze both files, and if no **public error** covered by this document has an effective resolution procedure (refer to **Section 6: Instructions for Releasing the App to Production**), proceed with **opening a ticket with First Tech**, including these two log files.


# Instructions for Deploying the App to Production

{% stepper %}
{% step %}

### **Review Code and Dependencies:**

* **Ensure that all dependencies and libraries are up to date.**
* **Verify that the code has been reviewed and validated to prevent security vulnerabilities.**
  {% endstep %}

{% step %}

### **Production Settings:**

* **Update the configuration file to point to the production backends** `e.g., gwpay-prod.first-tech.net`.
* **Ensure that logs are set to the appropriate level**, avoiding unnecessary exposure of sensitive information.
* **Open a ticket with First Tech**, providing the **Package Name, SHA-256, and Version Code** of the product for **production enablement**. This process may take **5 to 7 days**, so we recommend opening the ticket as soon as these details are available to streamline the deployment.

To obtain this information:

**Package Name:** This information can be found in the **`build.gradle`** file of your app's module.

**Variable path:** `android >> defaultConfig >> applicationId`

<figure><img src="/files/uSKWgohVDLkknZMLospj" alt=""><figcaption><p><strong>Figure 19: Location of the <code>applicationId</code> and <code>versionCode</code> Variables in the Build.Gradle File</strong></p></figcaption></figure>

**SHA-256:** This information can be obtained from the [**Google Play Console**](https://play.google.com/console/u/0/developers):

* **Access the application's page**

<figure><img src="/files/DWdwkdFRF9DMNLP0y0vt" alt=""><figcaption><p><strong>Figure 20: Main Application Page on the Google Play Console Website</strong></p></figcaption></figure>

**Access the menu**

* Navigate to **Test & Release** >> **Setup** >> **App Signing**

<figure><img src="/files/17mStxv7io2uf3P1pGe3" alt=""><figcaption><p><strong>Figure 21: App Signing Page of the Application on the Google Play Console Website</strong></p></figcaption></figure>

In the **"App Signing Key Certificate"** section:

* The **SHA-256 hash** can be found in the **"SHA-256 Certificate Fingerprint"** field.

<figure><img src="/files/cKhmw1oTzghuoKGFBYRP" alt=""><figcaption><p><strong>Figure 22: Location where the SHA-256 is generated and should be copied from.</strong></p></figcaption></figure>

**Version Code:** This can be found in the **`build.gradle`** file of your app's module.\
\
**Variable path:** `android >> defaultConfig >> versionCode`

<figure><img src="/files/ijQhq7ooobb4HzUfFiwv" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}

### **Credentials and Certificates:**

* **Enter the appropriate credentials for the production environment**, provided by **First Tech** or the **acquirers**.
* **Verify the validity of the certificates and encryption keys** being used.
  {% endstep %}

{% step %}

### **Final Testing:**

* **Perform final tests on real devices** to ensure the application works as expected.
* **Simulate real transaction scenarios** to validate the complete flow, from payment to authorization.
  {% endstep %}

{% step %}

### **Privacy Policy and Terms of Use:**

* **Ensure that the application includes a clear privacy policy and terms of use**, as required by local regulations.
  {% endstep %}

{% step %}

### **Publication on Google Play Store:**

* **Review all app metadata**, including name, description, screenshots, and category.
* **Configure app permissions correctly** to avoid rejections during the store review process.
* **Submit the APK/AAB for review** and wait for **Google Play approval**.
  {% endstep %}

{% step %}

### **Post-Launch Monitoring:**

* **Set up monitoring tools** to track app performance, such as **Firebase** or **Sentry**.
* **Monitor error logs and crash reports** to quickly identify and fix potential issues.
  {% endstep %}
  {% endstepper %}


# Troubleshooting During Testing and Production

Possible Causes and Solutions

The errors listed below typically occur during the **Proof of Concept (POC) process**, the **initial integration attempts**, or the **deployment of the SDK** in **staging and production environments**.

For each **transaction process stage**, we will present the **most common errors**, along with a **structured troubleshooting path** and the necessary **checks for each situation**.

This **systematic approach** facilitates the **identification and resolution of issues**, ensuring a **smoother transition** between the **development, staging, and production** phases.

### **How to Activate the Terminal**

Terminal activation, as discussed in previous sections, is a **critical step** that requires compliance with **specific prerequisites** in the **production environment** of the **Android operating system**.

During the **terminal creation process**, if these prerequisites are **not met**, the SDK will return an **error from the** `TerminalInitializingErrorViewData` **class**, with the description **`DEVICE_STATE_FAILED`**, indicating that the activation was **unsuccessful**.

Below, we outline the **main reasons** that may cause this failure.

#### **1. Required Permissions to Operate the SDK within the Application**

Initially, it is necessary to verify if the application has access to the following Android permissions:

<table><thead><tr><th width="189">Feature</th><th>Permission</th></tr></thead><tbody><tr><td>NFC</td><td>android.Manifest.permission.NFC</td></tr><tr><td>Vibrate</td><td>android.Manifest.permission.VIBRATE</td></tr><tr><td>Internet</td><td>android.permission.INTERNET</td></tr><tr><td>Network State</td><td>android.permission.ACCESS_NETWORK_STATE</td></tr><tr><td>Access Notification Policy</td><td>android.permission.ACCESS_NOTIFICATION_POLICY</td></tr><tr><td>Accurate Location</td><td>android.permission.ACCESS_FINE_LOCATION</td></tr><tr><td>Approximate Location</td><td>android.permission.ACCESS_COARSE_LOCATION</td></tr></tbody></table>

To verify if the permissions have been requested, open the **AndroidManifest.xml** file, which should be accessed by the **Android project developer**.

In this file, some permissions are **automatically configured**, while others need to be **explicitly declared** according to **Android's security policy**.

Additionally, you can request a **screenshot from the developer** to confirm the permissions directly on the device.

<figure><img src="/files/jsdSmqJ8GDbfU1W8WKNR" alt=""><figcaption><p><strong>Figure 23: Screenshot of the AndroidManifest.xml File from a React Native Project Using the TTP SDK</strong></p></figcaption></figure>

Even if the permissions are implemented in the application, in the **production environment** (when the app is downloaded from the store), **Android will request user confirmation** to access certain features, such as the **camera** or **microphone**.

It is essential to **verify** whether the application has made these requests and if the **user has granted permission** for these features.

If there are any doubts regarding **permission grants**, recommend **reinstalling the application**. This will allow the necessary steps to be repeated, ensuring that **permissions**, such as **microphone** and **NFC**, are **requested and granted** at the appropriate time.

***

2. **Root Mode**

If the **superuser** is logged in and enabled on Android, the **SDK will not be able to complete the terminal creation phase**, either in **staging** or **production**.

To check if the device is in **root mode**, follow a process similar to the one described in **Section 2** for **log collection**:

1. **Ask the application developer** to configure the **build variants** in **Android Studio** for the **staging environment (hml)** while using the **staging SDK**.
2. With the project open in **Android Studio**, **access the console window** by pressing **Alt + F12**.
   * If the developer is unfamiliar with **build variants**, recommend reading **Section 4: Environment Preparation to Get Started**.
3. **Connect the mobile device** to the computer using a **USB cable** and enter the following command:

```
adb shell
```

Next, check if it is possible to access the **Android superuser** on the mobile device:

```
su
```

If the device **requests permission** or **switches to superuser (root) mode**, it indicates that **root access is enabled**.

On the other hand, if the command returns a message like **"command not found"**, the device **does not have root access**.

***

3. **Developer Mode**

**Developer mode** is **allowed only for the staging SDK**, but **not for the production SDK**.

If you are in **production** and encounter the **`DEVICE_STATE_FAILURE`** error during the **terminal creation step**, you must **disable developer mode** on the **Android device** where the application is installed.

#### **To disable developer mode, follow these steps:**

1. Open the **Settings menu** on Android and look for **Developer Options** or **Programmer Options**, depending on the device model and Android version.
2. If this submenu is **not found**, it means that **developer mode has never been enabled**.

#### **To confirm if developer mode is active:**

1. Go to the **About Phone** submenu in the **Settings menu**.
2. Tap **seven times** on the **Build Number** field. After this, Android will display a message confirming that **Developer Options have been enabled**.
3. Open the newly created **Developer Options menu** and **disable developer mode**.

This action will ensure that the device is properly configured for the **production environment**.

***

4. **Potentially Malicious Applications**

Another reason for the **`DEVICE_STATE_FAILURE`** error during the **terminal creation phase** is the presence of **applications that can monitor data exchange between apps, enable root mode, or collect sensitive data**, compromising the **security of payment data read via NFC**.

This verification takes place in **both staging and production modes**.

Below is a list of **known applications** that may cause this error (**not limited to these, as variations with similar effects may exist**):

* Magisk
* Frida
* Cydia Substrate
* SuperSU
* Xposed

If any of these applications are found on the device, we **strongly recommend** performing a **factory reset**.

This ensures that **tests are restarted in a clean environment**, preventing **potential residual interference** with the integrity of the **operating system**, even after these applications have been removed.

***

5. **Apps Installed Outside the Store**

In the **production environment**, applications installed **outside the official store** may be flagged by **Play Integrity**, marking the **device as unsafe for transactions**.

If there is suspicion of such apps, **uninstall them** and **attempt to create the terminal again**.

The **SDK continuously performs security checks** to ensure that the **device is always classified as safe**, maintaining the **integrity and security of transactions**.

#### **Other less complex issues** returned by the `TerminalInitializingErrorViewData` view during the **initialization phase** may include:

| Error Returned by the View        | Cause                                                                        | Solution                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| --------------------------------- | ---------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| UNSUPPORTED\_ANDROID\_OS\_VERSION | <p></p><p>The Android version on the device is not supported by the SDK.</p> | <p>Request a <strong>screenshot of the Android version</strong> on the device and verify whether it meets the <strong>minimum specifications</strong> described in this document.</p><p>Additionally, if possible, <strong>guide the customer to update the Android version</strong>. This option is more feasible for <strong>recent models</strong> or <strong>devices that have been restored to factory settings</strong>.</p><p>If the customer is unsure how to find this option, <strong>ask for the device model</strong> and provide <strong>instructions</strong>. While <strong>names and descriptions may vary</strong>, the <strong>Android version</strong> is usually found in the <strong>About</strong> submenu within the device's <strong>Settings</strong> app.</p> |
| NETWORK\_CONNECTION\_ERROR        | The device has no internet access during the terminal creation process.      | <p>Ask the <strong>device holder</strong> to <strong>open a browser</strong> and access any website or use a <strong>speed test tool</strong> to check the <strong>connection quality</strong>.</p><p>Ideally, <strong>high-speed and low-latency networks</strong> should always be used, preferably by <strong>connecting to a reliable Wi-Fi network</strong> whenever possible.</p>                                                                                                                                                                                                                                                                                                                                                                                                 |
| TERMINAL\_NOT\_INITIALISED\_YET   | <p>Internal SDK failure.</p><p></p>                                          | <p>This is an <strong>internal product failure</strong> that currently has <strong>no mitigation procedure</strong>.</p><p>It is recommended to <strong>open a ticket with First Tech</strong>, attaching the <strong>collected logs</strong> for <strong>immediate investigation</strong>.</p>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| INTERNAL\_ERROR                   | Generic internal SDK error.                                                  | <p>This is an <strong>internal product failure</strong> that currently <strong>has no available mitigation procedure</strong>.</p><p>The error includes <strong>additional details</strong> in the <strong>exception field</strong>, which will be analyzed by the <strong>First Tech team</strong>.</p><p>It is recommended to <strong>open a ticket with First Tech</strong>, attaching the <strong>collected logs</strong> for <strong>immediate investigation</strong>.</p>                                                                                                                                                                                                                                                                                                         |

### **How to Activate the Session**

After **successfully completing** the **terminal integrity verification process**, the next step is **session creation**.

At this stage, the **application is validated** based on its **credentials and certificates** in **Google Play**. If no issues are detected, the **SDK will proceed to the card request process**.

The most common issues in this phase generally fall into **two categories**:

1. **Failure in Retrieving Application Data from the Store:**
   * #### The **developer must ensure** that all required information is **available and up to date**.
2. #### **Version Update Without Communication:**
   * #### When a **new version** of the application is published in the store, the **developer must officially request** the **release of this version in production** with **First Tech**.
   * #### This process ensures **authorized SDK usage control** on customer devices

#### **To release the version, a support ticket must be opened with the following three essential details:**

* **SHA-256 certificate fingerprint**
* **Package Name**
* **Version Code**

#### **SHA-256 - Application Signing Certificate Fingerprint**

The **SHA-256** is a **unique fingerprint** generated by the **application signing certificate** in **Google Play**. It is **public** and used to **authenticate the application**, ensuring its **exclusivity**.

**First Tech requires this data only the first time** the application is distributed in the store.

The **SHA-256 generation process** is managed by **Google** and involves several steps, which can be found in the **official documentation**.

**To provide the required value, follow these steps:**

* **Access the Google Play Console settings menu** ([**more details here**](https://support.google.com/googleplay/android-developer/answer/9842756?hl=pt-br)).
* Navigate to **Setup > App Integrity > App Signing Key Certificate > SHA-256 Certificate Fingerprint**.
* **Copy the displayed hexadecimal value** and **send it to First Tech**.

This step is **essential** to **validate the integration** and allow the **authorized use of the SDK**.

<figure><img src="/files/X4FOnF2leCK5VXoGARIS" alt=""><figcaption><p><strong>Figure 24: App Integrity Configuration Screen within the Google Portal where the SHA-256 Certificate Fingerprint can be viewed</strong></p></figcaption></figure>

Exemplo de SHA-256 certificate Fingerprint

```
BD : 92 : 64 : B0 : 1A : B9 : 08 : 08 : FC : FE : 7F : 94 : B2
```

#### **Package Name - Unique Identification Name of the Android Application**

The **Package Name** is the **unique identifier** for an Android application, used to differentiate it from other apps installed on the device. This **naming convention** prevents conflicts between applications and is essential for both **system functionality** and **software testing**, whether manual or automated.

Although the **Package Name** is automatically assigned when the app is submitted to Android, it can be **changed if necessary**. The format typically follows the pattern:\
**com.yourdomain.appname**.

For example, if the developer's website is **meusite.com** and the app is called **MeuApp**, the **Package Name** could be **com.meusite.meuapp**.

#### **How to locate the Package Name:**

Ask the developer to access the **build.gradle** file of the app module. Inside the **defaultConfig** object, locate the **applicationId** variable, which will contain the **Package Name**. This value will be **unique** for each supported app.

This information is **essential** for the **correct integration with the SDK** and for **accurately identifying the app** in the store and on devices.

<figure><img src="/files/6jc436uMcb8EiMwNN6Iz" alt=""><figcaption><p><strong>Figure 25: Example app with the Build.Gradle file open and the applicationId variable highlighted</strong></p></figcaption></figure>

#### **Version Codes - Application Version Identification**

The **Version Code** represents the version of the application and is used by **First Tech** to identify which product versions are valid for the **Tap to Phone SDK** during the **session creation phase**. This parameter is **cumulative**, meaning all valid versions must be sent, allowing multiple versions to be active simultaneously.

#### **Important Notes about Version Code:**

* The list of valid versions must include **all corresponding strings**, as only the **latest version** provided will be considered as the reference.
* Clients can submit **future versions**, allowing app updates to be performed without the need to immediately open new support tickets.
* It is a good practice to **notify First Tech** when older versions are no longer valid. This prevents transactions on those versions and forces end users to update the app, ensuring **greater security and compatibility**.

**How to Identify the Version Code:**

Follow the same procedure used to locate the **Package Name**, but look for the **versionCode** variable inside the **defaultConfig** object in the **build.gradle** file of the app module.

Ensuring the correct submission of this information is **essential for secure and efficient operation**.

<figure><img src="/files/3xnSjYtxI0aXfsoADIA4" alt=""><figcaption><p><strong>Figure 26: Example React Native app with the Build.Gradle file open and the versionCode variable displayed</strong></p></figcaption></figure>

**Example of Sending Data by Email to Enable Version in Production**

> Dear First Tech Team, good morning!
>
> Could you please enable our app in production?\
> Here are the details:
>
> **SHA-256 of the app on the store:** BD : 92 : 64 : B0 : 1A : B9 : 08 : 08 : FC : FE : 7F : 94 : B2\
> **Package Name of the app:** com.notke.paymentapp\
> **Version Codes:** 20, 21, 22, 23, 24, and 25

For **Tap to Phone SDK versions** above **1.0.20**, the **application registration process** in production will return to the developer **three fields** that should be used **exclusively in the production environment**. These fields should be added in the SDK call within the **StartPayment** method. The variables are:

{% code lineNumbers="true" %}

```
Client Id
Cliente Secret
Scope
```

{% endcode %}

These variables must be included in the call along with the **CPF**, **CNPJ**, **Customer ID**, and other information that the SDK already requests from customers. They are **essential** to complete the **session creation process** and allow progression to the following steps. Additional details about these variables can be found in the **technical specifications** intended for the developer.

If this step is not performed correctly, the **TerminalSessionCreatedErrorViewData** view will display the **DEVICE\_STATE\_FAILURE** error, which is the most common issue encountered during the **session activation** phase.

Other minor and rarer issues may also occur during the **session activation process**. Below, we list these issues along with their possible solutions:

| Error Returned by the View               | Cause                                                                                                                                                                            | Solution                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| INTERNAL\_ERROR                          | Generic Internal SDK Error                                                                                                                                                       | <p>This is an <strong>internal product failure</strong> that currently has <strong>no available mitigation procedure</strong>.</p><p>The error contains <strong>additional details</strong> in the <strong>exception field</strong>, which will be analyzed by the <strong>First Tech team</strong>. It is recommended to <strong>open a support ticket</strong> with <strong>First Tech</strong>, attaching the <strong>collected logs</strong>, to enable <strong>immediate investigation</strong>.</p>                                                                                                              |
| DEACTIVATED                              | The terminal was deactivated during the session creation process.                                                                                                                | <p>This may occur due to a <strong>manual action</strong> taken by the <strong>acquirer</strong>, by <strong>First Tech</strong> in cases of suspected fraud, or at the <strong>merchant's</strong> request.</p><p>The customer should <strong>restart the application</strong> to attempt creating a new terminal. If the error persists, there may be an issue with the SDK, and it is recommended to <strong>open a support ticket</strong> for the <strong>First Tech team</strong> to investigate the cause.</p>                                                                                                  |
| CONFIGURATION\_VALIDATION\_HASH\_FAILURE | The EMV configuration file (known as EMV Config) has been invalidated for security reasons or is being updated by the First Tech team for all users of the client's application. | <p>The <strong>EMV configuration file</strong> defines the types of products and cards recognized during the <strong>TTP reading phase</strong>. Its update is automatically checked with each new transaction, and if necessary, it will be performed at that time.</p><p>Advise the customer to <strong>wait a few minutes</strong> and try the transaction again. If the error persists, <strong>open a support ticket</strong> for the <strong>First Tech team</strong> to investigate the issue immediately.</p>                                                                                                  |
| NFC\_ERROR                               | The NFC has been requested by another application for use or has been disabled on Android.                                                                                       | Ask the customer to **close all applications**, check if **NFC is enabled** on the Android device, and confirm if the device **supports NFC**. Once these issues are addressed, try performing the operation again.                                                                                                                                                                                                                                                                                                                                                                                                    |
| NETWORK\_ERROR                           | The app has no internet access or there was a failure in the back-end server.                                                                                                    | <p>Guide the device holder to <strong>open a browser</strong> and access any website or use a <strong>speed test tool</strong> to check the <strong>connection quality</strong>.</p><p>Whenever possible, use <strong>high-speed and low-latency networks</strong>, preferably by connecting to a <strong>reliable Wi-Fi network</strong>.</p><p>If the problem persists even with internet connectivity, it is likely that the issue lies with the <strong>back-end</strong>. In this case, it is recommended to <strong>open a support ticket</strong> for <strong>First Tech</strong> to investigate the cause.</p> |

### **Bringing the Card Close and Starting the Transaction**

If the terminal and session are successfully activated, the device will be ready to perform the **card proximity**. To avoid issues, it is recommended to refer to **Section 7: Troubleshooting During Testing and Production** for best practices on handling the device, ensuring that the application does not experience **read timeouts** caused by improper card positioning or difficulties with the NFC reader within the time allowed for the operation.

Additionally, other important factors include:

* **Stable network:** Ensure that the connection is reliable to prevent interruptions.
* **Valid card:** Use an **active card**, not expired, with available balance or limit, and with the **proximity payment function** activated.
* **Correct card mode:** Some **neobanks** have inverted debit and credit functions. For example, using a debit card as credit may result in the error "**No application selector for the card**".

Another point of attention is during the **programming phase**. Ensure that the **PaymentType enums** are correctly configured, as **reversed values** can lead to similar failures.

A **rarer, but possible situation** is the **difficulty in reading newer or less common cards** due to the absence of **Application IDs** in the **SDK database**. This problem may also generate the error "**No application selector for the card**." In this case, it will be necessary to **open a ticket** so that **First Tech**, in collaboration with the **acquirer**, can review the tables responsible for recognizing the card and implement the necessary updates. The **SDK will be automatically updated**, with no action required from the developer, on the next transaction attempt.

At this point, the errors displayed in the **TerminalPaymentErrorViewData** view may have two distinct origins:

* **Errors related to the SDK.**
* **Errors related to authorization.**

Here are the common errors related to the SDK and their possible solutions:

| Error Returned by the View                                        | Cause                                                                                                         | Solution                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| NETWORK\_CONNECTION\_ERROR                                        | The device has no internet access during the terminal creation process.                                       | <p>Ask the device holder to <strong>open a browser</strong> and access any website or use a <strong>speed test tool</strong> to check the <strong>connection quality</strong>.</p><p>Ideally, always use <strong>high-speed and low-latency networks</strong>, preferably by connecting to a <strong>reliable Wi-Fi network</strong> whenever possible.</p>                                                                                                                                                                                                                                                                                                                                                                                         |
| MICROPHONE\_USAGE\_DETECTED                                       | Another app or process is using the microphone hardware.                                                      | The microphone needs to be **blocked** during the use of apps that might potentially be using the resource. **Close all programs** and reopen the app for a new attempt.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| <p>CAMERA\_USAGE\_DETECTED</p><p>EXTERNAL\_CAMERA\_DETECTED</p>   | Another app or process is using the front or external camera hardware of the phone.                           | The cameras need to be **blocked** during the use of apps that might potentially be using the resource. **Close all programs** and reopen the app for a new attempt.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| TOTAL\_ELAPSED\_TIMEOUT                                           | <p>The total operation time from card reading to transaction approval has been exceeded.</p><p></p>           | <p>The SDK is configured for a total transaction time of <strong>60 seconds</strong> in these stages, and this time is set directly by <strong>First Tech</strong> in the <strong>EMV Config files</strong>, which are verified and updated with each transaction. This is a more than reasonable time to complete the entire process. This error appears when there has been no interaction from the customer to bring the card close, or the <strong>transaction authorization time</strong> is too long.</p><p>We recommend opening a support ticket with <strong>First Tech</strong>, including a <strong>video recording</strong> of the app's behavior to better understand the cause.</p>                                                    |
| DISCOVERY\_TIMEOUT                                                | The designated time for card reading has expired.                                                             | <p>This problem may be caused by an issue with <strong>device handling</strong> or difficulty in reading the card, which may be <strong>damaged</strong> or <strong>invalid</strong>.</p><p>We recommend the following:</p><ol><li><strong>Test the same app on another device.</strong></li><li><strong>Test the same device with a different card</strong>, preferably from the same <strong>network</strong> and in the same <strong>mode</strong> (debit/credit).</li></ol>                                                                                                                                                                                                                                                                     |
| <p>PIN\_ENTRY\_ACCUMULATED\_TIMEOUT</p><p>PIN\_ENTRY\_TIMEOUT</p> | The time for displaying the PIN screen and entering the password has expired.                                 | <p>The <strong>PIN screen</strong> is presented through a <strong>cryptographic process</strong> for its generation between the SDK and the back-end. In addition to this time, there is also the <strong>time it takes for the user to enter the card PIN</strong>. The combination of these two times may cause this error.</p><p><strong>Test the transaction again</strong> to check if the behavior persists. If the issue occurs every two or three interactions, it may be necessary to <strong>increase the time</strong> for <strong>PIN entry</strong> or there might be a <strong>cryptographic error on the back-end</strong>. In this case, <strong>open a support ticket</strong> for <strong>First Tech</strong> to investigate.</p> |
| AUTHORIZATION\_IN\_PROGRESS\_TIMEOUT                              | <p>The transaction cannot be authorized within the maximum time set for transaction authorization.</p><p></p> | <p>There is a <strong>delay greater than expected</strong> between the SDK back-end and the <strong>Acquirer</strong>.</p><p>If the client has access to the panel with their transactions, it is helpful to check if the transaction was <strong>registered</strong> and is <strong>awaiting confirmation</strong>.</p><p>If there is no visibility within the <strong>acquirer context</strong>, it is likely that there was a <strong>problem in the SDK back-end</strong> in sending this message. In this case, <strong>open a ticket</strong> with <strong>First Tech</strong>, including the <strong>transaction evidence</strong> that is available.</p>                                                                                    |
| INTERNAL\_ERROR                                                   | Generic internal SDK error.                                                                                   | <p>This is an <strong>internal product failure</strong> that currently has <strong>no available mitigation procedure</strong>.<br>The error contains <strong>additional details</strong> in the <strong>exception field</strong>, which will be analyzed by the <strong>First Tech team</strong>.<br>It is recommended to <strong>open a support ticket</strong> with <strong>First Tech</strong>, attaching the <strong>collected logs</strong>, to enable <strong>immediate investigation</strong>.</p>                                                                                                                                                                                                                                           |
| HOST\_CALLBACK\_ERROR                                             | <p>The SDK is not receiving the approved or denied transaction response from the back-end.</p><p></p>         | <p>The <strong>Acquirer</strong> and <strong>First Tech</strong> need to verify the issue together.</p><p>If the transaction is indeed <strong>waiting for approval</strong> and there has been no response, the issue needs to be investigated with the <strong>acquirer</strong> by opening a <strong>specific support ticket</strong>.</p><p>If the transaction can be tracked on the <strong>acquirer’s console</strong> and already has a <strong>confirmed</strong> or <strong>denied</strong> status, then it is necessary to <strong>open a ticket with First Tech</strong>.</p>                                                                                                                                                            |
| PIN\_PAD\_OBSCURED\_ERROR                                         | An app with "appear on top of other apps" permission interfered with the PIN entry screen when it appeared.   | Find the app with this behavior and **uninstall it** or **temporarily remove this permission**. Then, **close the app** and **open it again** to perform the transaction.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| PIN\_PAD\_DETACHED\_ERROR                                         | The PIN screen process was manually closed on Android.                                                        | Close and reopen the app, then repeat the transaction. If the error persists, try to identify apps that might be causing this behavior. If that's not the case, **open a ticket with First Tech** to report the issue.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| PIN\_PAD\_LAUNCH\_TIMEOUT                                         | The PIN screen took more than 2 seconds to display.                                                           | Try a new transaction. If the issue persists, **open a ticket with First Tech** to report the problem.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| NFC\_ERROR                                                        | NFC has been requested by another app for use or has been disabled on Android.                                | Ask the customer to **close all applications**, check if **NFC is enabled** on the Android device, and confirm if the device **supports NFC**. Once these issues are resolved, try performing the operation again.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |

The transaction can also be **denied due to authorization failures** with the acquirer. This is related to **card failures**, **fraud prevention rules**, **password issues**, and the **availability of the payment ecosystem**: authorization services from card networks, acquirer availability, and others. The returned errors are aligned with **ABECS Normative 21**, which can be found [here ](https://api.abecs.org.br/wp-content/uploads/2019/09/Normativo-021.pdf)for issues with the acquirer.

It is important that these returns are displayed to customers, mimicking the behavior of a **common POS**, and providing visibility into errors that may or may not be retried. This helps protect the **merchant** from being charged fees for **misuse of authorization attempts** by the acquirer through the card networks (Visa, Mastercard, and Elo).

To verify these errors, in addition to the response in the **TerminalPaymentSuccessViewData** and **TerminalPaymentErrorViewData** views, respectively for transaction approvals and denials, the **meta field** will return an object with the details of this transaction from the **acquirer side**, indicating the authorization processing.

**Example of the Meta Field Filled if the Transaction is Denied**

```json
{
   "providerResponse": {
      "mti": "2210",
      "processingCode": "002000",
      "amount": "9862000000000041",
      "transmitionDateTime": "20250123133118",
      "stan": "842379",
      "transactionDateTime": "20250123133117",
      "authorizerId": "16",
      "muxipayResponseCode": "8001",
      "authorizerResponseCode": "05",
      "terminalId": "00000007",
      "merchantId": "00595154000173",
      "emvTags": "8a023035",
      "customerId": "FIRSTTECH",
      "displayCustomerMessage": "TRANSACAO NEGADA\nCONTATE A\nCENTRAL DO SEU\nCARTAO",
      "trackingNumber": "020001419451",
      "muxipayUniversalId": "00ad54c01b8d064501e1ec6b34df8eac",
      "initializationRequired": "10",
      "hostStan": "000725",
      "error": {
         "code": "invalid operation",
         "message": "Error occurred on authorize message",
         "metadata": {
            "acquirer": "rejected",
            "authorizer": "do_not_honour"
         }
      }
   },
   "error": {
      "type": "acquirer",
      "code": "invalid operation",
      "message": "Error occurred on authorize message",
      "metadata": {
         "acquirer": "rejected",
         "authorizer": "do_not_honour"
      }
   },
   "status": "COMPLETED_WITH_ERROR",
   "reason": "OPERATION_ERROR"
}

```

**Example of the Meta Field Filled if the Transaction is Authorized**

```json
{
   "mti": "2210",
   "muxipayUniversalId": "67bea6f89c319638f35e2b9273739df5",
   "receipt": {
      "merchant": {
         "message": "DOCK - Via Loja\n\nFIRST CUSTOMER\nCNPJ: 10179118609\nTID: 020001419130\n\n*** *** **** 5461\nMASTERCARD\nAID: A0000000041010\n23/01/25                         13:04\nCV: 855614\nValor: R$ 0,23\nForma de pagamento: Crédito\nÀ vista\nTerm: 00000486\n\nDADOS ORIGINAIS DA VENDA\nValor: R$ 0,23\nTerm: 00000486\nTransação autorizada pelo emissor\n"
      },
      "customer": {
         "message": "DOCK - Via Cliente\n\nFIRST CUSTOMER\nCNPJ: 10179118609\nTID: 020001419130\n\n*** *** **** 5461\nMASTERCARD\nAID: A0000000041010\n23/01/25                         13:04\nCV: 855614\nValor: R$ 0,23\nForma de pagamento: Crédito\nÀ vista\nTerm: 00000486\n\nDADOS ORIGINAIS DA VENDA\nValor: R$ 0,23\nTerm: 00000486\nTransação autorizada pelo emissor\n"
      }
   },
   "displayMessages": {
      "customer": "TRANSACAO APROVADA"
   },
   "providerResponse": {
      "mti": "2210",
      "processingCode": "003000",
      "amount": "9862000000000023",
      "transmitionDateTime": "20250123130431",
      "stan": "855614",
      "transactionDateTime": "20250123130429",
      "authorizerId": "16",
      "retrievalReferenceNumber": "020001419130",
      "authorizationCode": "043063",
      "muxipayResponseCode": "8000",
      "authorizerResponseCode": "00",
      "terminalId": "00000486",
      "merchantId": "10179118609",
      "emvTags": "8a023030",
      "customerId": "BIPPAGAMENTOS",
      "displayCustomerMessage": "TRANSACAO APROVADA",
      "trackingNumber": "020001419130",
      "muxipayUniversalId": "67bea6f89c319638f35e2b9273739df5",
      "initializationRequired": "10",
      "hostStan": "000012"
   },
   "status": "COMPLETED_SUCCESSFULLY",
   "reason": "COMPLETED_SUCCESSFULLY"
}

```


# SDK implementation (TTP)

Below is a step-by-step guide on how to create a project, integrate the dependency of our SDK (TTP), and use the method contained in the *ViewModel*.\
The guide consists of the following steps:

1. Project creation
2. Adding the repository
3. Downloading dependencies
4. Implementing the use of the SDK


# Project creation

This topic shows how to implement the TTP SDK, from creating the project to using the method to initiate payments. Code examples are available in the repository:

{% embed url="<https://bitbucket.org/first-tech-tecnologia/taponphone-mobileapp-mpp-native/src/main/>" %}

{% stepper %}
{% step %}
Open Android Studio and select “New Project”.

<figure><img src="/files/pjESuz2eRMjZ5h5jNkzw" alt=""><figcaption></figcaption></figure>

{% endstep %}

{% step %}
Now select the type of view system you prefer. To proceed with this example, we're going to use the XML-based view system.

<figure><img src="/files/FcP8L33knQpzuCprVmec" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}
Give your application a name. In addition, for this example we will set the minimum API to 30.

<figure><img src="/files/JWON3V0RrK9uhnRqb5sk" alt=""><figcaption></figcaption></figure>
{% endstep %}
{% endstepper %}


# Adding a Repository

{% stepper %}
{% step %}
In the “settings.gradle.kts” file, add the Nexus repository so that you can download the SDK dependency (TTP)

<figure><img src="/files/3GNWWovgTxojElAlxtlR" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}
Add the code snippet below inside the dependencyResolutionManagement block in the settings.gradle.kts file.

```
  maven {
            name = "Nexus"
            url = uri("https://nexus.first-tech.net/repository/taponphone-dock/")
            credentials {
                       username = "XXXXXXXXXXXXX"
                       password = "YYYYYYYYYYYYY"
            }
        }
```

{% endstep %}

{% step %}
After adding the code, the settings.gradle.kts file will look like this

<figure><img src="/files/gnOqSDC2DV8DtsPruG2N" alt=""><figcaption></figcaption></figure>
{% endstep %}
{% endstepper %}


# Downloading dependencies

{% stepper %}
{% step %}
Now, let's define our dependencies and their versions. Open the libs.versions.toml file, which is in the gradle folder.

We'll define the number of versions. The dependencies will be separated into hml and prod in the \[versions] section.

Ex: `taponphoneSdkV2HML = "1.0.23"`&#x20;

Then define the dependency in the \[libraries] section.

`= "com.first-tech:taponphone-sdk-v2-hml", version.ref = "taponphoneSdkV2HML" }`
{% endstep %}

{% step %}
With all the changes completed, the libs.versions.toml file will look like this:

<figure><img src="/files/AhswsqrQVKFUFOrCNqGt" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}
Now let's consume the SDK dependency (TTP) in the build.gradle.kts file of the application module (app). To do this, add the code snippet below in the dependencies block. We'll add each type of dependency separately: dev, hml and prod.

`"hmlImplementation"(libs.taponphone.sdk.v2.homol)`\
`"releaseImplementation"(libs.taponphone.sdk.v2.release)`&#x20;

<figure><img src="/files/2cDbAMLnNlItrMoX6G5g" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}
The build.gradle.kts file will look like this.

<figure><img src="/files/b6ibqs2Yne7FoN5HCsIy" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}
In the “buildTypes” topic, we'll add the following code snippet. So that the dependency is downloaded according to our build type.

```
release {
    resValue("string", "app_name", "taponphone-mobileapp-mpp-native")
    isMinifyEnabled = false
    proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
​
}
create("hml") {
    resValue("string", "app_name", "[HML] taponphone-mobileapp-mpp-native")
    applicationIdSuffix = ".hml"
    signingConfig = signingConfigs.getByName("debug")
}
```

{% endstep %}

{% step %}
Nosso arquivo build.gradle.kts,ficara com a seguinte maneira.Após adicionar o trecho de código, clique em Sync Now para realizar a sincronização e baixar a dependência do SDK (TTP).

<figure><img src="/files/HuAMHSQSznK2CCdN0vQO" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}
Depois disso, em External Libraries, veja que a dependência do SDK (TTP) foi baixada com sucesso. Agora, ela está disponível para uso.

<figure><img src="/files/gRuxPSMHYCWkZeHeoUBo" alt=""><figcaption></figcaption></figure>
{% endstep %}
{% endstepper %}


# Implementing the use of the SDK

{% stepper %}
{% step %}
Now that the dependency has been set up, you need to carry out the initial configuration. These settings are necessary to start the payment SDK. Let's define these settings in the Application class.

Create a class that extends Application and define the payment settings.

In your project's initialization class (Application), you should “extend” TapOnPhoneApplication

Call the isApplicationInitAllowed() method to check that the application can be initialized.

`if (!TapOnPhoneInitializer.isApplicationInitAllowed(this)) return`&#x20;

`TapOnPhoneInitializer.initializeTerminal(this)` <br>

The static initializeTerminal() method of the TapOnPhoneInitializer class must be executed. It initializes the terminal, an essential step for using the SDK.

<br>

To define the initial settings, run the `setTerminalConfig(config: TerminalConfigEntity)` method. To do this, create a TerminalConfigEntity object. The values entered below are for the sandbox scenario.

```
data class TerminalConfigEntity(
    val companyDocument: String?, // O número do CNPJ (Cadastro Nacional de Pessoa Jurídica) da empresa. - Contém o número do CNPJ da empresa.
    val companyName: String?,     // O nome da empresa.
    val merchantId: UUID?,        // O identificador único do comerciante, fornecido pela equipe FirstTech.
    val terminalNumber: String?,  // O número único atribuído ao terminal, fornecido pela equipe FirstTech.
    val clientId: String?,        // O ID do Cliente usado para autenticação, fornecido pela equipe FirstTech. 
    val clientSecret: String?,    // O Client Secret usado para autenticação, fornecido pela equipe FirstTech.
    val sdkScope: String?,        // O escopo necessário para autenticação do SDK, fornecido pela equipe FirstTech e enviado pelo consumidor deste SDK.
    val sdkClientId: String?,     // O ID do Cliente para autenticação do SDK, fornecido pela equipe FirstTech e enviado pelo consumidor deste SDK.
    val sdkClientSecret: String?, // O Client Secret para autenticação do SDK, fornecido pela equipe FirstTech e enviado pelo consumidor deste SDK.
    val packageName: String?,     // O nome do pacote da aplicação do cliente, enviado pelo consumidor deste SDK.O Nome do Pacote é usado para referência de onde a aplicação do cliente está sendo executada, enviado pelo consumidor deste SDK.
    val appVersion: String?,      // A versão atual da aplicação do cliente, enviado pelo consumidor deste SDK. - A Versão do Aplicativo é uma informação sobre a versão do aplicativo do cliente atual, enviado pelo consumidor deste SDK.
    val sdkOrganization: String?  // O nome da organização, enviado pelo consumidor deste SDK.
)
```

At the end of this process, the file structure should look like the one below.

Important: The values shown refer to the sandbox environment.

<figure><img src="/files/tacZWl7cWcjJP554EixH" alt=""><figcaption></figcaption></figure>

{% endstep %}

{% step %}
The project is already set up. Next, let's modify MainActivity. Below is an example layout to illustrate the use of our SDK. Feel free to adapt it to suit your layout. Our activity follows this model.

<figure><img src="/files/M89aO6REcBL5Cp6tNKbz" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}
All of the SDK's manipulation operations are carried out via the ViewModel, which receives the TapOnPhoneApplication as a parameter when it is created.

At the start of the Activity, we have the following declarations:

```
private val progressDialog by lazy { ProgressDialog(this) } //<- This Android user interface component is used to show a progress dialog box.
private val binding: ActivityMainBinding by lazy { ActivityMainBinding.inflate(layoutInflater) } //<- Define the binding variable as ActivityMainBinding. //<- This is a class automatically generated by Android's View Binding feature.
private val mppProviderViewModel by lazy { MPPPProviderViewModel(application as Application) } //<- ViewModel to manage the data and logic of the user interface.
```

```

  override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)
        setupView()
        setupObserver()
        askPermission()
        getVersionCode()
    }
```

<br>
{% endstep %}

{% step %}
Our MainActivity looks like this.

<figure><img src="/files/MMANdfA9UIeRHeyJCRAl" alt=""><figcaption></figcaption></figure>

**OBS**: We use the **askPermission** method to request permission to collect the user's location, information that will be used for better error analysis later.

```
private fun askPermission() {
        val permissionsToRequest = mutableListOf<String>()

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
            != PackageManager.PERMISSION_GRANTED
        ) {
            permissionsToRequest.add(Manifest.permission.ACCESS_FINE_LOCATION)
        }


        if (permissionsToRequest.isNotEmpty()) {
            Log.d("Signal", "Solicitando permissões.")

            ActivityCompat.requestPermissions(
                this,
                permissionsToRequest.toTypedArray(),
                ALL_PERMISSIONS_REQUEST_CODE
            )
        } else {
            Log.d("Signal", "Todas as permissões já concedidas.")
        }
    }
```

{% endstep %}

{% step %}
Start a payment

<br>

Execute the startPaymentFlow() function provided by MPPProviderViewModel. To do this, you need to pass the TransactionInfoEntity class as a parameter, which receives the following values in its constructor.

`installments:`An integer containing the number of parcels

`paymentType:`  One of the options  `PaymentType` , which can be `PaymentType.DEBIT`  or `PaymentType.CREDIT`

`amount:`  The total amount of the transaction, expressed `Long` .

| Value    | Long |
| -------- | ---- |
| R$ 23,34 | 2334 |
| R$ 15,00 | 1500 |
| R$ 0,15  | 15   |
| R$0,01   | 1    |

```
 private fun startPayment() {
   mppProviderViewModel.startPaymentFlow( // <- Este é o método que inicia o fluxo de pagamento
        TransactionInfoEntity(
            operationType, //<- Define o tipo da operação
            ((binding.etValor.text.toString().toDigits() ?: 0.0) * 100).toLong(), // <- Valor da transação, multiplicado por 100 (para representar centavos)
            binding.etInstallments.text.toString().toInt() //<- Número de parcelas  //<- Número de parcelas (quando o pagamento é a crédito)
            )
        )
    }
    
```

<figure><img src="/files/56C4zR1mDxzVrL36uwVN" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Manual stoppage of the payment process
{% endhint %}

If the payment flow is terminated, either by user action or by an internal flow of the application itself, you must use the method provided to terminate the session (transaction). The **clearCurrentTerminalSession()** method of the SessionHelper object must be called. This action is essential because otherwise the previous session would remain active. Consequently, when trying to move on to the transaction screen again, there would be an error in creating a new session, since there would already be one in progress.

This method can be called at any point in your application. In the examples below, we demonstrate how to implement it in Kotlin and React Native.

To use it in Kotlin, just call the following method:

```
SessionHelper.clearCurrentTerminalSession()
```

In the React Native application, we will use the “Back” button to trigger the session termination method provided by the SDK. The implementation detailed below is specific to the **React Native** environment.

```
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import com.facebook.react.bridge.Promise
import com.firsttech.taponphone.sdk.v2.utils.DeviceInformationUtils
import com.firsttech.taponphone.sdk.v2.utils.SessionHelper
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import android.util.Log
​
class DeviceInfoModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
    override fun getName(): String = "DeviceInfoModule"
​
    @ReactMethod
    fun getDeviceId(promise: Promise) {
        try {
            val id = DeviceInformationUtils.getDeviceIdentifier(reactApplicationContext)
            promise.resolve(id)
        } catch (e: Exception) {
            promise.reject("ERROR", e.message)
        }
    }
​
    @ReactMethod
    fun getDeviceInfo(promise: Promise) {
        CoroutineScope(Dispatchers.Default).launch {
            try {
                val info = DeviceInformationUtils.getDeviceInfo(reactApplicationContext)
                promise.resolve(info)
            } catch (e: Exception) {
                promise.reject("DEVICE_INFO_ERROR", e.message)
            }
        }
    }
    //
​
​
    fun addListener(eventName: String?) {
        // Requerido pelo NativeEventEmitter
    }
​
    fun removeListeners(count: Int) {
        // Requerido pelo NativeEventEmitter
    }
​
    @ReactMethod
    fun clearTerminalSession() {
        try {
            SessionHelper.clearCurrentTerminalSession()
        } catch (e: Exception) {
            Log.e("TerminalModule", "Erro ao limpar sessão do terminal", e)
        }
    }
}
```

Now we'll define how to use our new method, located in the DeviceInfoModule file, via the JavaScript wrapper that we've used before for other functions. Feel free to create a new file dedicated to this functionality or integrate it into the existing file in our sample application.

```

import { NativeModules } from 'react-native';
​
const { DeviceInfoModule } = NativeModules;
​
export function getDeviceInfo(): Promise<string> {
  return DeviceInfoModule.getDeviceInfo();
}
​
export function clearTerminal(): void {
  DeviceInfoModule.clearTerminalSession();
}
```

In our index file (or index.tsx), which defines our application's payment processing screen, we will import the clearTerminal method - previously defined in our native module - to be used when the “Back” button is pressed.

```
import { clearTerminal } from '../../native-modules/DeviceInfoModule
```

We'll also make the following imports

**BackHandler**: Manages Android's physical "Back" button.\
**useFocusEffect**: Executes effects (such as adding listeners from the BackHandler) when the screen gains focus and clears them when it loses focus.\
**useCallback**: Memoizes the function passed to useFocusEffect, optimizing it and ensuring that it is stable, preventing unnecessary recreations and executions of the focus effect.

And in our component that works as a "Back" button, we'll call the clearTerminal() method, implemented earlier. This, in turn, will use the session clearing method implemented in the SDK.

```
 <BackButtonWrapper
            onPress={() => {
              clearTerminal(); 
              goBack();        
            }}
        >
        <BackButtonArrowLeftVector source={arrowLeftVector} />
      </BackButtonWrapper>
```

{% endstep %}

{% step %}
Reacting to messages

The`MPPProviderViewModel` provides o`LiveData onMessage`, which will receive an “extended” object from the `MPPViewData` class.

{% hint style="info" %}
It is important to observe onMessage within the correct lifecycle, ensuring that there are no memory leaks or unexpected reactions.
{% endhint %}

In this project, we used the concept of Sealed Classes for a more efficient abstraction. Below, we list all the objects that can be returned in onMessage and their respective meanings.

Here, we get the reference to `LiveData onMessage` and start observing it:

```
private fun setupObserver() {
   mppProviderViewModel.onMessage.observe(this, ::onMessage)
}
```

{% hint style="info" %}
Note: In this example, we haven't listed all the MPPViewData classes, but we recommend implementing all the classes.

In our repository, our sample will contain a list of all the classes, which we can have in our when
{% endhint %}

{% hint style="info" %}
Note: Some MPPViewData classes contain objects that help you understand the message that should be displayed in a specific step.
{% endhint %}

```

private fun onMessage(viewData: MPPViewData?) {
        viewData?.let {
            when (viewData) {
                MPPViewData.TerminalInitializingViewData -> {
                    showLoadingDialog("Inicializando terminal")
                    binding.tvMessage.text = "Inicializando terminal"
                }
​
                MPPViewData.TerminalInitializingErrorViewData -> {
                    showFeedbackDialog("Erro ao inicializar terminal")
                    progressDialog.dismiss()
                }
​
                MPPViewData.TerminalInitializingSuccessViewData -> {
                    progressDialog.dismiss()
                    binding.tvMessage.text = "Inicialização concluída"
                }
                
                is MPPViewData.TerminalPaymentSuccessViewData -> {
                    enableEditFields(true)
                    binding.tvMessage.text =
                        if (viewData.result.isProcessingResultSuccess()) "Pagamento realizado" else "Pagamento recusado"
                    val metaData = viewData.result.getMetaDataTranslated()
​
                    binding.tvLog.text = "" +
                            "Resultado: ${viewData.result.uiMessage.messageId.sampleUiMessage}" +
                            createReceipt(metaData)
                }
                
                //Mapear todos os cenários de MPPViewData
​
            }
        }
    }

```

In this example TerminalPaymentSuccessViewData is when the transaction was successfully completed.

**OBS: To access the messageJson, retrieve the result you received in viewData and extract the messageJson as follows**

```
val metaData = viewData.result.getMetaDataTranslated()
val messageJson = metaData?.receipt?.merchant?.messageJson
```

{% endstep %}

{% step %}
Printing the receipt on the screen

Here is the implementation of the createReceipt function method, which returns a String. This string is set up to be a receipt and can be customized in any way you need.

<figure><img src="/files/4gJoHzK2l1AbmQOycME3" alt=""><figcaption></figcaption></figure>

```

package com.firsttech.taponphone.app.utils
​
import java.text.NumberFormat
import java.util.Locale
import com.firsttech.taponphone.sdk.v2.models.TransactionCompleted
​
fun createReceipt(metaDataTranslated: TransactionCompleted.Metadata?):String {
    val messageJson = metaDataTranslated?.receipt?.merchant?.messageJson
    val parcelas = messageJson?.transaction?.installments?.total ?: 0
    val valor = messageJson?.transaction?.amount
​
    return "\n${messageJson?.acquirer}" +
            "\n" +
            "\nCNPJ: ${messageJson?.businessDocument}" +
            "\nTID: ${messageJson?.transactionId}" +
            "\n" +
            "\n${messageJson?.card?.number}" +
            "\n${messageJson?.card?.brand}" +
            "\nAID: ${messageJson?.card?.aid}" +
            "\n${messageJson?.transaction?.datetime}" +
            "\nCV: ${messageJson?.transaction?.stan}" +
            "\nValor: ${messageJson?.transaction?.currency} ${valor?.let { it1 -> setCurrencyFormat(it1) }}" +
            "\nForma de Pagamento:  ${messageJson?.transaction?.paymentMethod}" +
            (if(messageJson?.transaction?.paymentMethod.equals("Crédito")){
                "\n${if(parcelas==1)"À vista" else "Valor de cada parcela: ${messageJson?.transaction?.currency} ${setCurrencyFormat(messageJson?.transaction?.installments?.value.toString())}" }" +
                        "\nQuantidade de parcela:  ${messageJson?.transaction?.installments?.total}"
            }else{
                "\n${setTextInstallments(parcelas)}"
            }) +
            "\nTerm: ${messageJson?.terminalCode}" +
            "\n" +
            "\nDADOS ORIGINAIS DA VENDA" +
            "\nValor: ${messageJson?.transaction?.currency} ${messageJson?.transaction?.amount?.let { it1 ->
                setCurrencyFormat(
                    it1
                )
            }}" +
            "\nTerm: ${messageJson?.terminalCode}" +
            "\n${messageJson?.transaction?.messageAuthorizedBy}"
}
​
private fun setCurrencyFormat(amount:String): String {
    val formatCurrency = NumberFormat.getCurrencyInstance(Locale("pt", "BR"))
    val amountToDouble = formatCurrency.format(amount.toDouble())
​
    val amountConverted = amountToDouble.replace("R$", "").trim()
    return amountConverted
}
private fun setTextInstallments(installements:Int): String {
    return if (installements==1) "À vista" else "Parcelado em $installements vezes"
}
```

Here's an example of the JSON with the messageJson field that we used to create our receipt

```

"receipt":{
      "merchant":{
         "message":"Via Loja\n\nCNPJ: 00.595.154/0001-73\nTID: 010000865033\n\n**** **** **** 2029\nMASTERCARD\nAID: A0000000041010\n17/06/25 11:32\nCV: 241393\nValor: R$ 50,00\nForma de pagamento: Crédito\nValor de cada parcela: 5\nQuantidade de parcelas: 10\nTerm: 00000026\n\nDADOS ORIGINAIS DA VENDA\nValor: R$ 50,00\nTerm: 00000026\nTransação autorizada pelo emissor\n",
         "messageJson":{
            "acquirer":"Via Loja",
            "merchant":"First Customer",
            "businessDocument":"00.595.154/0001-73",
            "transactionId":"010000865033",
            "card":{
               "number":"**** **** **** 2029",
               "brand":"MASTERCARD",
               "aid":"A0000000041010"
            },
            "transaction":{
               "amount":50,
               "currency":"BRL",
               "datetime":"17/06/25 11:32:25",
               "stan":"241393",
               "installments":{
                  "value":5,
                  "total":10
               },
               "paymentMethod":"Crédito",
               "messageAuthorizedBy":"Transação autorizada pelo emissor"
            },
            "terminalCode":"00000026"
         }
      },
```

Description of each messageJson field

* **acquirer** → Name of the acquirer or payment facilitator (e.g., "Via Loja")
* **merchant** → Name of the merchant or store (e.g., "First Customer")
* **businessDocument** → Tax ID of the merchant (CNPJ in Brazil)
* **transactionId** → Transaction identifier (TID - Terminal ID)
* **card** → Information about the card used in the transaction:
  * **number** → Masked card number (last visible digits)
  * **brand** → Card brand (e.g., MASTERCARD, VISA)
  * **aid** → Application Identifier (EMV card type identifier)
* **transaction** → Details of the transaction:
  * **amount** → Total transaction amount (e.g., 50)
  * **currency** → Currency used in the transaction (e.g., BRL)
  * **datetime** → Date and time of the transaction
  * **stan** → CV or STAN (System Trace Audit Number) — unique transaction identifier
  * **installments** → Installment details:
    * **value** → Value of each installment
    * **total** → Total number of installments
  * **paymentMethod** → Payment method (e.g., Credit)
  * **messageAuthorizedBy** → Authorization message of the transaction (e.g., "Transaction authorized by issuer")
* **terminalCode** → Code of the terminal (e.g., POS device) that processed the transaction
  {% endstep %}

{% step %}
Minimum value lock

Starting with version 1.0.29, the SDK has the function of preventing a transaction from being initiated if the transaction value exceeds the minimum limit previously registered in the back-end.

Below is the implementation of how this should be done when this condition is met, giving us the option to send a message as feedback to the user

Following the same example above, “6-Responding to messages,” from the moment version 1.0.29 is consumed, Kotlin itself will inform that a new viewData (“TerminalPaymentValueBelowMinimumLimitViewData”) has not been placed as a condition within the when.

We will insert this new condition and within it we will place the message that will be displayed to the user. Within viewData, we have the field (minValue), which will contain the registered minimum value

Kotlin

Here is an example of implementation

```
     is MPPViewData.TerminalPaymentValueBelowMinimunLimitViewData -> {
                    progressDialog.dismiss()
                    showFeedbackDialog("O valor do pagamento está abaixo do limite mínimo R$${viewData.minValue}")
                    binding.tvMessage.text = "O valor do pagamento está abaixo do limite mínimo."
                }
            }
```

React

Follow the implementation example

```
    is MPPViewData.TerminalPaymentValueBelowMinimunLimitViewData ->{
                      sendErrorMessage("O valor do pagamento está abaixo do limite mínimo R$${viewData.minValue}")
                }

```

{% endstep %}

{% step %}
Responding to invalid transactions

Starting with version 1.0.30, the SDK prevents a transaction from being initiated if certain parameters are incorrect (amount and installments).

When this occurs, specific **ViewData** (**PaymentInformationInvalidViewData**) will be sent.

The app needs to listen for these messages and, when this ViewData appears, **notify the user with a message.**

Kotlin

Follow the implementation example

```
  is  MPPViewData.PaymentInformationInvalidViewData -> {
                    showFeedbackDialog("Pagamento com parametros incorretos.")
                    binding.tvMessage.text = "Revise as condições de pagamento."
                }
```

React Native

Follow the implementation example

```
           is MPPViewData.PaymentInformationInvalidViewData -> {
                    sendErrorMessage("Condicoes de pagamento incorretos.")
                }
```

{% endstep %}
{% endstepper %}


# Migrating versions


# Upgrading from version 1.0.22 to version 1.0.25v19

In version 1.0.22 and earlier, in order to initialize the SDK it was necessary to extend the `TapOnPhoneApplication` class. This class, in turn, extended `Application()`, and many applications have their own class that extends `Application()`. As Android doesn't allow multiple inheritance of Application, this could cause an error in the application, as two Application classes were being extended. To fix this, we no longer require `TapOnPhoneApplication()` to be extended, but we now require it to be initialized with the `TapOnPhoneInitializer` class.

Below is how the implementation was done in version 1.0.22 and earlier.

```
class Application : TapOnPhoneApplication() {
    override val terminalConfig = TerminalConfigEntity(
        companyDocument = BuildConfig.COMPANY_DOCUMENT,
        companyName = BuildConfig.COMPANY_NAME,
        merchantId = UUID.fromString(BuildConfig.MERCHANT_ID),
        terminalNumber = BuildConfig.TERMINAL_NUMBER,
        clientId = BuildConfig.CLIENT_ID,
        clientSecret = BuildConfig.CLIENT_SECRET
    )
}
```

As of version 1.0.25v19, the implementation is as follows:

```
class Application : Application() {
​
    override fun onCreate() {
        super.onCreate()
​
        if (!TapOnPhoneInitializer.isApplicationInitAllowed(this)) return
​
        TapOnPhoneInitializer.initializeTerminal(this)
​
        TapOnPhoneInitializer.setTerminalConfig(
            TerminalConfigEntity(
                companyDocument = BuildConfig.COMPANY_DOCUMENT,
                companyName = BuildConfig.COMPANY_NAME,
                merchantId = UUID.fromString(BuildConfig.MERCHANT_ID),
                terminalNumber = BuildConfig.TERMINAL_NUMBER,
                clientId = BuildConfig.CLIENT_ID,
                clientSecret = BuildConfig.CLIENT_SECRET,
                sdkScope = BuildConfig.SDK_SCOPE,
                sdkClientId = BuildConfig.SKD_CLIENT_ID,
                sdkClientSecret = BuildConfig.SDK_CLIENT_SECRET,
                appVersion = "1.0.0",
                packageName = applicationContext.packageName,
                sdkOrganization = "Organization 123",
                versionCode = (if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                    packageManager.getPackageInfo(packageName, 0).longVersionCode
                } else {
                    packageManager.getPackageInfo(packageName, 0).versionCode.toLong()
                }).toString()
            )
        )
    }
}
```


# 1.0.26

Fix Closing Session

This topic deals with the session end functionality, which is triggered when a customer, after starting a transaction, returns to the previous screen (the value entry screen). In this situation, the previous session remains in progress. Consequently, when trying to go back to the transaction screen, an error occurred when creating a new session, as there was already an active one.

We'll use the “Back” button in the React Native application to trigger the session termination method in the SDK. To do this, we'll use our DeviceInfoModule file, created earlier, which acts as a bridge (Native Module) between the native functions written in Kotlin (Android) and the React Native JavaScript environment. There is the flexibility of creating a new file dedicated to this functionality or keeping the functions in the same file.\
The method we're going to use is **clearTerminalSession**.

```
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import com.facebook.react.bridge.Promise
import com.firsttech.taponphone.sdk.v2.utils.DeviceInformationUtils
import com.firsttech.taponphone.sdk.v2.utils.SessionHelper
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import android.util.Log

class DeviceInfoModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
    override fun getName(): String = "DeviceInfoModule"

    @ReactMethod
    fun getDeviceId(promise: Promise) {
        try {
            val id = DeviceInformationUtils.getDeviceIdentifier(reactApplicationContext)
            promise.resolve(id)
        } catch (e: Exception) {
            promise.reject("ERROR", e.message)
        }
    }

    @ReactMethod
    fun getDeviceInfo(promise: Promise) {
        CoroutineScope(Dispatchers.Default).launch {
            try {
                val info = DeviceInformationUtils.getDeviceInfo(reactApplicationContext)
                promise.resolve(info)
            } catch (e: Exception) {
                promise.reject("DEVICE_INFO_ERROR", e.message)
            }
        }
    }
    //


    fun addListener(eventName: String?) {
        // Requerido pelo NativeEventEmitter
    }

    fun removeListeners(count: Int) {
        // Requerido pelo NativeEventEmitter
    }

    @ReactMethod
    fun clearTerminalSession() {
        try {
            SessionHelper.clearCurrentTerminalSession()
        } catch (e: Exception) {
            Log.e("TerminalModule", "Erro ao limpar sessão do terminal", e)
        }
    }
}

```

Now we'll define how to use our new method, located in the DeviceInfoModule file, via the JavaScript wrapper that we've used before for other functions. Feel free to create a new file dedicated to this functionality or integrate it into the existing file in our sample application.

```

import { NativeModules } from 'react-native';
​
const { DeviceInfoModule } = NativeModules;
​
export function getDeviceInfo(): Promise<string> {
  return DeviceInfoModule.getDeviceInfo();
}
​
export function clearTerminal(): void {
  DeviceInfoModule.clearTerminalSession();
}
```

In our index file (or index.tsx), which defines our application's payment processing screen, we will import the clearTerminal method - previously defined in our native module - to be used when the “Back” button is pressed.

```
import { clearTerminal } from '../../native-modules/DeviceInfoModule';
```

We will also carry out the following imports

```
import { ..., BackHandler } from 'react-native';
import { ..., useCallback } from 'react';
import { ..., useFocusEffect } from '@react-navigation/native';
```

<br>

**BackHandler:** Manages Android's physical "Back" button.

**useFocusEffect:** Executes effects (such as adding listeners from the BackHandler) when the screen gains focus and clears them when it loses focus.

**useCallback:** Memoizes the function passed to useFocusEffect, optimizing it and ensuring that it is stable, preventing unnecessary recreations and executions of the focus effect.

And in our component that works as a "Back" button, we'll call the clearTerminal() method, implemented earlier. This, in turn, will use the session clearing method implemented in the SDK.

```
     <BackButtonWrapper
            onPress={() => {
              clearTerminal(); 
              goBack();        
            }}
        >
        <BackButtonArrowLeftVector source={arrowLeftVector} />
      </BackButtonWrapper>
```


# Best Practices for Handling the Device

### **Identify the Location of the NFC Chip on Your Device**

Failures in Tap to Phone transactions are often caused by delays in positioning the card correctly on the device. The NFC chip location varies between manufacturers and models, and identifying the ideal zone can prevent this issue. Tips for locating the NFC chip:

* Check the mobile device's user manual, which often includes a diagram indicating the physical location of the NFC chip (front, back, or top).
* Test in a staging environment by tapping the card while the application is in test mode.
* Listen to the sounds emitted by the application, which distinguish between successful and unsuccessful taps.
* Move the card calmly, without abrupt movements, until you find the ideal position. Test both sides (front and back).

This practice helps minimize failures, ensuring fast and efficient transactions in production environments.

### **Disable the Phone’s Battery Saver Mode**

Android's battery saver mode can terminate background processes or restrict power allocation to the NFC chip, reducing its efficiency and range. This may cause failures in terminal creation, session setup, or card reading during tap transactions. We recommend disabling this function during the process to ensure proper device operation and maintaining a good battery level to avoid interruptions.

### **Stay on Wi-Fi and Avoid Using the App During Network Changes**

A stable connection is essential for payment data exchange and receipt transmission. To ensure successful transactions, avoid using the application in situations that affect radio signal propagation, such as:

* Entering or exiting elevators, buildings, or construction sites.
* Moving into shadow areas (Wi-Fi/4G dead zones).
* Traveling or transitioning between different network coverage areas.

Remain still next to the customer during the transaction to prevent network fluctuations or switches that could interfere with payment processing and authorization.


# Description and Purpose of the Document

This document aims to establish **minimum standards for the user experience (UX)** in sales applications that implement the **Tap to Pay (TTP)** payment method. It provides guidance on the design, implementation, and validation of interfaces, flows, and behaviors within applications used by sellers (receiving users) and customers (paying users), with a focus on **efficiency, clarity, accessibility, and regulatory compliance**.

The proposed standardization seeks to:

* Promote a **consistent and intuitive experience** across different points of sale (POS) that use TTP;
* Reduce **operational errors and incomplete transactions** caused by interface issues or interaction ambiguities;
* Improve **user trust** by reinforcing perceptions of security, speed, and convenience;
* Comply with **regulatory requirements** associated with proximity payment methods (e.g., PCI MPoC);
* Facilitate **interoperability between systems** and alignment across product, engineering, support, and compliance teams.

This document is intended for **design, product, engineering, QA, and compliance teams**, and must be used as a **mandatory reference** for the development and validation of any application integrating the TTP payment flow—whether on **mobile devices, Android POS terminals, or web-based sales applications**.

The visual examples and illustrative flows contained in this document are **for guidance purposes only** and do not impose specific visual standards, as long as the described guidelines are faithfully followed regarding user experience, clarity, and expected behavior.


# App Initialization

**Objective**

This section defines the **minimum requirements** for the application startup flow, ensuring that the device environment is suitable and secure to process proximity-based payments (Tap to Pay).

**Insights**&#x20;

* Using friendly illustrations is recommended to **reduce friction** during verification.
* The “Continue” button must be visually and functionally linked to a successful security validation.
* This step is **mandatory** to ensure compliance with proximity payment security best practices (e.g., PCI MPoC).

***

<figure><img src="/files/5pdbUtATPiIvBOZ26Gh8" alt=""><figcaption></figcaption></figure>

## Welcome Screen

### 01 - Illustrative icon&#x20;

Must represent the store context. Custom branding is allowed, as long as it maintains legibility and proper contrast.

### 02 - Welcome message&#x20;

Must include the store name and a short message guiding the user through the app.

### 03 - “Enter” button&#x20;

Must be clearly highlighted as the main action. Triggers the mandatory security check before granting access to the app.

{% hint style="success" %}
**Mandatory:**&#x20;

A clear and visible button must be available to start the environment verification before enabling the payment functionality.
{% endhint %}

***

## Security Checklist

### 04 - Magnifying glass illustration

Optional visual element. Recommended to indicate inspection or safety check.

### 05 - Verification checklist

Must include all items that are checked during the security scan.

{% hint style="success" %}
**Mandatory:**&#x20;

Each item must visibly show either valid or invalid, so the user can clearly understand which requirements are met.
{% endhint %}

***

## Environment Ready

### 06 - All items marked as checked

All conditions must be positively validated.

### 07 - “Continue” button (enabled)

Must be displayed as the main action and only enabled when all conditions are fulfilled.

{% hint style="success" %}
**Mandatory:**&#x20;

The “Continue” button should only become available when all items in the checklist are validated. The action must lead to the sales interface.
{% endhint %}

***

## Environment with Restrictions

### 08 - Invalid item highlighted in red

Example: NFC deactivated. The item must be visually emphasized with a red icon and clear explanatory label.

### 09 - “Continue” button (disabled)

The button must be clearly inactive (greyed out) and non-clickable while any item in the checklist is not satisfied.

{% hint style="success" %}
**Mandatory:**&#x20;

The "Continue" button must remain disabled until all checklist requirements are met.
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Display contextual guidance for the user, such as “Activate NFC to continue.”
{% endhint %}

***

## Expected Behaviors

* The checklist must run automatically after pressing “Enter”.
* Immediate visual feedback must be provided (green or red icon) for each checklist item.
* If any requirement fails, the interface must **clearly inform** the user in non-technical language.
* The “Continue” button must **only** be available once all validations return.

## Mandatory Messages

* When NFC is deactivated:

  > **NFC is deactivated. Please activate NFC to continue using Tap to Pay.**
* When the app is running in a suspicious environment:

  > **Unsecure environment detected. Please check your device's integrity.**


# Login and Authentication

**Objective**

This section defines the **minimum requirements** for the login and **two-factor authentication (2FA)** flow, ensuring secure, clear, and accessible access to the sales environment, based on UX best practices and data protection standards.

Insights

* Authentication structure should be compatible with **offline contexts** (e.g., reconnection handling, secure caching) **where applicable**.
* This flow must comply with security regulations required for proximity-based payments via NFC (e.g., PCI MPoC).&#x20;

***

<figure><img src="/files/vD2qfcOkIxOH3Bk1VWIp" alt=""><figcaption></figcaption></figure>

## Login Screen with Empty Fields

### 01 - Email and password fields

Must appear empty with clear placeholders (e.g., `example@email.com`, `Password123@`)

{% hint style="success" %}
**Mandatory:**&#x20;

The “Login” button must only be enabled when both fields are correctly completed.
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Include a “Forgot your password?” link for recovery.
{% endhint %}

***

## Login Screen with Credentials Filled

### 02 - “Login” button (enabled)

Must be visually highlighted. Tapping it initiates sending a verification code to the registered email.

{% hint style="success" %}
**Mandatory:**&#x20;

Provide immediate visual feedback when the button is tapped (e.g., loading animation).
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Include a confirmation cue (visual or audio) after login attempt.
{% endhint %}

***

## Two-Factor Authentication (2FA) Code Entry

### 03 - Security info message

Must inform the user that a verification code has been sent to their email, partially masked (`us****@email.com`)

### 04 - Code input fields (6 digits)

Must support auto-advance on input and visual feedback per digit.

{% hint style="success" %}
**Mandatory:**&#x20;

Show countdown timer to resend the code (e.g., “Resend code in 00:30”)
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Automatically validate the code once all digits are entered.
{% endhint %}

***

## Code Fully Entered

### 05 - Complete 2FA code

Must automatically enable the “Login” button once all digits are valid

{% hint style="success" %}
**Mandatory:**&#x20;

After code validation, user must be redirected to the sales environment.
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Use smooth visual transitions to reinforce successful authentication.
{% endhint %}

***

## Access to Sales Environment

Show the sales home screen. This screen must display:

* Vendor name and photo
* Search bar
* Product list with name, category, price, stock
* Bottom navigation bar with visible sections: Home, Cart, Charge, User&#x20;

{% hint style="success" %}
**Mandatory:**&#x20;

Navigation is only accessible after full credential + code validation.
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Customize this screen with relevant info based on vendor profile.
{% endhint %}

> **Each component and user experience of the sales screen will be discussed in more detail in the next session.**

***

## Mandatory Messages

* When the code is incorrect:

  > Invalid code. Please check the number sent to your email and try again.
* When the code expires:

  > Code expired. Please request a new one to continue.

***

## Expected Behaviors

* The app must provide **visual and/or audio feedback** at each stage.
* The “Login” button must respect validation logic.
* Two-factor authentication is **mandatory** before accessing the sales system.
* Sensitive data (email, password) must be handled with **masking and encryption**, in accordance with LGPD and PCI standards.


# Password Recovery

**Objective**

This section defines the **minimum requirements** for the password recovery flow, ensuring clarity, security, and accessibility in the process of credential reset by seller users, in accordance with UX best practices and digital security standards.

**Insights**

* This flow must support **limited connectivity scenarios** (e.g., fallback to resend code).
* All messages and visual feedback must be clear, concise, and avoid technical jargon.
* The blue padlock illustration may be adapted to match brand identity, as long as semantic clarity is preserved.

***

<figure><img src="/files/AfAhMGD9AHPMqhbjIDRX" alt=""><figcaption></figcaption></figure>

## Accessing the Recovery Flow

### 01 - “Forgot your password?” link

Must always be visible on the login screen, placed below the authentication fields

{% hint style="success" %}
**Mandatory:**&#x20;

When the link is tapped, the user must be redirected to the password recovery screen.
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Provide visual feedback on tap (e.g., color change, underline, ripple effect).
{% endhint %}

***

## Password Recovery Screen (Email Input)

### 02 - Email input field

Must allow typing with validation for proper email format (e.g., `example@email.com`)

### 03 - “Send code” button

Must remain disabled until a valid email address is entered

{% hint style="success" %}
**Mandatory:**&#x20;

Upon submission, the system must send a verification code (2FA) to the provided email.
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Display a confirmation message after sending the code (e.g., “Verification code sent successfully to your email”).
{% endhint %}

***

New Password Creation Screen

04 - “Password” and “Repeat password” fields

Must include visibility toggle icons and validate minimum security criteria (e.g., 8 characters, symbol, number, etc)

05 - “Save” button

Must only be enabled when both passwords are valid and match

{% hint style="success" %}
**Mandatory:**&#x20;

Passwords must be encrypted during storage and transmission, following LGPD and PCI standards.
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Display real-time password strength and matching feedback (e.g., “Strong password”, “Passwords do not match”).
{% endhint %}

***

## Mandatory Messages

* When the email is invalid:

  > Please enter a valid email address to recover your password.
* After code submission:

  > A verification code has been sent to the provided email. Please check your inbox.
* When passwords do not match:

  > Passwords do not match. Please review the fields and try again.

***

## Expected Behaviors

* The “Send code” button must be linked to valid email input only.
* The “Save” button must remain disabled until all conditions are met.
* After setting the new password, the user must be redirected to the login screen with a success confirmation.


# Product Catalog, Product Details, and Add to Cart

**Objective**

This section defines the **minimum requirements** for browsing the product catalog, viewing detailed product information, and adding items to the cart. The flow must ensure clarity in product organization, ease of interaction, and transparency in pricing.

Insights

* Navigation must be smooth and accessible, with focus on fast conversions and clear product visuals.
* Images must follow contrast, sharpness, and mobile readability guidelines.
* This flow must comply with usability best practices for mobile e-commerce and assisted selling environments.

***

<figure><img src="/files/Klf4RHHZUZVQca5HCqof" alt=""><figcaption></figcaption></figure>

## Main Catalog Screen

### 01 - Category filters&#x20;

Must present visible filtering options (e.g., All, Shirts, Shoes), with the active filter clearly highlighted

### 02 - Product list&#x20;

Each product must display: image, name, category, price, and stock (icon and quantity)

### 03 - Add to cart button&#x20;

Cart icon must be visible at the top corner of each item; it should allow quick add-to-cart without leaving the list

{% hint style="success" %}
**Mandatory:** \
Product categorization must be clear and functional, with visible indicators for stock and price.
{% endhint %}

{% hint style="info" %}
**Recommended:** \
Provide immediate visual feedback when a product is added (e.g., cart animation).
{% endhint %}

***

## Product Detail Screen

### 04 - Enlarged product image&#x20;

Must be visually prominent and high resolution

### 05 - Detailed information&#x20;

Must include:

* Product name
* Price
* Available stock
* Functional product description (clear and objective)
* Quantity selector with +/− buttons&#x20;

{% hint style="success" %}
**Mandatory:**&#x20;

All relevant product information must be shown before the purchase.
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Use plain, functional language focused on benefits and usability.
{% endhint %}

***

## Add to Cart Action

### 06 - “Add to cart” button&#x20;

Must be clearly visible and only enabled when quantity is greater than zero

{% hint style="success" %}
**Mandatory:**&#x20;

After adding, redirect the user to the cart or show a non-intrusive confirmation.
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Display a quick summary (e.g., “2 items added”).
{% endhint %}

***

## Cart Screen

### 07 - Cart item list&#x20;

Each item must include: image, name, category, price, quantity selector, and remove option

Order summary must include:

* Subtotal
* Discount (if applicable)
* Final total with visual emphasis
* “Payment method” button
* Must be the next clear step, visually emphasized

{% hint style="success" %}
**Mandatory:**&#x20;

Cart must allow full review before moving to payment.
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Provide clear feedback when modifying quantities or removing items.
{% endhint %}

***

## Mandatory Messages

* When a product is added:

  > Product successfully added to cart.
* When stock is insufficient:

  > Selected quantity exceeds available stock. Please adjust and try again.

## Expected Behaviors

* Every product added must update the total item count in real time.
* The product detail screen must be accessible from both the catalog and personalized recommendations.
* Quantity fields must block negative or invalid values.
* The “Payment method” button must lead to the checkout and Tap to Pay flow.


# Product Search

**Objective**

Define the **minimum requirements** for the product search flow within the catalog, ensuring a fast, accessible, and efficient search experience that increases the likelihood of users finding the items they need.

#### Insights

* Search must account for synonyms and minor spelling variations to optimize results.
* Search architecture must prioritize performance, even with large product datasets.
* The behavior must be responsive and accessible across all screen sizes and device types.

***

<figure><img src="/files/FSHjOrwXLX3akbTCdbYy" alt=""><figcaption></figcaption></figure>

***

## Search Field

### 01 - Search input field on home screen&#x20;

Must be clearly visible and accessible, with a placeholder example and magnifying glass icon. When focused, it must navigate to a dedicated search screen.

{% hint style="success" %}
**Mandatory:**&#x20;

The search field must always be visible at the top of the catalog screen.
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Support voice search or screen reader accessibility.
{% endhint %}

***

## Active Search Screen

### 02 - Expanded search bar&#x20;

Must retain focus and allow continuous text input

### 03 - Search history&#x20;

Should show recently searched terms with a “Clear all” option

{% hint style="success" %}
**Mandatory:**&#x20;

History must be stored locally and never display sensitive data.
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Order results by frequency of use or seasonality.
{% endhint %}

***

## Suggestions and Relevant Results

### 04 - Popular suggestions&#x20;

Must be displayed below the search bar, including image, name, category, and price of each product. Add-to-cart action Results must include a direct add-to-cart button (cart icon clearly visible on the right)

{% hint style="success" %}
**Mandatory:**&#x20;

Must allow immediate action on the suggested item, without requiring navigation to product details.
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Display stock availability and product variants, if applicable.
{% endhint %}

***

## Filtered Search Results Screen

### 05 - Dynamic filters&#x20;

Must allow sorting by criteria such as “Most Popular”, “Lowest Price”, “All”

### 06 - Result list&#x20;

Each product must display: image, name, category, price, stock, and visible add-to-cart button

{% hint style="success" %}
**Mandatory:**&#x20;

The list must support infinite scrolling or pagination, with performance optimization.
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Highlight matching search terms in the results.
{% endhint %}

***

## Mandatory Messages

* When no results are found:

  > No products found for “{term}”. Try a different keyword or adjust your filters.
* When connection is unstable:

  > Unable to load results. Please check your internet connection.

## Expected Behaviors

* Typing into the search field must update results dynamically (predictive suggestions).
* Filter buttons must retain their active state and allow combined criteria (e.g., popular + cheapest).
* Search must work independently of the previously selected category.
* The input field should support quick correction and automatically clear when exiting the search interface.


# Product Scanning

**Objective**

Define the **minimum requirements** for the flow of scanning physical products using the device camera to read barcodes, automatically navigating to the product detail screen and enabling the addition to the shopping cart.

**Insights**

* The scanner UI must follow best practices in contrast, lighting, and user safety (e.g., no intrusive auto-flash).
* The system should be optimized for various lighting conditions and device camera capabilities.
* The time between scanning and redirection must not exceed 2 seconds under normal conditions.

***

<figure><img src="/files/QHRi9FqAqNr1jPiCmSoT" alt=""><figcaption></figcaption></figure>

***

## Access to Scanner

### 01 - Scanner icon&#x20;

Must be positioned next to the search field on the home screen. It should use a standard icon (barcode reader or camera) and be easily tappable.

{% hint style="success" %}
**Mandatory:**&#x20;

The scanner button must be clearly visible and accessible without scrolling.
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Display a brief animation or visual highlight upon tap to indicate camera activation.
{% endhint %}

***

## Scanning Interface

### 02 - Scan frame&#x20;

Must include a clearly defined area for barcode alignment. The camera must open automatically and maintain continuous focus.

### 03 - “Cancel” button&#x20;

Must be fixed at the bottom of the screen, closing the scanner immediately and returning to the catalog view.

{% hint style="success" %}
**Mandatory:**&#x20;

Upon barcode recognition, the system must automatically redirect to the corresponding product page.
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

If the code is not recognized, show a clear message: “Code not recognized. Please try again.”
{% endhint %}

***

## Redirection to Product Detail Page

### 04 - Product detail screen&#x20;

Must be displayed immediately after a successful scan. The screen must show full product information:

* Name
* Price
* Stock
* Description).

{% hint style="success" %}
**Mandatory:**&#x20;

The “Add to cart” button must be available to allow seamless continuation of the shopping flow.
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Display visual feedback (e.g., confirmation toast or mini popup) when adding the product via scanner.
{% endhint %}

***

## Mandatory Messages

* When the product is not found:

  > Product not identified. Please check the barcode or search manually.
* When scan fails:

  > Unable to read barcode. Adjust focus or try again.

## Expected Behaviors

* The camera must activate with a one-time permission per session or as required by the OS privacy policy.
* After successful scan, the scanner view must close automatically and redirect to the product screen.
* The “Cancel” button must exit the scanning flow immediately, without errors or delay.
* The system must correctly map duplicate codes, variants, or equivalents (SKU/GTIN).


# Manual Checkout

**Objective**

Establish the **minimum requirements** for the manual checkout flow, enabling sellers to input transaction amounts, select a payment method, and complete the operation via NFC (Tap to Pay), with clarity, security, and efficiency.

#### Insights

* The flow must comply with **PCI MPoC** standards for proximity payments.
* NFC interaction must be tested across multiple device types (POS terminals and smartphones).
* The delay between payment method selection and NFC detection must not exceed 5 seconds, except in justified technical scenarios.

***

<figure><img src="/files/y98FXNlMj4EACQ43K5El" alt=""><figcaption></figcaption></figure>

## Accessing the Checkout Flow

### 01 - “Charge” icon in bottom navigation&#x20;

Must always be visible as a main navigation item. When selected, it must open the amount input screen.

{% hint style="success" %}
**Mandatory:**&#x20;

The charge/checkout flow must be accessible from anywhere in the app and have visual emphasis equal to cart or catalog entries.
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Show active focus feedback when the icon is tapped.
{% endhint %}

***

## Entering the Checkout Amount

### 02 - Amount input field&#x20;

Must be centered, with readable font and active cursor. Only valid numeric input should be accepted.

### 03 - Quick amount suggestions&#x20;

Predefined values (e.g., R$ 50, R$ 85) must be visible and tappable

### 04 - Custom numeric keypad&#x20;

Must be in-app (not system default), with large, responsive buttons.

{% hint style="success" %}
**Mandatory:**&#x20;

The “Continue” button must remain disabled until a value greater than zero is entered.
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Automatically apply currency formatting while typing (e.g., 12200 → 122.00).
{% endhint %}

***

## Selecting Payment Method

### 05 - Payment method modal&#x20;

Must include at least the following:

* Tap to Pay
* Pix
* Payment Link\
  Order may vary, but Tap to Pay must be clearly visible and accessible.&#x20;

{% hint style="success" %}
**Mandatory:**&#x20;

Selection must be clear, with both icon and label, following accessibility standards.
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Remember the last selected payment method for faster reuse.
{% endhint %}

***

## Tap to Pay Definition

### 06 - Credit/Debit selection&#x20;

User must select between “Credit” or “Debit”, with clear visual indicatio

### 07 - Installment options (if applicable)&#x20;

If “Credit” is selected, show available installments with per-installment value and total

### 08 - “Continue” button&#x20;

Only enabled after selecting both payment type and number of installments (if required)

{% hint style="success" %}
**Mandatory:**&#x20;

Payment options must comply with card network and terminal rules.
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Show a summary of the selected options before moving to the final checkout screen.
{% endhint %}

***

## Checkout via NFC

**NFC prompt screen**&#x20;

Must show final amount and payment type (e.g., “Credit – one-time”) with clear illustration of card or phone proximity gesture.

{% hint style="success" %}
**Mandatory:**&#x20;

The system must wait for NFC proximity and process payment automatically upon detection
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Provide visual feedback (e.g., animation, sound, vibration) upon successful detection and completion.
{% endhint %}

***

## Mandatory Messages

* When no amount is entered:

  > Please enter an amount to continue.
* When NFC is not detected:

  > No contact detected. Please adjust the positioning and try again.

## Expected Behaviors

* The full flow must be concise (maximum 5 steps before payment).
* All values and options must be clearly visible at every step.
* The user must be able to correct inputs before final confirmation.


# Account Settings

**Objective**

Define the **minimum requirements** for the flow related to accessing, viewing, and editing the vendor user's account information, including personal data, password, and general preferences. The flow must ensure security, clarity, and usability in managing account settings.

#### Insights

* The settings screen must be responsive and adaptable to various screen sizes.
* The email field must reject invalid or duplicate addresses already in the system.
* Critical changes (e.g., password or email) should be auditable and optionally notified via email.

***

<figure><img src="/files/imE6LwtCuPQN8HEeFjsE" alt=""><figcaption></figcaption></figure>

## Accessing the User Area

### 01 - “User” icon in bottom navigation&#x20;

Must be visible and accessible from all main screens. Tapping it must lead to the account settings screen.

{% hint style="success" %}
**Mandatory:**

Access to account settings must be available at all times without requiring multiple steps.
{% endhint %}

{% hint style="info" %}
**Recommended:**

Display the user’s name and profile picture in the navigation when logged in.
{% endhint %}

***

## Account Settings Screen

### 02 - “Edit Profile” section&#x20;

Must be located at the top of the settings screen with clear icon and label.

### 03 - “Logout” option&#x20;

Must be positioned safely (at the bottom of the screen) and require confirmation before logging out.

{% hint style="success" %}
**Mandatory:**&#x20;

Logging out must terminate all active sessions.
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Include a “Preferences” section for visual and notification customizations.
{% endhint %}

***

## Profile Edit Screen

### 04 - Editable fields (name, email, password)&#x20;

Must allow free editing, include password visibility toggle, and validate email format. Password must be entered twice for confirmation.

### 05 - “Save changes” button&#x20;

Must remain disabled until at least one field is changed and all required fields are correctly filled.

{% hint style="success" %}
**Mandatory:**&#x20;

Passwords must meet a minimum policy (e.g., 8 characters, symbol, number).
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Display a confirmation alert and success feedback after saving changes.
{% endhint %}

***

## Mandatory Messages

* When passwords do not match:

  > Passwords do not match. Please check and try again.
* When changes are saved successfully:

  > Changes saved successfully.

## Expected Behaviors

* Data editing must be protected by a valid user session.
* Password fields must allow optional visibility via eye icon.
* The logout button must force token expiration and redirect to the login screen.
* All input fields must be compatible with screen reader accessibility.


# Checkout with Tap to Pay

**Objective**

Define the **minimum requirements** for completing a sale using Tap to Pay during the checkout process, ensuring clear order visualization, flexible payment options, and secure NFC-based payment interaction.

#### Insights

* This flow must be optimized for environments with poor connectivity (supporting order caching).
* Compatibility with NFC readers (Android/iOS) must be tested according to the hardware in use.
* The time between confirming and reading via NFC must not exceed 5 seconds to ensure a smooth experience.

***

<figure><img src="/files/ut2ZsGj5PuFfJmSBVLM1" alt=""><figcaption></figcaption></figure>

## Order Review

### 01 - Item list&#x20;

Must display image, name, category, price, and quantity controls for each product.

### 02 - Price summary&#x20;

Must show: number of items, gross amount, discount applied, and total amount clearly highlighted.

### 03 - “Payment method” button&#x20;

Must be prominently displayed as the main call-to-action and enabled once at least one item is in the cart

{% hint style="success" %}
**Mandatory:**&#x20;

All values must update dynamically as item quantities change.
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Use visual icons (e.g., bag, coin, discount) to enhance scannability.
{% endhint %}

***

## Selecting a Payment Method

### Payment method modal&#x20;

Must display all available payment options with clear icons and labels:

* Tap to Pay
* Pix
* Payment link&#x20;

{% hint style="success" %}
**Mandatory:**&#x20;

“Tap to Pay” must be visible and accessible, appropriately highlighted based on usage.
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Allow the system to reorder options based on user’s recent activity.
{% endhint %}

***

## Tap to Pay Definition

### Payment options

User must select **Credit** or **Debit**. If Credit is selected, installment options must be displayed showing:

* Number of installments
* Amount per installment
* Total amount&#x20;

{% hint style="success" %}
**Mandatory:**&#x20;

The “Continue” button must only be enabled after payment type and (if applicable) installment plan are selected.
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Clearly indicate the selected option using color, shadow, or a check icon.
{% endhint %}

***

## NFC Payment Screen

### NFC instruction screen must include:

* Highlighted final amount
* Payment type (e.g., credit – one-time)
* Illustration showing card or phone proximity gesture
* Animated NFC scan indicator or icon&#x20;

{% hint style="success" %}
**Mandatory:**&#x20;

The system must await NFC detection with real-time feedback.
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Display appropriate visual/sound alerts for errors (“Card not detected”) and confirmations (“Payment approved”).
{% endhint %}

***

## Mandatory Messages

* When no payment method is selected:

  > Please select a payment method to continue.
* When NFC fails:

  > Could not detect the card. Please adjust the position and try again.

***

## Expected Behaviors

* The item list must remain editable until a payment method is selected.
* The “Payment method” button must remain visible/fixed, even when scrolling.
* The total amount must be locked once the NFC phase starts.
* The transaction must be cancelable anytime before confirmation.


# NFC Contact and Payment

**Objective**

Establish the **minimum requirements** for the interface and system behavior during the NFC payment phase, when the card or device is tapped. This step is critical to the user experience and requires clarity, real-time feedback, and perceived security.

#### Insights

* NFC animations must follow platform standards (Android/iOS) for security and compatibility.
* The proximity illustration must respect proportionality and semantics between hand, card, and phone.
* This screen must be tested in different contexts: embedded POS, mobile NFC devices, digital wallets.

***

<figure><img src="/files/ONMyBseTUjE4iQFzYYps" alt=""><figcaption></figcaption></figure>

## NFC Contact Screen

### 01 - Amount and payment type&#x20;

Must be clearly displayed (e.g., “R$ 122.00 – Credit one-time”)

### 02 - Contactless illustration&#x20;

Must clearly indicate the proximity gesture between card and device

### 03 - Active NFC indicator&#x20;

Animated or pulsating icon signaling readiness to scan

### 04 - Promotional coupon (optional)&#x20;

May be shown at the bottom as a loyalty incentive

### 05 - Accepted payment methods&#x20;

Display updated icons of supported card networks and wallets

{% hint style="success" %}
**Mandatory:**&#x20;

The screen must block secondary interactions and focus user attention on the NFC action.
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Provide haptic or audio feedback when a compatible card or phone is detected.
{% endhint %}

***

## Approved Transaction

### 06 - Success indicator&#x20;

Green circle with checkmark and the message “Transaction approved”

### 07 - “Send receipt” button&#x20;

Must allow sending the receipt via email, WhatsApp, or other configured channels

### 08 - “Finish purchase” button&#x20;

Must complete the operation and return to the home screen or an empty cart state

{% hint style="success" %}
**Mandatory:**&#x20;

Feedback for success must appear instantly (<1s after approval).
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Reiterate the amount and payment method on the confirmation screen for visual assurance.
{% endhint %}

***

## Declined Transaction

### 09 - Error indicator&#x20;

Red circle with an “X” and the message “Transaction declined”

### 10 - “Cancel” button&#x20;

Must terminate the payment process and return to the catalog

### 11 - “Try again” button&#x20;

Must restart the NFC scanning process while keeping the current transaction data intact

{% hint style="success" %}
**Mandatory:**&#x20;

Messages must be clear and not blame the user (“Card declined”, not “User error”)
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

If possible, show the reason for failure (e.g., “Insufficient funds”, “Expired card”).
{% endhint %}

***

## Mandatory Messages

* On successful payment:

  > Transaction approved. Thank you!
* On failed payment:

  > Transaction declined. Please check your card or try another payment method.

## Expected Behaviors

* The NFC screen must remain active for up to 60 seconds or until manually cancelled.
* NFC response must occur in real time (max. 2 seconds latency).
* Users must have clear control to retry or exit the flow.
* After an error, the NFC module must be fully reset before a new attempt.


# Payment Receipt Delivery

**Objective**

Establish the **minimum requirements** for sending payment receipts to customers after a transaction is completed. This step must allow fast, secure, and clear sharing through different channels, ensuring both traceability and ease of use.

#### Insights

* It's recommended that the receipt include a unique transaction identifier (hash or order ID) for internal tracking.
* Delivery channels must follow best security practices (e.g., verified sender domains for email).
* This flow must support auditing for tax compliance and customer service validation.

***

<figure><img src="/files/wX0vKzX0Rbswbp2WRsoQ" alt=""><figcaption></figcaption></figure>

## Access to Receipt Delivery

### 01 - “Send receipt” button&#x20;

Must be available immediately after transaction approval, before completing the purchase. It should open the delivery method selection modal

{% hint style="success" %}
**Mandatory:**&#x20;

Sending the receipt must not block the ability to complete the purchase.
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Include a share icon next to the button label for visual clarity.
{% endhint %}

***

## Delivery Method Modal

### 02 Delivery options&#x20;

Must be listed with icons and labels, including at least:

* QR Code
* Email
* Phone number (SMS/WhatsApp) |

{% hint style="success" %}
**Mandatory:**&#x20;

Modal must be easy to navigate and automatically close after a successful send.
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Prioritize the most frequently used channels based on user history.
{% endhint %}

***

## Phone Delivery Flow

### 03 - “Phone number” field&#x20;

Must allow formatted input (e.g., (11) 91234-5678) and validate the number pattern.

### 04 - “Send” button&#x20;

Must remain disabled until a valid number is entered. After submission, display confirmation (e.g., “Receipt sent successfully”).

{% hint style="success" %}
**Mandatory:**&#x20;

Delivery via phone must be processed through a verified messaging service (with auditable trace).
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Allow the user to save the number for future transactions (with consent).
{% endhint %}

***

## Receipt View

### 05 - “Order” section&#x20;

Must include:

* Store name
* Tax ID (CNPJ)
* Date and time
* Order number
* Payment method

### 06 - “Products” section&#x20;

Itemized list including product names, individual prices, subtotal, discount, and total amount.&#x20;

### 07 - “Customer support” section

Contact information for post-sale support, including email and WhatsApp.

### 08 - “Start” button

Must return to the home screen with the session cleared.

{% hint style="success" %}
**Mandatory:**&#x20;

The receipt must be generated locally and optionally available via link or downloadable file.
{% endhint %}

{% hint style="info" %}
**Recommended:**&#x20;

Allow download as PDF or enable offline access.
{% endhint %}

***

## Mandatory Messages

* If the number is invalid:

  > Please enter a valid phone number to send the receipt.
* After successful delivery:

  > Receipt sent successfully!
* If delivery fails:

  > Failed to send receipt. Please check your connection or try again.

## Expected Behaviors

* Receipt delivery must be non-blocking (UI should remain responsive).
* The receipt must accurately reflect the details of the completed transaction.
* All sensitive data must be encrypted and compliant with privacy policies.
* The receipt screen must remain fully legible on small devices.


# Version 1.0.25v19 - Migration Guide

### Why a New Version?

Version 1.0.25v19 includes improvements to the information obtained and sent to the log in error scenarios. This information includes device information, transaction information, sdk configuration information and information from the client consuming the sdk.\
In addition, methods have been made available to be consumed by the client. These methods return information about the device running the sdk and the deviceID of the application installation.

### What are the main changes?

1 - From version 1.0.(23). We no longer require the TapOnPhoneApplication() class to be extended in order to avoid errors during application initialization. In the topic below we have an example of how the implementation should be done from now on.

{% embed url="<https://app.gitbook.com/o/BbVfaeaJPo6ctjdXPZyy/s/RHBTYHK49B1fSJrGzk2y/upgrading-from-version-1.0.22-to-version-1.0.23>" %}

2 - The getDeviceInfo(context) method of the DeviceInformationUtils class has been made available so that a JSON containing the device's information is returned.&#x20;

{% hint style="info" %}
An example of the implementation of this method can be found on this page
{% endhint %}

{% content-ref url="/pages/7enMGtznU4xIB5blI5yS" %}
[SDK Calls & Integration Guide](/first-tech-ttp-sdk/developer-zone/sdk-calls-and-integration-guide)
{% endcontent-ref %}

\
3 - In addition, a back-end feature has been added to collect and send information from the application and the device (to the back-end) during faults. To be used for the product support process.

4 - In addition, a feature has been added to collect and send information from the application and the device (to the back-end) during faults. To be used for the product support process.

5 - Reviewing and updating the Implementation Manual for Developers

6 - Provided 2 application dashboards (TTP).

* Device failure report (TTP).
* Payment transaction report.\
  \
  You can request access to this feature by opening a ticket via support e-mail.&#x20;


# Version 1.0.26

### Why a new version ?

Version 1.0.26 corrects a behavior of the SDK that kept a session open even when the client gave up on a transaction. Consequently, when starting a new transaction, the SDK identified that there was already a session (transaction) in progress, causing an error for those consuming this SDK. A new method has been made available which, when called, eliminates the current session. This way, when starting a new transaction, there will be no session previously in use.

### What are the main changes ?

1 - A method has been made available in the sdk, depending on how the app's screens are built, which should be called when pressing the back button to exit the transaction screen.

A demonstration of how to use this method can be found at the following link in section 5 (Initiate a payment>“Manual stop of the payment process”):

{% embed url="<https://ftcoders.first-tech.com/developer-zone/sdk-implementation-ttp/implementing-the-use-of-the-sdk>" %}


# Version 1.0.27

### Why a new version ?

Version 1.0.27 introduces a significant improvement in the flexibility with which developers can present transaction data. A new field called messageJson has been made available, which centralizes all the relevant information about the transaction carried out.

This new field has been created with the aim of allowing the client complete freedom to build the voucher layout according to the needs of their application or business, without relying on the standard structure previously provided by the SDK.

### What are the main changes ?

Provision of the `messageJson` field in the transaction return. This field contains all the data related to the operation, such as:<br>

* **Total transaction amount**
* **Card number** (masked format, e.g., #### #### #### 1030)
* **Payment method** (Credit or Debit)
* **Installment quantity and value per installment** (for credit payment with installments)
* **Transaction date and time**
* **Terminal information** (e.g., TID, AID, terminal code, etc.)
* **Indication that the transaction was completed with PIN entry**, when applicable
* **Authorization code** (CV)

With this, customers can create their own voucher with total control over the layout, organization of information and display rules, providing a more personalized experience in line with the visual identity of their application.

\
How to implement it can be found in the section **“Implementing the use of the SDK > Printing the receipt on the screen”.**


# Version 1.0.28

### Why a new version ?

Version 1.0.28 includes the integration of the latest version of our SDK, which has received several performance optimizations and internal improvements.

### What are the main changes ?

Integration of an updated internal SDK, optimized for greater speed and efficiency.


# Version 1.2.2

### Why a new version ?

Version 1.2.2, which is <mark style="color:red;">MANDATORY UNTIL JANUARY 30, 2026</mark>, includes the integration of the latest version of our SDK, which has undergone several performance optimizations and internal improvements.\ <mark style="color:red;">Versions prior to version 1.2.2 will be incompatible with the TAP-TO-PHONE service after that date.</mark>

### What are the main changes ?

Integration of an updated internal SDK, optimized for greater speed and efficiency.


# Version 1.0.29

### Why a new version ?

Version 1.0.29 includes functionality to prevent a transaction from being initiated if the transaction amount entered is greater than the amount previously registered in the back-end.

### What are the main changes ?

A new viewData (TerminalPaymentValueBelowMinimumLimitViewData) has been included, which is returned by the SDK to the client consuming the SDK (TTP) when the value of a transaction is below the minimum value registered for a specific CNPJ.<br>

How to implement this feature is described in section “8-Minimum value lock”.

{% embed url="<https://app.gitbook.com/o/BbVfaeaJPo6ctjdXPZyy/s/RHBTYHK49B1fSJrGzk2y/developer-zone/sdk-implementation-ttp/implementing-the-use-of-the-sdk>" %}


# Version 1.0.30

### Why a new version ?

Version 1.0.30 includes functionality to prevent a transaction from being initiated under the following conditions:

* when the amount is R$ 0.00;
* when there are invalid installments (for example, debit with an installment greater than 1).

### What are the main changes ?

A new **`viewData`** (**PaymentInformationInvalidViewData**) has been included, which is returned by the SDK to the client that consumes it (TTP) whenever any **inconsistency is identified in the transaction-related information.**

How to implement this feature can be found in section “9-Responding to Invalid Transactions.”

{% embed url="<https://app.gitbook.com/o/BbVfaeaJPo6ctjdXPZyy/s/RHBTYHK49B1fSJrGzk2y/developer-zone/sdk-implementation-ttp/implementing-the-use-of-the-sdk>" %}


# Version 1.1.0

### Why a new version ?

Version 1.1.0 includes an update that adapts to Google Play's new requirement for specific apps for Android 15. The update includes the adaptation of 16 KB of memory page size for native codes (C/C++, .so files).

### How to implement it?

There is no implementation to be done. This new SDK only includes updates to internal libraries. The only implementation to be done is to consume this new version of the TTP SDK.

{% embed url="<https://ftcoders.first-tech.com/developer-zone/sdk-implementation-ttp/implementing-the-use-of-the-sdk>" %}


# Version 1.2.1

### Why a new version ?

Version 1.2.1 includes the transaction cancellation feature.

### How to implement it?

Two new  `ViewData`     ViewData ( `TerminalRefundViewData` and      `OperationErrorViewData`  ) who will be responsible for controlling the flow in relation to transaction cancellations.

The way to implement this feature can be found in section “10 - Transaction Cancellation.”

{% embed url="<https://ftcoders.first-tech.com/developer-zone/sdk-implementation-ttp/implementing-the-use-of-the-sdk>" %}


# Version 1.2.2

### Why a new version ?

Version 1.2.2, which is <mark style="color:$danger;">MANDATORY UNTIL JANUARY 30, 2026</mark>, includes the integration of the latest version of our SDK, which has undergone several performance optimizations and internal improvements.

<mark style="color:$danger;">Versions prior to version 1.2.2 will be incompatible with the TAP-TO-PHONE service after that date.</mark>

### How to implement it?

Integration of an updated internal SDK, optimized for greater speed and efficiency.


# Version 1.2.3

### Why a new version ?

This version brings critical stability and security improvements for production builds (Release). We focused on full compatibility with obfuscation and minification tools (R8/ProGuard) and data communication resilience (JSON/Gson).

Strict mapping of @Keep annotations applied to all Model classes, DTOs (Data Transfer Objects), and public entities (MPPViewData, UiMessage, etc.). This ensures that the client application can enable R8 in its release builds without breaking communication with our SDK.

In addition, in the Application setup, the only change is that the packageName field now does not accept null values.

### How to implement it?

The only change required in the Application setup is that the packageName field no longer accepts null values. To fill in this field, you can pass the literal string or capture the value dynamically using applicationContext.packageName.

Note: When minifyEnabled true is enabled, the build itself will require changes to a file called

When minifyEnabled true is enabled, R8 (Android's code optimizer and obfuscator) scans all the code and may find references to classes that do not exist in your project. This usually happens because some third-party libraries reference other “optional” libraries that you did not include.

As a safety measure to prevent the app from breaking, R8 pauses the build, alerts you about these references, and automatically generates a text file containing the rules to ignore these alerts. This file is saved in the path: C:\path\_to\_your\_project\\...\release\missing\_rules.txt.

It is important to note that these rules are completely unique to each project, as they depend directly on the libraries being imported. Therefore, the file provided below is only an example, as each application will have its own custom-generated rules.

{% embed url="<https://ftcoders.first-tech.com/utilities/proguard-rules.pro-file>" %}




---

[Next Page](/llms-full.txt/1)

