Pular para o conteúdo principal

Modelos e Estruturas de Dados

Referência das estruturas públicas do SDK (com.tupifintech.apossdk.sdk.api.model, salvo indicação).

PaymentResult

Resultado de uma tentativa de pagamento/estorno. Retornado por onTransactionCompleted e onRefundCompleted.

data class PaymentResult(
var status: PaymentStatus,
var errorCode: SdkErrorCode? = null,
var displayMessage: String? = null,
val slip: String? = null,
val receipt: TransactionReceipt? = null, // null em DECLINED/ERROR
val requiresCardRemoval: Boolean = false // true se chip inserido (ICC)
) {
enum class PaymentStatus { APPROVED, DECLINED, ERROR }
}
CampoTipoDescrição
statusPaymentStatusAPPROVED, DECLINED ou ERROR
errorCodeSdkErrorCode?Código do erro quando não aprovado
displayMessageString?Mensagem amigável pronta para exibição
slipString?Texto do comprovante para impressão
receiptTransactionReceipt?Dados estruturados (apenas quando aprovado)
requiresCardRemovalBooleantrue se o cartão (chip) precisa ser removido

TransactionReceipt

Comprovante estruturado da transação. Valores monetários em centavos (Long).

data class TransactionReceipt(
val transactionId: String,
val amount: Long,
val feeAmount: Long? = null,
val transactionType: TransactionType,
val paymentMethod: PaymentMethod,
val authCode: String,
val installments: Int? = null,
val installmentValue: Long? = null,
val timestamp: Date = Date(),
val merchantId: String? = null,
val merchantName: String? = null,
val merchantCnpj: String? = null,
val merchantDocument: String,
val merchantAddress: String,
val merchantIdentifier: String? = null, // código EC no adquirente
val cardBrand: String? = null,
val cardLastDigits: String? = null,
val cardFirstDigits: String? = null, // BIN (6 primeiros dígitos)
val cvmMethod: CvmMethod? = null,
val arqc: String? = null,
val aid: String? = null,
val serialNumber: String? = null,
val terminalId: String? = null,
val signature: Boolean? = null,
val cardHolderName: String? = null,
val captureMethod: String? = null, // "CHIP", "CLESS", "TARJA"
val nsuLocal: String? = null, // NSU local do terminal
val originalAmount: Long? = null
)

Enums

PaymentMethod

Serializado para a API conforme o @SerializedName.

enum class PaymentMethod { DEBIT, CREDIT, PIX, CASH }
ValorAPIDescrição
DEBITdebit_cardDébito (com PIN)
CREDITcredit_cardCrédito (à vista/parcelado)
PIXpixPIX (use createPixPayment)
CASHcashDinheiro

TransactionType

enum class TransactionType {
AUTHORIZATION, VOID, PRE_AUTHORIZE, CONFIRM_PRE_AUTHORIZED,
TRANSACTION_CONFIRM, REVERSAL, ADVICE, PIXQR_CODE,
PIX_PAYMENT_STATUS_CHECK, UNKNOWN
}
ValorAPIDescrição
AUTHORIZATIONauthorizationAutorização (débito/crédito)
VOIDvoidCancelamento/estorno
PRE_AUTHORIZEpre_authorizationPré-autorização (reserva)
CONFIRM_PRE_AUTHORIZEDcaptureCaptura de pré-autorização
TRANSACTION_CONFIRMconfirmationConfirmação de transação
REVERSALreversalReversão
ADVICEadviceAdvice
PIXQR_CODEpix_qr_code_generateGeração de QR PIX
PIX_PAYMENT_STATUS_CHECKpix_payment_status_checkConsulta de status PIX
UNKNOWNNão mapeado

CardReadType

Retornado por waitForCard().

enum class CardReadType { CHIP, CONTACTLESS, MAGSTRIPE, UNKNOWN }

CvmMethod

com.tupifintech.apossdk.domain.model.CvmMethod — método de verificação do portador.

enum class CvmMethod(val displayName: String) {
NO_CVM("Sem verificação"),
SIGNATURE("Assinatura"),
ONLINE_PIN("Senha online"),
OFFLINE_PIN_CLEAR("Senha offline"),
OFFLINE_PIN_ENCRYPTED("Senha offline criptografada"),
CONTACTLESS("Aproximação"),
UNKNOWN("Desconhecido")
}

