# Guia Pix Biometria (iOS SDK + API)

Próximo Lançamento
Esta documentação cobre recursos do nosso próximo lançamento. Embora a funcionalidade principal e o fluxo de trabalho descritos aqui permaneçam inalterados, você pode notar algumas melhorias antes do lançamento final, como:

- Atualizações e otimizações do iOS SDK
- Melhorias na documentação (links, terminologia, diagramas)
- Atualizações de referência da API para endpoints de inscrição


Com o Pix Biometria da Belvo, coletar pagamentos de usuários se torna simples, eliminando a necessidade de os usuários navegarem até sua instituição financeira para aprovar cada solicitação de pagamento individual.

O primeiro passo para habilitar a coleta de pagamentos biométricos é **inscrever** o dispositivo do usuário na instituição deles. Durante a inscrição, dados chave sobre o dispositivo e as credenciais de chave pública do usuário são registrados de forma segura na instituição, garantindo que pagamentos futuros possam ser confirmados usando apenas autenticação biométrica. Uma vez que a inscrição esteja completa, você pode começar a solicitar pagamentos diretamente do dispositivo do usuário.

Neste guia, vamos conduzi-lo por cada etapa, desde a inscrição do dispositivo até a iniciação bem-sucedida de uma solicitação de pagamento em um dispositivo iOS.

Uso do SDK + API
Este guia demonstra o uso tanto do SDK quanto da API da Belvo para inscrever dispositivos, bem como para realizar pagamentos. No entanto, você pode completar todo o fluxo usando apenas o SDK da Belvo. Para mais informações, veja nosso guia Pix Biometria iOS SDK Only.

## Pré-requisitos

Antes de começar, certifique-se de que você tenha:

1. **Gerado suas Chaves de API do Belvo Payments**
2. **Configurado Webhooks** para receber atualizações de status de pagamento e inscrição
3. **Gerado um Token de Acesso SDK** (veja abaixo)
4. **Instalado o SDK iOS da Belvo** (veja abaixo)
5. **Criado um Cliente Belvo** para cada usuário que você deseja inscrever


### Token de Acesso do SDK

Autenticação do SDK
O SDK do Pix Biometria requer um token de acesso para autenticar solicitações da API. Gere este token a partir do seu servidor backend e passe-o para o SDK durante a inicialização.

Gere um token de acesso do SDK a partir do seu backend:

```bash
POST https://api.belvo.com/payments/api/widget-token/
Authorization: Basic <base64_encoded_secret_id:secret_password>
Content-Type: application/json
```

```json
{
  "access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
```

Melhores Práticas de Token
Nunca codifique tokens diretamente no seu aplicativo. Sempre os gere no lado do servidor e implemente lógica segura de armazenamento e atualização.

### Instalação do SDK

**Requisitos Mínimos**

- **iOS**: 15.0 ou superior
- **Swift**: 5.0 ou superior


**Instruções:**

Para integrar o Belvo Biometric PIX SDK ao seu projeto Xcode usando o Swift Package Manager:

1. No Xcode, selecione **File** → **Add Packages...**.
2. Insira a URL do repositório do pacote: `https://github.com/belvo-finance-opensource/biometric-pix-ios-sdk`.
3. Selecione os requisitos de versão e clique em **Add Package**.
4. Escolha o produto **BiometricPixSDK** e clique em **Add Package**.


**Adicione as permissões necessárias ao arquivo de permissões do seu aplicativo:**

```xml
<key>com.apple.developer.associated-domains</key>
 <array>
  <string>webcredentials:belvo.com</string>
 </array>
```

**Adicione a descrição de uso de localização no seu arquivo `Info.plist`:**

```xml
  <key>NSLocationWhenInUseUsageDescription</key>
  <string>Este aplicativo usa localização para fins de segurança e prevenção de fraudes.</string>
```

**Compartilhe seu Team ID e Bundle Identifier com a Belvo no seguinte formato:**

```shell
   ## Formato
   TEAM_ID.BUNDLE_ID

   ## Exemplo
   ABCDEFGHIJ.com.yourcompany.appname
```

## Inscrição

Crie um Cliente Primeiro
Antes de criar uma inscrição, você deve criar um cliente usando a API da Belvo (para ter um `customer.id` para associar à inscrição). Para detalhes sobre como criar um cliente, veja a solicitação Criar Cliente (Brasil), certificando-se de selecionar o corpo da solicitação **V1 - Criar Cliente**.

A inscrição é o processo de registrar o dispositivo de um usuário em sua instituição para permitir pagamentos biométricos para um determinado comerciante. Durante o processo, você usará uma **combinação** do Belvo Payments iOS SDK e API para recuperar detalhes chave sobre o dispositivo, bem como os dados públicos biométricos.

