# Estornar um Pagamento

Este guia detalha como implementar operações de estorno (refund) utilizando o `RefundRepository`. O estorno permite devolver fundos para o cartão de um cliente, seja vinculado a uma transação anterior ou como uma operação independente.

Antes de realizar qualquer estorno, certifique-se de que você já [**inicializou o TPV**](/pt/get-smart/get-smart-sdk/integration-guides/payment-operations/initialize-the-tpv).

## Métodos de Estorno

O `RefundRepository` suporta três fluxos distintos de estorno:

### 1. Estorno Padrão (Por ID)

Use este método quando você tiver o identificador da transação original (`operationId`) e quiser estornar um valor específico contra ela. Este é o cenário mais comum.

**Função**: `makeRefund`

**Parâmetros**:

* `operationId`: O identificador exclusivo da venda original.  
* `amount`: O objeto `Money` representando o valor a ser estornado.  
* `proprietaryExtraData` (Opcional): Dados de terceiros.  
* `language` (Opcional): Idioma para a interface do serviço.

**Exemplo**:

```kotlin
suspend fun refundTransaction(originalId: String, amount: Money) {
    val result = refundRepository.makeRefund(
        operationId = originalId,
        amount = amount
    )
    handleRefundResult(result)
}
```

### 2. Estorno com Leitura de Cartão

Use este método quando você tiver o `operationId` original, mas desejar forçar o cliente a apresentar o cartão novamente (ex: por motivos de segurança ou conformidade).

**Função**: `makeRefundReadingCard`

**Parâmetros**: Mesmos do Estorno Padrão.

**Exemplo**:

```kotlin
suspend fun refundWithCardCheck(originalId: String, amount: Money) {
    val result = refundRepository.makeRefundReadingCard(
        operationId = originalId,
        amount = amount
    )
    handleRefundResult(result)
}
```

### 3. Estorno Sem Original (Adhoc)

Use este método para emitir um estorno sem vinculá-lo a uma transação anterior. Esta funcionalidade geralmente requer que uma configuração específica (`noOriginal`) esteja habilitada no TPV.

**Função**: `makeRefundWithoutOriginal`

**Parâmetros**:

* `amount`: O objeto `Money` representando o valor a ser estornado.  
* `proprietaryExtraData` (Opcional): Dados de terceiros.  
* `language` (Opcional): Idioma para a interface do serviço.

**Exemplo**:

```kotlin
suspend fun adhocRefund(amount: Money) {
    val result = refundRepository.makeRefundWithoutOriginal(
        amount = amount
    )
    handleRefundResult(result)
}
```

## Interpretando o RefundResult

Quando a chamada do repositório é bem-sucedida (`RepositoryResult.Success`), ela retorna uma interface selada `RefundResult`. Você deve tratar os seguintes estados:

### 1. Aceito (RefundResult.Accepted)

O estorno foi autorizado pelo host.

* **Dados**: Contém um objeto `Transaction` com os detalhes da operação de estorno.  
* **Ação**: Imprima o comprovante de estorno e confirme o sucesso para o usuário.

### 2. Negado (`RefundResult.Denied`)

O estorno foi rejeitado.

* **Dados**: Contém um objeto `Transaction`, potencialmente com o motivo da rejeição.  
* **Ação**: Informe ao usuário que o estorno foi recusado.

### 3. Valor Excedido (`RefundResult.ExceededAmount`)

Erro específico indicando que o valor de estorno solicitado é maior que o valor da transação original (ou que o saldo estornável restante).

* **Ação**: Exiba um erro indicando que o valor é muito alto.

### Exemplo de Lógica de Tratamento

```kotlin
fun handleRefundResult(result: RepositoryResult<RefundResult>) {
    when (result) {
        is RepositoryResult.Success -> {
            when (val refundOutcome = result.data) {
                is RefundResult.Accepted -> {
                    println("✅ Refund Approved: ${refundOutcome.data.operationInfo.authorizationNumber}")
                }
                is RefundResult.Denied -> {
                    println("❌ Refund Denied")
                }
                is RefundResult.ExceededAmount -> {
                    println("⚠️ Error: Refund amount exceeds original transaction")
                }
            }
        }
        is RepositoryResult.ConnectionError -> println("❌ Connection Error")
        is RepositoryResult.Cancelled -> println("⚠️ Cancelled by user")
        is RepositoryResult.ProtocolError -> println("❌ Protocol Error: ${result.type}")
    }
}
```

## Próximos Passos

* [**Criar um Pagamento Pré-autorizado**](/pt/get-smart/get-smart-sdk/integration-guides/payment-operations/create-a-pre-authorized-payment): Saiba como reservar fundos em um cartão.
* [**Histórico de Transações**](): Consultando operações passadas.