InputCode

Tipo de dado solicitado em onRequestUserInput.

enum class InputCode { CVV, LAST_4_DIGITS }

NotificationType

Categoria da mensagem em onUiNotify.

enum class NotificationType { INFO, ERROR, WAITING_CARD, PROCESSING }

Impressão

PrintAttributes

data class PrintAttributes(
val align: Align = Align.LEFT,
val textSize: Int = 24,
val typeface: Typeface = Typeface.NORMAL,
val marginLeft: Int = 1,
val lineSpace: Int = 10, // mínimo aceito pela Positivo (~2mm)
val weight: Int = 10 // divisão proporcional em printColumns (ignorado em printText)
)

enum class Align(val value: Int) { CENTER(0), LEFT(1), RIGHT(2) }
enum class Typeface(val value: Int) { NORMAL(0), BOLD(1), SERIF(2), ARIAL(3) }

Configuração e Inicialização

TerminalConfigResponse

Personalização do terminal por parceiro, retornada por getTerminalConfig().

data class TerminalConfigResponse(
val partner: PartnerIdentity,
val scope: OrganizationScope,
val registrationSchema: RegistrationSchema? = null,
val dashboardButtons: Map<DashboardFeature, DashboardButtonConfig>? = null,
val legalDocuments: LegalDocuments,
val receiptCustom: ReceiptCustom? = null,
val resourceId: String? = null,
val updatedAt: String? = null
)

data class PartnerIdentity(
val brandName: String, val companyName: String,
val logoUrl: String, val logoPrintUrl: String? = null, val logoNegativeUrl: String? = null,
val supportPhone: String, val website: String,
val primaryColor: String, // #RRGGBB
val uiAlias: String? = null,
val fontFamily: String? = null // "roboto", "inter", "open_sans", "poppins"
)

data class OrganizationScope( // ao menos 1 não-nulo; viram headers nas chamadas
val acquirerId: String? = null, // X-Acquirer-Id
val subAcquirerId: String? = null, // X-Subacquirer-Id
val independentSalesOrganizationId: String? = null // X-Independent-Sales-Organization-Id
)

data class LegalDocuments(
val privacyPolicyUrl: String? = null,
val termsOfUseUrl: String? = null
)

RegistrationSchema

Define os campos da tela de registro. O app renderiza cada campo aplicando máscara/validação conforme type.

data class RegistrationSchema(
val title: String,
val submitLabel: String,
val fields: List<RegistrationSchemaField>
)

data class RegistrationSchemaField(
val id: String, // chave usada no payload de register (ex.: "cnpj", "token")
val type: String, // "EMAIL", "PASSWORD", "CNPJ", "TOKEN", ...
val label: String? = null,
val required: Boolean? = false,
val minLength: Int? = null,
val maxLength: Int? = null
)

DashboardFeature / DashboardButtonConfig

enum class DashboardFeature {
PAYMENT, REFUND, PRE_AUTH, CONFIRM_PRE_AUTH, REPRINT, SALES_HISTORY
}

data class DashboardButtonConfig(
val visible: Boolean = true,
val requiresPassword: Boolean = false
)

ReceiptCustom

data class ReceiptCustom(
val title: String? = null,
val description: String? = null,
val ouvidoriaPhone: String? = null // SAC/Ouvidoria (requisito BACEN)
)

AuthenticationRequest / AuthenticationResponse

data class AuthenticationRequest(val identifier: String, val password: String)

data class AuthenticationResponse(
val user: AuthenticatedUser? = null,
val expiresIn: Int? = null,
val issuedAt: String? = null,
val error: AuthError? = null,
val success: Boolean = (error == null) && (user != null)
)

data class AuthenticatedUser(val id: String, val name: String, val email: String, val role: String)
data class AuthError(val code: String, val message: String, val details: String? = null)

RegistrationResult

data class RegistrationResult(
val token: String? = null,
val refreshToken: String? = null,
val user: AuthenticatedUser? = null,
val terminalId: String? = null,
val merchantId: String? = null,
val merchantName: String? = null,
val acquirerId: String? = null,
val subacquirerId: String? = null,
val independentSalesOrganizationId: String? = null,
val error: AuthError? = null
) {
val success: Boolean get() = error == null && (terminalId != null || token != null)
}

