diff --git a/app/build.gradle.kts b/app/build.gradle.kts index cdbb89a..c2a11b4 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -61,10 +61,12 @@ dependencies { androidTestImplementation(libs.androidx.junit) debugImplementation(libs.androidx.compose.ui.test.manifest) debugImplementation(libs.androidx.compose.ui.tooling) - implementation("com.google.dagger:hilt-android:2.59.2") + implementation(libs.hilt.android.v2592) ksp(libs.hilt.android.compiler) implementation(libs.rxjava) implementation(libs.rxandroid) + implementation(libs.retrofit) + implementation(libs.converter.gson) // local libs implementation(project(":baselib")) implementation(project(":mpulib")) diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/navigation/AppNavGraph.kt b/app/src/main/java/com/mob/utsmyanmar/ui/navigation/AppNavGraph.kt index 317e74b..230d317 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/navigation/AppNavGraph.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/navigation/AppNavGraph.kt @@ -18,6 +18,7 @@ import com.mob.utsmyanmar.ui.dashboard.DashboardScreen import com.mob.utsmyanmar.ui.pinpad.PinPadRoute import com.mob.utsmyanmar.ui.processing_card.ProcessingCardRoute import com.mob.utsmyanmar.ui.processing_card.ProcessingCardViewModel +import com.mob.utsmyanmar.ui.transaction_result.TransactionResultRoute import com.mob.utsmyanmar.viewmodel.CardReaderViewModel import com.mob.utsmyanmar.viewmodel.EmvTransactionProcessViewModel import com.mob.utsmyanmar.ui.pinpad.PinPadViewModel @@ -138,14 +139,43 @@ fun AppNavGraph( } composable(Routes.PinPad.route) { + val sharedViewModel: SharedViewModel = hiltViewModel(activity) val pinPadViewModel: PinPadViewModel = hiltViewModel(activity) val transProcessViewModel: TransProcessViewModel = hiltViewModel(activity) PinPadRoute( pinPadViewModel = pinPadViewModel, + sharedViewModel = sharedViewModel, transProcessViewModel = transProcessViewModel, + onNavigateTransactionResult = { + navController.navigate(Routes.TransactionResult.route) + }, onBack = { navController.popBackStack() } ) } + + composable(Routes.TransactionResult.route) { + TransactionResultRoute( + onNavigateMain = { + navController.navigate(Routes.Dashboard.route) { + popUpTo(Routes.Dashboard.route) { + inclusive = false + } + launchSingleTop = true + } + }, + onNavigatePrintReceipt = { + navController.navigate(Routes.Dashboard.route) { + popUpTo(Routes.Dashboard.route) { + inclusive = false + } + launchSingleTop = true + } + }, + onShowError = {}, + onShowSuccess = {}, + onShowPrinterDialog = {} + ) + } } } diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/navigation/Routes.kt b/app/src/main/java/com/mob/utsmyanmar/ui/navigation/Routes.kt index d459005..6f167f2 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/navigation/Routes.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/navigation/Routes.kt @@ -8,4 +8,5 @@ sealed class Routes(val route: String) { data object CardWaiting : Routes("card_waiting") data object ProcessingCard : Routes("processing_card") data object PinPad : Routes("pin_pad") + data object TransactionResult : Routes("transaction_result") } diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/pinpad/PinPadRoute.kt b/app/src/main/java/com/mob/utsmyanmar/ui/pinpad/PinPadRoute.kt index 13caf2d..6eaf835 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/pinpad/PinPadRoute.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/pinpad/PinPadRoute.kt @@ -7,13 +7,17 @@ import androidx.compose.runtime.getValue import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.mob.utsmyanmar.model.PinPadStatus import com.mob.utsmyanmar.model.TransResultStatus -import com.mob.utsmyanmar.ui.pinpad.PinPadViewModel +import com.mob.utsmyanmar.viewmodel.SharedViewModel import com.mob.utsmyanmar.viewmodel.TransProcessViewModel +import com.utsmyanmar.paylibs.Constant +import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation @Composable fun PinPadRoute( pinPadViewModel: PinPadViewModel, + sharedViewModel: SharedViewModel, transProcessViewModel: TransProcessViewModel, + onNavigateTransactionResult: () -> Unit, onBack: () -> Unit ) { val pinText by pinPadViewModel.pinText.collectAsStateWithLifecycle() @@ -26,7 +30,15 @@ fun PinPadRoute( PinPadStatus.ON_CONFIRM, PinPadStatus.ON_NEXT_SCREEN, PinPadStatus.ON_EMPTY -> { - transProcessViewModel.startOnlineProcess() + if (SystemParamsOperation.getInstance().demoStatus) { + val payDetail = pinPadViewModel.getPayDetail() + payDetail?.tradeAnswerCode = Constant.ANSWER_CODE_APPROVED + sharedViewModel.payDetail.value = payDetail + transProcessViewModel.resetTransactionStatus() + onNavigateTransactionResult() + } else { + transProcessViewModel.startOnlineProcess() + } } PinPadStatus.ON_CANCEL, @@ -47,7 +59,11 @@ fun PinPadRoute( TransResultStatus.ERROR, TransResultStatus.REVERSAL_FAIL, TransResultStatus.REVERSAL_SUCCESS -> { - onBack() + sharedViewModel.payDetail.value = + transProcessViewModel.payDetailResult.value + ?: transProcessViewModel.payDetail + transProcessViewModel.resetTransactionStatus() + onNavigateTransactionResult() } else -> {} diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/pinpad/PinPadViewModel.kt b/app/src/main/java/com/mob/utsmyanmar/ui/pinpad/PinPadViewModel.kt index 10be5cb..aade38e 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/pinpad/PinPadViewModel.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/pinpad/PinPadViewModel.kt @@ -57,6 +57,7 @@ class PinPadViewModel @Inject constructor( private var mCancelCoordinate = intArrayOf(0, 48) private var dukptIndex = 0 private var tmkIndex = 9 + private val PIK_INDEX = 1 private var tradeData: TradeData? = null private var payDetail: PayDetail? = null private var pan: String = "" @@ -133,6 +134,7 @@ class PinPadViewModel @Inject constructor( return } initData() + testInjectPIK() initPinPad(customPinPadKeyboard) } @@ -168,83 +170,12 @@ class PinPadViewModel @Inject constructor( fun cancelPinPad() { try { mPinPadOptV2?.cancelInputPin() + Log.d(TAG, "PinPad Canceled") } catch (e: RemoteException) { throw RuntimeException(e) } } - - /* - * KSN - */ - - private fun increasedKSN() { - - try { - - val securityOptV2 = sunmiPayManager.securityOptV2; - if (securityOptV2 == null) { - Log.d(TAG, "Security service is not ready!") - return; - } - val result = securityOptV2.dukptIncreaseKSN(dukptIndex); - - if (result == 0) { - LogUtil.d( - TAG, - "--------KSN increased Success-----" - ) - } else { - LogUtil.d( - TAG, - "--------KSN result:$result-----" - ) - } - - } catch (e: Exception) { - e.printStackTrace() - } - } - - private fun getKSN() { - - try { - val securityOptV2 = sunmiPayManager.securityOptV2; - if (securityOptV2 == null) { - Log.d(TAG, "Security service is not ready!") - return; - } - - val dataOut = ByteArray(10) - - val result = securityOptV2.dukptCurrentKSN(dukptIndex, dataOut) - - if (result == 0) { - - val ksnStr = - ByteUtil.bytes2HexStr(dataOut) - - LogUtil.d(TAG, "ksnStr: $ksnStr") - - payDetail?.reference = ksnStr - payDetail?.tempKSN = ksnStr - - LogUtil.d( - TAG, - "final ksnStr: $ksnStr" - ) - - } else { - - LogUtil.e( - TAG, - "Result code for current KSN:$result" - ) - } - - } catch (e: Exception) { - e.printStackTrace() - } - } + /* * Init Pin Pad */ @@ -270,10 +201,8 @@ class PinPadViewModel @Inject constructor( pinType = mPinType this.timeout = timeout * 1000 isOrderNumKey = pinPadOrder - keySystem = AidlConstants.Security.SEC_MKSK - pinKeyIndex = tmkIndex - + pinKeyIndex = 1 pinblockFormat = AidlConstants.PinBlockFormat.SEC_PIN_BLK_ISO_FMT0 this.pan = getPanBytes(this@PinPadViewModel.pan) } @@ -301,6 +230,33 @@ class PinPadViewModel @Inject constructor( _pinStatus.value = PinPadStatus.ON_ERROR } } + + private fun testInjectPIK() { + try { + val securityOptV2 = sunmiPayManager.securityOptV2 ?: return + + val pik = ByteUtil.hexStr2Bytes( + "33DD20C9A0B5B861F2914D44BC2AF055" + ) + + val kcv = ByteUtil.hexStr2Bytes( + "28DBDB489D28BC92" + ) + + val code = securityOptV2.savePlaintextKey( + AidlConstants.Security.KEY_TYPE_PIK, + pik, + kcv, + AidlConstants.Security.KEY_ALG_TYPE_3DES, + PIK_INDEX + ) + + LogUtil.e(TAG, "saveTestPIK result:$code") + + } catch (e: Exception) { + e.printStackTrace() + } + } /* @@ -459,7 +415,6 @@ class PinPadViewModel @Inject constructor( } ON_ERROR_DUKPT -> { - increasedKSN() _alertMsg.value = "Try Again!" _pinStatus.value = PinPadStatus.ON_ERROR_DUKPT } @@ -493,49 +448,47 @@ class PinPadViewModel @Inject constructor( "onConfirm status:$status" ) - if (pinBlock != null) { - - increasedKSN() - - val hexStr = - ByteUtil.bytes2HexStr(pinBlock) - - if ( - SunmiSDK.getInstance().checkCardExist() == 2 || - payDetail?.cardType == AidlConstants.CardType.MAGNETIC.getValue() || - payDetail?.cardType == -9 - ) { - - payDetail?.pinCipher = hexStr - - if ( - transType.value == TransactionsType.PRE_AUTH_COMPLETE || - transType.value == TransactionsType.PRE_AUTH_VOID || - transType.value == TransactionsType.REFUND - ) { - - _pinStatus.value = - PinPadStatus.ON_NEXT_SCREEN - - } else { - - handler.obtainMessage( - ON_CONFIRM_CLICK - ).sendToTarget() - } - - } else { - - _pinStatus.value = - PinPadStatus.ON_CARD_REMOVED - } - - } else { - - handler.obtainMessage( - ON_EMPTY_PIN_BLOCK - ).sendToTarget() - } +// if (pinBlock != null) { +// +// val hexStr = +// ByteUtil.bytes2HexStr(pinBlock) +// +// if ( +// SunmiSDK.getInstance().checkCardExist() == 2 || +// payDetail?.cardType == AidlConstants.CardType.MAGNETIC.getValue() || +// payDetail?.cardType == -9 +// ) { +// +// payDetail?.pinCipher = hexStr +// +// if ( +// transType.value == TransactionsType.PRE_AUTH_COMPLETE || +// transType.value == TransactionsType.PRE_AUTH_VOID || +// transType.value == TransactionsType.REFUND +// ) { +// +// _pinStatus.value = +// PinPadStatus.ON_NEXT_SCREEN +// +// } else { +// +// handler.obtainMessage( +// ON_CONFIRM_CLICK +// ).sendToTarget() +// } +// +// } else { +// +// _pinStatus.value = +// PinPadStatus.ON_CARD_REMOVED +// } +// +// } else { +// +// handler.obtainMessage( +// ON_EMPTY_PIN_BLOCK +// ).sendToTarget() +// } } override fun onCancel() { diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/transaction_result/TransactionResultEvent.kt b/app/src/main/java/com/mob/utsmyanmar/ui/transaction_result/TransactionResultEvent.kt new file mode 100644 index 0000000..d049da0 --- /dev/null +++ b/app/src/main/java/com/mob/utsmyanmar/ui/transaction_result/TransactionResultEvent.kt @@ -0,0 +1,8 @@ +package com.mob.utsmyanmar.ui.transaction_result + +sealed interface TransactionResultEvent { + data object Start: TransactionResultEvent + data object BackClick: TransactionResultEvent + data object RetryPrint: TransactionResultEvent + data object PrintLater: TransactionResultEvent +} \ No newline at end of file diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/transaction_result/TransactionResultRoute.kt b/app/src/main/java/com/mob/utsmyanmar/ui/transaction_result/TransactionResultRoute.kt new file mode 100644 index 0000000..aac8e24 --- /dev/null +++ b/app/src/main/java/com/mob/utsmyanmar/ui/transaction_result/TransactionResultRoute.kt @@ -0,0 +1,36 @@ +package com.mob.utsmyanmar.ui.transaction_result + + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.mob.utsmyanmar.viewmodel.SharedViewModel + +@Composable +fun TransactionResultRoute( + viewModel: TransactionResultViewModel = hiltViewModel(), + sharedViewModel: SharedViewModel = hiltViewModel(), + onNavigateMain: () -> Unit, + onNavigatePrintReceipt: () -> Unit, + onShowError: (String) -> Unit, + onShowSuccess: (String) -> Unit, + onShowPrinterDialog: (String) -> Unit +) { + val state by viewModel.state.collectAsStateWithLifecycle() + + LaunchedEffect(Unit) { + viewModel.onEvent( + TransactionResultEvent.Start, + sharedViewModel + ) + } + + TransactionResultScreen( + state = state, + onEvent = { + viewModel.onEvent(it, sharedViewModel) + } + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/transaction_result/TransactionResultScreen.kt b/app/src/main/java/com/mob/utsmyanmar/ui/transaction_result/TransactionResultScreen.kt new file mode 100644 index 0000000..d8412ef --- /dev/null +++ b/app/src/main/java/com/mob/utsmyanmar/ui/transaction_result/TransactionResultScreen.kt @@ -0,0 +1,41 @@ +package com.mob.utsmyanmar.ui.transaction_result + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.Button +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier + +@Composable +fun TransactionResultScreen( + state: TransactionResultState, + onEvent: (TransactionResultEvent) -> Unit +) { + Column( + modifier = Modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + Text(text = state.title) + + if (state.message.isNotEmpty()) { + Text(text = state.message) + } + + if (state.isLoading) { + CircularProgressIndicator() + } + + Button( + onClick = { + onEvent(TransactionResultEvent.BackClick) + } + ) { + Text("Back") + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/transaction_result/TransactionResultState.kt b/app/src/main/java/com/mob/utsmyanmar/ui/transaction_result/TransactionResultState.kt new file mode 100644 index 0000000..01b8221 --- /dev/null +++ b/app/src/main/java/com/mob/utsmyanmar/ui/transaction_result/TransactionResultState.kt @@ -0,0 +1,7 @@ +package com.mob.utsmyanmar.ui.transaction_result + +data class TransactionResultState( + val title: String = "Transaction Result", + val message: String = "", + val isLoading: Boolean = false +) diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/transaction_result/TransactionResultUiEvent.kt b/app/src/main/java/com/mob/utsmyanmar/ui/transaction_result/TransactionResultUiEvent.kt new file mode 100644 index 0000000..3d59545 --- /dev/null +++ b/app/src/main/java/com/mob/utsmyanmar/ui/transaction_result/TransactionResultUiEvent.kt @@ -0,0 +1,9 @@ +package com.mob.utsmyanmar.ui.transaction_result + +sealed interface TransactionResultUiEvent { + data object NavigateMain : TransactionResultUiEvent + data object NavigatePrintReceipt : TransactionResultUiEvent + data class ShowError(val message: String) : TransactionResultUiEvent + data class ShowSuccess(val message: String) : TransactionResultUiEvent + data class ShowPrinterDialog(val message: String) : TransactionResultUiEvent +} \ No newline at end of file diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/transaction_result/TransactionResultViewModel.kt b/app/src/main/java/com/mob/utsmyanmar/ui/transaction_result/TransactionResultViewModel.kt new file mode 100644 index 0000000..043af4f --- /dev/null +++ b/app/src/main/java/com/mob/utsmyanmar/ui/transaction_result/TransactionResultViewModel.kt @@ -0,0 +1,281 @@ +package com.mob.utsmyanmar.ui.transaction_result + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.mob.utsmyanmar.model.ecr.ECRResultStatus +import com.mob.utsmyanmar.utils.CoreUtils +import com.mob.utsmyanmar.viewmodel.SharedViewModel +import com.utsmyanmar.baselib.emv.EmvParamOperation +import com.utsmyanmar.baselib.network.model.sirius.SiriusRequest +import com.utsmyanmar.ecr.ECRHelper +import com.utsmyanmar.ecr.ECRProcess +import com.utsmyanmar.ecr.data.model.TransactionsResp +import com.utsmyanmar.paylibs.Constant +import com.utsmyanmar.paylibs.model.PayDetail +import com.utsmyanmar.paylibs.print.PaperRollStatusCallback +import com.utsmyanmar.paylibs.print.PrintHelper +import com.utsmyanmar.paylibs.utils.PrintStatus +import com.utsmyanmar.paylibs.utils.core_utils.ByteUtil +import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation +import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.receiveAsFlow +import kotlinx.coroutines.launch +import sunmi.sunmiui.utils.LogUtil +import javax.inject.Inject + +@HiltViewModel +class TransactionResultViewModel @Inject constructor( + private val emvParamOperation: EmvParamOperation +) : ViewModel() { + + companion object { + private const val TAG = "TransactionResultVM" + private const val RESULT_TIMEOUT = 1000L + } + + private val _state = MutableStateFlow(TransactionResultState()) + val state = _state.asStateFlow() + + private val _uiEvent = Channel() + val uiEvent = _uiEvent.receiveAsFlow() + + private var started = false + + fun onEvent( + event: TransactionResultEvent, + sharedViewModel: SharedViewModel + ) { + when (event) { + TransactionResultEvent.Start -> start(sharedViewModel) + TransactionResultEvent.BackClick -> isCardInside() + TransactionResultEvent.RetryPrint -> startPrintProcess(sharedViewModel, false) + TransactionResultEvent.PrintLater -> isCardInside() + } + } + + private fun start(sharedViewModel: SharedViewModel) { + if (started) return + started = true + + sharedViewModel.setPrintStatus(PrintStatus.FIRST_PRINT) + sharedViewModel.printXStatus.value = null + + updateTitle(sharedViewModel) + observePrintStatus(sharedViewModel) + + if (sharedViewModel.isEcr.value == true) { + ecrAction(sharedViewModel) + } + + startResultTimeout(sharedViewModel) + } + + private fun updateTitle(sharedViewModel: SharedViewModel) { + val payDetail = sharedViewModel.payDetail.value + val resultCode = payDetail?.tradeAnswerCode.orEmpty() + val qrStatus = payDetail?.qrTransStatus ?: -100 + + val isDemoMode = SystemParamsOperation.getInstance().demoStatus + + val isSuccess = isDemoMode || + resultCode == Constant.ANSWER_CODE_ACCEPT || + resultCode == Constant.ANSWER_CODE_APPROVED + + val title = when { + isSuccess -> "Transaction Success" + qrStatus == 1 || qrStatus == -1 || qrStatus == 2 || qrStatus == 3 -> "QR Pay" + else -> "Error" + } + + val message = when { + isSuccess -> "Transaction approved" + payDetail?.tradeAnswerCode?.isNotBlank() == true -> payDetail.tradeAnswerCode + else -> "Transaction failed" + } + + _state.value = _state.value.copy( + title = title, + message = message + ) + } + + private fun startResultTimeout(sharedViewModel: SharedViewModel) { + viewModelScope.launch { + delay(RESULT_TIMEOUT) + + val payDetail = sharedViewModel.payDetail.value + + if (payDetail == null) { + navigateMain() + return@launch + } + + val transactionType = sharedViewModel.transactionsType.value + + when { + isNonApprovedTrade(payDetail) && + isNonWavepayTransaction(transactionType) -> { + startPrintProcess(sharedViewModel, false) + isCardInside() + } + + transactionType == TransactionsType.SETTLEMENT -> { + startPrintProcess(sharedViewModel, true) + sendUiEvent( + TransactionResultUiEvent.ShowSuccess( + "Configs are updated" + ) + ) + navigateMain() + } + + isWavePayNonSuccessTransaction(transactionType, payDetail) -> { + startPrintProcess(sharedViewModel, false) + navigateMain() + } + + else -> { + SystemParamsOperation.getInstance() + .setLastSuccessTrnx(payDetail.voucherNo) + + emvParamOperation.loadEmvTerminalParam() + navigatePrint() + } + } + } + } + + private fun isNonApprovedTrade(payDetail: PayDetail): Boolean { + return payDetail.tradeAnswerCode != Constant.ANSWER_CODE_APPROVED && + payDetail.tradeAnswerCode != Constant.ANSWER_CODE_ACCEPT + } + + private fun isNonWavepayTransaction(type: TransactionsType?): Boolean { + return type != TransactionsType.WAVEPAY && + type != TransactionsType.WAVE_INQUIRY_STATUS && + type != TransactionsType.WAVEPAY_REFUND + } + + private fun isWavePayNonSuccessTransaction( + type: TransactionsType?, + payDetail: PayDetail + ): Boolean { + return (type == TransactionsType.WAVEPAY && payDetail.qrTransStatus != 1) || + (type == TransactionsType.WAVE_INQUIRY_STATUS && payDetail.qrTransStatus != 1) || + (type == TransactionsType.WAVEPAY_REFUND && payDetail.qrTransStatus != 1) + } + + private fun observePrintStatus(sharedViewModel: SharedViewModel) { + sharedViewModel.printXStatus.observeForever { status -> + when (status) { + PrintStatus.EMPTY_PAPER_ROLL -> { + startPrintProcess(sharedViewModel, false) + } + + PrintStatus.DONE_PRINT -> { + isCardInside() + } + + else -> Unit + } + } + } + + private fun startPrintProcess( + sharedViewModel: SharedViewModel, + isSettlement: Boolean + ) { + PrintHelper.getInstance().checkPaperRollStatus( + object : PaperRollStatusCallback { + + override fun paperRollIsReady() { + if (isSettlement) { + sharedViewModel.startPrintProcessSettlement() + } else { + sharedViewModel.startPrintProcess() + } + } + + override fun paperRollIsEmpty() { + sendUiEvent( + TransactionResultUiEvent.ShowPrinterDialog( + "Paper roll not ready" + ) + ) + } + + override fun paperRollLipIsOpened() { + sendUiEvent( + TransactionResultUiEvent.ShowPrinterDialog( + "Printer lip is opened. Please close lip." + ) + ) + } + + override fun unknownStatusOccur(code: Int) { + sendUiEvent( + TransactionResultUiEvent.ShowError( + "Check printer status: $code" + ) + ) + } + } + ) + } + + private fun getECRResponseMessage( + sharedViewModel: SharedViewModel + ): String { + val resp: TransactionsResp = + CoreUtils.getInstance(sharedViewModel).generateResponseMsg() + + return ECRProcess.generateECRResponse(resp) + } + + private fun getECRResponseCMHL( + sharedViewModel: SharedViewModel + ): ByteArray { + return CoreUtils.getInstance(sharedViewModel) + .generateCMHLResponse(ECRResultStatus.RESPONSE_RECEIVED) + } + + private fun ecrAction(sharedViewModel: SharedViewModel) { + if (SystemParamsOperation.getInstance().isCMHLEnabled) { + val response = getECRResponseCMHL(sharedViewModel) + + LogUtil.d(TAG, "ECR Response: ${ByteUtil.bytes2HexStr(response)}") + + ECRHelper.send(response) + CoreUtils.getInstance(sharedViewModel).responseACKCMHL() + } else { + val response = getECRResponseMessage(sharedViewModel) + + LogUtil.d(TAG, "ECR Response: $response") + + ECRHelper.send(response.toByteArray()) + } + } + + private fun isCardInside() { + navigateMain() + } + + private fun navigateMain() { + sendUiEvent(TransactionResultUiEvent.NavigateMain) + } + + private fun navigatePrint() { + sendUiEvent(TransactionResultUiEvent.NavigatePrintReceipt) + } + + private fun sendUiEvent(event: TransactionResultUiEvent) { + viewModelScope.launch { + _uiEvent.send(event) + } + } +} \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7563956..fb49d78 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,8 @@ [versions] agp = "9.2.0" +converterGson = "3.0.0" coreKtx = "1.18.0" +hiltAndroid = "2.59.2" hiltAndroidCompiler = "2.59.2" junit = "4.13.2" junitVersion = "1.3.0" @@ -12,6 +14,7 @@ composeBom = "2026.02.01" navigationCompose = "2.9.8" hilt = "2.57.1" foundation = "1.11.1" +retrofit = "3.0.0" runtime = "1.11.1" rxandroid = "3.0.2" rxjava = "3.1.12" @@ -20,7 +23,9 @@ hiltNavigationCompose = "1.2.0" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigationCompose" } +converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "converterGson" } hilt-android-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hiltAndroidCompiler" } +hilt-android-v2592 = { module = "com.google.dagger:hilt-android", version.ref = "hiltAndroid" } junit = { group = "junit", name = "junit", version.ref = "junit" } androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } @@ -38,6 +43,7 @@ hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref hilt-compiler = { group = "com.google.dagger", name = "hilt-compiler", version.ref = "hilt" } androidx-compose-foundation = { group = "androidx.compose.foundation", name = "foundation", version.ref = "foundation" } androidx-compose-runtime = { group = "androidx.compose.runtime", name = "runtime", version.ref = "runtime" } +retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" } rxandroid = { module = "io.reactivex.rxjava3:rxandroid", version.ref = "rxandroid" } rxjava = { module = "io.reactivex.rxjava3:rxjava", version.ref = "rxjava" } androidx-hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version.ref = "hiltNavigationCompose" } diff --git a/paysdk-lib/build/.transforms/367e79aa20464c99f248358da6f2a28e/results.bin b/paysdk-lib/build/.transforms/367e79aa20464c99f248358da6f2a28e/results.bin new file mode 100644 index 0000000..c790d94 --- /dev/null +++ b/paysdk-lib/build/.transforms/367e79aa20464c99f248358da6f2a28e/results.bin @@ -0,0 +1 @@ +o/PayLib-release-1.4.64-runtime diff --git a/paysdk-lib/build/.transforms/367e79aa20464c99f248358da6f2a28e/transformed/PayLib-release-1.4.64-runtime/PayLib-release-1.4.64-runtime_dex/classes.dex b/paysdk-lib/build/.transforms/367e79aa20464c99f248358da6f2a28e/transformed/PayLib-release-1.4.64-runtime/PayLib-release-1.4.64-runtime_dex/classes.dex new file mode 100644 index 0000000..2dc28a9 Binary files /dev/null and b/paysdk-lib/build/.transforms/367e79aa20464c99f248358da6f2a28e/transformed/PayLib-release-1.4.64-runtime/PayLib-release-1.4.64-runtime_dex/classes.dex differ diff --git a/sunmiui-lib/build/.transforms/d6ec3a0c9e8287dd88c27edc68e2fc0c/results.bin b/sunmiui-lib/build/.transforms/d6ec3a0c9e8287dd88c27edc68e2fc0c/results.bin new file mode 100644 index 0000000..800956c --- /dev/null +++ b/sunmiui-lib/build/.transforms/d6ec3a0c9e8287dd88c27edc68e2fc0c/results.bin @@ -0,0 +1 @@ +o/sunmiui-1.1.27-runtime diff --git a/sunmiui-lib/build/.transforms/d6ec3a0c9e8287dd88c27edc68e2fc0c/transformed/sunmiui-1.1.27-runtime/sunmiui-1.1.27-runtime_dex/classes.dex b/sunmiui-lib/build/.transforms/d6ec3a0c9e8287dd88c27edc68e2fc0c/transformed/sunmiui-1.1.27-runtime/sunmiui-1.1.27-runtime_dex/classes.dex new file mode 100644 index 0000000..a06cd2e Binary files /dev/null and b/sunmiui-lib/build/.transforms/d6ec3a0c9e8287dd88c27edc68e2fc0c/transformed/sunmiui-1.1.27-runtime/sunmiui-1.1.27-runtime_dex/classes.dex differ