# Pix Biometria Guide (Android SDK - Simplified Integration)

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.

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 individualmente.

Este guia demonstra a integração usando os métodos de conveniência do SDK Android da Belvo. O SDK lida com a comunicação de backend, fluxos OAuth e registro FIDO internamente, proporcionando um caminho de integração simplificado.

O primeiro passo para habilitar a coleta de pagamentos biométricos é **registrar** o dispositivo do usuário com sua instituição. Durante o registro, dados chave sobre o dispositivo e as credenciais de chave pública do usuário são registrados de forma segura com sua instituição, garantindo que pagamentos futuros possam ser confirmados usando apenas autenticação biométrica.

Uma vez concluído o registro, você pode começar a solicitar pagamentos diretamente do dispositivo do usuário.

## Pré-requisitos

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

1. **Gerou suas Chaves de API do Belvo Payments**
2. **Configurou Webhooks** para receber atualizações de status de pagamento e inscrição
3. **Gerou um Token de Acesso SDK** (veja abaixo)
4. **Instalou o Belvo Android SDK**


### 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 para Tokens
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:**

- Android API Level 24 (Android 7.0) ou superior
- Kotlin 1.9.0 ou superior


**Adicione ao seu `build.gradle.kts` (nível do Módulo):**

```kotlin
dependencies {
    implementation("com.belvo:biometric-pix-core:1.0.0")
}
```

**Sincronize seu projeto** e você está pronto para começar!

### Configuração do App

**Adicione permissões ao `AndroidManifest.xml`:**

```xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
```

**Adicione suporte a App Links para callbacks OAuth:**

```xml
<activity android:name=".MainActivity">
    <intent-filter android:autoVerify="true">
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data
            android:scheme="https"
            android:host="yourdomain.com"
            android:pathPrefix="/callback" />
    </intent-filter>
</activity>
```

**Compartilhe o nome do seu pacote e a impressão digital do certificado SHA-256 com a Belvo:**

```bash
# Obtenha sua impressão digital SHA-256
keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android

# Formato para compartilhar com a Belvo:
# Package: com.yourcompany.appname
# SHA-256: AA:BB:CC:DD:EE:FF:...
```

## Permissões e Inicialização do SDK

Tempo de Permissão
As permissões **devem** ser solicitadas antes da inicialização do SDK. Além disso, a solicitação de permissão só pode ser chamada a partir de um contexto de Activity.

**Passo 1: Solicite Permissões Primeiro**

```kotlin
import com.belvo.biometricpixsdk.BiometricPixSDK
import androidx.activity.ComponentActivity

class EnrollmentActivity : ComponentActivity() {
    private lateinit var sdk: BiometricPixSDK
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        // DEVE solicitar permissões ANTES de inicializar o SDK
        requestPermissions()
    }
    
    private fun requestPermissions() {
        BiometricPixSDK.requestPermission(this) { granted ->
            if (granted) {
                // Permissões concedidas, agora inicialize o SDK
                initializeSDK()
            } else {
                // Lidar com a negação de permissão
                showError("Permissão de localização é necessária para o cadastro")
            }
        }
    }
    
    private fun initializeSDK() {
        // Inicializar APÓS as permissões serem concedidas
        sdk = BiometricPixSDK(
            context = this,
            accessToken = getAccessToken() // Do seu backend
        )
        // Agora pronto para prosseguir com o cadastro
    }
    
    override fun onDestroy() {
        super.onDestroy()
        if (::sdk.isInitialized) {
            sdk.cleanup()
        }
    }
}
```

Gerenciamento de Recursos
Sempre chame `cleanup()` quando terminar de usar o SDK (por exemplo, quando a activity for destruída ou o usuário fizer logout) para liberar adequadamente os recursos e limpar tarefas em segundo plano.

## Fluxo de Cadastro (6 Etapas)

O processo de cadastro registra o dispositivo de um usuário com sua instituição para pagamentos biométricos.