TerminalInitializationRequest / Response

data class TerminalInitializationRequest(val merchantId: String)

data class TerminalInitializationResponse(
val terminalId: String? = null,
val success: Boolean = true,
val merchant: MerchantInfo? = null
)

MerchantInfo

Dados do estabelecimento (header, recibo). accessPassword é sensível — nunca logar.

data class MerchantInfo(
val merchantId: String? = null,
val name: String? = null, val corporateName: String? = null,
val taxId: String? = null, val personType: String? = null, val mcc: String? = null,
val address: String? = null, val city: String? = null, val state: String? = null,
val postalCode: String? = null, val phone: String? = null,
val accessPassword: String? = null
)

DeviceInfo

data class DeviceInfo(
val manufacturer: String,
val hardwareModel: String,
val firmwareVersion: String,
val applicationVersion: String,
val specificationVersion: String,
val serialNo: String,
val deviceInterfaces: DeviceInterfacesInfo,
val ctlsVersion: String, val masterCtlsVersion: String, val visaCtlsVersion: String,
val amexCtlsVersion: String, val discoverCtlsVersion: String,
val jcbCtlsVersion: String, val unionPayCtlsVersion: String,
val soVersion: String,
val acquirerName: String, val acquirerVersion: String, val acquirerProprietaryInfo: String
) {
data class DeviceInterfacesInfo(
val hasCtlsInterface: Boolean,
val hasChipInterface: Boolean,
val hasMagstripeInterface: Boolean
)
}

TablesInfo

data class TablesInfo(val versions: List<TableVersionInfo>, val lastUpdateAtMs: Long?)

data class TableVersionInfo(
val acquirerName: String,
val tableVersion: String,
val keyTableVersion: String? = null,
val normalizedHash: String? = null
)

TransactionLimits

Limites por operação (valores 0 significam "sem limite"). Retornado por getTransactionLimits().

data class TransactionLimits(
val featureCode: Int,
val transactionName: String,
val minTransactionValueCents: Long, val maxTransactionValueCents: Long,
val minInstallments: Int, val maxInstallments: Int,
val minInstallmentValueCents: Long, val maxInstallmentValueCents: Long
)

HealthCheckResult

data class HealthCheckResult(
val isConnected: Boolean,
val hasNetworkConnection: Boolean,
val isApiReachable: Boolean,
val latencyMs: Long?,
val errorMessage: String?
)

PixQrCodeData

data class PixQrCodeData(
val qrCode: String,
val transactionId: String,
val expiresInSeconds: Int? = null
)

Consulta de Transações

QueryFilterBuilder

Builder para os filtros de getTransactionSummaries(). Padrão da API: <campo>_<operador>=<valor> (para EQ, apenas <campo>=<valor>).

val filters = QueryFilterBuilder()
.pagination(offset = 0, limit = 20, preloads = true)
.add(FilterField.STATUS, FilterOperator.EQ, "approved")
.add(FilterField.CREATED_AT, FilterOperator.GE, "2025-01-01")
.addIn(FilterField.CARD_BRAND, listOf("visa", "mastercard"))

Operadores (FilterOperator): EQ, NE, GT, LT, GE, LE, LK, IN.

Campos (FilterField): STATUS, PAYMENT_METHOD, ACQUIRER, CREATED_AT, UPDATED_AT, CARD_BRAND, CARD_FIRST_DIGITS, CARD_LAST_DIGITS, TYPE, SYSTEM_TRACE_AUDIT_NUMBER, AUTHORIZATION_CODE, GATEWAY_TRANSACTION_ID.

TransactionSummaryResponse / TransactionSummary

data class TransactionSummaryResponse(
val metadata: Metadata, // offset, limit
val links: Links?, // first
val data: List<TransactionSummary>
)