1. **Listar Instituições:** Solicite ao usuário que selecione sua instituição financeira desejada para se inscrever, usando a API da Belvo para exibir as opções disponíveis.
2. **Solicitar Permissões de Localização e Coletar Sinais de Risco:** Solicite ao usuário as permissões necessárias e colete sinais de risco, incluindo o ID do dispositivo.
3. **Criar e Atualizar Inscrição:** Envie os sinais de risco coletados, juntamente com o ID do cliente, ID da instituição e uma URL de callback, para o servidor da Belvo para criar a inscrição. Em seguida, redirecione o usuário para o aplicativo de sua instituição para aprovação. Uma vez que eles sejam redirecionados de volta para sua URL de callback com detalhes, envie esses detalhes para a Belvo para atualizar o estado da inscrição.
4. **Consultar Opções FIDO:** Consulte continuamente a API da Belvo (`GET /enrollments/{id}/fido-registration-options/`) para recuperar as opções FIDO necessárias para o registro biométrico.
⚠️ **Estratégia de Consulta:** Recomendamos consultar nosso servidor a cada dois segundos por até dois minutos. Se nenhuma resposta for recebida dentro desse período, instrua o usuário a tentar novamente.
5. **Solicitar Biometria:** Pegue as opções FIDO da API da Belvo e use o método `startRegistration(fidoOptions)` do Belvo iOS SDK para solicitar ao usuário seu gesto biométrico.
6. **Finalizar Inscrição:** Envie os dados públicos biométricos para a Belvo usando `POST /enrollments/{id}/confirm/`. Depois disso, consulte `GET /enrollments/{id}/` até que uma resposta seja recebida (status da inscrição = `SUCCEEDED` ou `FAILED`).


```mermaid
sequenceDiagram
    autonumber

    participant EndUser
    participant ClientAppBackend
    participant BiometricPixSDK
    participant Payments
    participant BankAPP

    Note over EndUser,BankAPP: 0. Solicite ao usuário que selecione a instituição para se inscrever (API da Belvo)

    ClientAppBackend ->> Payments: /institutions/
    Payments -->> ClientAppBackend: Lista de instituições
    ClientAppBackend ->> EndUser: Exibir lista de instituições
    EndUser -->> ClientAppBackend: Instituição selecionada

    Note over EndUser,BankAPP: 1. Solicitar Permissões de Localização e Coletar Sinais de Risco (iOS SDK)

    BiometricPixSDK ->> EndUser: requestPermission()
    EndUser -->> BiometricPixSDK: Concede permissão para coletar sinais de risco
    ClientAppBackend ->> BiometricPixSDK: collectRiskSignals(accountTenure)
    BiometricPixSDK -->> ClientAppBackend: Retorna riskSignals + deviceId (criptografado)
    ClientAppBackend ->> ClientAppBackend: Persiste deviceId (criptografado)

    Note over EndUser,BankAPP: 2. Enviar Sinais de Risco para a Belvo (API da Belvo)

    ClientAppBackend ->> Payments: POST /enrollments/ (riskSignals, callback_url)
    Payments -->> ClientAppBackend: 201 Created (enrollment_id, redirect_url)
    ClientAppBackend ->> ClientAppBackend: Persiste enrollment_id associado com deviceId (criptografado)

    Note over EndUser,BankAPP: 3. Redirecionar usuário para seu APP e atualizar inscrição

    ClientAppBackend ->> EndUser: Redirecionar para BankAPP (usando o redirect_url)
    EndUser ->> BankAPP: Aprova inscrição
    BankAPP ->> ClientAppBackend: Instituição redireciona para callback_url com detalhes nos parâmetros de consulta
    ClientAppBackend ->> Payments: Atualizar inscrição com valores recebidos usando POST /enrollments/complete-redirection/
    Payments -->> ClientAppBackend: Retorna payload de Inscrição atualizada

    Note over EndUser,BankAPP: 4. Consultar API da Belvo para opções FIDO

    ClientAppBackend ->> Payments: Consultar GET /enrollments/{id}/fido-registration-options/
    Payments -->> ClientAppBackend: Retorna fido_options

    Note over EndUser,BankAPP: 5. Solicitar Biometria (iOS SDK)

    ClientAppBackend ->> BiometricPixSDK: startRegistration(fidoOptions)
    BiometricPixSDK ->> EndUser: Solicitar dados biométricos
    EndUser -->> BiometricPixSDK: Fornece biometria (rosto/impressão digital/PIN)
    BiometricPixSDK -->> ClientAppBackend: encodedId, rawId, encodedAttestationObject, encodedClientDataJSON

    Note over EndUser,BankAPP: 6. Enviar biometria para finalizar inscrição e consultar resposta

    ClientAppBackend ->> Payments: POST /enrollments/{id}/confirm/ (attestationObject, clientDataJSON, credential)
    Payments -->> ClientAppBackend: 204 - No Content
    ClientAppBackend ->> Payments: Consultar GET /enrollments/{id}/
    Payments -->> ClientAppBackend: status = SUCCEEDED
```

## Solicitar ao usuário que selecione a instituição para se inscrever (Belvo API)

Método de Conveniência do SDK Disponível
O SDK iOS fornece um método `getPaymentInstitutions()` que simplifica a obtenção das instituições. Este método lida com a chamada da API internamente e retorna uma lista de objetos `Institution`. Consulte a seção de referência do método SDK para mais detalhes.

Em seu aplicativo, solicite ao usuário que selecione a instituição onde deseja inscrever o dispositivo. Use a solicitação Listar todas as instituições de pagamento para obter uma lista de todas as possíveis instituições. Uma vez que o usuário selecione a instituição, salve o id da instituição (necessário na etapa Enviar Sinais de Risco para Belvo (API)).