```mermaid
sequenceDiagram
    autonumber

    participant User
    participant YourApp
    participant BiometricPixSDK
    participant BelvoAPI
    participant Institution

    Note over YourApp,BiometricPixSDK: Chamada 1: getPaymentInstitutions()
    User->>YourApp: Inicia o cadastro
    YourApp->>BiometricPixSDK: getPaymentInstitutions()
    BiometricPixSDK->>BelvoAPI: Buscar instituições
    BelvoAPI-->>BiometricPixSDK: Lista de instituições
    BiometricPixSDK-->>YourApp: List&lt;Institution&gt;
    YourApp->>User: Exibir seletor de instituição
    User-->>YourApp: Seleciona instituição
    
    Note over YourApp,BiometricPixSDK: Chamada 2: createEnrollment() + openRedirectUrl()
    YourApp->>BiometricPixSDK: createEnrollment(cpf, institution, accountTenure, callbackUrl)
    BiometricPixSDK->>BiometricPixSDK: Coletar sinais de risco internamente
    BiometricPixSDK->>BelvoAPI: POST /enrollments/
    BelvoAPI-->>BiometricPixSDK: Cadastro criado (redirect_url)
    BiometricPixSDK-->>YourApp: Objeto de Cadastro
    YourApp->>BiometricPixSDK: openRedirectUrl(context, redirect_url)
    BiometricPixSDK->>Institution: Abrir app da instituição
    User->>Institution: Aprovar cadastro no app da instituição
    Institution-->>YourApp: Callback OAuth (code, state, id_token)
    
    Note over YourApp,BiometricPixSDK: Chamada 3: completeEnrollmentAfterRedirection()
    YourApp->>BiometricPixSDK: completeEnrollmentAfterRedirection(callbackUrl)
    BiometricPixSDK->>BelvoAPI: POST /enrollments/complete-redirection/
    BelvoAPI-->>BiometricPixSDK: Cadastro atualizado
    BiometricPixSDK-->>YourApp: Objeto de Cadastro
    
    Note over YourApp,BiometricPixSDK: Chamada 4: getFidoRegistrationOptions()
    YourApp->>BiometricPixSDK: getFidoRegistrationOptions(enrollmentId)
    BiometricPixSDK->>BelvoAPI: Consultar opções FIDO (auto-retry)
    BelvoAPI-->>BiometricPixSDK: Opções de registro FIDO
    BiometricPixSDK-->>YourApp: FidoRegistrationOptions
    
    Note over YourApp,BiometricPixSDK: Chamada 5: startRegistration()
    YourApp->>BiometricPixSDK: startRegistration(fidoOptions, callback)
    BiometricPixSDK->>User: Solicitar biometria (impressão digital/rosto)
    User-->>BiometricPixSDK: Fornece biometria
    BiometricPixSDK-->>YourApp: Credencial via callback
    
    Note over YourApp,BiometricPixSDK: Chamada 6: confirmEnrollment()
    YourApp->>BiometricPixSDK: confirmEnrollment(enrollmentId, credential)
    BiometricPixSDK->>BelvoAPI: POST /enrollments/{id}/confirm/
    BelvoAPI->>Institution: Registrar credencial FIDO
    Institution-->>BelvoAPI: Registro confirmado
    BelvoAPI-->>BiometricPixSDK: Cadastro SUCEDIDO
    BiometricPixSDK-->>YourApp: Sucesso (Boolean)
    YourApp->>User: Mostrar tela de sucesso
```

### Passo 1: Obter Instituições de Pagamento

Busque a lista de instituições que suportam pagamentos biométricos:

```kotlin
import com.belvo.biometricpixsdk.BiometricPixSDK
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launch

class EnrollmentViewModel(
    private val sdk: BiometricPixSDK
) : ViewModel() {
    
    private val _institutions = MutableStateFlow<List<Institution>>(emptyList())
    val institutions: StateFlow<List<Institution>> = _institutions
    
    fun loadInstitutions() {
        viewModelScope.launch {
            try {
                _institutions.value = sdk.getPaymentInstitutions()
            } catch (e: Exception) {
                // Tratar erro (rede, autenticação, etc.)
                _error.value = "Falha ao carregar instituições: ${e.message}"
            }
        }
    }
}
```

**Exibir instituições para o usuário:**

