A integração com app-to-app, ou integração entre aplicativos, refere-se ao processo de conectar e permitir a comunicação entre diferentes aplicativos de software, geralmente em dispositivos móveis ou em um ambiente de computação distribuída, ou seja, você pode integrar o app-to-app tanto no POS Android (smartPOS) quanto em um PDV Android (mobile).
No ecossistema Android, os aplicativos podem se comunicar entre si por meio de Intents. Um Intent é uma mensagem que pode ser usada para solicitar uma ação de outro componente do aplicativo. Por exemplo, um aplicativo pode lançar um Intent para solicitar que outro aplicativo abra uma determinada página da web.
Baixe aqui o exemplo da aplicação Android junto ao APK de pagamento Justa e a interface de comunicação entre aplicativos:
Baixe aqui: https://artifactory.aditum.com.br/ui/native/packages/dev/app-to-app/
Exemplo de implementação com Kotlin
dependencies {
... //Suas outras dependencias
implementation(files("libs/AditumSdkService-2.0.0-release.aar"))
... //Suas outras dependencias
}
Nosso primeiro passo é criar uma interface do nosso código...
class IAditumSdkService
Importações
import android.content.ServiceConnection
import android.os.Binder
import android.os.IBinder
import br.com.aditum.IAditumSdkService
ServiceConnection:
Feito as importações necessárias, precisamos declarar uma variável privada responsável pela conexão entre um componente do aplicativo (como uma atividade ou um serviço) e um serviço em execução em segundo plano. Quando um serviço é vinculado, o aplicativo pode interagir com o serviço, enviar e receber dados, ou solicitar execução de determinadas operações.
private val mServiceConnection = object : ServiceConnection {
override fun onServiceConnected(componentName: ComponentName, service: IBinder) {
Log.d(TAG, "onServiceConnected")
mAditumSdkService = IAditumSdkService.Stub.asInterface(service)
}
override fun onServiceDisconnected(componentName: ComponentName) {
Log.d(TAG, "onServiceDisconnected")
mAditumSdkService = null
}
}
StartAditumSdkServeice:
Após implementado a service connection, declare uma função pública que ficará responsável por iniciar o serviço AditumSdkIntegration, esta função deve instanciar uma Intent que permitirá iniciar uma atividade em outro app.
public fun startAditumSdkService() {
val intent: Intent = Intent("br.com.aditum.smartpostef.AditumSdkService")
intent.setPackage("br.com.aditum.smartpostef.AditumSdkService")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Log.d(TAG, "Android Oreo or higher: " + Build.VERSION.SDK_INT);
startForegroundService(intent);
} else {
Log.d(TAG, "Android Nougat or lower: " + Build.VERSION.SDK_INT);
startService(intent);
}
bindService(intent, mServiceConnection, (Context.BIND_AUTO_CREATE or Context.CONTEXT_IGNORE_SECURITY))
}
Funções
AbortOperation
Envia o comando para abortar a operação para o dispositivo.
fun AbortOperation ( )
Exemplo de Uso:
import br.com.aditum.IAditumSdkService
mAditumSdkService?.let { mAditumSdkService: IAditumSdkService ->
thread { mAditumSdkService.abortOperation() }
}
Cancel
Inicia uma operação de cancelamento.
fun cancel (request: CancelationRequest, callback: CancelationResponseCallback)
Paramêtros
Nome | Tipo | Descrição |
---|---|---|
request | CancelationRequest | Requisição de cancelamento |
callback | CancelationResponseCallback | Retorno com a resposta do cancelamento |
Exemplo de Uso:
import br.com.aditum.data.v2.model.cancelation.CancelationRequest
import br.com.aditum.data.v2.model.cancelation.CancelationResponse
import br.com.aditum.data.v2.model.cancelation.CancelationResponseCallback
import br.com.aditum.IAditumSdkService
private val mCancelationResponseCallback = object : CancelationResponseCallback.Stub() {
override fun onResponse(cancelationResponse: CancelationResponse?) {
Log.d(TAG, "onResponse - cancelationResponse: $cancelationResponse")
}
}
mAditumSdkService?.let { mAditumSdkService: IAditumSdkService ->
val mCancelationRequest = CancelationRequest()
mCancelationRequest.nsu = "000000001"
thread { mAditumSdkService.cancel(mCancelationRequest, mCancelationResponseCallback) }
} ?: run {
Log.e(TAG, "Communication service not available.")
}
CancelationRequest:
Classe que representa dados para uma requisição de cancelamento.
data class CancelationRequest (val nsu: String) : Parcelable
CancelationResponse:
Classe que representa os dados de resposta de um cancelamento.
data class CancelationResponse (
var canceled: Boolean = false,
var charge: Charge? = null,
var errors: List? = null
) : Parcelable
getMerchantData
Obtém os dados do estabelecimento e retorna um objeto MerchantData.
fun getMerchantData ( ) : MerchantData
Exemplo de Uso:
import br.com.aditum.IAditumSdkService
import br.com.aditum.data.v2.model.MerchantData
mAditumSdkService?.let { mAditumSdkService: IAditumSdkService ->
val merchantData: MerchantData? = mAditumSdkService.getMerchantData()
Log.d(TAG, "MerchantData: $merchantData")
} ?: run {
Log.e(TAG, "Communication service not available.")
}
registerNotificationCallback:
Registre um retorno de chamada para receber notificações do dispositivo.
fun registerNotificationCallback (callback: INotificationCallback)
Paramêtros
Nome | Tipo | Descrição |
---|---|---|
callback | INotificationCallback | Retorno de chamada a ser registrado |
Exemplo de Uso:
import br.com.aditum.data.v2.INotificationCallback
import br.com.aditum.IAditumSdkService
private val mNotificationCallback = object : INotificationCallback.Stub() {
override fun onNotification(message: String?, command: AbecsCommands?) {
Log.d(TAG, "message: $message, command: $command")
}
}
mAditumSdkService?.registerNotificationCallback(mNotificationCallback);
kService.init(initRequest, mInitResponseCallback)
Pay
Iniciar uma operação de pagamento.
fun pay (request: PaymentRequest, callback: PaymentResponseCallback)
Paramêtros
Nome | Tipo | Descrição |
---|---|---|
request | PaymentRequest | Requisição de pagamento |
callback | PaymentResponseCallback | Retorno com a resposta do pagamento |
Exemplo de Uso:
import br.com.aditum.data.v2.INotificationCallback
import br.com.aditum.data.v2.model.payment.PaymentResponse
import br.com.aditum.data.v2.model.payment.PaymentResponseCallback
import br.com.aditum.IAditumSdkService
private val mPayResponseCallback = object : PaymentResponseCallback.Stub() {
override fun onResponse(paymentResponse: PaymentResponse?) {
Log.d(TAG, "onResponse - paymentResponse: $paymentResponse")
}
}
mAditumSdkService?.let { mAditumSdkService: IAditumSdkService ->
val mPaymentRequest = PaymentRequest()
mPaymentRequest.amount = 1000
mPaymentRequest.paymentType = PaymentType.Debit
mPaymentRequest.operationType = PayOperationType.Authorization
thread { mAditumSdkService.pay(mPaymentRequest, mPayResponseCallback) }
} ?: run {
Log.e(TAG, "Communication service not available.")
}
PaymentRequest:
Classe que representa dados para a solicitação de um pagamento.
data class PaymentRequest (
var amount: Long = 0,
var isQrCode: Boolean = false,
var operationType: PayOperationType = PayOperationType.Authorization,
var paymentType: PaymentType = PaymentType.Undefined,
var installmentType: InstallmentType = InstallmentType.Undefined,
var installmentNumber: Int = 0,
var merchantChargeId: String = "",
var origin: String = "",
var originalNsu: String = "",
var currency: Int = 986,
var acquirer: Acquirer = Acquirer.Undefined,
var scheme: String = "",
var manualEntry: Boolean = false,
var allowContactless: Boolean = true
) : Parcelable
paymentResponse:
Classe que representa os dados de resposta de um pagamento.
data class PaymentResponse (
var isApproved: Boolean = false,
var charge: Charge? = null,
var errors: List? = null
) : Parcelable
paymentTypeRestriction:
Representa as restrições do tipo de pagamento.
data class PaymentTypeRestriction (
var paymentType: PaymentType? = null,
var installmentType: InstallmentType? = null,
var label: String? = null,
var minInstallmentAmount: Int? = null,
var minInstallmentNumber: Int? = null,
var minTransactionAmount: Int? = null,
var maxInstallmentAmount: Long? = null,
var maxInstallmentNumber: Int? = null,
var maxTransactionAmount: Long? = null
) : Parcelable
PaymentScheme:
Representa o esquema de um tipo de pagamento.
data class PaymentScheme (
var acquirer: Acquirer? = null,
var name: String? = null,
var paymentType: PaymentType? = null,
var scheme: String? = null,
var paymentTypeRestriction: List? = null
) : Parcelable
Init
Inicia a operação de inicialização do terminal, verifica o status de ativação e realiza a carga de tabelas. Este método deve ser chamado na inicialização do aplicativo.
fun init (request: InitRequest, callback: InitResponseCallback)
Paramêtros
Nome | Tipo | Descrição |
---|---|---|
request | InitRequest | Requisição de inicialização |
callback | InitResponseCallback | Retorno com a resposta da incialização |
Exemplo de Uso:
import br.com.aditum.data.v2.model.init.InitRequest
import br.com.aditum.data.v2.model.init.InitResponse
import br.com.aditum.data.v2.model.init.InitResponseCallback
import br.com.aditum.IAditumSdkService
val mInitResponseCallback = object : InitResponseCallback.Stub() {
override fun onResponse(initResponse: InitResponse?) {
initResponse?.let {
Log.d(TAG, "onResponse - initResponse: $initResponse")
} ?: run {
Log.e(TAG, "onResponse - initResponse is null")
}
}
}
val pinpadMessages = PinpadMessages()
pinpadMessages.mainMessage = "Payment Example"
val initRequest = InitRequest()
initRequest.pinpadMessages = pinpadMessages
initRequest.activationCode = activationCode
initRequest.applicationName = "PaymentExample"
initRequest.applicationVersion = "1.0.0"
initRequest.applicationToken = "mk_Lfq9yMzRoYaHjowfxLvoyi"
mAditumSdkService.init(initRequest, mInitResponseCallback)
InitRequest:
Classe que representa os dados da solicitação de inicialização.
data class InitRequest (
var applicationToken : String ? = null,
var applicationName: String? = null,
var applicationVersion: String? = null,
var activationCode: String? = null,
var pinpadMessages: PinpadMessages? = null
) : Parcelable
InitResponse:
Classe que representa os dados para inicialização do terminal.
data class InitResponse (
var terminalInfo: TerminalInfo? = null,
var availableBrands: List\< CardBrand >? = null,
var success: Boolean = false,
var httpStatusResponse: Int? = null,
var errors: List\< ResponseError >? = null
) : BaseResponse
Classes Auxiliares
BaseResponse:
Classe de resposta base do SDK. Contém propriedades comuns a todas as respostas.
open class BaseResponse (
var success: Boolean = false,
var httpStatusResponse: Int? = null,
var errors: List\< ResponseError >? = null
) : BaseResponse
Charge:
Informações retornadas após o processamento de uma transação.
Charge(
var isApproved: Boolean = false,
var isCanceled: Boolean = false,
var amount: Long = 0,
var currency: Int = 986,
var aid: String = "",
var brand: CardBrand = CardBrand.Undefined,
var chargeStatus: ChargeStatus? = null,
var acquirer: Acquirer = Acquirer.Undefined,
var paymentType: PaymentType = PaymentType.Undefined,
var installmentType: InstallmentType = InstallmentType.Undefined,
var installmentNumber: Int = 0,
var transactionId: String? = null,
var nsu: String? = null,
var creationDateTime: String? = null,
var captureDateTime: String? = null,
var cancelationDateTime: String? = null,
var cardholderName: String? = null,
var cardNumber: String? = null,
var authorizationCode: String? = null,
var authorizationResponseCode: String? = null,
var merchantChargeId: String? = null,
var origin: String? = null,
var merchantReceipt: List? = null,
var cardholderReceipt: List? = null
) : Parcelable
Customization:
Classe para customização de estabelecimento.
data class Customization (
var primaryColor: String = "",
var secondaryColor: String = "",
var hostName: String = ""
) : Parcelable
ErrorMessage:
Classe para mensagens de erro.
data class ErrorMessage (
var code: Int? = null,
var message: String? = null,
var description: String? = null
) : Parcelable
MerchantData:
Esta classe representa os dados de estabelecimento e o esquema de pagamentos suportados.
data class MerchantData (
var id: String = "",
var fantasyName: String? = null,
var incrementalPreAuthorizationEnabled: Boolean = false,
var preAuthorizationEnabled: Boolean = false,
var preAuthorizationInstallmentEnabled: Boolean = false,
var contaclessEnabled: Boolean = false,
var typedPanEnabled: Boolean = false,
var paymentScheme: List? = null
) : Parcelable
Profile:
Classe que representa o perfil do estabelecimento.
data class Profile (var customization: Customization) : Parcelable
PinpadMessages:
Classe que representa as mensagens e notificações exibidas no Pinpad.
data class PinpadMessages ( var approvedMessage: String? = null,
var declinedMessage: String? = null,
var initializationMessage: String? = null,
var mainMessage: String? = null,
var processingMessage: String? = null
) : Parcelable
ResponseError:
Classe que representa respostas de erro.
data class ResponseError (
var code: Int? = null,
var message: String? = null,
var description: String? = null
) : Parcelable
TerminalInfo:
Classe que contém informações sobre o terminal.
data class TerminalInfo (
var model: String? = null,
var osVersion: String? = null,
var specVersion: String? = null,
var serialNumber: String? = null,
var manufacturerName: String? = null,
var manufacturerVersion: String? = null,
var contactlessSupported: Boolean = false
) : Parcelable
Interfaces
INotificationCallback
Interface para recebimento de notificações do dispositivo.
Interface INotificationCallback
Funções:
Chamado quando uma notificação é recebida do dispositivo.
abstract fun onNotification (message: String, command: AbecsCommands)
Paramêtros
Nome | Tipo | Descrição |
---|---|---|
message | String | A mensagem de notificação |
command | AbecsCommands | O comando que acionou a notificação |
PaymentResponseCallback
Retorno de chamada quando o processo de pagamento é concluído.
Interface PaymentResponseCallback
Paramêtros
Nome | Tipo | Descrição |
---|---|---|
response | InitResponse | Objeto InitResponse |
Funções:
onResponse é chamado quando o processo de pagamento é concluído com PaymentResponse.
abstract fun onResponse (response: PaymentResponse)
Paramêtros
Nome | Tipo | Descrição |
---|---|---|
response | PaymentResponse | Objeto PaymentResponse |
CancelationResponseCallback
Retorno de chamada quando o processo de cancelamento é concluído.
Interface CancelationResponseCallback
Paramêtros
Nome | Tipo | Descrição |
---|---|---|
response | CancelationResponse | Objeto CancelationResponse |
InitResponseCallback
Retorno de chamada para resposta de inicialização do terminal.
Interface InitResponseCallback
Paramêtros
Nome | Tipo | Descrição |
---|---|---|
response | InitResponse | Objeto InitResponse |
Funções:
onResponse é chamado quando o terminal foi inicializado com InitResponse.
abstract fun onResponse (response: InitResponse)
Paramêtros
Nome | Tipo | Descrição |
---|---|---|
response | InitResponse | Objeto InitResponse |
UpdateEmvTablesCallback
Retorno de chamada para resposta de atualização de uma carga de tabelas.
Interface UpdateEmvTablesCallback
Funções:
onResponse é chamado quando a carga de tabelas é atualizado.
abstract fun onResponse (success: Boolean)
Paramêtros
Nome | Tipo | Descrição |
---|---|---|
success | Boolean | true caso a carga de tabelas tenha ocorrido com sucesso; caso contrário, false. |
SPLIT
Como Funciona?
O split de pagamentos é uma solução adotada para distribuir o valor de uma transação entre múltiplos destinatários, onde cada recebedor, seja Pessoa Física ou Jurídica, recebe uma parte específica do montante total. Em suma, o recebedor representa um participante identificado na operação financeira.
No contexto prático, essa ferramenta é frequentemente empregada para estruturar comissões ou compartilhar custos na prestação de serviços, ou comercialização de produtos.
No POS, o split funciona como um fluxo paralelo e subsequente à captura da transação. Após a conclusão bem-sucedida da transação, inicia-se o processo de split, modificando a transação e adicionando os recebedores (participantes) a ela.
O ideal da integração app-to-app é, ao receber o callback da cobrança autorizada deve-se chamar o endpoint de split, passando no cabeçalho (header) o merchantID do estabelecimento ativo no POS e como parâmetro a chargeID da cobrança que foi autorizada e retornada no callback.
PUT/charge/split/{{chargeId}}
Versão v2.0
Requisição HTTP
PUT {{ENDPOINT_GATEWAY}}/v2/charge/split/{{chargeId}}
Exemplo de requisição
var myHeaders = new Headers();
myHeaders.append("Authorization", "Bearer {{accessToken}}");
myHeaders.append("Content-Type", "application/json");
var raw = JSON.stringify({"receivers":["e66d8ebb-41f5-43b9-b0f3-bde8fb59b261"]});
var requestOptions = {
method: 'PUT',
headers: myHeaders,
body: raw,
redirect: 'follow'
};
fetch("{{ENDPOINT_GATEWAY}}/v2/charge/split/{{chargeId}}", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
O comando acima retorna um JSON estruturado assim:
{
"success": true,
"errors": \[],
"traceKey": "4c2f6bf8-912b-4895-92b7-e6c0a4e0c765"
}
O endpoint utilizado para criar uma regra de divisão adicionando uma lista de receptores a uma determinada cobrança. A cobrança deve ser aprovada e os destinatários devem ser relacionados ao comerciante solicitante. Se a cobrança já contém o receptor, este ponto final irá substituí-los.
Requisição
Propriedade | Tipo | Obrigatório | Descrição |
---|---|---|---|
receivers | string[] | Sim | O ID da cobrança. |
Resposta
Propriedade | Tipo | Descrição |
---|---|---|
success | string | Se o endpoint processou a requisição com sucesso. |
errors | Error[] | Se success: false, esse array contem a descrição dos erros retornados. |
errors.errorCode | int | Código do erro. |
errors.message | string | Mensagem para identificar qual foi o erro retornado. |
traceKey | string | Identificador da operação. |
HEADERS
Propriedade | Descrição |
---|---|
Bearer Token | BCrypt gerado a partir da concatenação do CNPJ da loja e o Merchant Token. |