## Solicitar Permissões de Localização e Coletar Sinais de Risco (SDK iOS)

Em seguida, no seu aplicativo, você precisará fazer as seguintes chamadas:

### requestPermission()

Este método `requestPermission()` cria e lança uma solicitação de permissão para permissões de localização e estado do telefone.

```swift
import SwiftUI
import BiometricPixSDK
import Foundation

struct PermissionRequestExample: View {
    @State private var permissionGranted: Bool? = nil
    private let sdk = BiometricPixSDK()

    private func requestPermission() {
        sdk.requestPermission { granted in
            DispatchQueue.main.async {
								// Se necessário, converta granted para Bool
                permissionGranted = granted as? Bool
								// Se necessário, manipule a UI
            }
        }
    }
}
```

Quando o usuário concede sua permissão, você pode então extrair os sinais de risco do dispositivo usando `collectRiskSignals(accountTenure)`.

### collectRiskSignals(accountTenure)

O método `collectRiskSignals(accountTenure)` coleta dados abrangentes de impressão digital do dispositivo e sinais de segurança. Os dados coletados incluem ID do dispositivo, status de segurança, informações de hardware e sinais comportamentais, que são cruciais para a instituição realizar avaliação de risco e detecção de fraude. O método retorna um objeto RiskSignals que você precisa salvar e encaminhar para os servidores da Belvo em uma chamada de API. Além disso, você precisa persistir o valor de `deviceId` que o objeto RiskSignals retorna para que mais tarde você possa associá-lo ao ID de Inscrição (posteriormente, ao listar Inscrições, você precisa fornecer o `deviceID` para receber todas as Inscrições).

Parâmetro accountTenure
No argumento `accountTenure`, você deve passar a data em que o usuário foi criado como um Cliente na API da Belvo, no formato `YYYY-MM-DD`.

Isso é derivado do timestamp created_at do Cliente. No entanto, você só precisa enviar os primeiros 10 caracteres correspondentes ao ano, mês e data (`YYYY-MM-DD`). Uma regex útil para extrair isso do parâmetro `created_at` poderia ser: `\d{4}-\d{2}-\d{2}`.

```swift
import SwiftUI
import BiometricPixSDK
import Foundation

struct RiskSignalsView: View {
    private let sdk = BiometricPixSDK()

    private func collectRiskSignals() {
        do {
            // Coletar sinais de risco com a data de criação do usuário
            signals = sdk.collectRiskSignals(
                accountTenure: "YYYY-MM-DD" // [!code highlight]
            )
        } catch {
            // Lidar com erros que podem ocorrer durante a coleta de sinais de risco.
            // Possíveis erros incluem:
            // - Formato inválido de `accountTenure`
            // - Problemas de conectividade de rede
            // Considere registrar o erro ou exibir uma mensagem apropriada para o usuário.
        }
    }
}
```

Uma vez que você tenha os sinais de risco e o ID do dispositivo, você pode encaminhar essa informação para a Belvo usando o método Create Enrollment.

## Criar Cadastro Usando Sinais de Risco (API)

Método de Conveniência do SDK Disponível
O SDK iOS fornece um método `createEnrollment()` que simplifica o processo de cadastro. Este método:

- Coleta automaticamente sinais de risco internamente
- Aceita CPF diretamente (não é necessário criar o Customer primeiro)
- Lida com a chamada da API para criar o cadastro
- Retorna um objeto `Enrollment` enriquecido com dados da instituição


**Exemplo:**

```swift
let enrollment = sdk.createEnrollment(
    cpf: "12345678900",
    institution: institutionId,
    accountTenure: "2024-01-15",
    callbackUrl: "https://myapp.com/callback"
)
```

```curl
POST /enrollments/
```

```json
// Corpo da Requisição
{
    "type": "open_finance_biometric_pix",
    "details": {
        "customer": "{{created_customer_uuid}}",
        "institution": "{{selected_institution_uuid}}",
        "name": "Nome para o cadastro",
        "platform": "IOS",
        "callback_url": "{{https://deeplink_to_your_application}}",
        "risk_signals": {} // [!code highlight]
    }
}
```

| Parâmetro | Tipo | Descrição |
|  --- | --- | --- |
| `type` | string (enum) | O tipo de cadastro. Para Pix Biometria, isso deve ser definido como `open_finance_biometric_pix`. |
| `details` | object | Detalhes sobre o cadastro do dispositivo. |
| `details.customer` | string (uuid) | O ID Belvo para o seu usuário. |
| `details.institution` | string (uuid) | O ID Belvo para a instituição que seu usuário selecionou para o cadastro. |
| `details.callback_url` | string (uri) | O deeplink para onde seu usuário deve ser redirecionado em seu aplicativo após aprovar o cadastro no aplicativo da instituição. Deve ser compatível com HTTPS. |
| `details.name` | string | Um nome legível para o cadastro. |
| `details.platform` | string | A plataforma à qual este cadastro se refere. Para dispositivos iOS, isso deve ser definido como `IOS`. |
| `details.risk_signals` | object | O objeto `RiskSignals` (convertido para JSON) que você recebeu após usar o método `collectRiskSignals`. |


Registre seu callback_url
O `callback_url` que você fornecer **deve** ser registrado em seus applinks. Para detalhes sobre como registrar seu URL de callback, consulte a documentação da Apple sobre applinks.