```kotlin
@Composable
fun InstitutionPickerScreen(
    viewModel: EnrollmentViewModel
) {
    val institutions by viewModel.institutions.collectAsState()
    
    LazyColumn {
        items(institutions) { institution ->
            InstitutionItem(
                institution = institution,
                onClick = { viewModel.selectInstitution(institution) }
            )
        }
    }
    
    LaunchedEffect(Unit) {
        viewModel.loadInstitutions()
    }
}

@Composable
fun InstitutionItem(
    institution: Institution,
    onClick: () -> Unit
) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .clickable(onClick = onClick)
            .padding(16.dp)
    ) {
        AsyncImage(
            model = institution.iconLogo,
            contentDescription = institution.displayName,
            modifier = Modifier.size(40.dp)
        )
        Spacer(modifier = Modifier.width(16.dp))
        Text(text = institution.displayName)
    }
}
```

### Passo 2: Criar Inscrição e Abrir o App da Instituição

Crie a inscrição e imediatamente abra o app da instituição:

```kotlin
fun startEnrollment() {
    val institution = _selectedInstitution.value ?: return
    
    viewModelScope.launch {
        try {
            // Criar inscrição
            val enrollment = sdk.createEnrollment(
                cpf = userCPF,                           // CPF do usuário
                institution = institution.id,             // ID da instituição selecionada
                accountTenure = customerCreatedDate,      // Formato "YYYY-MM-DD"
                callbackUrl = "https://yourdomain.com/callback"
            )
            
            // Salvar ID da inscrição e ID do dispositivo para uso posterior
            _enrollmentId.value = enrollment.id
            _deviceId.value = enrollment.details.riskSignals.deviceId
            
            // Imediatamente abrir o app da instituição usando a URL de redirecionamento
            enrollment.details.redirectUrl?.let { url ->
                sdk.openRedirectUrl(context, url)
            } ?: run {
                _error.value = "Nenhuma URL de redirecionamento recebida da inscrição"
            }
            
        } catch (e: Exception) {
            _error.value = "Falha na criação da inscrição: ${e.message}"
        }
    }
}
```

Formato de Duração da Conta
O parâmetro `accountTenure` deve ser a data em que o usuário foi criado como Cliente Belvo, no formato `YYYY-MM-DD`. Extraia isso do timestamp `created_at` do Cliente (primeiros 10 caracteres).

O método `openRedirectUrl()` do SDK lida com a abertura do app da instituição automaticamente. A instituição redirecionará de volta para o seu `callbackUrl` com parâmetros OAuth.

### Passo 5: Completar o Cadastro Após Redirecionamento

Trate o callback OAuth na sua atividade e complete o cadastro:

```kotlin
// No seu MainActivity
override fun onNewIntent(intent: Intent?) {
    super.onNewIntent(intent)
    intent?.data?.let { uri ->
        handleEnrollmentCallback(uri)
    }
}

fun handleEnrollmentCallback(uri: Uri) {
    viewModelScope.launch {
        try {
            val enrollment = sdk.completeEnrollmentAfterRedirection(
                callbackUrl = uri.toString()  // SDK analisa os parâmetros automaticamente
            )
            
            // Verifique se foi bem-sucedido
            when (enrollment.status) {
                "PENDING" -> {
                    // Sucesso - prossiga para o registro FIDO
                    getFidoOptions(enrollment.id)
                }
                "FAILED" -> {
                    // Trate a falha
                    _error.value = "${enrollment.statusReasonCode}: ${enrollment.statusReasonMessage}"
                }
            }
            
        } catch (e: Exception) {
            _error.value = "Falha ao completar o cadastro: ${e.message}"
        }
    }
}
```

Alternativa: Parâmetros Manuais
Se preferir analisar a URL de callback você mesmo, pode passar os parâmetros individualmente:

```kotlin
val enrollment = sdk.completeEnrollmentAfterRedirection(
    state = stateParam,
    code = codeParam,
    idToken = idTokenParam
)
```

### Passo 4: Obter Opções de Registro FIDO

Recupere as opções FIDO necessárias para o registro biométrico. O SDK faz a verificação automaticamente por até 5 minutos:

```kotlin
fun getFidoOptions(enrollmentId: String) {
    viewModelScope.launch {
        // O SDK verifica automaticamente a cada 1 segundo por até 5 minutos
        val fidoOptions = sdk.getFidoRegistrationOptions(enrollmentId)
        
        if (fidoOptions != null) {
            // Opções FIDO recebidas, prossiga para o registro biométrico
            startBiometricRegistration(fidoOptions)
        } else {
            // Tempo de verificação esgotado (5 minutos se passaram)
            _error.value = "Tempo esgotado aguardando as opções FIDO. Por favor, tente novamente."
        }
    }
}
```

Verificação Automática
O método `getFidoRegistrationOptions()` lida com toda a lógica de verificação automaticamente. Ele verifica a cada 1 segundo por até 5 minutos, então você não precisa implementar nenhuma lógica de tentativa novamente.

### Passo 5: Registrar Biometria e Confirmar

Solicite ao usuário os dados biométricos e confirme o registro:

```kotlin
class EnrollmentViewModel(
    private val sdk: BiometricPixSDK
) : ViewModel() {
    
    private var enrollmentId: String? = null
    
    fun startBiometricRegistration(fidoOptions: FidoRegistrationOptions) {
        try {
            sdk.startRegistration(
                fidoOptions = fidoOptions.toJsonString(),
                callback = object : FidoRegistrationCallback {
                    override fun onSuccess(credential: PublicKeyCredential, response: AuthenticatorAttestationResponse) {
                        // SDK lida com a criação do payload automaticamente
                        confirmEnrollment(credential, response)
                    }
                    
                    override fun onError(error: String) {
                        _error.value = "Registro biométrico falhou: $error"
                    }
                }
            )
        } catch (e: Exception) {
            _error.value = "Falha ao iniciar o registro: ${e.message}"
        }
    }
    
    private fun confirmEnrollment(
        credential: PublicKeyCredential,
        response: AuthenticatorAttestationResponse
    ) {
        val enrollmentId = this.enrollmentId ?: return
        
        viewModelScope.launch {
            val success = sdk.confirmEnrollment(
                enrollmentId = enrollmentId,
                credential = credential,
                response = response
            )
            
            if (success) {
                _state.value = EnrollmentState.Success
            } else {
                _error.value = "Confirmação de registro falhou"
            }
        }
    }
}
```

Registro Completo!
O dispositivo agora está registrado e pronto para pagamentos biométricos.

## Fluxo de Pagamento (4 Etapas)

Uma vez inscrito, iniciar pagamentos requer quatro chamadas de método:

```mermaid
sequenceDiagram
    autonumber
    participant User
    participant YourApp
    participant BiometricPixSDK
    participant BelvoAPI
    participant Institution

    Note over YourApp,BiometricPixSDK: Chamada 1: listEnrollments()
    User->>YourApp: Inicia pagamento
    YourApp->>BiometricPixSDK: listEnrollments(deviceId)
    BiometricPixSDK->>BelvoAPI: GET /enrollments/?device_id=...
    BelvoAPI-->>BiometricPixSDK: List&lt;Enrollment&gt;
    BiometricPixSDK-->>YourApp: Lista de inscrições
    YourApp->>User: Exibir seletor de inscrição
    User-->>YourApp: Seleciona inscrição
    
    Note over YourApp,BiometricPixSDK: Chamada 2: createPaymentIntent()
    YourApp->>BiometricPixSDK: createPaymentIntent(payload)
    BiometricPixSDK->>BelvoAPI: POST /payment-intents/
    BelvoAPI-->>BiometricPixSDK: PaymentIntent (com opções FIDO)
    BiometricPixSDK-->>YourApp: Objeto PaymentIntent
    
    Note over YourApp,BiometricPixSDK: Chamada 3: startSigning() + collectRiskSignals()
    YourApp->>BiometricPixSDK: startSigning(fidoOptions, callback)
    BiometricPixSDK->>User: Solicitar biometria (impressão digital/rosto)
    User-->>BiometricPixSDK: Fornece biometria
    BiometricPixSDK-->>YourApp: Asserção via callback
    YourApp->>BiometricPixSDK: collectRiskSignals(accountTenure)
    BiometricPixSDK-->>YourApp: RiskSignals
    
    Note over YourApp,BiometricPixSDK: Chamada 4: authorizePaymentIntent()
    YourApp->>BiometricPixSDK: authorizePaymentIntent(paymentIntentId, payload)
    BiometricPixSDK->>BelvoAPI: POST /payment-intents/{id}/authorize/
    BelvoAPI->>Institution: Processar pagamento
    Institution-->>BelvoAPI: Pagamento confirmado
    BelvoAPI-->>BiometricPixSDK: Pagamento SUCCEEDED
    BiometricPixSDK-->>YourApp: Sucesso na autorização (Boolean)
    YourApp->>User: Mostrar confirmação de pagamento
```

