Eagle · Pagamentos
SoftPOS · Tap on Phone

Android nativo

Integração do SDK SoftPOS em um app Android nativo com Kotlin — inicialização, ativação do vendedor e cobrança

Em construção

Esta seção documenta um SDK ainda em desenvolvimento. A API pode mudar, os pacotes ainda não estão publicados e os fluxos descritos não foram homologados em produção.

Guia completo da integração em Kotlin. Cada passo mostra o código mínimo; a referência detalha tipos e parâmetros.

1. Adicionar a dependência

app/build.gradle.kts
dependencies {
    implementation("com.eagleix.softpos:sdk:0.1.0")
}

O AAR é publicado em repositório Maven privado. Declare o repositório informado pelo time da Eagle no settings.gradle.kts do app.

O SDK exige compileOptions em Java 17 e traz Kotlin Coroutines, OkHttp e kotlinx.serialization como dependências internas — nenhuma delas vaza para o classpath do seu app.

2. Inicializar

Uma vez por processo, tipicamente no Application:

EagleApp.kt
class EagleApp : Application() {
    override fun onCreate() {
        super.onCreate()

        Eagle.initialize(
            context = applicationContext,
            config = EagleConfig(
                apiKey = BuildConfig.EAGLE_API_KEY,
                environment = EagleEnvironment.SANDBOX,
                backend = HttpEagleBackend(
                    baseUrl = BuildConfig.EAGLE_BASE_URL,
                    apiKey = BuildConfig.EAGLE_API_KEY,
                ),
            ),
        )
    }
}

initialize devolve a EagleSession criada, caso você prefira injetá-la explicitamente em vez de usar a fachada global — útil em testes e em apps com mais de uma configuração.

3. Garantir o m-SiTef

if (!Eagle.isAndroidVersionSupported()) {
    // Android < 12: esconda a opção de cobrar.
    return
}

if (!Eagle.isMSitefInstalled()) {
    startActivity(Eagle.playStoreIntent())
    return
}

playStoreIntent() abre o app da Play Store quando disponível e cai para o navegador quando não.

4. Ativar o vendedor

Uma vez por vendedor, com o token emitido pelo backend da sua empresa:

lifecycleScope.launch {
    runCatching { Eagle.activateSeller(sellerToken) }
        .onSuccess { activation ->
            // activation.posId identifica o PDV do vendedor
        }
        .onFailure { erro ->
            // EagleError.Network, EagleError.Backend, ...
        }
}

5. Cobrar

EaglePayments precisa ser criado no onCreate da Activity — o registro do resultado da Intent (registerForActivityResult) tem que acontecer antes de a Activity ficar RESUMED.

CheckoutActivity.kt
class CheckoutActivity : ComponentActivity() {

    private lateinit var payments: EaglePayments

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        payments = EaglePayments(this) // obrigatoriamente aqui
        setContentView(R.layout.checkout)
    }

    private fun cobrar() = lifecycleScope.launch {
        val result = payments.startSale(
            SaleRequest(
                amountInCents = 5_000,           // R$ 50,00
                method = PaymentMethod.CREDIT,
                installments = 3,
                receiptNumber = "CUPOM-1042",
            ),
        )

        if (result.approved) {
            mostrarComprovante(result.customerReceipt)
        } else {
            mostrarRecusa(result.codResp.description)
        }
    }
}

Criar EaglePayments fora do onCreate (por exemplo dentro do clique do botão) lança IllegalStateException do Android ao registrar o launcher. Se o seu checkout vive num Fragment ou numa tela Compose, crie o EaglePayments na Activity hospedeira e passe-o adiante.

Recusa não é exceção

startSale devolve SaleResult também quando a transação é negada ou cancelada — só falhas fora do fluxo transacional (rede, backend, m-SiTef ausente, vendedor não ativado) lançam EagleError.

val result = try {
    payments.startSale(request)
} catch (e: EagleError.MSitefNotInstalled) {
    startActivity(Eagle.playStoreIntent()); return@launch
} catch (e: EagleError.SellerNotActivated) {
    irParaAtivacao(); return@launch
} catch (e: EagleError) {
    mostrarErro(e.message); return@launch
}

when (result.codResp.category) {
    CodResp.Category.SUCCESS  -> mostrarComprovante(result.customerReceipt)
    CodResp.Category.DENIED   -> mostrarRecusa(result.codResp.description)
    CodResp.Category.CANCELED -> mostrarCancelamento()
    CodResp.Category.ERROR    -> mostrarErro(result.codResp.description)
}

6. Observar o estado

O SDK é headless: ele publica estado e o seu app decide o que desenhar.

lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.STARTED) {
        Eagle.state.collect { state ->
            when (state) {
                EagleState.Idle              -> esconderProgresso()
                EagleState.MSitefMissing     -> ofereceInstalacao()
                EagleState.ActivationPending -> mostrarProgresso("Ativando vendedor…")
                EagleState.Processing        -> mostrarProgresso("Aguardando pagamento…")
                is EagleState.Approved       -> mostrarComprovante(state.result.customerReceipt)
                is EagleState.Denied         -> mostrarRecusa(state.result.codResp.description)
                is EagleState.Failed         -> mostrarErro(state.error.message)
            }
        }
    }
}

Colete Eagle.state somente depois de Eagle.initialize — acessá-lo antes lança EagleError.NotInitialized.

7. Telemetria (opcional)

Forneça um EagleLogger para encaminhar eventos do SDK ao seu monitoramento:

EagleConfig(
    apiKey = apiKey,
    environment = EagleEnvironment.PRODUCTION,
    backend = backend,
    logger = object : EagleLogger {
        override fun debug(message: String) = Timber.d(message)
        override fun info(message: String) = Timber.i(message)
        override fun error(message: String, throwable: Throwable?) {
            Crashlytics.recordException(throwable ?: Exception(message))
        }
    },
)

Nunca registre PAN, PIN ou o conteúdo de customerReceipt / merchantReceipt no seu logger. Metadados de transação (CODRESP, NSU, timestamps) são seguros; as vias do comprovante podem conter dados do portador.

Fluxo completo

On this page