No payload de resposta, você receberá um `redirect_url` que precisa ser exibido para seu usuário para que ele possa ser redirecionado para sua instituição e confirmar seu cadastro.

```json
// 201 Created
{
  "id": "82666cde-3f80-4350-b0f7-24cb8e9294c9",
  "created_by": "56689ef8-4c92-44ae-b2c1-60505da4a7e1",
  "created_at": "2024-11-26T11:20:57.389056Z",
  "updated_at": "2024-11-26T11:20:57.389056Z",
  "type": "open_finance_biometric_pix",
  "status": "PENDING",
  "details": {
    "status": "AWAITING_ACCOUNT_HOLDER_VALIDATION",
    "customer": "f78b14f3-5c1a-409a-966f-7b052b067cf0",
    "institution": "188716fb-39ad-44a7-a992-6c278d2b24a4",
    "platform": "IOS",
    "name": "Primeiro Cadastro",
    "callback_url": "deeplink-to-your-application",
    "redirect_url": "https://www.user-banking-institituon.com/?enrollment_request=true...", // [!code highlight]
    "risk_signals": "*****"
  }
}
```

## Redirecionar o usuário para o APP e atualizar a inscrição

Agora você precisa redirecionar seu usuário para a instituição dele usando o `redirect_url` para que ele possa confirmar o processo de inscrição. Durante o processo, ele fará login na instituição, revisará a solicitação de inscrição e, em seguida, a autorizará. Uma vez que o usuário autoriza a inscrição, a instituição o redirecionará de volta para o `callback_url` que você forneceu.

Exemplo de Sucesso
```json
https://redirect.clientApplication.com/
	?state=<state>
	&code=<code>
	&id_token=<long_id_token>
```

Exemplo de Erro
```json
https://redirect.clientApplication.com/
	?state=<state>
	&error=<error>
	&error_description=<error_description>
```

A instituição passará dados nos parâmetros de consulta que você deve encaminhar para a Belvo usando a solicitação da **API de Atualização de Estado de Inscrição**. Recomendamos transformar os parâmetros de consulta em um objeto JSON e enviá-lo diretamente para a Belvo.

## Atualizar Estado de Inscrição

Método de Conveniência do SDK Disponível
O SDK iOS fornece um método `completeEnrollmentAfterRedirection()` que simplifica o tratamento de callbacks OAuth:

- Aceita a URL completa do callback e analisa automaticamente os parâmetros
- Ou aceita parâmetros individuais `state`, `code` e `idToken`
- Lida com a chamada da API internamente
- Retorna um objeto `Enrollment` enriquecido


**Exemplo:**

```swift
// Opção 1: Analisar URL de callback automaticamente
let enrollment = sdk.completeEnrollmentAfterRedirection(
    callbackUrl: callbackUrl // URL completa com parâmetros de consulta
)

// Opção 2: Fornecer parâmetros individualmente
let enrollment = sdk.completeEnrollmentAfterRedirection(
    state: state,
    code: code,
    idToken: idToken
)
```

Com o valor da string de consulta salvo como um objeto JSON, você pode fazer a seguinte solicitação:

```json
POST /enrollments/complete-redirection/
```

Exemplo de Sucesso
```json Corpo da Solicitação de Sucesso
{
    "state": "{{state}}",
    "code": "{{code}}",
    "id_token": "{{id_token}}",
}
```

No caso de um callback bem-sucedido, na resposta da solicitação o `status` da inscrição ainda será definido como `PENDING`.

```json Atualização de Status de Inscrição Bem-Sucedida
// 200 OK
{
    "id": "{{enrollment.id}}", // [!code highlight]
    "type": "open_finance_biometric_pix",
    "status": "PENDING",  // [!code highlight]
    "details": {
        "callback_url": "https://merchant.com/enrollment-success/",
        "customer": "{{customer.id}}",
        "expires_at": "2022-10-31T00:00:00Z",
        "institution": "uuid",
        "name": "My Enrollment",
        "payer_information": {
            "bank_account": {
                "institution_id": "{{institution.id}}",
                "agency": "1234",
                "number": "*****6789",
                "account_type": "CHECKINGS"
            }
        },
        "platform": "IOS",
        "redirect_url": "https://example.com/redirect-enrollment/",
        "risk_signals": "*******",
        "status": "AWAITING_ACCOUNT_HOLDER_VALIDATION"
    },
    "external_id": null,
    "metadata": {},
    "status_reason_code": null,
    "status_reason_message": null,
    "created_by": "{{belvo_client.id}}",
    "created_at": "{{timestamp}}",
    "updated_at": "{{timestamp}}"
}
```

A instituição agora processará os dados de inscrição e fornecerá à Belvo as Opções FIDO necessárias para gerar o desafio biométrico. Você precisará consultar nossa API para recuperar esses dados e então solicitar dados biométricos do seu usuário.

Exemplo de Erro
```json
{
    "state": "{{state}}",
    "error": "{{error}}",  
    "error_description": "{{error_description}}"
}
```

No caso de um callback de erro, nossa API ainda responderá com um `200 - OK` com o `status` da inscrição ainda definido como `FAILED`. Além disso, o `status_reason_code` e o `status_reason_message` serão definidos para fornecer mais informações sobre a falha.

