---
title: "Android"
url: "https://devcenter.stone.com.br/tap-to-pay-android"
image: "https://devcenter.stone.com.br/_og/d/c_Ocean.takumi,title_Android,props_eyJ0aGVtZSI6eyJtb2RlIjoibGlnaHQiLCJjb2xvcnMiOnsicHJpbWFyeSI6IiMzMEE2NkQifX19,p_Ii90YXAtdG8tcGF5LWFuZHJvaWQi,s_6BP-zyikTRRcEbxJ.png"
---

# Android

Configuração, venda e exemplo completo em Kotlin.

Importante

Antes de publicar, registre os version codes no Play Integrity — veja [Version Codes (Android)](https://devcenter.stone.com.br/tap-to-pay-version-codes).

## [Requisitos](#requisitos)

| Item          | Valor                                     |
| :------------ | :---------------------------------------- |
| minSdk        | 29 (Android 10)                           |
| Java / Kotlin | JDK 17 · Kotlin 2.1.20 ou mais novo       |
| Activity      | ComponentActivity ou AppCompatActivity    |
| Aparelho      | NFC obrigatório; emulador não é suportado |

## [Dependência](#dependência)

O repositório Maven e as credenciais de acesso ao SDK são enviados pela Stone no início da integração.

```kotlin
// app/build.gradle.kts
dependencies {
    implementation("com.stone.tapsdk:tap-core:<versão informada pela Stone>")
    // para coletar o Flow do pay()
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:<versão>")
}

android {
    packaging {
        resources {
            excludes += setOf(
                "META-INF/LICENSE.md", "META-INF/LICENSE.txt", "META-INF/NOTICE.md",
                "META-INF/NOTICE.txt", "META-INF/LICENSE-notice.md",
            )
        }
    }
}
```

O SDK tem a variante de testes (SDX) e a de produção. Se o build de release usa minificação (R8), valide a venda completa no build minificado antes de publicar.

## [Configuração](#configuração)

AndroidManifest.xml

```xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-permission android:name="android.permission.INTERNET" />
    <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" />
    <uses-feature android:name="android.hardware.nfc" android:required="true" />

    <application android:name=".MainApplication" ...>
        <!-- suas activities -->
    </application>
</manifest>
```

A localização é permissão de runtime e é usada na validação do aparelho. Peça antes do primeiro setup. Sem ela, o setup falha com `331` (permissão ausente) ou `332` (localização desligada).

Confira se o NFC está ligado (`NfcAdapter.isEnabled`). Se não estiver, leve o usuário às configurações.

A classe Application cria o SDK, como em [Setup do SDK](https://devcenter.stone.com.br/tap-to-pay-sdk-setup) (seção 3.1).

Imports usados nos exemplos:

```kotlin
import br.com.stone.sdk.android.error.StoneStatus
import com.stone.tap.core.TapFeeScreens
import com.stone.tap.core.TapSaleExit
import com.stone.tap.core.TapSdk
import com.stone.tap.core.TapStoneCo
import com.stone.tap.core.internal.di.Environment
import com.stone.tap.core.internal.transaction.model.PaymentMethod
import com.stone.tap.core.internal.transaction.model.TransactionData
import com.stone.tap.core.internal.transaction.model.TransactionEvent
import com.stone.tap.core.session.model.Credential
import com.stone.tap.core.session.model.SetupData
```

## [Processar Transação](#processar-transação)

O setup deve ser feito antes — veja [Setup do SDK](https://devcenter.stone.com.br/tap-to-pay-sdk-setup). O SDK exibe todas as telas da venda ([Setup do SDK](https://devcenter.stone.com.br/tap-to-pay-sdk-setup), seção 3.4); o app só trata o resultado final.

```kotlin
val data = TransactionData(
    amount = 1000,                        // R$ 10,00 (centavos)
    paymentMethod = PaymentMethod.CREDIT, // CREDIT, DEBIT ou VOUCHER
    installments = 1,                     // 1 = à vista
    softDescriptor = "",                  // texto na fatura do cliente
)

viewModelScope.launch {
    tapStoneCo.pay(data).collect { event ->
        if (event is TransactionEvent.OnResult) {
            if (event.result == StoneStatus.SUCCESS) {
                handleApproved(event.transactionResult)
            } else {
                handleError(event.result, event.transactionResult)
            }
        }
    }
}
```

-   O `pay()` não recebe o lojista: o SDK usa o da sessão ativa criada no `setup()`.
-   A forma de pagamento e as parcelas finais são escolhidas pelo lojista na tela do SDK. Com repasse da taxa, o valor cobrado muda; ele chega em `TapFeeScreens.onPaymentMethodConfirmed`.
-   **Operação:** toda venda é autorização com captura. **Parcelas:** parcelado é sempre lojista.
-   **`softDescriptor`:** obrigatório; passe `""` se não usar.
-   O `OnResult` é sempre o último evento. Os demais eventos do fluxo podem ser ignorados.

## [Cancelamento](#cancelamento)

O lojista cancela pelas próprias telas do SDK; nesse caso o `OnResult` vem com `7011` (`OPERATION_CANCELLED_BY_USER`). Não cancele a coleta do `pay()` antes do `OnResult`: o SDK fecha as telas e o resultado se perde.

## [Exemplo Completo — ViewModel](#exemplo-completo-viewmodel)

```kotlin
class PaymentViewModel(
    private val tapStoneCo: TapStoneCo,
) : ViewModel() {

    private val _uiState = MutableStateFlow<PaymentUiState>(PaymentUiState.Idle)
    val uiState: StateFlow<PaymentUiState> = _uiState

    init {
        // Valor final da venda (pode ter repasse da taxa)
        TapFeeScreens.onPaymentMethodConfirmed = { finalData ->
            saveFinalAmount(finalData)
        }
        // Saída da venda aprovada: nova venda ou fechar
        TapFeeScreens.onSaleFinished = { exit ->
            _uiState.value = when (exit) {
                TapSaleExit.NEW_SALE -> PaymentUiState.NewSale
                TapSaleExit.CLOSE -> PaymentUiState.Home
            }
        }
    }

    fun processPayment(amountCents: Int) {
        val data = TransactionData(
            amount = amountCents,
            paymentMethod = PaymentMethod.CREDIT,
            installments = 1,
            softDescriptor = "",
        )
        viewModelScope.launch {
            tapStoneCo.pay(data).collect { event ->
                if (event is TransactionEvent.OnResult) {
                    if (event.result == StoneStatus.SUCCESS) {
                        registerSale(event.transactionResult)
                    } else {
                        _uiState.value = PaymentUiState.Error(event.result.message)
                    }
                }
            }
        }
    }
}
```

## [Veja também](#veja-também)

[**Setup do SDK**Criação do SDK e setup() antes de transacionar.](https://devcenter.stone.com.br/tap-to-pay-sdk-setup)[**iOS**A mesma integração em Swift.](https://devcenter.stone.com.br/tap-to-pay-ios)[**Referência de API**TransactionData, TransactionEvent, StoneStatus.](https://devcenter.stone.com.br/tap-to-pay-reference)[**Version Codes (Android)**Obrigatório antes de publicar — Play Integrity.](https://devcenter.stone.com.br/tap-to-pay-version-codes)

---

**Integração: [Tap to Pay para Terceiros](https://devcenter.stone.com.br/tap-to-pay)**  
Etapa 4 de 7

[**Etapa anterior**Setup do SDK](https://devcenter.stone.com.br/tap-to-pay-sdk-setup)[**Próxima etapa**iOS](https://devcenter.stone.com.br/tap-to-pay-ios)

Siga a Stone nas redes sociais

[](https://www.facebook.com/stonepagamentos/)[](https://x.com/sejastone/)[](https://www.instagram.com/stone/)[](https://br.linkedin.com/company/stone-co)[](https://www.youtube.com/channel/UCk4L4JykgoDkN8YeuxkNqIQ)

© Stone Instituição de Pagamento S.A. CNPJ 16.501.555/0001-57

Av. Rebouças, 2880, 4º andar, Pinheiros, CEP 05.402-500 – São Paulo/SP

Instituição de pagamento autorizada pelo Banco Central do Brasil, nas modalidades de credenciadora e emissora de moeda eletrônica.