diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 4f3cc09..cac232d 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -40,8 +40,8 @@ android { dimension = "env" applicationIdSuffix = ".uat" versionNameSuffix = "-UAT" - versionCode = 21 - versionName = "3.9" + versionCode = 29 + versionName = "4.7" buildConfigField("String", "ENV", "\"UAT\"") resValue("string", "app_name", "MOB-UAT") } diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/history_functions/HistoryComponents.kt b/app/src/main/java/com/mob/utsmyanmar/ui/history_functions/HistoryComponents.kt index a779c99..0cdf640 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/history_functions/HistoryComponents.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/history_functions/HistoryComponents.kt @@ -10,13 +10,15 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.rounded.Backspace +import androidx.compose.material.icons.automirrored.rounded.Backspace import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon +import androidx.compose.ui.draw.shadow +import androidx.compose.ui.unit.sp import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -64,7 +66,7 @@ internal fun HistoryTransactionCard( style = MaterialTheme.typography.titleSmall ) Text( - "${convertDateString(payDetail.transDate)} ${payDetail.transTime}", + "${convertDateString(payDetail.transDate.orEmpty())} ${payDetail.transTime.orEmpty()}".trim(), style = MaterialTheme.typography.titleSmall ) } @@ -92,7 +94,7 @@ internal fun HistoryTransactionCard( style = MaterialTheme.typography.titleSmall ) Text( - text = payDetail.voucherNo.ifBlank { "-" }, + text = payDetail.voucherNo.orEmpty().ifBlank { "-" }, style = MaterialTheme.typography.titleSmall ) } @@ -106,7 +108,7 @@ internal fun HistoryTransactionCard( style = MaterialTheme.typography.titleSmall ) Text( - text = payDetail.referNo.ifBlank { "-" }, + text = payDetail.referNo.orEmpty().ifBlank { "-" }, style = MaterialTheme.typography.titleSmall ) } @@ -120,7 +122,7 @@ internal fun HistoryTransactionCard( style = MaterialTheme.typography.titleSmall ) Text( - text = payDetail.approvalCode.ifBlank { "-" }, + text = (payDetail.approvalCode ?: payDetail.authNo).orEmpty().ifBlank { "-" }, style = MaterialTheme.typography.titleSmall ) } @@ -133,29 +135,29 @@ internal fun HistoryTransactionDetailCard( payDetail: PayDetail, modifier: Modifier = Modifier, ) { - val dateStr = if (payDetail.transDate.isNotBlank()) { + val dateStr = if (!payDetail.transDate.isNullOrBlank()) { convertDateString(payDetail.transDate) } else { - payDetail.tradeDate.ifBlank { "-" } + payDetail.tradeDate.orEmpty().ifBlank { "-" } } - val timeStr = payDetail.transTime.ifBlank { payDetail.tradeTime }.ifBlank { "-" } - val merchantNameStr = payDetail.merchantName.takeIf { it.isNotBlank() } + val timeStr = payDetail.transTime.orEmpty().ifBlank { payDetail.tradeTime.orEmpty() }.ifBlank { "-" } + val merchantNameStr = payDetail.merchantName?.takeIf { it.isNotBlank() } ?: SystemParamsOperation.getInstance().merchantName?.takeIf { it.isNotBlank() } ?: "-" - val midStr = payDetail.merchantNo.takeIf { it.isNotBlank() } + val midStr = payDetail.merchantNo?.takeIf { it.isNotBlank() } ?: SystemParamsOperation.getInstance().merchantId?.takeIf { it.isNotBlank() } ?: "-" - val tidStr = payDetail.terminalNo.takeIf { it.isNotBlank() } + val tidStr = payDetail.terminalNo?.takeIf { it.isNotBlank() } ?: SystemParamsOperation.getInstance().terminalId?.takeIf { it.isNotBlank() } ?: "-" - val traceNoStr = payDetail.voucherNo.ifBlank { "-" } - val refNoStr = payDetail.referNo.ifBlank { "-" } + val traceNoStr = payDetail.voucherNo.orEmpty().ifBlank { "-" } + val refNoStr = payDetail.referNo.orEmpty().ifBlank { "-" } val aprCodeStr = payDetail.approvalCode?.takeIf { it.isNotBlank() } - ?: payDetail.authNo.takeIf { it.isNotBlank() } + ?: payDetail.authNo?.takeIf { it.isNotBlank() } ?: "-" val transTypeStr = displayTransactionTitle(payDetail) val amountStr = displayAmountWithSign(payDetail) - val cardTypeStr = payDetail.accountType.ifBlank { "-" } + val cardTypeStr = payDetail.accountType.orEmpty().ifBlank { "-" } val cleanPan = payDetail.cardNo.orEmpty().replace(" ", "") val cardNoStr = if (cleanPan.length > 10) { cleanPan.take(6) + "*".repeat(cleanPan.length - 10) + cleanPan.takeLast(4) @@ -187,12 +189,12 @@ internal fun HistoryTransactionDetailCard( style = MaterialTheme.typography.titleMedium, fontWeight = FontWeight.Bold ) - Text( - text = amountStr, - color = Color.Black, - style = MaterialTheme.typography.titleMedium, - fontWeight = FontWeight.Bold - ) +// Text( +// text = amountStr, +// color = Color.Black, +// style = MaterialTheme.typography.titleMedium, +// fontWeight = FontWeight.Bold +// ) } HorizontalDivider( @@ -202,7 +204,7 @@ internal fun HistoryTransactionDetailCard( SummaryLine("Date", dateStr) SummaryLine("Time", timeStr) - SummaryLine("Merchant Name", merchantNameStr) +// SummaryLine("Merchant Name", merchantNameStr) SummaryLine("Mid", midStr) SummaryLine("Tid", tidStr) SummaryLine("Trace No", traceNoStr) @@ -315,7 +317,7 @@ internal fun HistoryNumericKeypad( ) ) { if (key == "⌫") { - Icon(Icons.Rounded.Backspace, contentDescription = "Backspace") + Icon(Icons.AutoMirrored.Rounded.Backspace, contentDescription = "Backspace") } else { Text(key, style = MaterialTheme.typography.headlineMedium) } @@ -326,6 +328,74 @@ internal fun HistoryNumericKeypad( } } +internal val searchKeys = listOf( + listOf("1", "2", "3"), + listOf("4", "5", "6"), + listOf("7", "8", "9"), + listOf("C", "0", "\u232B") +) + +@Composable +internal fun SearchInputBox( + query: String, + isFocused: Boolean, + onFocus: () -> Unit, + label: String = if (isFocused) "Trace or RRN" else "Tap to search by Trace or RRN", + onDelete: (() -> Unit)? = null, +) { + Card( + modifier = Modifier + .fillMaxWidth() + .clickable(onClick = onFocus), + colors = CardDefaults.cardColors(containerColor = Color.White), + shape = RoundedCornerShape(12.dp), + elevation = CardDefaults.cardElevation(defaultElevation = if (isFocused) 6.dp else 2.dp) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 14.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Column(modifier = Modifier.weight(1f)) { + Text( + text = label, + style = MaterialTheme.typography.bodySmall, + color = if (isFocused) Color.LegacyRed else Color.Gray + ) + Spacer(modifier = Modifier.height(4.dp)) + Text( + text = query.ifEmpty { "_" }, + color = Color.LegacyRed, + style = MaterialTheme.typography.headlineSmall.copy( + fontWeight = FontWeight.Bold, + letterSpacing = 2.sp + ) + ) + } + + if (query.isNotEmpty()) { + Card( + shape = RoundedCornerShape(18.dp), + colors = CardDefaults.cardColors(containerColor = Color.White), + elevation = CardDefaults.cardElevation(defaultElevation = 4.dp), + modifier = Modifier + .shadow(2.dp, RoundedCornerShape(18.dp)) + .clickable(enabled = onDelete != null) { onDelete?.invoke() } + ) { + Icon( + imageVector = Icons.AutoMirrored.Rounded.Backspace, + contentDescription = "Delete", + tint = Color.LegacyRed, + modifier = Modifier.padding(horizontal = 14.dp, vertical = 12.dp) + ) + } + } + } + } +} + @Preview(showBackground = true) @Composable private fun HistoryTransactionCardPreview() { diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/history_functions/HistoryFilters.kt b/app/src/main/java/com/mob/utsmyanmar/ui/history_functions/HistoryFilters.kt index f9b7272..da25b1d 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/history_functions/HistoryFilters.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/history_functions/HistoryFilters.kt @@ -55,11 +55,17 @@ internal fun displayTransactionStatus(payDetail: PayDetail): String { if (payDetail.transactionType == TransactionsType.REVERSAL.value) { return if (payDetail.isNeedReversal) "REVERSAL FAILED" else "REVERSAL SUCCESS" } - return POSUtil.getInstance().getResponse(payDetail.tradeAnswerCode.orEmpty().ifBlank { "-" }) + val code = payDetail.tradeAnswerCode.orEmpty().ifBlank { "-" } + return try { + POSUtil.getInstance().getResponse(code) + } catch (_: Throwable) { + if (code == "00") "Approved" else code + } } internal fun displayTransactionTitle(payDetail: PayDetail): String { val title = payDetail.transType + .orEmpty() .ifBlank { "TRANSACTION" } .replace("CASH_OUT", "CASH_ADV", ignoreCase = true) return if (payDetail.transactionType == TransactionsType.REVERSAL.value) { diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/history_functions/HistoryViewModel.kt b/app/src/main/java/com/mob/utsmyanmar/ui/history_functions/HistoryViewModel.kt index 05be6db..df9d93d 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/history_functions/HistoryViewModel.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/history_functions/HistoryViewModel.kt @@ -21,6 +21,7 @@ class HistoryViewModel @Inject constructor( fun getLastSettlement(): LiveData> = repository.getLastSettlement() + fun getReviewBatchTransaction(batchNo: String): LiveData> = repository.getReviewBatchTransaction(batchNo) @@ -28,5 +29,9 @@ class HistoryViewModel @Inject constructor( repository.getSmileSummaryTrans(batchNo) fun searchTransaction(voucherNo: String): LiveData = - repository.searchTransaction(voucherNo) + if (voucherNo.length > 6) { + repository.searchPayDetail(voucherNo) + } else { + repository.searchTransaction(voucherNo.padStart(6, '0')) + } } diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/history_functions/ReprintAnyTransactionScreen.kt b/app/src/main/java/com/mob/utsmyanmar/ui/history_functions/ReprintAnyTransactionScreen.kt index 4b0e303..fb85545 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/history_functions/ReprintAnyTransactionScreen.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/history_functions/ReprintAnyTransactionScreen.kt @@ -48,13 +48,6 @@ import com.mob.utsmyanmar.ui.theme.MOBPOSTheme import com.utsmyanmar.paylibs.model.PayDetail import com.utsmyanmar.paylibs.utils.enums.HostType -private val searchKeys = listOf( - listOf("1", "2", "3"), - listOf("4", "5", "6"), - listOf("7", "8", "9"), - listOf("C", "0", "\u232B") -) - @Composable fun ReprintAnyTransactionScreen( viewModel: HistoryViewModel, @@ -128,7 +121,8 @@ fun ReprintAnyTransactionContent( SearchInputBox( query = searchQuery, isFocused = isFocused, - onFocus = { isFocused = true } + onFocus = { isFocused = true }, + onDelete = { searchQuery = searchQuery.dropLast(1) } ) Spacer(modifier = Modifier.height(8.dp)) @@ -191,64 +185,6 @@ fun ReprintAnyTransactionContent( } } -@Composable -private fun SearchInputBox( - query: String, - isFocused: Boolean, - onFocus: () -> Unit, -) { - Card( - modifier = Modifier - .fillMaxWidth() - .clickable(onClick = onFocus), - colors = CardDefaults.cardColors(containerColor = Color.White), - shape = RoundedCornerShape(12.dp), - elevation = CardDefaults.cardElevation(defaultElevation = if (isFocused) 6.dp else 2.dp) - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = 14.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween - ) { - Column(modifier = Modifier.weight(1f)) { - Text( - text = if (isFocused) "Trace or RRN" else "Tap to search by Trace or RRN", - style = MaterialTheme.typography.bodySmall, - color = if (isFocused) Color.LegacyRed else Color.Gray - ) - Spacer(modifier = Modifier.height(4.dp)) - Text( - text = query.ifEmpty { "_" }, - color = Color.LegacyRed, - style = MaterialTheme.typography.headlineSmall.copy( - fontWeight = FontWeight.Bold, - letterSpacing = 2.sp - ) - ) - } - - if (query.isNotEmpty()) { - Card( - shape = RoundedCornerShape(18.dp), - colors = CardDefaults.cardColors(containerColor = Color.White), - elevation = CardDefaults.cardElevation(defaultElevation = 4.dp), - modifier = Modifier - .shadow(2.dp, RoundedCornerShape(18.dp)) - .clickable { } - ) { - Icon( - imageVector = Icons.AutoMirrored.Rounded.Backspace, - contentDescription = "Delete", - tint = Color.LegacyRed, - modifier = Modifier.padding(horizontal = 14.dp, vertical = 12.dp) - ) - } - } - } - } -} @Preview(showBackground = true) @Composable diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/history_functions/ReviewDetailScreen.kt b/app/src/main/java/com/mob/utsmyanmar/ui/history_functions/ReviewDetailScreen.kt index 359232c..e9df418 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/history_functions/ReviewDetailScreen.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/history_functions/ReviewDetailScreen.kt @@ -124,3 +124,42 @@ private fun ReviewDetailScreenPreview() { ) } } + +@P2Preview +@P3Preview +@Composable +private fun ReviewDetailScreenWithReprintPreview() { + MOBPOSTheme { + ReviewDetailContent( + transaction = PayDetail().apply { + transDate = "21/09/26" + transTime = "14:04:15" + merchantName = "UTS Merchant" + merchantNo = "100089476209176" + terminalNo = "10420257" + voucherNo = "000001" + referNo = "123456789012" + approvalCode = "123456" + transType = "SALE" + amount = 1500000L + accountType = "MPU" + cardNo = "9503036867315548" + tradeAnswerCode = "00" + }, + onBack = {}, + onReprint = {} + ) + } +} + +@P2Preview +@P3Preview +@Composable +private fun ReviewDetailScreenNotFoundPreview() { + MOBPOSTheme { + ReviewDetailContent( + transaction = null, + onBack = {} + ) + } +} diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/history_functions/ReviewTraceScreen.kt b/app/src/main/java/com/mob/utsmyanmar/ui/history_functions/ReviewTraceScreen.kt index b5d417d..d4a9c95 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/history_functions/ReviewTraceScreen.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/history_functions/ReviewTraceScreen.kt @@ -1,18 +1,20 @@ package com.mob.utsmyanmar.ui.history_functions -import androidx.compose.foundation.layout.Box +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.slideInVertically +import androidx.compose.animation.slideOutVertically import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults -import androidx.compose.material3.Card -import androidx.compose.material3.CardDefaults +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -22,16 +24,16 @@ import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.material3.MaterialTheme -import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData +import com.mob.utsmyanmar.ui.components.NumericKeypad import com.mob.utsmyanmar.ui.components.appbar.AppBar +import com.mob.utsmyanmar.ui.preview.P2Preview +import com.mob.utsmyanmar.ui.preview.P3Preview import com.mob.utsmyanmar.ui.theme.Color +import com.mob.utsmyanmar.ui.theme.MOBPOSTheme import com.utsmyanmar.paylibs.model.PayDetail @Composable @@ -40,7 +42,6 @@ fun ReviewTraceScreen( onBack: () -> Unit, onNavigateReviewDetail: (String) -> Unit, ) { - var traceNumber by remember { mutableStateOf("") } var searchedTrace by remember { mutableStateOf("") } var lastNavigatedTrace by remember { mutableStateOf(null) } @@ -61,6 +62,24 @@ fun ReviewTraceScreen( onNavigateReviewDetail(matchedTrace) } + ReviewTraceContent( + searchedTrace = searchedTrace, + transactionFound = transaction != null, + onBack = onBack, + onSearch = { query -> searchedTrace = query } + ) +} + +@Composable +fun ReviewTraceContent( + searchedTrace: String, + transactionFound: Boolean, + onBack: () -> Unit, + onSearch: (String) -> Unit, +) { + var traceNumber by remember { mutableStateOf("") } + var isFocused by remember { mutableStateOf(true) } + Scaffold( containerColor = Color.IvoryBeige, topBar = { @@ -78,12 +97,12 @@ fun ReviewTraceScreen( .padding(16.dp) ) { Text( - text = if (searchedTrace.isNotBlank() && transaction == null) { + text = if (searchedTrace.isNotBlank() && !transactionFound) { "No transaction found for trace $searchedTrace." } else { "Input trace number to review transaction." }, - color = if (searchedTrace.isNotBlank() && transaction == null) { + color = if (searchedTrace.isNotBlank() && !transactionFound) { Color.LegacyRed } else { Color.Black @@ -93,49 +112,66 @@ fun ReviewTraceScreen( Spacer(modifier = Modifier.height(16.dp)) - Card( - modifier = Modifier.fillMaxWidth(), - colors = CardDefaults.cardColors(containerColor = Color.White) - ) { - Text( - text = traceNumber.padStart(6, '0').ifEmpty { "000000" }, - modifier = Modifier - .fillMaxWidth() - .padding(24.dp), - textAlign = TextAlign.Center, - style = MaterialTheme.typography.displayMedium.copy(fontSize = 28.sp) - ) - } + SearchInputBox( + query = traceNumber, + isFocused = isFocused, + onFocus = { isFocused = true }, + onDelete = { traceNumber = traceNumber.dropLast(1) } + ) Spacer(modifier = Modifier.height(16.dp)) - HistoryNumericKeypad( - onDigit = { digit -> - if (traceNumber.length < 6) traceNumber += digit - }, - onBackspace = { - if (traceNumber.isNotEmpty()) { - traceNumber = traceNumber.dropLast(1) + AnimatedVisibility( + visible = isFocused, + enter = slideInVertically(initialOffsetY = { it }), + exit = slideOutVertically(targetOffsetY = { it }) + ) { + NumericKeypad( + keys = searchKeys, + modifier = Modifier + .fillMaxWidth() + .height(280.dp) + .padding(top = 8.dp), + onKeyClick = { key -> + when (key) { + "C" -> traceNumber = "" + "\u232B" -> traceNumber = traceNumber.dropLast(1) + else -> if (traceNumber.length < 12) traceNumber += key + } } - }, - onClear = { traceNumber = "" } - ) + ) + } Spacer(modifier = Modifier.weight(1f)) Button( - onClick = { searchedTrace = traceNumber.padStart(6, '0') }, + onClick = { onSearch(traceNumber.trim()) }, enabled = traceNumber.isNotBlank(), modifier = Modifier .fillMaxWidth() .height(56.dp), + shape = RoundedCornerShape(8.dp), colors = ButtonDefaults.buttonColors( containerColor = Color.LegacyRed, contentColor = Color.White ) ) { - Text("Search") + Text("Search", style = MaterialTheme.typography.titleMedium) } } } } + +@P2Preview +@P3Preview +@Composable +private fun ReviewTraceScreenPreview() { + MOBPOSTheme { + ReviewTraceContent( + searchedTrace = "", + transactionFound = false, + onBack = {}, + onSearch = {} + ) + } +} diff --git a/app/src/main/java/com/mob/utsmyanmar/utils/Converter.kt b/app/src/main/java/com/mob/utsmyanmar/utils/Converter.kt index 6d6921f..12f9483 100644 --- a/app/src/main/java/com/mob/utsmyanmar/utils/Converter.kt +++ b/app/src/main/java/com/mob/utsmyanmar/utils/Converter.kt @@ -20,6 +20,7 @@ fun String?.maskCardNumber(): String { return maskedPan.toString() } -fun convertDateString(dateStr: String): String { +fun convertDateString(dateStr: String?): String { + if (dateStr.isNullOrEmpty()) return "" return dateStr.replace(Regex("/(\\d{2})$"), "/20$1") } \ No newline at end of file diff --git a/paylibs/src/main/java/com/utsmyanmar/paylibs/system/BaseErrorCode.java b/paylibs/src/main/java/com/utsmyanmar/paylibs/system/BaseErrorCode.java index 4f157c2..b88819e 100644 --- a/paylibs/src/main/java/com/utsmyanmar/paylibs/system/BaseErrorCode.java +++ b/paylibs/src/main/java/com/utsmyanmar/paylibs/system/BaseErrorCode.java @@ -88,23 +88,33 @@ public class BaseErrorCode { } public static String getCode(String code) { - if (instance == null) instance = new BaseErrorCode(); + if (instance == null || (instance.errorCode.isEmpty() && PayLibsUtils.getInstance().context != null)) { + instance = new BaseErrorCode(); + } String errorMsg = instance.errorCode.get(code); // return (errorMsg != null ? "RESPONSE CODE"+"(" + code + ")\n ("+errorMsg+")" : getString(R.string.errorOthers)); if(code.length() == 2) { - return (errorMsg != null ? errorMsg : getString(R.string.errorOthers)); + if (errorMsg != null) return errorMsg; + String defaultError = getString(R.string.errorOthers); + return defaultError != null ? defaultError : ("00".equals(code) ? "Approved" : "Others"); } else if(code.isEmpty()) { return "NO RESPONSE"; } else { - return (errorMsg != null ? code + " - "+errorMsg : getString(R.string.errorOthers)); + if (errorMsg != null) return code + " - "+errorMsg; + String defaultError = getString(R.string.errorOthers); + return defaultError != null ? code + " - " + defaultError : code + " - Others"; } } public static String getErrorMessage(String code) { - if (instance == null) instance = new BaseErrorCode(); + if (instance == null || (instance.errorCode.isEmpty() && PayLibsUtils.getInstance().context != null)) { + instance = new BaseErrorCode(); + } String errorMsg = instance.errorCode.get(code); - return (errorMsg != null ?" "+ errorMsg+" " :getString(R.string.errorOthers)); + if (errorMsg != null) return " " + errorMsg + " "; + String defaultError = getString(R.string.errorOthers); + return " " + (defaultError != null ? defaultError : "Others") + " "; } private static BaseErrorCode instance; @@ -117,14 +127,21 @@ public class BaseErrorCode { if (KeyValueSet == null) return; int size = KeyValueSet.length; if (size % 2 == 0) - for (int i = 0; i < size; i += 2) - errorCode.put((String) KeyValueSet[i],getString((Integer)KeyValueSet[i + 1])); + for (int i = 0; i < size; i += 2) { + String val = getString((Integer)KeyValueSet[i + 1]); + if (val != null) { + errorCode.put((String) KeyValueSet[i], val); + } + } else throw new RuntimeException("Error code key value pairs must be even numbers"); } private Map errorCode = new HashMap<>(); private static String getString(int id) { + if (PayLibsUtils.getInstance() == null || PayLibsUtils.getInstance().context == null) { + return null; + } return PayLibsUtils.getInstance().context.getString(id); }