data class TransactionSummary(
val id: String,
val acquirerId: String?,
val createdAt: String, val updatedAt: String?,
val gatewayTransactionId: String?,
val acquirer: String?, val currency: String?,
val paymentMethod: PaymentMethod,
val status: String, // "approved", "pre_approved", "refunded", "voided", "pending", ...
val amount: Amount, // Amount(amount, scale)
val installments: Int? = null,
val installmentsInterest: Boolean? = null,
val card: TransactionCard?,
val payer: Payer? = null, // PIX
val endToEndId: String? = null,
val cycles: List<TransactionCycle>? = null, // com preloads=true
val transactionType: TransactionType? = null
)

TransactionSummary expõe helpers úteis: cardBrand, cardLastDigits, amountInCents, amountAsDouble, isApproved, isPreApproved, isRefunded, nsu, authorizationCode, etc.

data class Amount(val amount: Long, val scale: Int) {
fun toDouble(): Double // Amount(15000, 2).toDouble() == 150.0
fun toCents(): Long
}

data class TransactionCard(
val brand: String?, val firstDigits: String?, val lastDigits: String?,
val holderName: String?, val expirationMonth: Int?, val expirationYear: Int?
)

data class TransactionCycle(
val type: String?, val authorizationCode: String?,
val systemTraceAuditNumber: String?, val retrievalReferenceNumber: String?,
val processedAt: String?
)

data class Payer(val name: String?, val taxId: String?, val bankName: String?)

SdkErrorCode

com.tupifintech.apossdk.sdk.model.SdkErrorCode — catálogo de erros recebido em onAppError(error, message) e PaymentResult.errorCode. Cada valor tem um code: Int.

Erros do SDK (customizados)

CódigoValorDescrição
UNKNOWN_ERROR-1Erro desconhecido
NO_CONTEXT1001Contexto de transação ausente
TERMINAL_NOT_INITIALIZED1002Terminal não inicializado
TERMINAL_INITIALIZATION_FAILED1003Falha na inicialização
INVALID_CARD_ENTRYMODE1004Modo de entrada de cartão inválido
MAGNETIC_STRIPE_WITH_CHIP1005Tarja usada em cartão com chip
PRODUCT_NOT_FOUND1006Produto/operação não encontrado
INVALID_SELECTION1007Seleção inválida
INVALID_LAST_DIGITS1008Últimos 4 dígitos inválidos
INVALID_CVV1009CVV inválido
ENCRYPTION_ERROR1010Erro de criptografia
PIN_ERROR1011Erro de PIN
GO_ON_CHIP_DENIED1012EMV (go on chip) negado
FINISH_CHIP_DENIED1013EMV (finish chip) negado
CACHE_INVALID1014Cache inválido
GATEWAY_UNAUTHORIZED1015Gateway: não autorizado
GATEWAY_INVALID_REQUEST1016Gateway: requisição inválida
GATEWAY_NETWORK_ERROR1017Gateway: erro de rede
NO_PRE_AUTHORIZATIONS1018Nenhuma pré-autorização
CONNECTION_FAILED1019Falha ao conectar ao pinpad
DISCONNECTION_FAILED1020Falha ao desconectar
NO_TRANSACTIONS_FOUND1021Nenhuma transação encontrada
PRE_AUTH_NOT_FOUND_FOR_CARD1022Pré-autorização não encontrada para o cartão
GATEWAY_TIMEOUT1023Gateway: timeout
TRANSACTION_UNDONE1024Transação desfeita
PIN_BLOCKED1025PIN offline bloqueado
AMOUNT_BELOW_MINIMUM1026Valor abaixo do mínimo
AMOUNT_ABOVE_MAXIMUM1027Valor acima do máximo
INSTALLMENTS_EXCEEDED1028Parcelas acima do permitido
INSTALLMENT_VALUE_BELOW_MINIMUM1029Valor da parcela abaixo do mínimo
CONTACTLESS_LIMIT_EXCEEDED1030Limite contactless excedido
MAGNETIC_FALLBACK_NOT_ALLOWED1031Fallback para tarja não permitido
INVALID_PAN_LENGTH1032Tamanho de PAN inválido
INVALID_TRACK_DATA1033Track2 vazia/inválida

Há também os códigos da lib SmartPOS da Positivo (prefixo PP_*, ex.: PP_TIMEOUT(12), PP_CANCEL(13), PP_CARDBLOCKED(63), PP_ERRPIN(42)), úteis para diagnóstico de hardware/EMV.

Próximos Passos