This commit is contained in:
moon 2026-06-08 08:49:54 +06:30
commit 3301cb15e0
27 changed files with 336 additions and 86 deletions

View File

@ -1,5 +1,5 @@
package com.mob.utsmyanmar.model
enum class CardTransactionType {
MPU, EMV, MAG, FALLBACK
MPU, EMV, MAG, FALLBACK, MOCK
}

View File

@ -87,7 +87,8 @@ fun CardWaitingScreen(
amount = amount,
uiState = uiState,
onBackClick = viewModel::onBackPressed,
onManualEntryClick = viewModel::onManualEntryClick
onManualEntryClick = viewModel::onManualEntryClick,
onMockClick = viewModel::onMockClick
)
}
@ -96,7 +97,8 @@ private fun CardWaitingScreenContent(
amount: String,
uiState: CardWaitingUiState,
onBackClick: () -> Unit,
onManualEntryClick: () -> Unit
onManualEntryClick: () -> Unit,
onMockClick: () -> Unit
) {
Column(
modifier = Modifier
@ -210,7 +212,7 @@ private fun CardWaitingScreenContent(
Spacer(modifier = Modifier.height(12.dp))
InsertCardRow()
InsertCardRow(onMockClick = onMockClick)
Spacer(modifier = Modifier.height(18.dp))
@ -294,7 +296,7 @@ private fun CircleBorder(
}
@Composable
private fun InsertCardRow() {
private fun InsertCardRow(onMockClick: ()->Unit) {
Row(
modifier = Modifier.height(44.dp),
verticalAlignment = Alignment.CenterVertically
@ -304,6 +306,7 @@ private fun InsertCardRow() {
contentDescription = null,
tint = Color.LegacyRed,
modifier = Modifier.size(28.dp)
.clickable(onClick = onMockClick)
)
Spacer(modifier = Modifier.width(10.dp))
@ -437,6 +440,7 @@ fun PreviewCardWaitingScreen() {
amount = "50,000",
uiState = CardWaitingUiState(),
onBackClick = {},
onManualEntryClick = {}
onManualEntryClick = {},
onMockClick = {}
)
}

View File

@ -23,6 +23,7 @@ import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import sunmi.sunmiui.utils.LogUtil
class CardWaitingViewModel(
private val cardReadViewModel: CardReaderViewModel,
@ -121,6 +122,21 @@ class CardWaitingViewModel(
}
}
fun onMockClick() {
onScreenPause()
cardReadViewModel.setCardTransactionType(CardTransactionType.MOCK)
viewModelScope.launch {
_uiState.update {
it.copy(
alertMessage = "Mock card detected.",
isLoading = false,
isCardCaptured = true
)
}
_events.send(CardWaitingEvent.GoProcessingCard)
}
}
private fun startCardReadWhenReady(isFallback: Boolean) {
readerInitJob?.cancel()
readerInitJob = viewModelScope.launch {

View File

@ -34,9 +34,11 @@ import com.mob.utsmyanmar.ui.sale_void.VoidTraceScreen
import com.mob.utsmyanmar.viewmodel.CardReaderViewModel
import com.mob.utsmyanmar.viewmodel.EmvTransactionProcessViewModel
import com.mob.utsmyanmar.ui.pinpad.PinPadViewModel
import com.mob.utsmyanmar.ui.settlement.SettlementViewModel
import com.mob.utsmyanmar.ui.version.VersionScreen
import com.mob.utsmyanmar.viewmodel.SharedViewModel
import com.mob.utsmyanmar.viewmodel.TransProcessViewModel
import com.utsmyanmar.ecr.data.TransType
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType
@SuppressLint("ContextCastToActivity")
@ -125,12 +127,14 @@ fun AppNavGraph(
composable(Routes.Settlement.route) {
val sharedViewModel: SharedViewModel = hiltViewModel(activity)
val settlementViewMode: SettlementViewModel = hiltViewModel(activity)
SettlementScreen(
sharedViewModel = sharedViewModel,
settlementViewMode = settlementViewMode,
onBack = { navController.popBackStack(Routes.Dashboard.route,false) },
onStartSettlement = {
sharedViewModel.transactionsType.value = com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.SETTLEMENT
sharedViewModel.transactionsType.value = TransactionsType.SETTLEMENT
navController.navigate(Routes.Processing.route) {
popUpTo(Routes.Settlement.route) {
inclusive = true
@ -150,6 +154,7 @@ fun AppNavGraph(
)
) { backStackEntry ->
val voidViewModel: VoidViewModel = hiltViewModel()
val transProcessViewModel: TransProcessViewModel = hiltViewModel(activity)
val sharedViewModel: SharedViewModel = hiltViewModel(activity)
val trace = backStackEntry.arguments?.getString("trace").orEmpty()
@ -158,7 +163,8 @@ fun AppNavGraph(
trace = trace,
onBack = { navController.popBackStack() },
onProceedVoid = { payDetail ->
sharedViewModel.transactionsType.value = com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.VOID
sharedViewModel.transactionsType.value = TransactionsType.VOID
transProcessViewModel.setTransType(TransactionsType.VOID)
sharedViewModel.payDetail.value = payDetail
navController.navigate(Routes.Processing.route) {
popUpTo(Routes.VoidTranDetail.route) {
@ -365,10 +371,11 @@ fun AppNavGraph(
composable(Routes.Processing.route) {
val sharedViewModel: SharedViewModel = hiltViewModel(activity)
val transProcessViewModel: TransProcessViewModel = hiltViewModel(activity)
val settlementViewModel: SettlementViewModel = hiltViewModel(activity)
ProcessingRoute(
sharedViewModel = sharedViewModel,
transProcessViewModel = transProcessViewModel,
settlementViewModel = settlementViewModel,
onNavigateTransactionResult = {
navController.navigate(Routes.TransactionResult.route) {
popUpTo(Routes.Processing.route) {
@ -376,6 +383,14 @@ fun AppNavGraph(
}
launchSingleTop = true
}
},
onNavigateMain = {
navController.navigate(Routes.Dashboard.route) {
popUpTo(Routes.Dashboard.route) {
inclusive = false
}
launchSingleTop = true
}
}
)
}

View File

@ -1,5 +1,6 @@
package com.mob.utsmyanmar.ui.pinpad
import android.text.TextUtils
import androidx.activity.compose.BackHandler
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
@ -10,6 +11,8 @@ import com.mob.utsmyanmar.model.PinPadStatus
import com.mob.utsmyanmar.viewmodel.SharedViewModel
import com.mob.utsmyanmar.viewmodel.TransProcessViewModel
import com.utsmyanmar.paylibs.Constant
import com.utsmyanmar.paylibs.model.TradeData
import com.utsmyanmar.paylibs.utils.POSUtil
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType
@Composable
@ -30,6 +33,19 @@ fun PinPadRoute(
onBack()
}
LaunchedEffect(Unit) {
val tradeData: TradeData = pinPadViewModel.getTradeData()!!
val payDetail = tradeData.getPayDetail()
val processCode = sharedViewModel.processCode.getValue()
val amount = sharedViewModel.amount.getValue()
payDetail.setAmount(POSUtil.getInstance().convertAmount(amount))
if (!TextUtils.equals(processCode, "")) {
payDetail.setProcessCode(processCode)
}
}
LaunchedEffect(pinStatus) {
when (pinStatus) {
PinPadStatus.ON_CONFIRM,
@ -38,7 +54,7 @@ fun PinPadRoute(
payDetail?.tradeAnswerCode = Constant.ANSWER_CODE_APPROVED
sharedViewModel.payDetail.value = payDetail
transProcessViewModel.resetTransactionStatus()
if (sharedViewModel.transactionsType.value == TransactionsType.REFUND) {
if (sharedViewModel.transactionsType.value == TransactionsType.REFUND || sharedViewModel.transactionsType.value == TransactionsType.PRE_AUTH_VOID || sharedViewModel.transactionsType.value == TransactionsType.PRE_AUTH_COMPLETE) {
onNavigateInputRrn()
} else {
onNavigateProcessing()

View File

@ -472,15 +472,15 @@ class PinPadViewModel @Inject constructor(
return
}
val isCardValid = SunmiSDK.getInstance().checkCardExist() == 2 ||
payDetail?.cardType == AidlConstants.CardType.MAGNETIC.getValue() ||
payDetail?.cardType == -9
if (!isCardValid) {
isTerminalStateReached = true
_pinStatus.value = PinPadStatus.ON_CARD_REMOVED
return
}
// val isCardValid = SunmiSDK.getInstance().checkCardExist() == 2 ||
// payDetail?.cardType == AidlConstants.CardType.MAGNETIC.getValue() ||
// payDetail?.cardType == -9
//
// if (!isCardValid) {
// isTerminalStateReached = true
// _pinStatus.value = PinPadStatus.ON_CARD_REMOVED
// return
// }
if (pinBlock != null) {
payDetail?.pinCipher = ByteUtil.bytes2HexStr(pinBlock)

View File

@ -6,10 +6,12 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import com.mob.utsmyanmar.model.CardTransactionType
import com.mob.utsmyanmar.ui.pinpad.PinPadViewModel
import com.mob.utsmyanmar.utils.MockCardData
import com.mob.utsmyanmar.utils.MockData
import com.mob.utsmyanmar.utils.TransactionUtil
import com.mob.utsmyanmar.viewmodel.CardReaderViewModel
import com.mob.utsmyanmar.viewmodel.EmvTransactionProcessViewModel
import com.mob.utsmyanmar.ui.pinpad.PinPadViewModel
import com.mob.utsmyanmar.viewmodel.SharedViewModel
import com.mob.utsmyanmar.viewmodel.TransProcessViewModel
import com.utsmyanmar.checkxread.model.CardDataX
@ -23,7 +25,6 @@ import com.utsmyanmar.paylibs.model.enums.TransCVM
import com.utsmyanmar.paylibs.utils.POSUtil
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation
import com.utsmyanmar.paylibs.utils.enums.TransMenu
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType
import com.utsmyanmar.paylibs.utils.params.Params
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.MutableStateFlow
@ -86,6 +87,7 @@ class ProcessingCardViewModel(
private fun checkCardTransactionType() {
when (cardReadViewModel.getCardTransactionType()) {
CardTransactionType.MOCK -> mockCardData()
CardTransactionType.MPU -> readMPUCard()
CardTransactionType.EMV -> handlePreEmvProcess()
CardTransactionType.FALLBACK -> readMAGStripe(
@ -107,6 +109,22 @@ class ProcessingCardViewModel(
}
}
private fun mockCardData() {
sharedViewModel.setEmvTrans(false)
transProcessViewModel.setTransType(sharedViewModel.transactionsType.value)
pinPadViewModel.setTransType(sharedViewModel.transactionsType.value)
val cardDataX = MockData.generateMPUCard();
val tradeData = TransactionUtil.initMPUTransaction(cardDataX, CardTypeX.IC)
transProcessViewModel.setTradeData(tradeData)
pinPadViewModel.setTradeData(tradeData)
sharedViewModel.setCardDataExist(true)
sendUiEvent(ProcessingCardUiEvent.NavigateToPinPad)
}
private fun readMPUCard() {
cardReadViewModel.startReadXProcess(
MPUXReadCard.getInstance(),

View File

@ -1,6 +1,7 @@
package com.mob.utsmyanmar.ui.refund_rrn
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
@ -22,6 +23,11 @@ fun InputRrnRoute(
}
var errorMessage by rememberSaveable { mutableStateOf<String?>(null) }
LaunchedEffect(Unit) {
rrn = ""
errorMessage = null
}
NumericEntryScreen(
title = "Input RRN",
prompt = "Enter RRN",

View File

@ -0,0 +1,5 @@
package com.mob.utsmyanmar.ui.sending_to_host
data class ProcessingState(
val title: String = "Processing",
)

View File

@ -8,7 +8,14 @@ import com.mob.utsmyanmar.viewmodel.SharedViewModel
import com.mob.utsmyanmar.viewmodel.TransProcessViewModel
import kotlinx.coroutines.delay
import androidx.compose.runtime.getValue
import com.mob.utsmyanmar.ui.transaction_result.TransactionResultState
import com.mob.utsmyanmar.viewmodel.ProcessingTransaction
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import androidx.compose.runtime.collectAsState
import com.mob.utsmyanmar.model.TransactionStatus
import com.mob.utsmyanmar.ui.settlement.SettlementViewModel
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType
private const val MOCK_HOST_DELAY_MS = 2000L
@ -16,30 +23,52 @@ private const val MOCK_HOST_DELAY_MS = 2000L
fun ProcessingRoute(
sharedViewModel: SharedViewModel,
transProcessViewModel: TransProcessViewModel,
onNavigateTransactionResult: () -> Unit
settlementViewModel: SettlementViewModel,
onNavigateTransactionResult: () -> Unit,
onNavigateMain: ()-> Unit
) {
val transStatus by transProcessViewModel.transResultStatus.collectAsStateWithLifecycle()
val state by transProcessViewModel.state.collectAsStateWithLifecycle()
val settlementStatus by settlementViewModel.uiState.collectAsStateWithLifecycle()
if(sharedViewModel.transactionsType.value == TransactionsType.SETTLEMENT) {
LaunchedEffect(Unit) {
settlementViewModel.startSettlementProcess()
}
} else {
LaunchedEffect(Unit) {
transProcessViewModel.startOnlineProcess()
}
}
LaunchedEffect(transStatus) {
// sharedViewModel.saveMockHostResultForTesting()
// delay(MOCK_HOST_DELAY_MS)
when(transStatus) {
TransResultStatus.SUCCESS -> onNavigateTransactionResult()
TransResultStatus.FAIL -> onNavigateTransactionResult()
TransResultStatus.REVERSAL_SUCCESS -> onNavigateMain()
TransResultStatus.REVERSAL_FAIL -> onNavigateMain()
else -> {}
}
}
ProcessingScreen()
LaunchedEffect(settlementStatus.status) {
when(settlementStatus.status) {
TransactionStatus.ON_SUCCESS -> onNavigateTransactionResult()
else -> {}
}
}
if(sharedViewModel.transactionsType.value == TransactionsType.SETTLEMENT) {
ProcessingScreen(settlementStatus.processingState)
} else {
ProcessingScreen(state)
}
}

View File

@ -20,12 +20,13 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.mob.utsmyanmar.ui.processing_card.ProcessingCardState
import com.mob.utsmyanmar.ui.theme.Black
import com.mob.utsmyanmar.ui.theme.Primary
import com.mob.utsmyanmar.ui.theme.White
@Composable
fun ProcessingScreen() {
fun ProcessingScreen(state: ProcessingState) {
Scaffold(
containerColor = White
) { paddingValues ->
@ -57,7 +58,7 @@ fun ProcessingScreen() {
Spacer(modifier = Modifier.height(20.dp))
Text(
text = "Processing",
text = state.title,
color = White,
fontSize = 24.sp,
fontWeight = FontWeight.Bold

View File

@ -20,6 +20,7 @@ import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Modifier
@ -35,12 +36,14 @@ import com.utsmyanmar.paylibs.utils.POSUtil
@Composable
fun SettlementScreen(
sharedViewModel: SharedViewModel,
settlementViewMode: SettlementViewModel,
onBack: () -> Unit,
onStartSettlement: () -> Unit
) {
val records by sharedViewModel.getSettlementRecords().observeAsState(emptyList())
val records by settlementViewMode.getSettlementPOS().observeAsState(emptyList())
val totalAmount = records.sumOf { it.amount }
Scaffold(
containerColor = Color.IvoryBeige,
topBar = {

View File

@ -2,10 +2,12 @@ package com.mob.utsmyanmar.ui.settlement
import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.asFlow
import androidx.lifecycle.viewModelScope
import com.mob.utsmyanmar.config.Constants
import com.mob.utsmyanmar.model.SettlementType
import com.mob.utsmyanmar.model.TransactionStatus
import com.mob.utsmyanmar.ui.sending_to_host.ProcessingState
import com.utsmyanmar.baselib.repo.Repository
import com.utsmyanmar.paylibs.Constant
import com.utsmyanmar.paylibs.batch_upload.BatchListener
@ -56,7 +58,8 @@ data class SettlementUiState(
val bottomLayout: Int = 0,
val status: TransactionStatus? = null,
val isLoading: Boolean = false
val isLoading: Boolean = false,
val processingState: ProcessingState = ProcessingState("Processing")
)
sealed interface SettlementEvent {
@ -84,11 +87,20 @@ class SettlementViewModel @Inject constructor(
private var bitmap = ""
val records: LiveData<List<PayDetail>> = getSettlementPOS()
init {
viewModelScope.launch {
records.asFlow().collect { list ->
setSettlementData(list)
}
}
}
private val isoMsgX: ISOMsgX =
ISOMsgX.ISOMsgXBuilder(
ISOVersion.VERSION_1993,
ISOMode.BOTH_HEADER_TPDU,
HostName.BPC
HostName.MPU
).build()
private val _uiState = MutableStateFlow(SettlementUiState())
@ -123,6 +135,51 @@ class SettlementViewModel @Inject constructor(
payDetails = list
}
fun setSettlementData(list: List<PayDetail>) {
val newState = list.fold(_uiState.value) { state, payDetail ->
val transType = payDetail.transactionType
val transName = payDetail.transType
when {
(transType == TransactionType.SALE || transName.equals("SALE", ignoreCase = true))
&& !payDetail.isCanceled ->
state.copy(
saleCount = state.saleCount + 1,
saleAmount = state.saleAmount + payDetail.amount
)
(transType == TransactionType.PRE_SALE_COMPLETE
|| transName.equals("PREAUTH COMPLETION", ignoreCase = true)
|| transName.equals("PRE_AUTH_COMPLETE", ignoreCase = true))
&& !payDetail.isCanceled ->
state.copy(
preCount = state.preCount + 1,
preAmount = state.preAmount + payDetail.amount
)
transType == TransactionType.REFUND
|| transName.equals("REFUND", ignoreCase = true) ->
state.copy(
refundCount = state.refundCount + 1,
refundAmount = state.refundAmount + payDetail.amount
)
transType == TransactionType.CASH_ADVANCE
|| transName.equals("CASH_OUT", ignoreCase = true)
|| transName.equals("CASH_ADVANCE", ignoreCase = true) ->
state.copy(
caCount = state.caCount + 1,
caAmount = state.caAmount + payDetail.amount
)
else -> state
}
}
LogUtil.d(TAG,"sale count ${newState.saleCount} and sale amount ${newState.saleAmount}")
_uiState.update { newState }
}
fun setSettlementSummary(
saleCount: Int,
saleAmount: Long,
@ -195,12 +252,14 @@ class SettlementViewModel @Inject constructor(
private fun requestOnlineProcessSettlement() {
val state = _uiState.value
val hostName = HostName.BPC
val hostName = HostName.MPU
val field60 = SystemParamsOperation.getInstance().getCurrentBatchNum()
val sale2Count = state.saleCount + state.preCount
val sale2Amount = state.saleAmount + state.preAmount
LogUtil.d(TAG,"Sale count :$sale2Count and Sale amount :$sale2Amount")
val totalSaleCount = String.format(Locale.getDefault(), "%03d", sale2Count)
val totalSaleAmount = String.format(Locale.getDefault(), "%010d00", sale2Amount)
@ -226,7 +285,7 @@ class SettlementViewModel @Inject constructor(
payDetail = currentPayDetail
bitmap = BitmapConfig.BPC_SETTLEMENT
bitmap = BitmapConfig.MPU_NEW_SETTLE
currentPayDetail.transType = TransactionsType.SETTLEMENT.name
currentPayDetail.transactionType = TransactionType.SETTLEMENT
@ -234,8 +293,8 @@ class SettlementViewModel @Inject constructor(
if (!flag) {
currentPayDetail.processCode = TransactionsType.SETTLEMENT.processCode
} else {
bitmap = BitmapConfig.BPC_SETTLEMENT_TRAILER
currentPayDetail.processCode = "910000"
bitmap = BitmapConfig.MPU_NEW_SETTLE
currentPayDetail.processCode = "960000"
}
currentPayDetail.batchNo = SystemParamsOperation.getInstance().getCurrentBatchNum()
@ -384,6 +443,7 @@ class SettlementViewModel @Inject constructor(
}
private fun batchUploadProcess() {
_uiState.value = _uiState.value.copy(processingState = ProcessingState("Processing Batch Upload"))
postStatus(TransactionStatus.ON_BATCH_UPLOAD)
val currentPayDetails = payDetails

View File

@ -24,6 +24,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.mob.utsmyanmar.ui.preview.P2Preview
import com.mob.utsmyanmar.ui.theme.Color
import com.utsmyanmar.paylibs.model.PayDetail
import com.utsmyanmar.paylibs.print.PrintReceipt
@ -75,14 +76,14 @@ fun TransactionResultScreen(
Spacer(modifier = Modifier.height(28.dp))
AmountCard(amount = "50,000")
AmountCard(amount = state.payDetail?.amount.toString())
Spacer(modifier = Modifier.height(16.dp))
InfoCard(
date = "26 May 2026",
time = "12:06 PM",
transactionId = "1234568333"
transactionId = state.payDetail?.referNo.toString()
)
}
@ -281,7 +282,8 @@ private fun InfoItem(
fun PreviewTransactionResultScreen() {
TransactionResultScreen(
state = TransactionResultState(
"Success"
"Success",
payDetail = PayDetail()
),
canGoBack = true,
onEvent = {},

View File

@ -1,7 +1,10 @@
package com.mob.utsmyanmar.ui.transaction_result
import com.utsmyanmar.paylibs.model.PayDetail
data class TransactionResultState(
val title: String = "Transaction Result",
val message: String = "",
val isLoading: Boolean = false
val isLoading: Boolean = false,
val payDetail: PayDetail? = null
)

View File

@ -62,6 +62,8 @@ class TransactionResultViewModel @Inject constructor(
if (started) return
started = true
_state.value = _state.value.copy(payDetail = sharedViewModel.payDetail.value)
sharedViewModel.setPrintStatus(PrintStatus.FIRST_PRINT)
sharedViewModel.printXStatus.value = null

View File

@ -0,0 +1,57 @@
package com.mob.utsmyanmar.utils
import com.utsmyanmar.checkxread.model.CardDataX
data class MockCardData(
val cardNo: String = "",
val expDate: String = "",
val cardScheme: String = "",
val cardHolderName: String = "",
val phoneNo: String = "",
val iccData: String = ""
)
object MockData {
private val mockCardData: MockCardData = MockCardData(
cardNo="9503712156912514",
expDate="2912",
cardScheme="MPU",
cardHolderName="Htin Kyaw Win",
iccData="9503712156912514=29121010000000000000"
)
fun generateMPUCard(): CardDataX = CardDataX().apply {
pan = mockCardData.cardNo
exp = mockCardData.expDate
cardHolderName = mockCardData.cardHolderName
track2 = mockCardData.iccData
}
/*
// VISA
MockCardData(cardNo="3230101288181", expDate="0425", cardScheme="VISA",
cardHolderName="U AYE", iccData="5F21BLAHBLAH")
// MPU - KBZ Debit
MockCardData(cardNo="9503051034047056", expDate="3002", cardScheme="MPU",
cardHolderName="KBZ Debit", iccData="9503051034047056=30021015930000000000")
// MPU - KBZ Credit
MockCardData(cardNo="9505050161133125", expDate="2701", cardScheme="MPU",
cardHolderName="KBZ Credit", iccData="9505050161133125=27011017250000000000")
// MPU - Htin Kyaw Win
MockCardData(cardNo="9503712156912514", expDate="2912", cardScheme="MPU",
cardHolderName="Htin Kyaw Win", iccData="9503712156912514=29121010000000000000")
// MPU - Bank Q
MockCardData(cardNo="9503742975107251", expDate="0629", cardScheme="MPU",
cardHolderName="Bank Q", iccData="9503742975107251=22081010000000000000")
// WALLET
MockCardData(phoneNo="9794452506", expDate="0425", cardScheme="WALLET",
cardHolderName="YOMA VALUED CUSTOMER")
*/
}

View File

@ -5,6 +5,8 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.mob.utsmyanmar.model.SettlementType
import com.mob.utsmyanmar.ui.processing_card.ProcessingCardState
import com.mob.utsmyanmar.ui.sending_to_host.ProcessingState
import com.utsmyanmar.baselib.network.model.sirius.SiriusRequest
import com.utsmyanmar.baselib.network.model.sirius.SiriusResponse
import com.utsmyanmar.baselib.repo.Repository
@ -24,6 +26,8 @@ import com.utsmyanmar.paylibs.utils.enums.TransMenu
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType
import dagger.hilt.android.lifecycle.HiltViewModel
import io.reactivex.rxjava3.core.Observable
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import sunmi.sunmiui.utils.LogUtil
import javax.inject.Inject
@ -150,6 +154,8 @@ class SharedViewModel @Inject constructor(
private val _isAmountExist = SingleLiveEvent<Boolean>()
private var mPayDetail = PayDetail()
init {

View File

@ -3,6 +3,8 @@ package com.mob.utsmyanmar.viewmodel
import android.text.TextUtils
import androidx.lifecycle.ViewModel
import com.mob.utsmyanmar.model.TransResultStatus
import com.mob.utsmyanmar.ui.processing_card.ProcessingCardState
import com.mob.utsmyanmar.ui.sending_to_host.ProcessingState
import com.utsmyanmar.baselib.repo.Repository
import com.utsmyanmar.paylibs.model.PayDetail
import com.utsmyanmar.paylibs.model.TradeData
@ -103,6 +105,9 @@ class TransProcessViewModel @Inject constructor(
fun setOldTransPayDetail(payDetail: PayDetail) {
oldTransPayDetail = payDetail
}
private val _state = MutableStateFlow(ProcessingState())
val state = _state.asStateFlow()
/*
* Transaction
@ -110,6 +115,8 @@ class TransProcessViewModel @Inject constructor(
override fun startOnlineProcess() {
_state.value = _state.value.copy("Processing")
TransactionsOperation.getInstance()
.getStartOperation(
tradeData,
@ -188,6 +195,7 @@ class TransProcessViewModel @Inject constructor(
_transResultStatus.value =
TransResultStatus.REVERSAL_PREPARE
_state.value = _state.value.copy("Preparing Reversal")
callReversal(tradeData)
}
@ -261,6 +269,7 @@ class TransProcessViewModel @Inject constructor(
private fun callReversal(tradeData: TradeData) {
_state.value = _state.value.copy("Processing Reversal")
payDetail = tradeData.payDetail
ReversalAction.getInstance()

View File

@ -48,7 +48,7 @@ public interface PayDetailDao {
// 1 = SALE & 7 = PRE_SALE_COMPLETE & 4 = REFUND & 9 = CASH_ADVANCE & 18 = TIP ADJUSTMENT
// @Query("SELECT * FROM paydetail WHERE isSettle = 0 AND isCanceled = 0 AND accountType != 'MPU' and accountType != 'UPI' AND (transactionType = 1 OR transactionType = 7 OR transactionType = 4 OR transactionType = 9)")
@Query("SELECT * FROM paydetail WHERE isSettle = 0 AND isCanceled = 0 AND accountType NOT IN ( 'MPU','UnionPay') AND transactionType IN (1, 7, 4, 9)")
@Query("SELECT * FROM paydetail WHERE isSettle = 0 AND isCanceled = 0 AND transactionType IN (1, 7, 4, 9)")
LiveData<List<PayDetail>> getSettlementPOS();
// 1 = SALE & 7 = PRE_SALE_COMPLETE & 4 = REFUND & 9 = CASH_ADVANCE & 18 = TIP ADJUSTMENT & 6 = PRE_AUTH_VOID & 20 = WALLET

View File

@ -329,10 +329,10 @@ public class ISOSocket {
public void switchIp() {
isSwitchIp = true;
serverIP = "posuat.myanmarorientalbank.com";
serverPort = 5033;
// serverIP = "192.168.0.107";
// serverPort = 5001;
// serverIP = "posuat.myanmarorientalbank.com";
// serverPort = 5033;
serverIP = "192.168.0.100";
serverPort = 5001;
// serverIP = getSecondaryIp();
// serverPort = getSecondaryPort();
}
@ -353,11 +353,11 @@ public class ISOSocket {
if (!isSwitchIp) {
// serverIP = getIp();
// serverPort = getPort();
// serverIP = "192.168.0.107";
// serverPort = 5001;
SystemParamsOperation.getInstance().setSslSwitchStatus(true);
serverIP = "posuat.myanmarorientalbank.com";
serverPort = 5033;
serverIP = "192.168.0.100";
serverPort = 5001;
SystemParamsOperation.getInstance().setSslSwitchStatus(false);
// serverIP = "posuat.myanmarorientalbank.com";
// serverPort = 5033;
} else {
isSwitchIp = false;
}

View File

@ -50,7 +50,7 @@ public class SignOnProcess {
private SignOnProcess() {
tradeData = Params.newTrade(true);
// payDetail = tradeData.getPayDetail();
isoMsgX = new ISOMsgX.ISOMsgXBuilder(ISOVersion.VERSION_1993, ISOMode.ONLY_HEADER,HostName.CARDZONE)
isoMsgX = new ISOMsgX.ISOMsgXBuilder(ISOVersion.VERSION_1993, ISOMode.BOTH_HEADER_TPDU,HostName.MPU)
.build();
}
@ -59,13 +59,13 @@ public class SignOnProcess {
flag = false;
return listener -> {
// LogUtil.d(TAG, "Starting TX SignOn");
HostName hostName = HostName.CARDZONE;
HostName hostName = HostName.MPU;
PayDetail payDetail = tradeData.getPayDetail();
payDetail.setProcessCode(TransactionsType.SIGN_ON.processCode);
payDetail.setTransType(TransactionsType.SIGN_ON.name);
payDetail.setTransactionType(TransactionsType.SIGN_ON.value);
payDetail.setHostName(HostName.CARDZONE.name);
payDetail.setHostName(hostName.name);
byte[] sendBytes = isoMsgX.buildISOPackets(tradeData, BitmapConfig.CZ_SIGN_ON, MessageType.NETWORK_MANAGEMENT);
ISOSocket.getInstance().enqueue(sendBytes, sendBytes.length,false, new ISOCallback() {

View File

@ -3,7 +3,9 @@ package com.utsmyanmar.paylibs.utils.enums;
public enum HostName {
BPC("BPC"),
FINEXUS("FINEXUS"),
CARDZONE("CARDZONE");
CARDZONE("CARDZONE"),
MPU("MPU");
public final String name;

View File

@ -26,69 +26,65 @@ public class HostUtils {
boolean isVisaMaster = cardScheme.equals(CardScheme.VISA.name) || cardScheme.equals(CardScheme.MASTERCARD.name);
switch (transactionsType) {
case SALE:
if (hostName == HostName.BPC){
bitmap = BitmapConfig.BPC_SALE;
if (hostName == HostName.MPU){
bitmap = BitmapConfig.MPU_NEW_SALE;
} else {
bitmap = BitmapConfig.CZ_SALE;
}
break;
case CASH_OUT:
if (hostName == HostName.BPC) {
bitmap = BitmapConfig.BPC_SALE;
if (hostName == HostName.MPU) {
bitmap = BitmapConfig.MPU_NEW_CASH_ADVANCE;
} else {
bitmap = BitmapConfig.CZ_SALE;
}
break;
case VOID:
if (hostName == HostName.BPC) {
if(isVisaMaster) {
bitmap = BitmapConfig.BPC_VOID;
break;
}
bitmap = BitmapConfig.BPC_VOID;
if (hostName == HostName.MPU) {
bitmap = BitmapConfig.MPU_NEW_VOID;
} else {
bitmap = BitmapConfig.FINEXUS_VOID;
}
break;
case SETTLEMENT:
if (hostName == HostName.BPC) {
bitmap = BitmapConfig.BPC_SETTLEMENT;
if (hostName == HostName.MPU) {
bitmap = BitmapConfig.MPU_NEW_BATCH_UPLOAD;
} else {
bitmap = BitmapConfig.FINEXUS_BATCH_UPLOAD;
}
break;
case PRE_AUTH_SALE:
if (hostName == HostName.BPC) {
bitmap = BitmapConfig.BPC_PRE_AUTH_SALE;
if (hostName == HostName.MPU) {
bitmap = BitmapConfig.MPU_NEW_PRE_AUTH;
} else {
bitmap = BitmapConfig.FUND_TRANSFER_PRE_CHECK;
}
break;
case PRE_AUTH_VOID:
if (hostName == HostName.BPC) {
bitmap = BitmapConfig.BPC_PRE_AUTH_SALE_VOID_REVERSAL;
if (hostName == HostName.MPU) {
bitmap = BitmapConfig.MPU_NEW_PRE_AUTH_CANCEL;
} else {
bitmap = BitmapConfig.CZ_SALE;
}
break;
case PRE_AUTH_COMPLETE:
if (hostName == HostName.BPC) {
bitmap = BitmapConfig.BPC_PRE_AUTH_SALE_COMPLETE;
if (hostName == HostName.MPU) {
bitmap = BitmapConfig.MPU_NEW_PRE_AUTH_COMPLETE_BITMAP;
} else {
bitmap = BitmapConfig.CZ_SALE;
}
break;
case PRE_AUTH_COMPLETE_VOID:
if (hostName == HostName.BPC) {
bitmap = BitmapConfig.BPC_VOID;
if (hostName == HostName.MPU) {
bitmap = BitmapConfig.MPU_NEW_PRE_AUTH_COMPLETE_CANCEL;
} else {
bitmap = BitmapConfig.FINEXUS_PRE_AUTH_VOID;
}
break;
case REFUND:
if (hostName == HostName.BPC) {
bitmap = BitmapConfig.BPC_REFUND;
if (hostName == HostName.MPU) {
bitmap = BitmapConfig.MPU_NEW_REFUND;
} else {
bitmap = BitmapConfig.CZ_SALE;
}

View File

@ -535,8 +535,8 @@ public class FieldUtils {
break;
case 63: //Private Use
// String settleData = payDetail.getSettleData();
// field.setDataStr(settleData);
String settleData = payDetail.getSettleData();
field.setDataStr(settleData);
break;
case 64: //Message Authentication Code (MAC) Required when the 39 field in the response message is "00"
field.setDataStr("0000000000000000");

View File

@ -82,7 +82,7 @@ public class Params {
payDetail.setIsCanceled(false);
payDetail.transNum = System.currentTimeMillis() / 1000;
// need to add host logic in another place
payDetail.setHostName("CARDZONE");
payDetail.setHostName("MPU");
payDetail.setOriginalTransDate(SystemDateTime.getMMDD()+SystemDateTime.getYYYY());

Binary file not shown.