```json Atualização de Status de Inscrição Falha
// 200 OK
{
    "id": "{{enrollment.id}}", // [!code highlight]
    "type": "open_finance_biometric_pix",
    "status": "FAILED",  // [!code highlight]
    "details": {
        "callback_url": "https://merchant.com/enrollment-success/",
        "customer": "{{customer.id}}",
        "expires_at": "2022-10-31T00:00:00Z",
        "institution": "uuid",
        "name": "My Enrollment",
        "payer_information": {
            "bank_account": {
                "institution_id": "{{institution.id}}",
                "agency": "1234",
                "number": "*****6789",
                "account_type": "CHECKINGS"
            }
        },
        "platform": "IOS",
        "redirect_url": "https://example.com/redirect-enrollment/",
        "risk_signals": "*******",
        "status": "AWAITING_ACCOUNT_HOLDER_VALIDATION"
    },
    "external_id": null,
    "metadata": {},
    "status_reason_code": "insufficient_funds", // [!code highlight]
    "status_reason_message": "No funds", // [!code highlight]
    "created_by": "{{belvo_client.id}}",
    "created_at": "{{timestamp}}",
    "updated_at": "{{timestamp}}"
}
```

## Consultar a API da Belvo para opções FIDO (API)

Método de Conveniência do SDK com Auto-Polling
O SDK para iOS fornece um método `getFidoRegistrationOptions()` que simplifica a recuperação de opções FIDO:

- Faz polling automaticamente a cada 1 segundo por até 5 minutos
- Retorna `FidoRegistrationOptions` quando pronto, ou `nil` se o polling expirar
- Elimina a necessidade de lógica de polling manual


**Exemplo:**

```swift
let fidoOptions = sdk.getFidoRegistrationOptions(enrollmentId: enrollmentId)
if let fidoOptions = fidoOptions {
    // Opções prontas, prossiga com o registro
    sdk.startRegistration(fidoResponseString: fidoOptions.toJsonString(), callback: self)
} else {
    // Polling falhou ou expirou
}
```

Dicas para Polling Manual
Se estiver implementando polling manual: Envie uma solicitação a cada dois segundos até receber uma resposta ou passarem dois minutos sem resposta. Se não receber resposta após dois minutos, exiba uma tela de "Tente novamente" para o seu usuário e reinicie o processo. Em segundo plano, a Inscrição irá transitar para o `status` = `FAILED`.

Após receber a resposta bem-sucedida da solicitação **Update Enrollment State**, você precisa consultar o endpoint abaixo para receber as opções de registro FIDO necessárias para solicitar dados biométricos.

```bash
GET /enrollments/{enrollment_id}/fido-registration-options/
```

Você receberá a seguinte resposta `200 - OK` da nossa API. Certifique-se de salvar o objeto (`fidoOptions`) pois ele é um parâmetro necessário para o método `startRegistration()` do SDK.

```json
// 200 OK
{
    "rp": {
        "id": "belvo.com",
        "name": "Raidiam Mockbank - Pipeline NRJ"
    },
    "user": {
        "id": "a5bd0ef9-f8ab-41a2-b968-489761a91de6",
        "name": "Ralph Bragg",
        "displayName": "Ralph Bragg"
    },
    "challenge": "R3dsT2REOE5oZ25JbVE",
    "pubKeyCredParams": [
        {
            "alg": -257,
            "type": "public-key"
        },
        {
            "alg": -7,
            "type": "public-key"
        }
    ],
    "extensions": {
        "appid": "true"
    }
}
```

## Prompt for Biometrics (iOS SDK)

Com o payload recebido, você precisa usar o método **startRegistration(fidoOptions)**. Este método inicia o registro de credenciais biométricas usando protocolos FIDO2. Ele processa as opções de registro FIDO (uma string JSON) recebidas do seu servidor backend e inicia o fluxo de autenticação biométrica nativa do dispositivo (por exemplo, impressão digital ou reconhecimento facial).

```swift
import Foundation
import BiometricPixSDK

class FidoRegistrationViewModel : NSObject, ObservableObject {
    private let sdk = BiometricPixSDK()

    func startRegistration(fidoOptions: String) {
        do {
            sdk.startRegistration(
                fidoResponseString: fidoOptions, // [!code highlight]
                callback: self // Instância de Callback
            )
        } catch {
            // Tratar erros
        }
    }
}

// Implementando callback para registro
extension FidoRegistrationViewModel: FidoRegistrationCallback {
    func onError(error: String) {
            // Tratar erros de registro
    }

    func onSuccess(response attestationResponse: AttestationResponse) {
            // Tratar registro bem-sucedido
            // O objeto attestationResponse contém os dados necessários para o próximo passo.
            let encodedId = attestationResponse.encodedId
            let rawId = attestationResponse.rawId
            let encodedAttestationObject = attestationResponse.encodedAttestationObject
            let encodedClientDataJSON = attestationResponse.encodedClientDataJSON
            
            // Persistir esses valores para serem enviados ao seu backend.
    }
}
```

Ao usar este view model em views SwiftUI, declare-os como propriedades @ObservedObject para garantir que não sejam destruídos durante as re-renderizações da view. Isso é crítico para que os callbacks funcionem corretamente.