### Passo 1: Listar Inscrições

Busque todas as inscrições para o dispositivo atual e permita que o usuário selecione uma:

```kotlin
class PaymentViewModel(
    private val sdk: BiometricPixSDK
) : ViewModel() {
    
    private val _enrollments = MutableStateFlow<List<Enrollment>>(emptyList())
    val enrollments: StateFlow<List<Enrollment>> = _enrollments
    
    fun loadEnrollments(deviceId: String) {
        viewModelScope.launch {
            try {
                _enrollments.value = sdk.listEnrollments(deviceId)
            } catch (e: Exception) {
                _error.value = "Falha ao carregar inscrições: ${e.message}"
            }
        }
    }
}
```

**Exibir inscrições para o usuário:**

```kotlin
@Composable
fun EnrollmentSelectionScreen(
    viewModel: PaymentViewModel
) {
    val enrollments by viewModel.enrollments.collectAsState()
    
    LazyColumn {
        items(enrollments) { enrollment ->
            enrollment.institution?.let { institution ->
                EnrollmentItem(
                    enrollment = enrollment,
                    institution = institution,
                    onClick = { viewModel.selectEnrollment(enrollment) }
                )
            }
        }
    }
    
    LaunchedEffect(Unit) {
        viewModel.loadEnrollments(savedDeviceId)
    }
}

@Composable
fun EnrollmentItem(
    enrollment: Enrollment,
    institution: Institution,
    onClick: () -> Unit
) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .clickable(onClick = onClick)
            .padding(16.dp)
    ) {
        AsyncImage(
            model = institution.iconLogo,
            contentDescription = institution.displayName,
            modifier = Modifier.size(40.dp)
        )
        Spacer(modifier = Modifier.width(16.dp))
        Column {
            Text(text = institution.displayName)
            Text(
                text = "Status: ${enrollment.status}",
                style = MaterialTheme.typography.bodySmall,
                color = MaterialTheme.colorScheme.onSurfaceVariant
            )
        }
    }
}
```

### Passo 2: Criar Intenção de Pagamento

Crie uma intenção de pagamento com todos os detalhes do pagamento:

```kotlin
fun createPayment(
    amount: Double,
    enrollmentId: String,
    beneficiaryAccountId: String
) {
    val payload = CreatePaymentIntentPayload(
        amount = amount,
        customer = Customer(identifier = userCPF),  // CPF do usuário
        description = "Pagamento por serviços",
        statementDescription = "Compra ACME Corp",
        allowedPaymentMethodTypes = listOf("open_finance_biometric_pix"),
        paymentMethodDetails = PaymentMethodDetails(
            openFinanceBiometricPix = OpenFinanceBiometricPixPaymentMethodDetails(
                beneficiaryBankAccount = beneficiaryAccountId,
                enrollment = enrollmentId
            )
        ),
        confirm = true
    )
    
    viewModelScope.launch {
        try {
            val paymentIntent = sdk.createPaymentIntent(payload)
            
            // Salvar ID da intenção de pagamento
            _paymentIntentId.value = paymentIntent.id
            
            // Extrair opções FIDO para o próximo passo
            paymentIntent.paymentMethodInformation?.openFinanceBiometricPix?.fidoOptions?.let { fidoOptions ->
                promptForBiometric(fidoOptions)
            }
            
        } catch (e: Exception) {
            _error.value = "Falha ao criar intenção de pagamento: ${e.message}"
        }
    }
}
```

### Passo 3: Coletar Sinais Biométricos e de Risco

Solicite a autenticação biométrica e colete sinais de risco:

```kotlin
class PaymentViewModel(
    private val sdk: BiometricPixSDK
) : ViewModel() {
    
    private var paymentIntentId: String? = null
    private var riskSignals: RiskSignals? = null
    private var assertionResponse: AssertionResponse? = null
    
    fun promptForBiometric(fidoOptions: FidoOptions) {
        try {
            sdk.startSigning(
                fidoOptions = fidoOptions.toJsonString(),
                fallbackCredential = null,  // Opcional: forneça se você tiver um
                callback = object : FidoAuthenticationCallback {
                    override fun onSuccess(response: AssertionResponse) {
                        // Armazene a resposta de asserção
                        assertionResponse = response
                        
                        // Colete sinais de risco
                        collectRiskSignals()
                    }
                    
                    override fun onError(error: String) {
                        _error.value = "Falha na autenticação biométrica: $error"
                    }
                }
            )
        } catch (e: Exception) {
            _error.value = "Falha ao iniciar a assinatura: ${e.message}"
        }
    }
    
    private fun collectRiskSignals() {
        try {
            riskSignals = sdk.collectRiskSignals(
                accountTenure = customerCreatedDate  // "YYYY-MM-DD"
            )
            
            // Assim que tivermos tanto a asserção quanto os sinais de risco, autorize o pagamento
            if (assertionResponse != null && riskSignals != null) {
                authorizePayment()
            }
        } catch (e: Exception) {
            _error.value = "Falha ao coletar sinais de risco: ${e.message}"
        }
    }
}
```

### Passo 4: Autorizar Pagamento

Autorize o pagamento com os dados coletados:

```kotlin
private fun authorizePayment() {
    val paymentIntentId = this.paymentIntentId ?: return
    val riskSignals = this.riskSignals ?: return
    val assertion = this.assertionResponse ?: return
    
    val payload = AuthorizePaymentIntentPayload(
        platform = "android",
        riskSignals = riskSignals,
        assertion = assertion
    )
    
    viewModelScope.launch {
        val success = sdk.authorizePaymentIntent(
            paymentIntentId = paymentIntentId,
            payload = payload
        )
        
        if (success) {
            _state.value = PaymentState.Success
        } else {
            _error.value = "Falha na autorização do pagamento"
        }
    }
}
```

Fluxo de Pagamento Completo!
O pagamento agora está autorizado e em processamento. Você precisa monitorar eventos de webhook para acompanhar seu status final.

## Tratamento de Erros

Todos os métodos do SDK que realizam operações de rede podem lançar exceções. Certifique-se de tratá-las adequadamente:

```kotlin
try {
    val institutions = sdk.getPaymentInstitutions()
    // Sucesso
} catch (e: BiometricPixSDKException) {
    when (e) {
        is BiometricPixSDKException.NetworkError -> {
            // Tratar problemas de rede
            Log.e(TAG, "Erro de rede: ${e.message}")
        }
        is BiometricPixSDKException.AuthenticationError -> {
            // Tratar token inválido ou expirado
            Log.e(TAG, "Falha na autenticação - o token pode estar expirado")
        }
        is BiometricPixSDKException.InvalidParametersError -> {
            // Tratar entrada inválida
            Log.e(TAG, "Parâmetros inválidos: ${e.message}")
        }
        is BiometricPixSDKException.UnknownError -> {
            // Tratar erros desconhecidos
            Log.e(TAG, "Erro: ${e.message}")
        }
    }
} catch (e: Exception) {
    Log.e(TAG, "Erro inesperado: ${e.message}")
}
```

## Webhooks

Embora o SDK gerencie a maior parte do fluxo de trabalho, você ainda deve escutar notificações de webhook para lidar com atualizações assíncronas:

- **Mudanças no status de inscrição:** tipo de webhook `ENROLLMENTS`
- **Mudanças no status de pagamento:** tipo de webhook `PAYMENT_INTENTS`


Para a documentação completa de webhooks, veja Webhooks de Pagamentos (Brasil).

## Referência de Método SDK

### Inicialização

**`BiometricPixSDK(context: Context, accessToken: String)`**

- Cria uma nova instância do SDK com o contexto e o access token fornecidos
- Deve ser inicializado uma vez e reutilizado em todo o seu aplicativo
- Access token obtido a partir do endpoint `/payments/api/widget-token/`


