adicionando enum de erros

This commit is contained in:
Ighor Moura 2025-07-18 17:16:48 -04:00
parent f53369428d
commit 06c9c4abea
6 changed files with 381 additions and 24 deletions

View File

@ -1,5 +1,40 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<JavaCodeStyleSettings>
<option name="IMPORT_LAYOUT_TABLE">
<value>
<package name="" withSubpackages="true" static="false" module="true" />
<package name="android" withSubpackages="true" static="true" />
<package name="androidx" withSubpackages="true" static="true" />
<package name="com" withSubpackages="true" static="true" />
<package name="junit" withSubpackages="true" static="true" />
<package name="net" withSubpackages="true" static="true" />
<package name="org" withSubpackages="true" static="true" />
<package name="java" withSubpackages="true" static="true" />
<package name="javax" withSubpackages="true" static="true" />
<package name="" withSubpackages="true" static="true" />
<emptyLine />
<package name="android" withSubpackages="true" static="false" />
<emptyLine />
<package name="androidx" withSubpackages="true" static="false" />
<emptyLine />
<package name="com" withSubpackages="true" static="false" />
<emptyLine />
<package name="junit" withSubpackages="true" static="false" />
<emptyLine />
<package name="net" withSubpackages="true" static="false" />
<emptyLine />
<package name="org" withSubpackages="true" static="false" />
<emptyLine />
<package name="java" withSubpackages="true" static="false" />
<emptyLine />
<package name="javax" withSubpackages="true" static="false" />
<emptyLine />
<package name="" withSubpackages="true" static="false" />
<emptyLine />
</value>
</option>
</JavaCodeStyleSettings>
<JetCodeStyleSettings>
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@ -14,11 +14,15 @@ android {
targetSdk = 36
versionCode = 1
versionName = "1.0"
buildConfigField ("String", "ACTIVATION_CODE", "\"\"")
buildConfigField ("String", "APPLICATION_TOKEN", "\"\"")
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
debug {
buildConfigField ("String", "APPLICATION_TOKEN", "\"mk_MbQ92RRHEOcGFRIf9/R1A\"")
}
release {
isMinifyEnabled = false
proguardFiles(
@ -43,6 +47,7 @@ android {
dependencies {
implementation(files("libs/AditumSdkIntegration-2.3.6.67824-release.aar"))
implementation("com.google.code.gson:gson:2.13.1")
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.activity.compose)

View File

@ -0,0 +1,42 @@
package com.example.mypos.data
object AditumError {
const val SERVICE_NOT_AVAILABLE = "SERVICE_NOT_AVAILABLE"
const val SERVICE_NOT_AVAILABLE_MESSAGE = "Failed to connect to Aditum SDK service"
const val SERVICE_NULL = "SERVICE_NULL"
const val SERVICE_NULL_MESSAGE = "Aditum SDK service is null"
const val INIT_RESPONSE_NULL = "INIT_RESPONSE_NULL"
const val INIT_RESPONSE_NULL_MESSAGE = "Init response is null"
const val INIT_ERROR = "INIT_ERROR"
const val INIT_ERROR_MESSAGE = "Initialization failed"
const val MERCHANT_DATA_NULL = "MERCHANT_DATA_NULL"
const val MERCHANT_DATA_NULL_MESSAGE = "Merchant data is null"
const val MERCHANT_DATA_ERROR = "MERCHANT_DATA_ERROR"
const val MERCHANT_DATA_ERROR_MESSAGE = "Failed to retrieve merchant data"
const val PAYMENT_RESPONSE_NULL = "PAYMENT_RESPONSE_NULL"
const val PAYMENT_RESPONSE_NULL_MESSAGE = "Payment response is null"
const val PAYMENT_ERROR = "PAYMENT_ERROR"
const val PAYMENT_ERROR_MESSAGE = "Payment processing failed"
const val INVALID_NSU = "INVALID_NSU"
const val INVALID_NSU_MESSAGE = "NSU cannot be null"
const val CONFIRM_ERROR = "CONFIRM_ERROR"
const val CONFIRM_ERROR_MESSAGE = "Transaction confirmation failed"
const val CANCEL_RESPONSE_NULL = "CANCEL_RESPONSE_NULL"
const val CANCEL_RESPONSE_NULL_MESSAGE = "Cancelation response is null"
const val CANCEL_ERROR = "CANCEL_ERROR"
const val CANCEL_ERROR_MESSAGE = "Cancelation processing failed"
const val DEACTIVATE_ERROR = "DEACTIVATE_ERROR"
const val DEACTIVATE_ERROR_MESSAGE = "Deactivation failed"
}

View File

@ -0,0 +1,231 @@
package com.example.mypos.services
import android.util.Log
import br.com.aditum.data.v2.enums.InstallmentType
import br.com.aditum.data.v2.enums.PayOperationType
import br.com.aditum.data.v2.enums.PaymentType
import br.com.aditum.data.v2.model.MerchantData
import br.com.aditum.data.v2.model.PinpadMessages
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.data.v2.model.deactivation.DeactivationResponseCallback
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.data.v2.model.payment.PaymentRequest
import br.com.aditum.data.v2.model.payment.PaymentResponse
import br.com.aditum.data.v2.model.payment.PaymentResponseCallback
import br.com.aditum.data.v2.model.transactions.ConfirmTransactionCallback
import com.example.mypos.BuildConfig
import com.example.mypos.data.AditumError
import com.google.gson.Gson
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.util.UUID
class AditumSdkService(private val paymentApplication: PaymentApplication) {
companion object {
private const val TAG = "AditumSdkModule"
}
private val gson = Gson()
private val coroutineScope = CoroutineScope(Dispatchers.IO)
fun getName(): String = "AditumSdkModule"
fun initAditumSdk(
applicationName: String,
applicationVersion: String,
activationCode: String?,
resolve: (Boolean) -> Unit = {},
reject: (String, String?) -> Unit = { _, _ -> }
) {
coroutineScope.launch {
try {
if (!paymentApplication.ensureServiceConnected()) {
reject(AditumError.SERVICE_NOT_AVAILABLE, AditumError.SERVICE_NOT_AVAILABLE_MESSAGE)
return@launch
}
val pinpadMessages = PinpadMessages().apply {
mainMessage = applicationName
}
val initRequest = InitRequest().apply {
this.pinpadMessages = pinpadMessages
this.activationCode = if (BuildConfig.DEBUG) BuildConfig.ACTIVATION_CODE else activationCode
this.applicationName = applicationName
this.applicationVersion = applicationVersion
this.applicationToken = BuildConfig.APPLICATION_TOKEN
}
val callback = object : InitResponseCallback.Stub() {
override fun onResponse(initResponse: InitResponse?) {
if (initResponse != null) {
resolve(initResponse.initialized)
} else {
Log.e(TAG, "onResponse - initResponse is null")
reject(AditumError.INIT_RESPONSE_NULL, AditumError.INIT_RESPONSE_NULL_MESSAGE)
}
}
}
paymentApplication.communicationService?.init(initRequest, callback)
?: reject(AditumError.SERVICE_NULL, AditumError.SERVICE_NULL_MESSAGE)
} catch (e: Exception) {
reject(AditumError.INIT_ERROR, "${AditumError.INIT_ERROR_MESSAGE}: ${e.message}")
}
}
}
fun getMerchantData(resolve: (MerchantData) -> Unit = {}, reject: (String, String?) -> Unit = { _, _ -> }) {
coroutineScope.launch {
try {
if (!paymentApplication.ensureServiceConnected()) {
reject(AditumError.SERVICE_NOT_AVAILABLE, AditumError.SERVICE_NOT_AVAILABLE_MESSAGE)
return@launch
}
val merchantData: MerchantData? = paymentApplication.communicationService?.merchantData
if (merchantData != null) {
resolve(merchantData)
} else {
reject(AditumError.MERCHANT_DATA_NULL, AditumError.MERCHANT_DATA_NULL_MESSAGE)
}
} catch (e: Exception) {
reject(AditumError.MERCHANT_DATA_ERROR, "${AditumError.MERCHANT_DATA_ERROR_MESSAGE}: ${e.message}")
}
}
}
fun pay(
amount: Int,
installments: Int,
merchantChargeId: String?,
resolve: (Any) -> Unit = {},
reject: (String, String?) -> Unit = { _, _ -> }
) {
coroutineScope.launch {
try {
if (!paymentApplication.ensureServiceConnected()) {
reject(AditumError.SERVICE_NOT_AVAILABLE, AditumError.SERVICE_NOT_AVAILABLE_MESSAGE)
return@launch
}
val paymentRequest = PaymentRequest().apply {
operationType = PayOperationType.Authorization
paymentType = PaymentType.Credit
this.amount = amount.toLong()
this.merchantChargeId = merchantChargeId ?: UUID.randomUUID().toString()
currency = 986
allowContactless = true
manualEntry = false
installmentType = InstallmentType.Merchant
installmentNumber = installments
}
val callback = object : PaymentResponseCallback.Stub() {
override fun onResponse(paymentResponse: PaymentResponse?) {
if (paymentResponse != null) {
val json = gson.toJson(paymentResponse)
resolve(json)
} else {
Log.e(TAG, "onResponse - paymentResponse is null")
reject(AditumError.PAYMENT_RESPONSE_NULL, AditumError.PAYMENT_RESPONSE_NULL_MESSAGE)
}
}
}
paymentApplication.communicationService?.pay(paymentRequest, callback)
?: reject(AditumError.SERVICE_NULL, AditumError.SERVICE_NULL_MESSAGE)
} catch (e: Exception) {
reject(AditumError.PAYMENT_ERROR, "${AditumError.PAYMENT_ERROR_MESSAGE}: ${e.message}")
}
}
}
fun confirm(nsu: String?, resolve: (Boolean) -> Unit = {}, reject: (String, String?) -> Unit = { _, _ -> }) {
coroutineScope.launch {
try {
if (!paymentApplication.ensureServiceConnected()) {
reject(AditumError.SERVICE_NOT_AVAILABLE, AditumError.SERVICE_NOT_AVAILABLE_MESSAGE)
return@launch
}
if (nsu == null) {
reject(AditumError.INVALID_NSU, AditumError.INVALID_NSU_MESSAGE)
return@launch
}
val callback = object : ConfirmTransactionCallback.Stub() {
override fun onResponse(confirmed: Boolean) {
resolve(confirmed)
}
}
paymentApplication.communicationService?.confirmTransaction(nsu, callback)
?: reject(AditumError.SERVICE_NULL, AditumError.SERVICE_NULL_MESSAGE)
} catch (e: Exception) {
reject(AditumError.CONFIRM_ERROR, "${AditumError.CONFIRM_ERROR_MESSAGE}: ${e.message}")
}
}
}
fun cancel(nsu: String?, isReversal: Boolean, resolve: (Boolean) -> Unit = {}, reject: (String, String?) -> Unit = { _, _ -> }) {
coroutineScope.launch {
try {
if (!paymentApplication.ensureServiceConnected()) {
reject(AditumError.SERVICE_NOT_AVAILABLE, AditumError.SERVICE_NOT_AVAILABLE_MESSAGE)
return@launch
}
if (nsu == null) {
reject(AditumError.INVALID_NSU, AditumError.INVALID_NSU_MESSAGE)
return@launch
}
val cancelationRequest = CancelationRequest(nsu, isReversal)
val callback = object : CancelationResponseCallback.Stub() {
override fun onResponse(cancelationResponse: CancelationResponse?) {
if (cancelationResponse != null) {
resolve(cancelationResponse.canceled)
} else {
Log.e(TAG, "onResponse - cancelationResponse is null")
reject(AditumError.CANCEL_RESPONSE_NULL, AditumError.CANCEL_RESPONSE_NULL_MESSAGE)
}
}
}
paymentApplication.communicationService?.cancel(cancelationRequest, callback)
?: reject(AditumError.SERVICE_NULL, AditumError.SERVICE_NULL_MESSAGE)
} catch (e: Exception) {
reject(AditumError.CANCEL_ERROR, "${AditumError.CANCEL_ERROR_MESSAGE}: ${e.message}")
}
}
}
fun deactivate(resolve: (Boolean) -> Unit = {}, reject: (String, String?) -> Unit = { _, _ -> }) {
coroutineScope.launch {
try {
if (!paymentApplication.ensureServiceConnected()) {
reject(AditumError.SERVICE_NOT_AVAILABLE, AditumError.SERVICE_NOT_AVAILABLE_MESSAGE)
return@launch
}
val callback = object : DeactivationResponseCallback.Stub() {
override fun onResponse(status: Boolean) {
Log.d(TAG, "onDeactivationResponse - deactivationResponse: $status")
resolve(status)
}
}
paymentApplication.communicationService?.deactivate(callback)
?: reject(AditumError.SERVICE_NULL, AditumError.SERVICE_NULL_MESSAGE)
} catch (e: Exception) {
reject(AditumError.DEACTIVATE_ERROR, "${AditumError.DEACTIVATE_ERROR_MESSAGE}: ${e.message}")
}
}
}
}

View File

@ -8,19 +8,22 @@ import android.content.ServiceConnection
import android.os.Build
import android.os.IBinder
import android.util.Log
import br.com.aditum.IAditumSdkService
import br.com.aditum.data.v2.model.MerchantData
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.withContext
class PaymentApplication : Application() {
public val TAG = PaymentApplication::class.simpleName
public val PACKAGE_BASE_NAME: String = "br.com.aditum"
public val PACKAGE_NAME: String = PACKAGE_BASE_NAME + ".smartpostef"
public val ACTION_COMMUNICATION_SERVICE: String = PACKAGE_BASE_NAME + ".AditumSdkService"
companion object {
private const val TAG = "PaymentApplication"
private const val PACKAGE_BASE_NAME = "br.com.aditum"
const val PACKAGE_NAME = "$PACKAGE_BASE_NAME.smartpostef"
const val ACTION_COMMUNICATION_SERVICE = "$PACKAGE_BASE_NAME.AditumSdkService"
}
private val _isServiceConnectedFlow = MutableStateFlow(false)
val isServiceConnectedFlow: StateFlow<Boolean> = _isServiceConnectedFlow.asStateFlow()
@ -36,7 +39,7 @@ class PaymentApplication : Application() {
get() = mAditumSdkService
@Volatile
public var merchantData: MerchantData? = null
var merchantData: MerchantData? = null
private val mServiceConnection = object : ServiceConnection {
override fun onServiceConnected(componentName: ComponentName, service: IBinder) {
@ -59,40 +62,75 @@ class PaymentApplication : Application() {
mServiceConnectionListener = listener
}
public interface OnServiceConnectionListener {
interface OnServiceConnectionListener {
fun onServiceConnection(serviceConnected: Boolean)
}
override fun onCreate() {
super.onCreate()
Log.d(TAG, "onCreate")
startAditumSdkService()
}
override fun onTerminate() {
super.onTerminate()
Log.d(TAG, "onTerminate")
}
public fun startAditumSdkService() {
fun startAditumSdkService() {
Log.d(TAG, "startAditumSdkService")
val intent: Intent = Intent(ACTION_COMMUNICATION_SERVICE)
intent.setPackage(PACKAGE_NAME)
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);
val intent = Intent(ACTION_COMMUNICATION_SERVICE).apply {
setPackage(PACKAGE_NAME)
}
bindService(intent, mServiceConnection, (BIND_AUTO_CREATE or CONTEXT_IGNORE_SECURITY))
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, BIND_AUTO_CREATE or CONTEXT_IGNORE_SECURITY)
Log.d(TAG, "startAditumSdkService - bindService")
}
suspend fun ensureServiceConnected(): Boolean = withContext(Dispatchers.IO) {
if (isServiceConnected && mAditumSdkService?.asBinder()?.isBinderAlive == true) {
Log.d(TAG, "Service already connected")
return@withContext true
}
Log.d(TAG, "Service not connected, attempting to reconnect...")
val intent = Intent(ACTION_COMMUNICATION_SERVICE).apply {
setPackage(PACKAGE_NAME)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(intent)
} else {
startService(intent)
}
val bound = bindService(
intent,
mServiceConnection,
BIND_AUTO_CREATE or CONTEXT_IGNORE_SECURITY
)
if (bound) {
repeat(30) {
delay(100)
if (isServiceConnected && mAditumSdkService?.asBinder()?.isBinderAlive == true) {
Log.d(TAG, "Service reconnected successfully")
return@withContext true
}
}
}
Log.e(TAG, "Failed to reconnect service")
return@withContext false
}
private fun setServiceConnected(isConnected: Boolean) {
Log.d(TAG, "setServiceConnected - isConnected: $isConnected")
@ -102,4 +140,4 @@ class PaymentApplication : Application() {
mServiceConnectionListener?.onServiceConnection(mIsServiceConnected)
}
}
}
}