```swift
import SwiftUI

struct MyView: View {
    @ObservedObject var registrationViewModel = FidoRegistrationViewModel()
// ...
}
```

Você precisa armazenar os seguintes valores em variáveis, pois eles são usados para confirmar a Inscrição na etapa seguinte:

- `encodedId`
- `rawId`
- `encodedAttestationObject`
- `encodedClientDataJSON`


## Enviar biometria para finalizar o cadastro e verificar a resposta (API)

Método de Conveniência do SDK Disponível
O SDK iOS fornece um método `confirmEnrollment()` que simplifica a confirmação do cadastro:

- Lida automaticamente com a criação do payload a partir das credenciais FIDO
- Lida com a chamada da API internamente
- Retorna `Bool` indicando sucesso


**Exemplo:**

```swift
extension ViewModel: FidoRegistrationCallback {
    func onSuccess(credential: PublicKeyCredential, response: AuthenticatorAttestationResponse) {
        // O SDK lida com a criação do payload automaticamente
        let success = sdk.confirmEnrollment(enrollmentId: enrollmentId, credential: credential, response: response)
        if success {
            // Cadastro confirmado
        }
    }
    
    func onError(error: String) {
        // Lidar com erro
    }
}
```

Para completar o processo de Cadastro, você precisará enviar os valores que recebeu para o seguinte endpoint:

```bash
POST /payments/br/enrollments/{enrollment_id}/confirm/
```

```json
// Corpo da Requisição
{
  "confirmation_data": {
    "authenticatorAttachment": "platform",
    "id": "{{encodedId}}",
    "rawId": "{{rawId}}",
    "type": "public-key",
    "response": {
      "attestationObject": "{{encodedAttestationObject}}",
      "clientDataJSON": "{{encodedClientDataJSON}}"
    }
  }
}
```

| Parâmetro | Tipo | Descrição |
|  --- | --- | --- |
| `authenticatorAttachment` | string | O tipo de autenticador. Deve ser definido como `platform`. |
| `id` | string | O `encodedId` que você recebeu do método `startRegistration()`. |
| `rawId` | string | O `rawId` que você recebeu do método `startRegistration()`. |
| `type` | string | O tipo de credencial FIDO sendo gerada. Deve ser definido como `public-key`. |
| `response.attestationObject` | string | O `encodedAttestationObject` que você recebeu do método `startRegistration()`. |
| `response.clientDataJSON` | string | O `encodedClientDataJSON` que você recebeu do método `startRegistration()`. |


A Belvo responderá com um `204 - No Content` e encaminhará a informação para a instituição para completar o processo de cadastro.

Dicas de Verificação
Envie uma requisição a cada dois segundos até receber uma resposta ou dois minutos se passarem sem resposta. Se você não receber uma resposta após dois minutos, exiba uma tela de “Tente novamente” para o seu usuário e reinicie o processo. Em segundo plano, o Cadastro irá transitar para o `status` = `FAILED`.

Você precisará verificar o seguinte endpoint até receber uma resposta da API da Belvo. Assim que receber uma resposta, verifique o campo `status`.

```bash
GET /enrollments/{enrollment_id}/
```

Se o `status` for `SUCCEEDED`, perfeito! O cadastro está pronto e você pode começar a fazer pagamentos!

## Realizando um Pagamento

Uma vez que o dispositivo de um usuário esteja registrado com sucesso, você pode iniciar solicitações de pagamento usando suas credenciais biométricas armazenadas. Este processo envolve:

1. Selecionar um Registro
2. Criar uma intenção de pagamento
3. Coletar dados de autenticação biométrica
4. Autorizar o pagamento


```mermaid
sequenceDiagram
    autonumber

    participant EndUser
    participant ClientAppBackend
    participant BiometricPixSDK
    participant Payments

    %% 1 - Criação de Intenção de Pagamento usando registro autorizado
    Note over EndUser,Payments: 1. Usuário seleciona Registro (API)

    EndUser ->> ClientAppBackend: Clica "Realizar Pagamento"
    ClientAppBackend ->> Payments: GET /enrollments/?device_id=1234
    Payments -->> ClientAppBackend: Retorna lista de registros
    ClientAppBackend -->> EndUser: Mostra lista de registros
    EndUser ->> ClientAppBackend: Escolhe da lista de registros

    Note over EndUser,Payments: 2. Criar Intenção de Pagamento (API)

    ClientAppBackend ->> Payments: POST /payment-intents/ (enrollment_id)
    Payments -->> ClientAppBackend: Retorna dados de payment_intent (id, fido_options)
    ClientAppBackend ->> ClientAppBackend: Persiste ID da Intenção de Pagamento

    %% 2 - Autorização de Intenção de Pagamento usando AttestationObject + RiskSignals
    Note over EndUser,Payments: 3. Coletar dados biométricos (SDK)

    ClientAppBackend ->> BiometricPixSDK: startSigning(fidoOptions)
    ClientAppBackend ->> BiometricPixSDK: collectRiskSignals(accountTenure)
    BiometricPixSDK -->> ClientAppBackend: Retorna credentialId, attestationObject, clientDataJSON, riskSignals

    Note over EndUser,Payments: 4. Autorizar pagamento (API)

    ClientAppBackend ->> Payments: POST /payment-intents/{id}/authorize/ (credentialId, attestationObject, clientDataJSON, riskSignals)
    Payments -->> ClientAppBackend: 204 - No Content
    ClientAppBackend ->> Payments: Poll GET /payment-intents/{id}/
    Payments -->> ClientAppBackend: status = SUCCEEDED

    ClientAppBackend ->> EndUser: Mostra tela de sucesso
```

