Pular para o conteúdo principal

Instalação do SDK

Guia de instalação do SDK (apossdk) para Android.

Requisitos​

Hardware​

  • Terminal POS Positivo L300, L400 ou OCTA 400
  • Conexão de rede (Wi-Fi, dados móveis ou Ethernet)

Software​

  • Android 8.0 (API 26) ou superior (minSdk = 26)
  • Kotlin com coroutines (boa parte da API é suspend). O SDK é compilado com Kotlin 2.3.10; recomenda-se Kotlin 2.3 ou superior no app
  • Java 17 (sourceCompatibility/targetCompatibility e jvmTarget 17)
  • compileSdk = 36 (a versão com que o SDK é compilado)

Distribuição​

O SDK é distribuído como um AAR Fused Library — um único artefato que combina o módulo :apossdk com as bibliotecas de hardware da Positivo. O arquivo AAR é disponibilizado por e-mail; após recebê-lo, publique-o no seu repositório Maven local conforme o guia abaixo.

São dois artefatos, um por ambiente. A coordenada escolhe ao mesmo tempo os endpoints e o certificado mTLS:

ArtefatoAmbienteObservação
com.tupifintech:apossdk-release-prodProduçãoSem POS simulado
com.tupifintech:apossdk-debug-stagingHomologação (staging)Inclui PosPinpad.createFake(...), um POS simulado para testes sem hardware

Maven local​

Publique o SDK no seu repositório Maven local a partir do projeto do SDK:

./gradlew publishToMavenLocal

Configure o mavenLocal() no settings.gradle.kts do seu app, antes dos demais repositórios:

dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
mavenLocal() // 👈 antes de google()/mavenCentral()
google()
mavenCentral()
}
}

Adicione a dependência no build.gradle.kts do módulo app:

dependencies {
debugImplementation("com.tupifintech:apossdk-debug-staging:<versao>")
releaseImplementation("com.tupifintech:apossdk-release-prod:<versao>")
}

O repositório local fica em ~/.m2/repository/ (macOS/Linux) ou C:\Users\{usuario}\.m2\repository\ (Windows). Verifique a publicação com ls ~/.m2/repository/com/tupifintech/.

As dependências de terceiros que o SDK usa em runtime (okhttp, Gson, kotlinx-serialization, kotlinx-coroutines, androidx core-ktx, work-runtime e security-crypto) vêm pelo POM do artefato, em escopo runtime, e o Gradle as resolve sozinho.

Usando o .aar como arquivo​

Um AAR solto (copiado para libs/ ou via flatDir) não traz POM, então nenhuma dependência é resolvida e o app quebra em runtime com NoClassDefFoundError. Nesse caso, declare as dependências você mesmo:

dependencies {
implementation(files("libs/apossdk-release-prod.aar"))

// O que viria pelo POM se o SDK fosse consumido de um repositório Maven:
implementation("androidx.core:core-ktx:1.17.0")
implementation("androidx.work:work-runtime-ktx:2.11.1")
implementation("androidx.security:security-crypto:1.1.0")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.10.2")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.10.0")
implementation("com.squareup.okhttp3:okhttp:5.3.2")
implementation("com.google.code.gson:gson:2.13.2")
}

Prefira o Maven local sempre que possível: a lista acima corresponde à versão atual do SDK, e a do POM acompanha cada versão.

Certificado mTLS​

O gateway exige mTLS. O certificado cliente vem dentro do SDK, um por ambiente: o apossdk-debug-staging leva o de staging e o apossdk-release-prod o de produção. Na integração normal, o app não faz nada.

Para usar outro certificado (um ambiente fora do padrão, por exemplo), passe um MtlsCertificate ao criar a instância. Veja Configuração.

Permissões​

O SDK declara no próprio manifest as permissões de hardware do terminal (com.pos.permission.*: leitores de cartão, impressora, segurança, EMV) e ACCESS_NETWORK_STATE. Elas chegam ao seu app pelo merge de manifest.

Declare no manifest do app a permissão de internet:

<!-- AndroidManifest.xml -->
<uses-permission android:name="android.permission.INTERNET" />

Assinatura do APK​

As permissões com.pos.permission.* só são concedidas a apps assinados com a chave de plataforma do modelo de terminal. Sem ela, o app instala e abre, mas não acessa o leitor de cartão, a impressora nem o módulo de segurança. A keystore de plataforma de cada modelo é fornecida pela Tupi.