**`cleanup()`**

- Libera os recursos do SDK e limpa as tarefas em segundo plano
- Chame em `onCleared()` ou quando o usuário fizer logout


### Métodos de Inscrição

**`getPaymentInstitutions(): List<Institution>`**

- Busca todas as instituições que suportam pagamentos biométricos
- Retorna uma lista de objetos `Institution` com `id`, `displayName`, `iconLogo`, etc.
- Lança exceções em erros de rede ou autenticação


**`createEnrollment(cpf: String, institution: String, accountTenure: String, callbackUrl: String): Enrollment`**

- Cria a inscrição e coleta sinais de risco automaticamente
- `cpf`: Número de CPF do usuário
- `institution`: ID da instituição de `getPaymentInstitutions()`
- `accountTenure`: Data de criação do cliente no formato "YYYY-MM-DD"
- `callbackUrl`: Deep link para callback OAuth (deve ser registrado como App Link)
- Retorna um objeto `Enrollment` com `id`, `redirect_url`, `device_id`


**`openRedirectUrl(context: Context, url: String)`**

- Abre o aplicativo da instituição usando o URL de redirecionamento fornecido
- Lida com o redirecionamento automaticamente, incluindo deep linking
- Deve ser chamado imediatamente após `createEnrollment()` com o `redirect_url` da resposta de inscrição
- `context`: Contexto da Activity ou Application
- `url`: O URL de redirecionamento do objeto de inscrição


**`completeEnrollmentAfterRedirection(callbackUrl: String): Enrollment`**

- Completa a inscrição após o callback OAuth da instituição
- Analisa automaticamente os parâmetros OAuth do URL completo de callback
- Alternativa: `completeEnrollmentAfterRedirection(state: String, code: String, idToken: String)`


**`getFidoRegistrationOptions(enrollmentId: String): FidoRegistrationOptions?`**

- Faz polling para opções FIDO (tentativa automática: intervalo de 1 segundo, timeout de 5 minutos)
- Retorna `FidoRegistrationOptions` quando pronto
- Retorna `null` se o polling expirar


**`startRegistration(fidoOptions: String, callback: FidoRegistrationCallback)`**

- Inicia o fluxo de registro biométrico (reconhecimento de impressão digital/face)
- `fidoOptions`: String JSON de `FidoRegistrationOptions.toJsonString()`
- `callback`: Interface para receber callbacks de sucesso/erro


**`confirmEnrollment(enrollmentId: String, credential: PublicKeyCredential, response: AuthenticatorAttestationResponse): Boolean`**

- Confirma a inscrição com credencial FIDO
- Retorna `true` em caso de sucesso, `false` em caso de falha


### Métodos de Pagamento

**`listEnrollments(deviceId: String): List<Enrollment>`**

- Busca todas as inscrições para um dispositivo
- Retorna uma lista de objetos `Enrollment` com dados enriquecidos da instituição
- Filtre por `status == "SUCCEEDED"` para mostrar apenas inscrições ativas


**`createPaymentIntent(payload: CreatePaymentIntentPayload): PaymentIntent`**

- Cria uma intenção de pagamento
- Retorna `PaymentIntent` com `id` e `paymentMethodInformation.openFinanceBiometricPix.fidoOptions`


**`startSigning(fidoOptions: String, fallbackCredential: String?, callback: FidoAuthenticationCallback)`**

- Inicia a autenticação biométrica para pagamento
- `fallbackCredential`: Credencial opcional para cenários de tentativa novamente
- `callback`: Interface para receber a resposta de asserção


**`collectRiskSignals(accountTenure: String): RiskSignals`**

- Coleta impressões digitais do dispositivo e sinais de segurança
- `accountTenure`: Data de criação do cliente no formato "YYYY-MM-DD"
- Retorna objeto `RiskSignals` para carga de autorização


**`authorizePaymentIntent(paymentIntentId: String, payload: AuthorizePaymentIntentPayload): Boolean`**

- Autoriza pagamento com asserção biométrica e sinais de risco
- Retorna `sim` em caso de sucesso, `false` em caso de falha