## **Selecionar Inscrição (API)**

Método de Conveniência do SDK Disponível
O SDK iOS fornece um método `listEnrollments()` que simplifica a obtenção de inscrições:

- Lida automaticamente com a chamada da API com o ID do dispositivo
- Retorna `[Enrollment]` com dados enriquecidos da instituição
- Cada inscrição inclui opcionalmente o objeto completo `Institution`


**Exemplo:**

```swift
let enrollments = sdk.listEnrollments(deviceId: deviceId)
enrollments.forEach { enrollment in
    if let institution = enrollment.institution {
        print("\(institution.displayName): \(enrollment.status)")
    }
}
```

Use o método da API Listar todas as inscrições, com o parâmetro de consulta obrigatório `device_id`, para solicitar todas as inscrições que seu usuário fez usando seu aplicativo e seu dispositivo atual. Exiba esta lista de inscrições para o usuário, permitindo que ele escolha qual inscrição usar para o pagamento. Salve o `id` dessa inscrição (usado na próxima etapa Criar Intenção de Pagamento).

```bash
GET /enrollments/?device_id={device_id}
```

## **Criar Payment Intent (API)**

Método de Conveniência do SDK Disponível
O SDK iOS fornece um método `createPaymentIntent()` que simplifica a criação de payment intents:

- Lida com a chamada da API internamente
- Retorna o objeto completo `PaymentIntent` com opções FIDO
- Suporta todos os parâmetros de payment intent


**Exemplo:**

```swift
let payload = CreatePaymentIntentPayload(
    amount: 100.50,
    customer: Customer(identifier: "12345678900"),
    description: "Pagamento por serviços",
    allowedPaymentMethodTypes: ["open_finance_biometric_pix"],
    paymentMethodDetails: PaymentMethodDetails(
        openFinanceBiometricPix: OpenFinanceBiometricPixPaymentMethodDetails(
            beneficiaryBankAccount: "bank-account-id",
            enrollment: "enrollment-id"
        )
    )
)
let paymentIntent = sdk.createPaymentIntent(payload: payload)
```

Uma vez que você tenha o Enrollment selecionado pelo usuário, você pode criar um Payment Intent:

```shell
POST /payments/br/payment-intents/
```

```json
{
    "amount": 0.13,
    "allowed_payment_method_types": [
        "open_finance_biometric_pix"
    ],
    "customer": "{{customer.id}}",
    "description": "Teste Payment Intent com Enrollment",
    "statement_description": "Descrição para mostrar no extrato",
    "payment_method_details": {
        "open_finance_biometric_pix": {
            "beneficiary_bank_account": "{{bank_account.id}}",
            "enrollment": "{{enrollment.id}}"
        }
    },
    "confirm": true
}
```

| Parâmetro | Tipo | Obrigatório | Descrição |
|  --- | --- | --- | --- |
| `amount` | number | sim | O valor a ser pago. |
| `allowed_payment_method_types` | string | sim | O tipo de método de pagamento. Deve ser definido como `open_finance_biometric_pix`. |
| `customer` | string (uuid) | sim | O `id` do cliente de quem você está solicitando pagamentos. |
| `description` | string | sim | Sua descrição para o pagamento. |
| `statement_description` | string | sim | A descrição que aparecerá no extrato bancário do seu usuário. |
| `payment_method_details.open_finance_biometric_pix.beneficiary_bank_account` | string (uuid) | sim | O `id` da conta bancária que receberá os fundos. |
| `payment_method_details.open_finance_biometric_pix.enrollment` | string (uuid) | sim | O `id` do Enrollment selecionado pelo usuário. |
| `confirm` | boolean | sim | Confirma que o pagamento está pronto para ser processado. Deve ser definido como `true`. |


Na resposta, a Belvo retornará o `payment_intent.id` e o objeto `fido_options` que são necessários para o próximo passo da autenticação biométrica. Você precisa:

- Persistir o `payment_intent.id` no seu backend.
- Salvar o `fido_options` em uma variável para ser usado no próximo passo no SDK da Belvo.


```json
{
  "id": "uuid", // [!code highlight]
  "status": "PENDING",
  "payment_method_information": {
	  "open_finance_biometric_pix": {
	      "provider": "belvo",
	      "consent_id": "urn:nubank:023230b9-1211-3420-bf6d-e7d56e87bdf1",
	      "fido_options": { // [!code highlight]
	          "rpId": "belvo.com",
	          "timeout": 300000,
	          "challenge": "oGW096Hvr8sVUIOf-10iqWI7ZfSx2GhoU359bBRK9h4",
	          "allowCredentials": [
	              {
	                  "id": "AfD-uI4LUzJAuzyLBRrPncocLusMgZ8yHNuuUl-7NSFbBlqrW2rMF0D_Ao-orNqdX3YZVf8_wk1jj--HuNH1uKE",
	                  "type": "public-key"
	              }
	          ]
	      },
	      "end_to_end_id": "E432158152025061315009OzwiMmDSO7",
	      "external_payment_id": "bde3bb4d-5b48-4875-b69d-7f2beee4fb42",
	      "provider_request_id": "afc99a8b-e0c7-4a8b-85d7-193bd70e4cc0"
	  }
	}
}
```