// build.gradle.kts
android {
signingConfigs {
create("platform") {
storeFile = file("<keystore-de-plataforma-do-modelo>.jks")
storePassword = providers.gradleProperty("platform.storePassword").get()
keyAlias = "platform"
keyPassword = providers.gradleProperty("platform.keyPassword").get()
}
}

buildTypes {
debug { signingConfig = signingConfigs.getByName("platform") }
release { signingConfig = signingConfigs.getByName("platform") }
}
}

Não versione a keystore nem as senhas no repositório do app.

Configuração do JVM Target e SDK​

android {
compileSdk = 36

defaultConfig {
minSdk = 26
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
}

kotlin {
compilerOptions {
jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
}
}

Configuração do R8/ProGuard​

O SDK usa serialização por reflexão (Gson), proxies dinâmicos e as bibliotecas da Positivo, que o R8 quebraria se renomeasse ou removesse.

Versões posteriores à 1.0.7: o AAR já traz as regras necessárias (consumer rules), aplicadas automaticamente quando o seu app compila com isMinifyEnabled = true. Não é preciso declarar nada. Elas cobrem:

  • o SDK (modelos serializados pelo Gson, enums, interfaces públicas e os proxies internos);
  • as bibliotecas da Positivo (br.com.positivo, com.pos.sdk, o serviço de impressão com.xcheng.printerservice) e o kernel EMV (com.emv), que é chamado por nome a partir do código nativo: sem a regra, a venda por aproximação derruba o app;
  • o componente de tela secundária da Kozen;
  • o TypeToken do Gson e os workers do WorkManager usados na fila de pendências.

Versão 1.0.7 e anteriores: o AAR não traz regras. Declare no proguard-rules.pro do seu app:

# Tupi apossdk
-keepattributes Signature,InnerClasses,EnclosingMethod,RuntimeVisibleAnnotations,RuntimeVisibleParameterAnnotations,AnnotationDefault
-keep class com.tupifintech.apossdk.** { *; }
-keep interface com.tupifintech.apossdk.** { *; }

# Gson e WorkManager
-keep class com.google.gson.reflect.TypeToken { *; }
-keep class * extends com.google.gson.reflect.TypeToken
-keep class * extends androidx.work.ListenableWorker {
<init>(android.content.Context, androidx.work.WorkerParameters);
}

# Bibliotecas Positivo, impressora e kernel EMV
-keep class br.com.positivo.** { *; }
-keep class com.pos.sdk.** { *; }
-keep class com.xcheng.printerservice.** { *; }
-keep class com.emv.** { *; }

# Tela secundária (Kozen)
-keep class com.kozen.** { *; }

-dontwarn br.com.positivo.**
-dontwarn com.pos.**
-dontwarn com.xcheng.printerservice.**
-dontwarn com.emv.**
-dontwarn com.kozen.**

Verificação da Instalação​

Após sincronizar o projeto, valide que o SDK carrega criando uma instância e consultando o dispositivo:

import com.tupifintech.apossdk.sdk.api.PosPinpad

val posPinpad = PosPinpad.create(this, myCallback)

// A conexão com o pinpad acontece em segundo plano após create
try {
val deviceInfo = posPinpad.getDeviceInfo()
Log.d("YBY", "Terminal: ${deviceInfo.hardwareModel}")
Log.d("YBY", "Serial: ${deviceInfo.serialNo}")
} catch (e: IllegalStateException) {
Log.d("YBY", "Pinpad ainda conectando")
}

Problemas Comuns​

SDK não encontrado​

  • Confirme que mavenLocal() está configurado antes de google()/mavenCentral().
  • Verifique se as coordenadas (apossdk-debug-staging / apossdk-release-prod) e as versões em dependencies coincidem com as publicadas.
  • Limpe o cache: ./gradlew clean e ./gradlew --refresh-dependencies.

NoClassDefFoundError em runtime​

  • O SDK foi adicionado como AAR solto. Declare as dependências de terceiros (seção Usando o .aar como arquivo) ou consuma pelo Maven local.

Leitor de cartão ou impressora não respondem​

  • O APK não foi assinado com a chave de plataforma do modelo do terminal.

Erro de compatibilidade​

  • Certifique-se de que minSdk é 26 ou superior e que o projeto usa Java 17.

Crash na primeira chamada de rede (sslSocketFactory has not been initialized)​

  • Sempre obtenha a instância via PosPinpad.create(context, callback). O create() inicializa o HttpClient com o socket factory mTLS — usar a implementação diretamente pula essa etapa.