## Coletar Dados Biométricos e Sinais de Risco (SDK)

Usando o `fido_options` recebido da intenção de pagamento, inicie o processo de autenticação biométrica usando o método `startSigning(fidoOptions)` do Belvo iOS SDK. Após o usuário autenticar, você também precisará chamar `collectRiskSignals(accountTenure)` para coletar informações do dispositivo.

Os resultados desses métodos contêm os valores que você precisará enviar para o seu backend para autorizar o pagamento.

```swift
import Foundation
import BiometricPixSDK

class FidoAuthenticationViewModel : NSObject, ObservableObject {
    private let sdk = BiometricPixSDK()

    func startSigning(fidoOptions: String) {
        do {
            // Nota: O método para iniciar a autenticação de pagamento é startSigning.
            sdk.startSigning(
                fidoResponseString: fidoOptions,// string json solicitada da api do backend
                fallbackCredential: nil,// string de credencial alternativa se disponível
                callback: self// instância de callback
            )
        } catch {
                        // Tratamento de erro
        }
    }
    
    private func collectRiskSignals() {
        do {
            // Coletar sinais de risco com a data de criação do usuário
            let signals = sdk.collectRiskSignals(
                accountTenure: "YYYY-MM-DD"
            )
            // Envie os sinais para o seu backend para serem usados na etapa de autorização.
        } catch {
            // tratar erro
        }
    }
}

// implementando callback para autenticação
extension FidoAuthenticationViewModel: FidoAuthenticationCallback {
    func onError(error: String) {
                // Tratar erros de autenticação
    }

    func onSuccess(response assertionResponse: AssertionResponse) {
                // Tratar autenticação bem-sucedida
        // Extraia dados de assertionResponse e envie para o seu backend.
        // Em seguida, chame collectRiskSignals.
        collectRiskSignals()
    }
}
```

Ao usar este view model em views SwiftUI, declare-os como propriedades @ObservedObject para garantir que não sejam destruídos durante as re-renderizações da view. Isso é crítico para que os callbacks funcionem corretamente.

```swift
import SwiftUI

struct MyView: View {
    @ObservedObject var registrationViewModel = FidoRegistrationViewModel()
// ...
}
```

## Autorizar Pagamento (API)

Método de Conveniência do SDK Disponível
O SDK iOS fornece um método `authorizePaymentIntent()` que simplifica a autorização de pagamento:

- Lida com a chamada da API internamente
- Aceita `AuthorizePaymentIntentPayload` com plataforma, sinais de risco e asserção
- Retorna `Bool` indicando sucesso


**Exemplo:**

```swift
let payload = AuthorizePaymentIntentPayload(
    platform: "ios",
    riskSignals: riskSignals,
    assertion: assertion
)
let success = sdk.authorizePaymentIntent(paymentIntentId: paymentIntentId, payload: payload)
```

Após recuperar todas as informações necessárias na etapa Coletar Dados Biométricos e Sinais de Risco (SDK), você pode agora autorizar o pagamento usando a API da Belvo.

```shell
POST /payment-intents/{payment_intent_id}/authorize/
```

- A Belvo processará a autorização. Você precisará fazer polling em `GET /payment-intents/{id}/` até que o `status` da intenção de pagamento se torne `SUCCEEDED`.
**Estratégia de Polling:** Similar ao cadastro, recomendamos fazer polling do status da intenção de pagamento (`GET /payment-intents/{payment_intent_id}/`) a cada dois segundos por até dois minutos até que o status seja `SUCCEEDED`. Se o status não mudar ou ocorrer um erro, informe o usuário e sugira tentar novamente.
- Uma vez que o pagamento for bem-sucedido, exiba uma tela de confirmação para o Usuário Final.


```json
// Exemplo de Corpo de Requisição POST /payment-intents/{id}/authorize/
{
  "risk_signals": {}, // O objeto de Sinais de Risco coletado
  "assertion": {
    "authenticatorAttachment": "platform",
    "id": "{{encodedId}}",
    "rawId": "{{rawId}}",
    "response": {
      "authenticatorData": "{{encodedAuthenticatorData}}",
      "clientDataJSON": "{{encodedClientDataJSON}}",
      "signature": "{{encodedSignature}}",
      "userHandle": "{{userHandle}}"
      
    },
    "type": "public-key"
  }
}
```

A API da Belvo retornará um `204 - Not Content`. Após isso, você precisará fazer polling no seguinte endpoint para recuperar o status final do pagamento:

```shell
GET /payment-intents/{payment_intent_id}/
```

Dicas de Polling
Envie uma requisição a cada dois segundos até receber uma resposta ou até que dois minutos se passem sem resposta. Se você não receber uma resposta após dois minutos, exiba uma tela de “Tente novamente” para o seu usuário e reinicie o processo. Em segundo plano, a Intenção de Pagamento e a Cobrança associada irão transitar para o `status` = `FAILED`.