Merge remote-tracking branch 'origin/tms' into dev
This commit is contained in:
commit
5d51f53440
@ -14,8 +14,9 @@ android {
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "com.mob.ustmm"
|
||||
applicationId = "com.mob.utsmyanmar"
|
||||
minSdk = 24
|
||||
//noinspection OldTargetApi
|
||||
targetSdk = 36
|
||||
versionCode = 1
|
||||
versionName = "1.0"
|
||||
@ -38,6 +39,7 @@ android {
|
||||
}
|
||||
buildFeatures {
|
||||
compose = true
|
||||
buildConfig = true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
package com.mob.utsmyanmar.model.sirius
|
||||
|
||||
import com.utsmyanmar.baselib.network.model.sirius.SiriusHost
|
||||
import com.utsmyanmar.baselib.network.model.sirius.SiriusMerchant
|
||||
import com.utsmyanmar.baselib.network.model.sirius.SiriusProperty
|
||||
|
||||
data class SiriusResponse (
|
||||
var serial: String,
|
||||
var ecrKey: String,
|
||||
var address: String,
|
||||
var merchant : SiriusMerchant,
|
||||
var hosts : List<SiriusHost>,
|
||||
var properties: List<SiriusProperty>
|
||||
)
|
||||
@ -0,0 +1,6 @@
|
||||
package com.mob.utsmyanmar.model.sirius
|
||||
|
||||
enum class TMSUpdate {
|
||||
UPDATE,
|
||||
CHECK
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
package com.mob.utsmyanmar.model.sirius
|
||||
|
||||
data class TMSValidity(
|
||||
var status: ValidityStatus? = null,
|
||||
var message: String? = null
|
||||
)
|
||||
@ -0,0 +1,6 @@
|
||||
package com.mob.utsmyanmar.model.sirius
|
||||
|
||||
enum class ValidityStatus {
|
||||
SUCCESS,
|
||||
FAILURE
|
||||
}
|
||||
@ -47,6 +47,7 @@ fun DashboardScreen2(
|
||||
onNavigateSeeMore: () -> Unit = {},
|
||||
onNavigateSettlement: () -> Unit = {},
|
||||
onNavigateVersion: () -> Unit = {},
|
||||
onNavigateFunctions: () -> Unit = {},
|
||||
deviceInfoViewModel: DeviceInfoViewModel = viewModel()
|
||||
) {
|
||||
val deviceInfo by deviceInfoViewModel.uiState.collectAsState()
|
||||
@ -250,6 +251,7 @@ fun DashboardScreen2(
|
||||
)
|
||||
DrawerItem("Function", Icons.Default.Dashboard) {
|
||||
scope.launch { drawerState.close() }
|
||||
onNavigateFunctions()
|
||||
}
|
||||
DrawerItem("Version", Icons.Default.Dashboard) {
|
||||
scope.launch { drawerState.close() }
|
||||
|
||||
@ -0,0 +1,235 @@
|
||||
package com.mob.utsmyanmar.ui.functions
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
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.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material.icons.filled.ChevronRight
|
||||
import androidx.compose.material.icons.filled.OnDeviceTraining
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.ElevatedButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
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.R
|
||||
@Composable
|
||||
fun FunctionsScreen(
|
||||
onBack: () -> Unit = {}
|
||||
) {
|
||||
Scaffold(
|
||||
containerColor = Color.IvoryBeige,
|
||||
topBar = {
|
||||
AppBar(
|
||||
title = "Settings",
|
||||
icon = Icons.AutoMirrored.Filled.ArrowBack,
|
||||
onIconClick = onBack
|
||||
)
|
||||
}
|
||||
) { paddingValues ->
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues)
|
||||
.padding(16.dp).verticalScroll(rememberScrollState()),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||
) {
|
||||
Text(text = "General Settings")
|
||||
FunctionButton(
|
||||
onClick = {},
|
||||
title = "App Version",
|
||||
subTitle = "1.0-uat",
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
modifier = Modifier.size(24.dp),
|
||||
painter = painterResource(R.drawable.ic_device_info),
|
||||
contentDescription = "icon",
|
||||
tint = Color.LegacyRed
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
FunctionButton(
|
||||
onClick = {},
|
||||
title = "Host Config",
|
||||
subTitle = "Detail for bound hosts",
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
modifier = Modifier.size(24.dp),
|
||||
painter = painterResource(R.drawable.ic_database_config),
|
||||
contentDescription = "icon",
|
||||
tint = Color.LegacyRed
|
||||
)
|
||||
},
|
||||
trailingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.ChevronRight,
|
||||
contentDescription = "icon",
|
||||
tint = Color.LegacyRed
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
Text(text = "System Configuration")
|
||||
|
||||
FunctionButton(
|
||||
onClick = {},
|
||||
title = "Clear Batch",
|
||||
subTitle = "Detail for bound hosts",
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
modifier = Modifier.size(24.dp),
|
||||
painter = painterResource(R.drawable.ic_refresh),
|
||||
contentDescription = "icon",
|
||||
tint = Color.LegacyRed
|
||||
)
|
||||
},
|
||||
trailingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.ChevronRight,
|
||||
contentDescription = "icon",
|
||||
tint = Color.LegacyRed
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
FunctionButton(
|
||||
onClick = {},
|
||||
title = "Clear Reversal",
|
||||
subTitle = "Detail for bound hosts",
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
modifier = Modifier.size(24.dp),
|
||||
painter = painterResource(R.drawable.ic_clear),
|
||||
contentDescription = "icon",
|
||||
tint = Color.LegacyRed
|
||||
)
|
||||
},
|
||||
trailingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.ChevronRight,
|
||||
contentDescription = "icon",
|
||||
tint = Color.LegacyRed
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
FunctionButton(
|
||||
onClick = {},
|
||||
title = "TMS Server Url",
|
||||
subTitle = "Detail for bound hosts",
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
modifier = Modifier.size(24.dp),
|
||||
painter = painterResource(R.drawable.ic_address_global),
|
||||
contentDescription = "icon",
|
||||
tint = Color.LegacyRed
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
FunctionButton(
|
||||
onClick = {},
|
||||
title = "Download Config",
|
||||
subTitle = "Download terminal config from host",
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
modifier = Modifier.size(24.dp),
|
||||
painter = painterResource(R.drawable.ic_circle_download_arrow),
|
||||
contentDescription = "icon",
|
||||
tint = Color.LegacyRed
|
||||
)
|
||||
},
|
||||
trailingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.ChevronRight,
|
||||
contentDescription = "icon",
|
||||
tint = Color.LegacyRed
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun FunctionButton(
|
||||
onClick: () -> Unit,
|
||||
title: String,
|
||||
subTitle: String,
|
||||
leadingIcon: (@Composable () -> Unit)? = null,
|
||||
trailingIcon: (@Composable () -> Unit)? = null,
|
||||
) {
|
||||
ElevatedButton(
|
||||
onClick = onClick,
|
||||
shape = RoundedCornerShape(12.dp),
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
containerColor = Color.White,
|
||||
contentColor = Color.Black
|
||||
),
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 16.dp)
|
||||
) {
|
||||
leadingIcon?.invoke()
|
||||
Spacer(modifier = Modifier.width(12.dp))
|
||||
Column(modifier = Modifier
|
||||
.weight(1f)
|
||||
.padding(horizontal = 8.dp)) {
|
||||
Text(text = title)
|
||||
Text(
|
||||
text = subTitle,
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = Color.Gray
|
||||
)
|
||||
}
|
||||
|
||||
trailingIcon?.invoke()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@P3Preview
|
||||
@P2Preview
|
||||
@Composable
|
||||
fun PreviewFunctionsScreen() {
|
||||
FunctionsScreen()
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun PreviewFunctionButton() {
|
||||
FunctionButton(
|
||||
onClick = {},
|
||||
title = "title",
|
||||
subTitle = "sub-title"
|
||||
)
|
||||
}
|
||||
@ -37,6 +37,9 @@ import com.mob.utsmyanmar.ui.pinpad.PinPadViewModel
|
||||
import com.mob.utsmyanmar.ui.settlement.SettlementViewModel
|
||||
import com.mob.utsmyanmar.ui.transaction_result.TransactionResultEvent
|
||||
import com.mob.utsmyanmar.ui.transaction_result.TransactionResultViewModel
|
||||
import com.mob.utsmyanmar.ui.functions.FunctionsScreen
|
||||
import com.mob.utsmyanmar.ui.tms_setup.TmsSetupRoute
|
||||
import com.mob.utsmyanmar.ui.tms_setup.TmsSetupViewModel
|
||||
import com.mob.utsmyanmar.ui.version.VersionScreen
|
||||
import com.mob.utsmyanmar.viewmodel.SharedViewModel
|
||||
import com.mob.utsmyanmar.viewmodel.TransProcessViewModel
|
||||
@ -52,8 +55,23 @@ fun AppNavGraph(
|
||||
|
||||
NavHost(
|
||||
navController = navController,
|
||||
startDestination = Routes.Dashboard.route
|
||||
startDestination = Routes.TmsSetup.route
|
||||
) {
|
||||
composable(Routes.TmsSetup.route) {
|
||||
val tmsSetupViewModel: TmsSetupViewModel = hiltViewModel()
|
||||
TmsSetupRoute(
|
||||
viewModel = tmsSetupViewModel,
|
||||
onNavigateDashboard = {
|
||||
navController.navigate(Routes.Dashboard.route) {
|
||||
popUpTo(Routes.TmsSetup.route) {
|
||||
inclusive = true
|
||||
}
|
||||
launchSingleTop = true
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
composable(Routes.Dashboard.route) {
|
||||
val sharedViewModel: SharedViewModel = hiltViewModel(activity);
|
||||
DashboardScreen2(
|
||||
@ -62,7 +80,7 @@ fun AppNavGraph(
|
||||
sharedViewModel.transactionsType.value = TransactionsType.SALE;
|
||||
sharedViewModel.processCode.value = ProcessCode.SALE_PURCHASE + ProcessCode.SMART + ProcessCode.TO_ACCOUNT;
|
||||
}
|
||||
|
||||
|
||||
navController.navigate(Routes.Amount.createRoute(action)) {
|
||||
launchSingleTop = true
|
||||
}
|
||||
@ -83,7 +101,12 @@ fun AppNavGraph(
|
||||
}
|
||||
},
|
||||
onNavigateVersion = {
|
||||
navController.navigate(Routes.Version.route);
|
||||
navController.navigate(Routes.Version.route)
|
||||
},
|
||||
onNavigateFunctions = {
|
||||
navController.navigate(Routes.Functions.route) {
|
||||
launchSingleTop = true
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
@ -113,6 +136,12 @@ fun AppNavGraph(
|
||||
)
|
||||
}
|
||||
|
||||
composable(Routes.Functions.route) {
|
||||
FunctionsScreen(
|
||||
onBack = { navController.popBackStack() }
|
||||
)
|
||||
}
|
||||
|
||||
composable(Routes.VoidTrace.route) {
|
||||
val voidViewModel: VoidViewModel = hiltViewModel()
|
||||
|
||||
|
||||
@ -3,6 +3,7 @@ package com.mob.utsmyanmar.ui.navigation
|
||||
import android.net.Uri
|
||||
|
||||
sealed class Routes(val route: String) {
|
||||
data object TmsSetup : Routes("tms_setup")
|
||||
data object Dashboard : Routes("dashboard")
|
||||
data object Amount : Routes("amount/{action}") {
|
||||
fun createRoute(action: String): String = "amount/${Uri.encode(action)}"
|
||||
@ -27,4 +28,5 @@ sealed class Routes(val route: String) {
|
||||
data object TransactionResult : Routes("transaction_result")
|
||||
data object PrintReceipt : Routes("print_receipt")
|
||||
data object Version : Routes("version")
|
||||
data object Functions : Routes("functions")
|
||||
}
|
||||
|
||||
@ -0,0 +1,173 @@
|
||||
package com.mob.utsmyanmar.ui.tms_setup
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
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.layout.size
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.CloudDownload
|
||||
import androidx.compose.material.icons.filled.ErrorOutline
|
||||
import androidx.compose.material.icons.filled.Refresh
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CardDefaults
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.LinearProgressIndicator
|
||||
import androidx.compose.material3.OutlinedButton
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.StrokeCap
|
||||
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.theme.Color as AppColor
|
||||
|
||||
@Composable
|
||||
fun TmsSetupRoute(
|
||||
viewModel: TmsSetupViewModel,
|
||||
onNavigateDashboard: () -> Unit
|
||||
) {
|
||||
val state by viewModel.uiState.collectAsState()
|
||||
|
||||
LaunchedEffect(viewModel) {
|
||||
viewModel.navigateToDashboard.collect { onNavigateDashboard() }
|
||||
}
|
||||
|
||||
TmsSetupScreen(
|
||||
state = state,
|
||||
onRetry = viewModel::downloadConfigs,
|
||||
onSkip = viewModel::skipDownload
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TmsSetupScreen(
|
||||
state: TmsSetupUiState,
|
||||
onRetry: () -> Unit,
|
||||
onSkip: () -> Unit
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(AppColor.IvoryBeige),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(32.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.spacedBy(24.dp)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = if (state.isError) Icons.Default.ErrorOutline else Icons.Default.CloudDownload,
|
||||
contentDescription = null,
|
||||
tint = if (state.isError) AppColor.Error else AppColor.LegacyRed,
|
||||
modifier = Modifier.size(72.dp)
|
||||
)
|
||||
|
||||
Text(
|
||||
text = if (state.isError) "Configuration Error" else "Setting Up Terminal",
|
||||
fontSize = 22.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = AppColor.LegacyRed,
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
|
||||
Card(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
shape = RoundedCornerShape(20.dp),
|
||||
colors = CardDefaults.cardColors(containerColor = AppColor.White),
|
||||
elevation = CardDefaults.cardElevation(defaultElevation = 4.dp)
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(24.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp)
|
||||
) {
|
||||
if (state.isLoading) {
|
||||
CircularProgressIndicator(
|
||||
color = AppColor.CrimsonRed,
|
||||
modifier = Modifier.size(40.dp)
|
||||
)
|
||||
LinearProgressIndicator(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
color = AppColor.CrimsonRed,
|
||||
trackColor = AppColor.GoldenGlow.copy(alpha = 0.3f),
|
||||
strokeCap = StrokeCap.Round
|
||||
)
|
||||
}
|
||||
|
||||
Text(
|
||||
text = state.statusText,
|
||||
fontSize = 14.sp,
|
||||
color = AppColor.Black,
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
|
||||
if (state.isError) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(
|
||||
AppColor.Error.copy(alpha = 0.08f),
|
||||
RoundedCornerShape(12.dp)
|
||||
)
|
||||
.padding(12.dp)
|
||||
) {
|
||||
Text(
|
||||
text = state.errorMessage,
|
||||
fontSize = 13.sp,
|
||||
color = AppColor.Error,
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (state.isError) {
|
||||
Button(
|
||||
onClick = onRetry,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
shape = RoundedCornerShape(12.dp),
|
||||
colors = ButtonDefaults.buttonColors(containerColor = AppColor.CrimsonRed)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Refresh,
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.padding(end = 8.dp)
|
||||
.size(18.dp)
|
||||
)
|
||||
Text(text = "Retry", fontSize = 16.sp)
|
||||
}
|
||||
|
||||
OutlinedButton(
|
||||
onClick = onSkip,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
shape = RoundedCornerShape(12.dp),
|
||||
colors = ButtonDefaults.outlinedButtonColors(contentColor = AppColor.LegacyRed)
|
||||
) {
|
||||
Text(text = "Skip", fontSize = 16.sp)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,165 @@
|
||||
package com.mob.utsmyanmar.ui.tms_setup
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.mob.utsmyanmar.model.sirius.SiriusResponse
|
||||
import com.mob.utsmyanmar.model.sirius.TMSUpdate
|
||||
import com.mob.utsmyanmar.model.sirius.ValidityStatus
|
||||
import com.mob.utsmyanmar.utils.tms.TMSSetupsImpl
|
||||
import com.mob.utsmyanmar.utils.tms.TMSUtil
|
||||
import com.utsmyanmar.baselib.BaseApplication
|
||||
import com.utsmyanmar.baselib.emv.EmvParamOperation
|
||||
import com.utsmyanmar.baselib.network.model.sirius.SiriusRequest
|
||||
import com.utsmyanmar.baselib.repo.Repository
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharedFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import sunmi.sunmiui.utils.LogUtil
|
||||
import javax.inject.Inject
|
||||
|
||||
data class TmsSetupUiState(
|
||||
val isLoading: Boolean = false,
|
||||
val statusText: String = "Initializing...",
|
||||
val isError: Boolean = false,
|
||||
val errorMessage: String = ""
|
||||
)
|
||||
|
||||
@HiltViewModel
|
||||
class TmsSetupViewModel @Inject constructor(
|
||||
private val repository: Repository,
|
||||
private val emvParamOperation: EmvParamOperation
|
||||
) : ViewModel() {
|
||||
|
||||
private val _uiState = MutableStateFlow(TmsSetupUiState())
|
||||
val uiState: StateFlow<TmsSetupUiState> = _uiState.asStateFlow()
|
||||
|
||||
private val _navigateToDashboard = MutableSharedFlow<Unit>()
|
||||
val navigateToDashboard: SharedFlow<Unit> = _navigateToDashboard.asSharedFlow()
|
||||
|
||||
private val disposables = CompositeDisposable()
|
||||
private val tmsSetups = TMSSetupsImpl()
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
waitForHardware()
|
||||
downloadConfigs()
|
||||
}
|
||||
}
|
||||
|
||||
fun downloadConfigs() {
|
||||
_uiState.update {
|
||||
it.copy(isLoading = true, isError = false, statusText = "Connecting to TMS server...")
|
||||
}
|
||||
|
||||
val disposable = repository.getParams(buildRequest())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
{ response ->
|
||||
_uiState.update { it.copy(statusText = "Applying configuration...") }
|
||||
|
||||
val appResponse = SiriusResponse(
|
||||
serial = response.serial.orEmpty(),
|
||||
ecrKey = response.ecrKey.orEmpty(),
|
||||
address = response.address.orEmpty(),
|
||||
merchant = response.merchant,
|
||||
hosts = response.hosts,
|
||||
properties = response.properties
|
||||
)
|
||||
|
||||
tmsSetups.initParams(appResponse, TMSUpdate.UPDATE, emvParamOperation)
|
||||
onConfigApplied()
|
||||
},
|
||||
{ error ->
|
||||
_uiState.update {
|
||||
it.copy(
|
||||
isLoading = false,
|
||||
isError = true,
|
||||
statusText = "Download failed",
|
||||
errorMessage = formatNetworkError(error)
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
disposables.add(disposable)
|
||||
}
|
||||
|
||||
private suspend fun waitForHardware() {
|
||||
_uiState.update { it.copy(isLoading = true, statusText = "Starting hardware...") }
|
||||
var elapsed = 0
|
||||
while (BaseApplication.basicOptV2 == null && elapsed < 10_000) {
|
||||
delay(500)
|
||||
elapsed += 500
|
||||
}
|
||||
}
|
||||
|
||||
private fun onConfigApplied() {
|
||||
val validity = TMSUtil.getInstance().checkParams()
|
||||
if (validity.status == ValidityStatus.SUCCESS) {
|
||||
_uiState.update { it.copy(isLoading = false, statusText = "Ready.") }
|
||||
viewModelScope.launch { _navigateToDashboard.emit(Unit) }
|
||||
} else {
|
||||
_uiState.update {
|
||||
it.copy(
|
||||
isLoading = false,
|
||||
isError = true,
|
||||
statusText = "Configuration incomplete",
|
||||
errorMessage = validity.message ?: "Invalid TMS configuration"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun skipDownload() {
|
||||
viewModelScope.launch { _navigateToDashboard.emit(Unit) }
|
||||
}
|
||||
|
||||
private fun formatNetworkError(error: Throwable): String {
|
||||
return when (error) {
|
||||
is javax.net.ssl.SSLHandshakeException ->
|
||||
"SSL handshake failed: ${error.message ?: "Certificate or protocol mismatch"}"
|
||||
is javax.net.ssl.SSLException ->
|
||||
"SSL/TLS error: ${error.message ?: "Secure connection could not be established"}"
|
||||
is java.security.cert.CertificateException ->
|
||||
"Server certificate error: ${error.message ?: "Certificate is invalid or untrusted"}"
|
||||
is java.net.UnknownHostException ->
|
||||
"Host not found: ${error.message ?: "Check server URL and network connection"}"
|
||||
is java.net.ConnectException ->
|
||||
"Connection refused: ${error.message ?: "Server is unreachable"}"
|
||||
is java.net.SocketTimeoutException ->
|
||||
"Connection timed out: ${error.message ?: "Server did not respond in time"}"
|
||||
is retrofit2.HttpException ->
|
||||
"HTTP ${error.code()} ${error.message()}"
|
||||
else ->
|
||||
error.message ?: "Unknown network error"
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
private fun buildRequest(): SiriusRequest {
|
||||
return try {
|
||||
val tranTime: Long = System.currentTimeMillis()
|
||||
TMSUtil.getInstance().generateRequestParams("...", tranTime)
|
||||
} catch (e: Exception) {
|
||||
LogUtil.e("TmsSetupViewModel", e.message)
|
||||
SiriusRequest()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
disposables.clear()
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,89 @@
|
||||
package com.mob.utsmyanmar.utils.tms
|
||||
|
||||
import android.content.Context
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.NetworkCapabilities
|
||||
import android.os.Build
|
||||
import android.telephony.TelephonyManager
|
||||
import androidx.annotation.RequiresPermission
|
||||
|
||||
object Connectivity {
|
||||
|
||||
fun isConnected(context: Context): Boolean {
|
||||
val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||
val network = cm.activeNetwork ?: return false
|
||||
val capabilities = cm.getNetworkCapabilities(network) ?: return false
|
||||
return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) &&
|
||||
capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
|
||||
}
|
||||
|
||||
fun isConnectedWifi(context: Context): Boolean {
|
||||
val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||
val capabilities = cm.getNetworkCapabilities(cm.activeNetwork ?: return false) ?: return false
|
||||
return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
|
||||
}
|
||||
|
||||
fun isConnectedMobile(context: Context): Boolean {
|
||||
val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||
val capabilities = cm.getNetworkCapabilities(cm.activeNetwork ?: return false) ?: return false
|
||||
return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
|
||||
}
|
||||
|
||||
fun isConnectedFast(context: Context): Boolean {
|
||||
val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||
val capabilities = cm.getNetworkCapabilities(cm.activeNetwork ?: return false) ?: return false
|
||||
return when {
|
||||
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) ||
|
||||
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true
|
||||
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> {
|
||||
// Downstream bandwidth in Kbps; 2000 Kbps = ~2 Mbps threshold for "fast"
|
||||
capabilities.linkDownstreamBandwidthKbps >= 2000
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
|
||||
fun getNetworkType(context: Context): String {
|
||||
val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||
val capabilities = cm.getNetworkCapabilities(cm.activeNetwork ?: return "None") ?: return "None"
|
||||
|
||||
if (!capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
|
||||
return when {
|
||||
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> "WiFi"
|
||||
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> "Ethernet"
|
||||
else -> "Unknown"
|
||||
}
|
||||
}
|
||||
|
||||
val tm = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
|
||||
val networkType = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
tm.dataNetworkType
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
tm.networkType
|
||||
}
|
||||
|
||||
return when (networkType) {
|
||||
TelephonyManager.NETWORK_TYPE_GPRS,
|
||||
TelephonyManager.NETWORK_TYPE_EDGE,
|
||||
TelephonyManager.NETWORK_TYPE_CDMA,
|
||||
TelephonyManager.NETWORK_TYPE_1xRTT,
|
||||
TelephonyManager.NETWORK_TYPE_IDEN -> "2G"
|
||||
|
||||
TelephonyManager.NETWORK_TYPE_UMTS,
|
||||
TelephonyManager.NETWORK_TYPE_EVDO_0,
|
||||
TelephonyManager.NETWORK_TYPE_EVDO_A,
|
||||
TelephonyManager.NETWORK_TYPE_EVDO_B,
|
||||
TelephonyManager.NETWORK_TYPE_HSDPA,
|
||||
TelephonyManager.NETWORK_TYPE_HSUPA,
|
||||
TelephonyManager.NETWORK_TYPE_HSPA,
|
||||
TelephonyManager.NETWORK_TYPE_EHRPD,
|
||||
TelephonyManager.NETWORK_TYPE_HSPAP -> "3G"
|
||||
|
||||
TelephonyManager.NETWORK_TYPE_LTE -> "4G"
|
||||
TelephonyManager.NETWORK_TYPE_NR -> "5G"
|
||||
else -> "Unknown"
|
||||
}
|
||||
}
|
||||
}
|
||||
25
app/src/main/java/com/mob/utsmyanmar/utils/tms/TMSSetups.kt
Normal file
25
app/src/main/java/com/mob/utsmyanmar/utils/tms/TMSSetups.kt
Normal file
@ -0,0 +1,25 @@
|
||||
package com.mob.utsmyanmar.utils.tms
|
||||
|
||||
import com.mob.utsmyanmar.model.sirius.SiriusResponse
|
||||
import com.mob.utsmyanmar.model.sirius.TMSUpdate
|
||||
import com.utsmyanmar.baselib.emv.EmvParamOperation
|
||||
|
||||
interface TMSSetups {
|
||||
|
||||
fun initParams(
|
||||
siriusResponse: SiriusResponse,
|
||||
tmsUpdate: TMSUpdate,
|
||||
emvParamOperation: EmvParamOperation
|
||||
)
|
||||
|
||||
fun initParams(json: String)
|
||||
|
||||
fun convertToArray(string: String): ArrayList<String>
|
||||
|
||||
fun getPayHardwareVersion(): String
|
||||
|
||||
fun getRomVersion(): String
|
||||
|
||||
fun generateFinalVersion(): String
|
||||
|
||||
}
|
||||
274
app/src/main/java/com/mob/utsmyanmar/utils/tms/TMSSetupsImpl.kt
Normal file
274
app/src/main/java/com/mob/utsmyanmar/utils/tms/TMSSetupsImpl.kt
Normal file
@ -0,0 +1,274 @@
|
||||
package com.mob.utsmyanmar.utils.tms
|
||||
|
||||
import com.google.gson.Gson
|
||||
import com.mob.utsmyanmar.model.sirius.SiriusResponse
|
||||
import com.mob.utsmyanmar.model.sirius.TMSUpdate
|
||||
import com.utsmyanmar.baselib.BaseApplication
|
||||
import com.utsmyanmar.baselib.emv.EmvParamOperation
|
||||
import com.utsmyanmar.baselib.network.model.sirius.SiriusHost
|
||||
import com.utsmyanmar.baselib.network.model.sirius.SiriusMerchant
|
||||
import com.utsmyanmar.baselib.network.model.sirius.SiriusProperty
|
||||
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation
|
||||
import com.utsmyanmar.paylibs.utils.enums.CurrencyType
|
||||
import sunmi.sunmiui.utils.LogUtil
|
||||
|
||||
class TMSSetupsImpl : TMSSetups {
|
||||
|
||||
companion object {
|
||||
private const val TAG = "TMSSetupsImpl"
|
||||
private const val UPI = "UPI"
|
||||
private const val JCB = "JCB"
|
||||
private const val VISA = "VISA"
|
||||
private const val MASTERCARD = "MASTERCARD"
|
||||
}
|
||||
|
||||
private fun currencyTextToCurrencyType(currencyText: String): CurrencyType {
|
||||
return try {
|
||||
CurrencyType.valueOf(currencyText)
|
||||
} catch (e: Exception) {
|
||||
CurrencyType.MMK
|
||||
}
|
||||
}
|
||||
|
||||
private fun currencyTextToCode(currencyText: String): String {
|
||||
return when (currencyText) {
|
||||
"USD" -> "804"
|
||||
"CNY" -> "156"
|
||||
"THB" -> "764"
|
||||
"RUB" -> "643"
|
||||
else -> "104"
|
||||
}
|
||||
}
|
||||
|
||||
private fun currencyCodeToText(currencyCode: String): String {
|
||||
return when (currencyCode) {
|
||||
"804" -> "USD"
|
||||
"156" -> "CNY"
|
||||
"764" -> "THB"
|
||||
"643" -> "RUB"
|
||||
else -> "MMK"
|
||||
}
|
||||
}
|
||||
|
||||
private fun init() {
|
||||
SystemParamsOperation.getInstance().apply {
|
||||
hostName = ""
|
||||
terminalId = ""
|
||||
merchantId = ""
|
||||
ipAddress = ""
|
||||
secIpAddress = ""
|
||||
|
||||
secHostName = ""
|
||||
secHostTerminalId = ""
|
||||
secHostMerchantId = ""
|
||||
secHostIpAddress = ""
|
||||
secHostSecIpAddress = ""
|
||||
}
|
||||
}
|
||||
|
||||
override fun initParams(
|
||||
siriusResponse: SiriusResponse,
|
||||
tmsUpdate: TMSUpdate,
|
||||
emvParamOperation: EmvParamOperation
|
||||
) {
|
||||
val siriusMerchant: SiriusMerchant = siriusResponse.merchant
|
||||
val siriusHosts: List<SiriusHost> = siriusResponse.hosts
|
||||
val siriusProperty: List<SiriusProperty> = siriusResponse.properties
|
||||
val imgUrls = mutableListOf<String>()
|
||||
val ops = SystemParamsOperation.getInstance()
|
||||
|
||||
if (tmsUpdate == TMSUpdate.UPDATE) ops.isNeedSettlement = false
|
||||
|
||||
siriusResponse.address.takeIf { it.isEmpty() }?.let { ops.merchantAddress = "" }
|
||||
|
||||
init()
|
||||
|
||||
siriusMerchant.let { m ->
|
||||
ops.merchantName = m.name
|
||||
ops.merchantAddress = m.address
|
||||
ops.merchantPhoneNo = m.phone
|
||||
}
|
||||
|
||||
siriusResponse.address.takeIf { it.isNotEmpty() }?.let { ops.merchantAddress = it }
|
||||
//host
|
||||
if (siriusHosts.isNotEmpty()) {
|
||||
for (host in siriusHosts) {
|
||||
val isMMQR = listOf(host.name, host.description).any {
|
||||
it.lowercase().run { contains("mmqr") }
|
||||
}
|
||||
|
||||
if (isMMQR) {
|
||||
ops.secHostName = host.name
|
||||
ops.secHostTerminalId = host.tid
|
||||
ops.secHostMerchantId = host.mid
|
||||
|
||||
host.secondaryIP.trim().let { ip ->
|
||||
ops.secHostIpAddress = if (ip.contains(":")) "$ip/" else ""
|
||||
}
|
||||
host.currency.takeIf { it.isNotEmpty() }?.let {
|
||||
ops.secHostCurrency = currencyTextToCode(it)
|
||||
}
|
||||
if (host.tid.isEmpty()) ops.secHostTerminalId = ""
|
||||
if (host.mid.isEmpty()) ops.secHostTerminalId = ""
|
||||
} else {
|
||||
ops.hostName = host.name
|
||||
ops.terminalId = host.tid
|
||||
ops.merchantId = host.mid
|
||||
|
||||
host.primaryIP.trim().let { ip ->
|
||||
ops.ipAddress = if (ip.contains(":")) ip else ""
|
||||
}
|
||||
host.secondaryIP.trim().let { ip ->
|
||||
ops.secIpAddress = if (ip.contains(":")) ip else ""
|
||||
}
|
||||
host.currency.takeIf { it.isNotEmpty() }?.let {
|
||||
ops.currencyType = currencyTextToCurrencyType(it)
|
||||
}
|
||||
if (host.tid.isEmpty()) ops.terminalId = ""
|
||||
if (host.mid.isEmpty()) ops.merchantId = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Properties
|
||||
for (prop in siriusProperty) {
|
||||
val name = prop.name
|
||||
val data = prop.property
|
||||
|
||||
when (name) {
|
||||
//image
|
||||
"carousel_img_1",
|
||||
"carousel_img_2",
|
||||
"carousel_img_3",
|
||||
"carousel_img_4",
|
||||
"carousel_img_5",
|
||||
"carousel_img_6" -> imgUrls.add(data)
|
||||
//host
|
||||
"host_timeout",
|
||||
"host_connect_timeout" -> ops.hostResponseTimeout = data
|
||||
"host_read_timeout" -> ops.hostReadTimeout = data
|
||||
"reversal_delay" -> ops.reversalDelay = data
|
||||
"key_index" -> ops.tmkIndex = data
|
||||
"receipt_footer" -> ops.receiptFooter = data
|
||||
"time_out" -> ops.setTmsTimeout(data)
|
||||
"manual_update" -> ops.manualUpdate = parseBoolean(data)
|
||||
"emv_enable" -> ops.setEmvEnable(parseBoolean(data))
|
||||
"hostport" -> ops.portAddress = data.toInt()
|
||||
"pre_auth_enable" -> ops.preAuthStatus = parseBoolean(data)
|
||||
"void_enable" -> ops.voidStatus = parseBoolean(data)
|
||||
"cash_advance_enable" -> ops.cashAdvanceStatus = parseBoolean(data)
|
||||
"refund_enable" -> ops.refundStatus = parseBoolean(data)
|
||||
"settlement_enable" -> ops.settlementStatus = parseBoolean(data)
|
||||
"system_password" -> ops.systemPassword = data.take(6).ifEmpty { data }
|
||||
"settlement_password" -> ops.settlementPassword = data.take(6).ifEmpty { data }
|
||||
"setting_password" -> ops.settingPassword = data.take(6).ifEmpty { data }
|
||||
"terminal_enable" -> ops.isActive = parseBoolean(data)
|
||||
"terminal_enable_msg" -> ops.disabledMsg = data
|
||||
"ssl_enable" -> ops.setSslSwitchStatus(parseBoolean(data))
|
||||
"wave_pay_inquiry_status_enable" -> ops.wavePayInquiryStatus = parseBoolean(data)
|
||||
"tips_adjustment_enable" -> ops.tipsAdjustmentStatus = parseBoolean(data)
|
||||
"wave_enable" -> ops.wavePayStatus = parseBoolean(data)
|
||||
"print_iso_enable" -> ops.printISOStatus = parseBoolean(data)
|
||||
"receipt_header" -> ops.receiptHeader = data
|
||||
"random_pin_pad_enable" -> ops.isRandomPinPad = parseBoolean(data)
|
||||
"clear_batch_time" -> ops.clearBatchTime = data
|
||||
"alert_sound_enable" -> ops.isAlertSound = parseBoolean(data)
|
||||
"auto_print_enable" -> ops.isAutoPrintCustomerCopy = parseBoolean(data)
|
||||
"ecr_enable" -> ops.ecrStatus = parseBoolean(data)
|
||||
"manual_entry_enable" -> ops.setManualEntyrStatus(parseBoolean(data))
|
||||
"mmqr_interval_waiting_time" -> ops.waveIntervalTime = data
|
||||
"full_void_preauth_enable" -> ops.fullVoidPreauthStatus = parseBoolean(data)
|
||||
"partial_void_preauth_enable" -> ops.partialVoidPreauthStatus = parseBoolean(data)
|
||||
"clear_batch_day" -> ops.clearBatchDay = data
|
||||
"qr_min_amount" -> ops.minAmount = data
|
||||
"qr_max_amount" -> ops.maxAmount = data
|
||||
"mmqr_auth_token" -> ops.authToken = data
|
||||
"mmqr_grant_type" -> ops.grantType = data
|
||||
"mmqr_token_host_address" -> ops.tokenHostAddress = "${data.trim()}/"
|
||||
"mmpay_enable" -> ops.isMMPayEnabled = parseBoolean(data)
|
||||
"fallback_enable" -> ops.fallbackEnabled = parseBoolean(data)
|
||||
"magstripe_enable" -> ops.isMagStripeEnabled = parseBoolean(data)
|
||||
"nfc_enable" -> ops.isNfcEnabled = parseBoolean(data)
|
||||
"cvv_bypass_enable" -> ops.cvvBypassStatus = parseBoolean(data)
|
||||
"upi_chip_cvm" -> emvParamOperation.updateChipCVM(UPI, data.toLong())
|
||||
"upi_contactless_cvm" -> {
|
||||
val limit = data.toLong()
|
||||
ops.upiCvmLimit = limit
|
||||
emvParamOperation.updateUpiCVM(limit)
|
||||
}
|
||||
|
||||
"upi_currency_code" -> emvParamOperation.updateUpiCurrencyCode(data)
|
||||
"jcb_chip_cvm" -> emvParamOperation.updateChipCVM(JCB, data.toLong())
|
||||
"visa_chip_cvm" -> emvParamOperation.updateChipCVM(VISA, data.toLong())
|
||||
"visa_contactless_cvm" -> emvParamOperation.updatePayWaveCVM(data.toLong())
|
||||
"visa_currency_code" -> emvParamOperation.updatePayWaveCurrencyCode(data)
|
||||
"master_chip_cvm" -> emvParamOperation.updateChipCVM(MASTERCARD, data.toLong())
|
||||
"master_contactless_cvm" -> emvParamOperation.updatePayPassCVM(data.toLong())
|
||||
"master_currency_code" -> emvParamOperation.updatePayPassCurrencyCode(data)
|
||||
"terminal_capability" -> {
|
||||
if (data.isNotEmpty()) ops.setTerminalCapability(data)
|
||||
}
|
||||
|
||||
"upi_ttq" -> emvParamOperation.updateQuickPassTTQ(data)
|
||||
"visa_ttq" -> emvParamOperation.updatePayWaveTTQ(data)
|
||||
"master_ttq" -> emvParamOperation.updatePayPassTTQ(data)
|
||||
"upi_tc_enabled" -> ops.setUpiTCEnabled(parseBoolean(data))
|
||||
"debug_feature_enable" -> ops.setDebugFeatureEnabled(parseBoolean(data))
|
||||
"master_terminal_capability" -> {
|
||||
if (data.isNotEmpty()) emvParamOperation.updatePayPassTerminalCapability(data)
|
||||
}
|
||||
|
||||
"speedup_contactless_enable" -> ops.setSpeedUpContactless(parseBoolean(data))
|
||||
"manual_entry_pin_enable" -> ops.isManualEntryPinEnable = parseBoolean(data)
|
||||
"cmhl_enabled" -> ops.setCMHLEnable(parseBoolean(data))
|
||||
}
|
||||
}
|
||||
ops.carouselUrls = imgUrls.joinToString(",")
|
||||
}
|
||||
|
||||
override fun initParams(json: String) {
|
||||
val response = Gson().fromJson<SiriusResponse>(json, SiriusResponse::class.java)
|
||||
response.properties.forEach { prop ->
|
||||
LogUtil.d(TAG, "name : ${prop.name}")
|
||||
LogUtil.d(TAG, "value: ${prop.property}")
|
||||
}
|
||||
}
|
||||
|
||||
override fun convertToArray(string: String): ArrayList<String> {
|
||||
if (string.isEmpty()) return ArrayList()
|
||||
return ArrayList(string.split(",").filter { it.isNotEmpty() })
|
||||
}
|
||||
|
||||
override fun getPayHardwareVersion(): String {
|
||||
return try {
|
||||
BaseApplication.getInstance().applicationContext.packageManager
|
||||
.getPackageInfo("com.sunmi.pay.hardware_v3", 0)
|
||||
.versionName ?: "?"
|
||||
} catch (e: Exception) {
|
||||
"?"
|
||||
}
|
||||
}
|
||||
|
||||
override fun getRomVersion(): String {
|
||||
return try {
|
||||
android.os.Build.VERSION.RELEASE
|
||||
} catch (e: Exception) {
|
||||
"UNKNOWN"
|
||||
}
|
||||
}
|
||||
|
||||
override fun generateFinalVersion(): String {
|
||||
val phv = getPayHardwareVersion()
|
||||
val rv = getRomVersion()
|
||||
val sv = try {
|
||||
BaseApplication.getInstance().applicationContext.packageManager
|
||||
.getPackageInfo(BaseApplication.getInstance().packageName, 0)
|
||||
.versionName ?: "?"
|
||||
} catch (e: Exception) {
|
||||
"?"
|
||||
}
|
||||
return "PHV$phv-RV$rv-SV$sv"
|
||||
}
|
||||
private fun parseBoolean(data: String): Boolean =
|
||||
data.toIntOrNull()?.let { it == 1 } ?: data.toBoolean();
|
||||
}
|
||||
169
app/src/main/java/com/mob/utsmyanmar/utils/tms/TMSUtil.kt
Normal file
169
app/src/main/java/com/mob/utsmyanmar/utils/tms/TMSUtil.kt
Normal file
@ -0,0 +1,169 @@
|
||||
package com.mob.utsmyanmar.utils.tms
|
||||
|
||||
import android.Manifest
|
||||
import android.content.Context
|
||||
import android.os.BatteryManager
|
||||
import android.os.Build
|
||||
import androidx.annotation.RequiresPermission
|
||||
import com.mob.utsmyanmar.BuildConfig
|
||||
import com.mob.utsmyanmar.model.sirius.TMSValidity
|
||||
import com.mob.utsmyanmar.model.sirius.ValidityStatus
|
||||
import com.mob.utsmyanmar.viewmodel.SharedViewModel
|
||||
import com.sunmi.pay.hardware.aidl.AidlConstants
|
||||
import com.utsmyanmar.baselib.BaseApplication
|
||||
import com.utsmyanmar.baselib.network.model.sirius.SiriusRequest
|
||||
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation
|
||||
import sunmi.sunmiui.utils.LogUtil
|
||||
|
||||
class TMSUtil private constructor() {
|
||||
private val tmsSetups: TMSSetups = TMSSetupsImpl();
|
||||
|
||||
companion object {
|
||||
private val TAG = TMSUtil::class.java.simpleName
|
||||
|
||||
@Volatile
|
||||
private var app: TMSUtil? = null
|
||||
|
||||
fun getInstance(): TMSUtil = app ?: synchronized(this) {
|
||||
app ?: TMSUtil().also { app = it }
|
||||
}
|
||||
}
|
||||
|
||||
// --- Param Init ---
|
||||
fun initParams(json: String) {
|
||||
tmsSetups.initParams(json)
|
||||
}
|
||||
|
||||
fun convertToArray(string: String): ArrayList<String> = tmsSetups.convertToArray(string)
|
||||
|
||||
fun getPayHardwareVersion(): String = tmsSetups.getPayHardwareVersion()
|
||||
|
||||
fun getRomVersion(): String = tmsSetups.getRomVersion()
|
||||
|
||||
fun generateFinalVersion(): String = tmsSetups.generateFinalVersion()
|
||||
|
||||
//---shared view model---
|
||||
fun loadDownloadParameters(sharedViewModel: SharedViewModel) {
|
||||
sharedViewModel.setManualEntryStatus(SystemParamsOperation.getInstance().manualEntryStatus)
|
||||
}
|
||||
|
||||
//---system params---
|
||||
fun getSystemParams(name: String): String = runCatching {
|
||||
BaseApplication.basicOptV2.getSysParam(name)
|
||||
}.getOrDefault("")
|
||||
|
||||
fun getSerialNumber(): String = runCatching {
|
||||
BaseApplication.basicOptV2.getSysParam("SN")
|
||||
}.getOrDefault("")
|
||||
|
||||
@RequiresPermission(Manifest.permission.READ_PHONE_STATE)
|
||||
fun generateRequestParams(lastTransName: String, lastTransTime: Long): SiriusRequest =
|
||||
SiriusRequest().apply {
|
||||
serial = getSerialNumber()
|
||||
appPackage = BuildConfig.APPLICATION_ID
|
||||
androidVersion = Build.VERSION.RELEASE
|
||||
firmwareVersion = getSystemParams(AidlConstants.SysParam.FIRMWARE_VERSION)
|
||||
applicationVersion = BuildConfig.VERSION_NAME
|
||||
currentNetwork = getNetworkType()
|
||||
lastTransaction = lastTransName
|
||||
lastTranTime = lastTransTime
|
||||
latitude = 0.000000
|
||||
longitude = 0.000000
|
||||
value = "YourValueHere"
|
||||
}
|
||||
|
||||
//---logging--
|
||||
fun retrieveParameters() {
|
||||
val ops = SystemParamsOperation.getInstance()
|
||||
LogUtil.d(TAG, "TID: ${ops.terminalId}")
|
||||
LogUtil.d(TAG, "MID: ${ops.merchantId}")
|
||||
LogUtil.d(TAG, "Merchant Name: ${ops.merchantName}")
|
||||
LogUtil.d(TAG, "Merchant Address: ${ops.merchantAddress}")
|
||||
LogUtil.d(TAG, "Host Timeout: ${ops.hostResponseTimeout}")
|
||||
LogUtil.d(TAG, "TMS Timeout: ${ops.tmsTimeOut}")
|
||||
LogUtil.d(TAG, "Key Index: ${ops.tmkIndex}")
|
||||
LogUtil.d(TAG, "Receipt Footer: ${ops.receiptFooter}")
|
||||
LogUtil.d(TAG, "Manual Update: ${ops.manualUpdate}")
|
||||
LogUtil.d(TAG, "Master Enabled: ${ops.isEmvEnabled}")
|
||||
}
|
||||
|
||||
//---checks---
|
||||
fun checkParams(): TMSValidity {
|
||||
val ops = SystemParamsOperation.getInstance()
|
||||
val tid = ops.terminalId
|
||||
val mid = ops.merchantId
|
||||
val hostIp = ops.ipAddress
|
||||
val secIp = ops.secIpAddress
|
||||
val keyIndex = ops.tmkIndex
|
||||
|
||||
return when {
|
||||
tid.length == 8 && mid.length == 15 && hostIp.isNotEmpty() && secIp.isNotEmpty() && keyIndex.isNotEmpty() -> TMSValidity(
|
||||
ValidityStatus.SUCCESS, "Success"
|
||||
)
|
||||
|
||||
tid.length != 8 -> TMSValidity(ValidityStatus.FAILURE, "Tid is invalid")
|
||||
mid.length != 15 -> TMSValidity(ValidityStatus.FAILURE, "Mid is invalid")
|
||||
hostIp.isEmpty() -> TMSValidity(ValidityStatus.FAILURE, "host ip is empty")
|
||||
secIp.isEmpty() -> TMSValidity(ValidityStatus.FAILURE, "sec ip is empty")
|
||||
|
||||
else -> TMSValidity(ValidityStatus.FAILURE, "KeyIndex is invalid")
|
||||
}
|
||||
}
|
||||
|
||||
fun checkSecHostParams(): TMSValidity {
|
||||
val ops = SystemParamsOperation.getInstance()
|
||||
val tid = ops.secHostTerminalId
|
||||
val mid = ops.secHostMerchantId
|
||||
val hostIp = ops.secHostIpAddress
|
||||
val secIp = ops.secHostSecIpAddress
|
||||
val keyIndex = ops.tmkIndex
|
||||
|
||||
return when {
|
||||
tid.length == 8 && mid.length == 15 && hostIp.isNotEmpty() && secIp.isNotEmpty() && keyIndex.isNotEmpty()
|
||||
-> TMSValidity(ValidityStatus.SUCCESS, "Success")
|
||||
|
||||
tid.length != 8 -> TMSValidity(ValidityStatus.FAILURE, "MMQR Tid is invalid!")
|
||||
mid.length != 15 -> TMSValidity(ValidityStatus.FAILURE, "MMQR Mid is invalid!")
|
||||
hostIp.isEmpty() -> TMSValidity(ValidityStatus.FAILURE, "MMQR Pri-Ip is invalid!")
|
||||
else -> TMSValidity(ValidityStatus.FAILURE, "MMQR Sec-Ip is invalid!")
|
||||
}
|
||||
}
|
||||
|
||||
//---helpers---
|
||||
private fun getTransactionStatus(code: String): String = when (code) {
|
||||
"00" -> "Transaction Approved"
|
||||
else -> "Transaction Failed, reason : $code"
|
||||
}
|
||||
|
||||
private fun getBoolean(data: String): Boolean = data == "1"
|
||||
|
||||
private fun getBatteryLevel(context: Context): Int {
|
||||
val bm = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
|
||||
return bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
|
||||
}
|
||||
|
||||
@RequiresPermission(Manifest.permission.READ_PHONE_STATE)
|
||||
private fun getNetworkType(): String {
|
||||
val ctx = BaseApplication.getInstance().applicationContext
|
||||
|
||||
return when {
|
||||
Connectivity.isConnectedWifi(ctx) -> {
|
||||
LogUtil.d(TAG, "Connected to Wifi")
|
||||
"WIFI"
|
||||
}
|
||||
|
||||
Connectivity.isConnectedMobile(ctx) -> {
|
||||
val type = try {
|
||||
Connectivity.getNetworkType(ctx)
|
||||
} catch (e: SecurityException) {
|
||||
LogUtil.d(TAG, "READ_PHONE_STATE permission not granted: ${e.message}")
|
||||
"MOBILE"
|
||||
}
|
||||
LogUtil.d(TAG, "Connected to Mobile Network: $type")
|
||||
type
|
||||
}
|
||||
|
||||
else -> "No Internet Connection"
|
||||
}
|
||||
}
|
||||
}
|
||||
9
app/src/main/res/drawable/ic_address_global.xml
Normal file
9
app/src/main/res/drawable/ic_address_global.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M12,2C6.5,2 2,6.5 2,12s4.5,10 10,10s10,-4.5 10,-10v-1c-0.6,0.9 -1.2,1.7 -1.7,2.4c-0.4,2.2 -1.6,4.1 -3.3,5.4c-0.1,-0.3 -0.2,-0.7 -0.3,-1c-0.1,-0.4 -0.2,-0.8 -0.4,-1.2c-0.1,-0.4 -0.2,-0.8 -0.4,-1.1c-0.1,-0.1 -0.3,-0.2 -0.5,-0.3c-0.7,-0.2 -1.6,0.1 -2.1,-0.6c-0.2,-0.3 -0.2,-0.6 -0.1,-1c0.2,-0.3 0.3,-0.6 0.5,-0.9c0.2,-0.4 0.5,-0.9 0.6,-1.4c-0.8,-1.2 -1.6,-2.6 -2,-3.9h-0.1c-0.1,0 -0.1,0 -0.2,-0.1c-0.2,-0.2 -0.3,-0.7 -0.2,-1c0,-0.5 0.3,-0.8 0.2,-1.3c0,-0.1 -0.1,-0.9 -0.1,-0.9c-0.3,0 -0.8,0 -0.7,-0.5V3.5H12h0.5c0.2,-0.6 0.6,-1.1 0.9,-1.5H12zM18,2c-2.2,0 -4,1.8 -4,4s4,7 4,7s4,-4.8 4,-7S20.2,2 18,2zM18,4.5c0.8,0 1.5,0.7 1.5,1.5S18.8,7.5 18,7.5S16.5,6.8 16.5,6S17.2,4.5 18,4.5zM8,5.1c0.4,0 0.7,0 1,0.1s0.6,0.3 0.8,0.5s0.5,0.5 0.5,0.8c0,0.1 0,0.2 -0.1,0.2C10.1,6.8 10,6.8 9.9,6.8c-0.3,0 -0.6,0 -0.8,-0.1C9,6.6 8.8,6.4 8.6,6.3C8.1,6.1 7.2,7.4 7.1,7.8C7,8.1 7,8.8 7.5,8.9c0.3,0 1,-0.6 1.2,-0.8C8.9,8 9,7.9 9.2,7.8c0.8,-0.1 1.4,0.6 1.6,1.3C11,9.9 9.6,10.5 9,10.7c-0.2,0.1 -0.3,-0.1 -0.5,0c-0.5,0.2 -1.1,0.9 -1.1,1.4s-0.1,1 -0.2,1.5c-0.1,0 -0.2,-0.1 -0.2,-0.1v-0.2c0,-0.3 -0.1,-0.6 -0.4,-0.8c-0.1,0 -0.1,-0.1 -0.2,-0.1c-0.3,-0.1 -0.6,-0.4 -0.9,-0.1c-0.2,0.2 -0.4,0.5 -0.4,0.8c0,0.1 0,0.2 0.1,0.3c0.2,0.1 0.4,0 0.6,0c0.1,0 0.2,0.2 0.3,0.3c0.2,0.3 0.3,0.8 0.7,0.8h0.7h1.3c0.3,0.1 0.8,0.2 1,0.4c0.1,0.2 0.1,0.4 0.2,0.6c0.4,0.5 1.1,0.5 1.7,0.7c0.2,0.1 0.3,0.2 0.3,0.4c0,0.3 -0.1,0.7 -0.2,1s-0.2,0.7 -0.4,0.9s-0.4,0.3 -0.6,0.4c-0.4,0.2 -0.6,0.6 -0.8,0.9c0,0 -0.1,0.2 -0.2,0.3c-0.8,-0.2 -1.5,-0.5 -2.2,-1v-0.2c-0.1,-0.4 -0.2,-0.7 -0.3,-1c-0.2,-0.5 -0.5,-1.1 -0.6,-1.6c0,-0.5 0.1,-1 -0.2,-1.4c-0.3,-0.5 -1.1,-0.5 -1.6,-0.8c-0.4,-0.4 -0.9,-0.8 -1.3,-1.3V12c0,-2.7 1.3,-5.1 3.3,-6.7C7.3,5.2 7.6,5.1 8,5.1z"
|
||||
android:fillColor="#000000"/>
|
||||
</vector>
|
||||
12
app/src/main/res/drawable/ic_circle_download_arrow.xml
Normal file
12
app/src/main/res/drawable/ic_circle_download_arrow.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="800dp"
|
||||
android:height="800dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:pathData="M512.8,1002.4c-65.6,0 -129.6,-12.8 -189.6,-38.4 -58.4,-24.8 -110.4,-60 -155.2,-104.8S88,761.6 64,703.2c-25.6,-60 -38.4,-124 -38.4,-190.4 0,-65.6 12.8,-130.4 38.4,-190.4 24,-57.6 59.2,-110.4 104,-155.2s96.8,-80 155.2,-104.8C383.2,36.8 447.2,24 512.8,24s129.6,12.8 189.6,38.4c58.4,24.8 110.4,60 155.2,104.8 44.8,44.8 80,96.8 104.8,155.2 25.6,60 38.4,124 38.4,190.4 0,65.6 -12.8,130.4 -38.4,190.4 -24.8,58.4 -60,110.4 -104.8,155.2 -44.8,44.8 -96.8,80 -155.2,104.8 -60,25.6 -123.2,39.2 -189.6,39.2zM512.8,71.2c-242.4,0 -440,198.4 -440,441.6s197.6,441.6 440.8,441.6c243.2,0 440.8,-198.4 440.8,-441.6S756,71.2 512.8,71.2z"
|
||||
android:fillColor="#000000"/>
|
||||
<path
|
||||
android:pathData="M512,811.2c-5.6,0 -12,-2.4 -16,-6.4 -1.6,-0.8 -2.4,-1.6 -4,-3.2L280,589.6c-9.6,-9.6 -9.6,-24 0,-33.6 4.8,-4.8 10.4,-7.2 16.8,-7.2s12,2.4 16.8,7.2L488,731.2V236c0,-12.8 10.4,-24 24,-24 12.8,0 24,10.4 24,24v495.2l175.2,-175.2c4.8,-4.8 10.4,-7.2 16.8,-7.2s12,2.4 16.8,7.2c9.6,9.6 9.6,24 0,33.6l-212,212c-1.6,1.6 -2.4,2.4 -4,3.2 -5.6,4 -11.2,6.4 -16.8,6.4z"
|
||||
android:fillColor="#000000"/>
|
||||
</vector>
|
||||
9
app/src/main/res/drawable/ic_clear.xml
Normal file
9
app/src/main/res/drawable/ic_clear.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="128dp"
|
||||
android:height="128dp"
|
||||
android:viewportWidth="128"
|
||||
android:viewportHeight="128">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="m15.3,13.52c-4.61,2.66 -6.21,8.52 -3.54,13.14L32.21,62.09 15.73,71.6c-4.61,2.66 -6.18,8.51 -3.52,13.12l5.59,9.68 8.03,-4.64c3.18,4.61 7.29,10.53 11,15.48 2.79,3.72 3.86,6.62 7.09,8.89 1.62,1.13 3.79,1.7 5.91,1.63 2.11,-0.07 4.28,-0.6 7.03,-1.47a3.88,3.88 0,0 0,0.44 -0.15L104.38,92.85c2.94,-1.33 5.3,-2.31 7.09,-3.05 1.79,-0.74 2.7,-0.95 4.13,-1.93 0.36,-0.25 0.86,-0.47 1.46,-1.65 0.3,-0.59 0.6,-1.57 0.4,-2.58 -0.19,-1.01 -0.81,-1.8 -1.29,-2.23 -0.95,-0.86 -1.46,-0.9 -1.88,-1.01 -0.42,-0.11 -0.73,-0.15 -1.06,-0.19 -1.32,-0.17 -2.92,-0.2 -5.33,-0.32L95.76,79.25C92.9,79.1 88.82,75.69 86.64,72.48L77.95,59.68 83.07,56.73 77.48,47.04c-2.66,-4.61 -8.53,-6.16 -13.15,-3.5l-15.46,8.92 -20.45,-35.43c-2.66,-4.61 -8.51,-6.18 -13.12,-3.52zM32.55,85.89 L71.21,63.58 80.23,76.84c2.98,4.38 7.96,9.79 15.14,10.16l2.78,0.15 -43.6,19.75c-0.03,0.01 -0.04,-0.01 -0.07,0 -2.38,0.74 -4.04,1.09 -4.91,1.12 -0.89,0.03 -0.87,-0.04 -1.15,-0.24 -0.58,-0.4 -2.22,-2.97 -5.36,-7.16C39.67,96.11 35.71,90.46 32.55,85.89z"/>
|
||||
</vector>
|
||||
52
app/src/main/res/drawable/ic_database_config.xml
Normal file
52
app/src/main/res/drawable/ic_database_config.xml
Normal file
@ -0,0 +1,52 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="800dp"
|
||||
android:height="800dp"
|
||||
android:viewportWidth="48"
|
||||
android:viewportHeight="48">
|
||||
<path
|
||||
android:pathData="M0,0h48v48h-48z"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillAlpha="0.01"/>
|
||||
<path
|
||||
android:pathData="M34,12V20V21C31.045,21 28.389,22.282 26.559,24.32C24.968,26.091 24,28.432 24,31C24,31.579 24.049,32.146 24.144,32.698C24.658,35.705 26.514,38.253 29.074,39.705C26.412,40.51 22.878,41 19,41C10.716,41 4,38.761 4,36V28V20V12"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="4"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M34,12C34,14.761 27.284,17 19,17C10.716,17 4,14.761 4,12C4,9.239 10.716,7 19,7C27.284,7 34,9.239 34,12Z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="4"
|
||||
android:fillColor="#CD2029"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M4,28C4,30.761 10.716,33 19,33C20.807,33 22.539,32.894 24.144,32.698"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="4"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M4,20C4,22.761 10.716,25 19,25C21.756,25 24.339,24.752 26.559,24.32"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="4"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M44,31C44,36.523 39.523,41 34,41C32.209,41 30.528,40.529 29.074,39.705C26.514,38.253 24.658,35.705 24.144,32.698C24.049,32.146 24,31.579 24,31C24,28.432 24.968,26.091 26.559,24.32C28.389,22.282 31.045,21 34,21C39.523,21 44,25.477 44,31Z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="4"
|
||||
android:fillColor="#CD2029"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M34,27V31M37.464,29L34,31M37.464,33L34,31M34,35V31M30.536,33L34,31M30.536,29L34,31"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="4"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#ffffff"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
||||
28
app/src/main/res/drawable/ic_device_info.xml
Normal file
28
app/src/main/res/drawable/ic_device_info.xml
Normal file
@ -0,0 +1,28 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="800dp"
|
||||
android:height="800dp"
|
||||
android:viewportWidth="192"
|
||||
android:viewportHeight="192">
|
||||
<path
|
||||
android:pathData="M96.01,63.63c-3.32,0 -6.12,2.71 -6.12,6.1a6.12,6.12 0,0 0,6.12 6.12c3.38,0 6.1,-2.8 6.1,-6.12s-2.78,-6.1 -6.1,-6.1z"
|
||||
android:strokeAlpha="0.98"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="3.78002"
|
||||
android:fillColor="#000000"
|
||||
android:strokeColor="#000000"
|
||||
android:fillAlpha="0.98"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M83.43,122.37h25.13M87.48,90.96h8.54v31.41"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="12"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M54,46h84M60,22h72c5.54,0 10,4.46 10,10v128c0,5.54 -4.46,10 -10,10L60,170c-5.54,0 -10,-4.46 -10,-10L50,32c0,-5.54 4.46,-10 10,-10zM54,146h84"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="12"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#000000"/>
|
||||
</vector>
|
||||
9
app/src/main/res/drawable/ic_refresh.xml
Normal file
9
app/src/main/res/drawable/ic_refresh.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="800dp"
|
||||
android:height="800dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:pathData="M643.8,876.9c77.5,-26.7 141.1,-75.8 186,-137.3a19.7,19.7 0,0 0,5.7 -17.4,19.4 19.4,0 0,0 -0.1,-0.6l-0,-0a19.7,19.7 0,0 0,-10.7 -14.2l-56.5,-40.1a19.8,19.8 0,0 0,-17.3 -5.4c-0.2,0 -0.3,0 -0.5,0.1l-0.1,0a19.8,19.8 0,0 0,-14.1 10.5c-31.4,42.9 -75.6,76.9 -129.8,95.6 -140.8,48.5 -293.6,-25.7 -342,-166.1s26.4,-292.9 167.2,-341.4c132,-45.4 273.6,15 330.8,138.1l-89.4,0.6c-9,-1.2 -17.6,3.9 -21,12.3a19.7,19.7 0,0 0,6.3 23.1l153.7,155.2c3.8,3.8 9,6 14.5,5.8s10.6,-2.5 14.2,-6.5l148.2,-162.7c6.5,-5.3 8.9,-14.2 6,-22 -0.1,-0.1 -0.1,-0.3 -0.2,-0.4a19.4,19.4 0,0 0,-1.2 -2.6l-0,-0.1c-4,-7.1 -12,-11 -20.1,-9.8l-89.5,0.9 -1.2,-3.4c-68.9,-200 -287.9,-306.3 -488.5,-237.3S86.4,439.6 155.2,639.6c68.9,200 287.9,306.3 488.5,237.3l0,0z"
|
||||
android:fillColor="#000000"/>
|
||||
</vector>
|
||||
@ -1,7 +1,5 @@
|
||||
package com.utsmyanmar.baselib.di;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.utsmyanmar.baselib.BuildConfig;
|
||||
@ -11,8 +9,6 @@ import com.utsmyanmar.baselib.network.WaveTokenApiService;
|
||||
import com.utsmyanmar.baselib.network.interceptor.HostSelectionInterceptor;
|
||||
import com.utsmyanmar.baselib.network.interceptor.QRAuthInterceptor;
|
||||
import com.utsmyanmar.baselib.network.interceptor.SiriusInterceptor;
|
||||
import com.utsmyanmar.baselib.network.interceptor.WaveAuthInterceptor;
|
||||
import com.utsmyanmar.paylibs.Constant;
|
||||
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
@ -38,7 +34,6 @@ import okhttp3.OkHttpClient;
|
||||
import okhttp3.logging.HttpLoggingInterceptor;
|
||||
import retrofit2.Retrofit;
|
||||
import retrofit2.converter.gson.GsonConverterFactory;
|
||||
import sunmi.sunmiui.utils.LogUtil;
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent.class)
|
||||
@ -355,7 +350,7 @@ public class NetworkModule {
|
||||
tmsAddress = getTMSUrlFromNative();
|
||||
}
|
||||
|
||||
String baseUrl = tmsAddress.trim() + "/api/v1/";
|
||||
String baseUrl = tmsAddress.trim() + "/";
|
||||
|
||||
|
||||
final Gson gson =
|
||||
|
||||
@ -3,12 +3,10 @@ package com.utsmyanmar.baselib.network.interceptor;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.utsmyanmar.baselib.util.TerminalUtil;
|
||||
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
@ -18,13 +16,6 @@ public class SiriusInterceptor implements Interceptor {
|
||||
|
||||
private static final String TAG = SiriusInterceptor.class.getSimpleName();
|
||||
|
||||
public static native String getHiddenFromNative();
|
||||
|
||||
static {
|
||||
System.loadLibrary("native-lib");
|
||||
}
|
||||
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Response intercept(@NonNull Chain chain) throws IOException {
|
||||
@ -35,9 +26,9 @@ public class SiriusInterceptor implements Interceptor {
|
||||
String hashed = "";
|
||||
String nonce = TerminalUtil.getInstance().generateRandomNumbers();
|
||||
try {
|
||||
hashed = TerminalUtil.getInstance().generateHashedString(nonce);
|
||||
hashed = TerminalUtil.getInstance().generateHashedString(nonce).toLowerCase();
|
||||
|
||||
// LogUtil.d(TAG,"hashed :"+ hashed);
|
||||
LogUtil.d(TAG,"hashed :"+ hashed);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@ -48,8 +39,13 @@ public class SiriusInterceptor implements Interceptor {
|
||||
.addHeader("request-id", hashed)
|
||||
.addHeader("request-code",nonce)
|
||||
.build();
|
||||
|
||||
LogUtil.d(TAG, "URL: " + newRequest.url());
|
||||
LogUtil.d(TAG, "Method: " + newRequest.method());
|
||||
LogUtil.d(TAG, "Headers: " + newRequest.headers());
|
||||
LogUtil.d(TAG, "request-id: " + hashed);
|
||||
LogUtil.d(TAG, "request-code: " + nonce);
|
||||
|
||||
return chain.proceed(newRequest);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@ package com.utsmyanmar.baselib.network.model.sirius;
|
||||
|
||||
public class SiriusMerchant {
|
||||
|
||||
private int id;
|
||||
private String id;
|
||||
|
||||
private String name;
|
||||
|
||||
@ -16,7 +16,7 @@ public class SiriusMerchant {
|
||||
|
||||
private String mobile;
|
||||
|
||||
public SiriusMerchant(int id, String name, String description, String address,String address2,String phone,String mobile) {
|
||||
public SiriusMerchant(String id, String name, String description, String address,String address2,String phone,String mobile) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
@ -50,7 +50,7 @@ public class SiriusMerchant {
|
||||
return mobile;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@ -66,7 +66,7 @@ public class SiriusMerchant {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
@ -2,12 +2,12 @@ package com.utsmyanmar.baselib.network.model.sirius;
|
||||
|
||||
public class SiriusProperty {
|
||||
|
||||
private int id;
|
||||
private int terId;
|
||||
private String id;
|
||||
private String terId;
|
||||
|
||||
private int appId;
|
||||
private String appId;
|
||||
|
||||
private int configId;
|
||||
private String configId;
|
||||
|
||||
private String name;
|
||||
|
||||
@ -17,7 +17,7 @@ public class SiriusProperty {
|
||||
|
||||
private String property;
|
||||
|
||||
public SiriusProperty(int id, int terId, int appId, int configId, String name, String description, String type, String property) {
|
||||
public SiriusProperty(String id, String terId, String appId, String configId, String name, String description, String type, String property) {
|
||||
this.id = id;
|
||||
this.terId = terId;
|
||||
this.appId = appId;
|
||||
@ -28,19 +28,19 @@ public class SiriusProperty {
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setTerId(int terId) {
|
||||
public void setTerId(String terId) {
|
||||
this.terId = terId;
|
||||
}
|
||||
|
||||
public void setAppId(int appId) {
|
||||
public void setAppId(String appId) {
|
||||
this.appId = appId;
|
||||
}
|
||||
|
||||
public void setConfigId(int configId) {
|
||||
public void setConfigId(String configId) {
|
||||
this.configId = configId;
|
||||
}
|
||||
|
||||
@ -60,19 +60,19 @@ public class SiriusProperty {
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public int getTerId() {
|
||||
public String getTerId() {
|
||||
return terId;
|
||||
}
|
||||
|
||||
public int getAppId() {
|
||||
public String getAppId() {
|
||||
return appId;
|
||||
}
|
||||
|
||||
public int getConfigId() {
|
||||
public String getConfigId() {
|
||||
return configId;
|
||||
}
|
||||
|
||||
|
||||
@ -15,10 +15,30 @@ public class SiriusRequest {
|
||||
|
||||
private String lastTransaction;
|
||||
|
||||
private String lastTranTime;
|
||||
private Long lastTranTime;
|
||||
|
||||
public SiriusRequest() {}
|
||||
public SiriusRequest(String serial, String appPackage, String androidVersion, String firmwareVersion, String applicationVersion, String currentNetwork, String lastTransaction, String lastTranTime) {
|
||||
private String value;
|
||||
|
||||
private double latitude;
|
||||
|
||||
private double longitude;
|
||||
|
||||
public SiriusRequest() {
|
||||
}
|
||||
|
||||
public SiriusRequest(
|
||||
String serial,
|
||||
String appPackage,
|
||||
String androidVersion,
|
||||
String firmwareVersion,
|
||||
String applicationVersion,
|
||||
String currentNetwork,
|
||||
String lastTransaction,
|
||||
Long lastTranTime,
|
||||
String value,
|
||||
double latitude,
|
||||
double longitude
|
||||
) {
|
||||
this.serial = serial;
|
||||
this.appPackage = appPackage;
|
||||
this.androidVersion = androidVersion;
|
||||
@ -27,6 +47,9 @@ public class SiriusRequest {
|
||||
this.currentNetwork = currentNetwork;
|
||||
this.lastTransaction = lastTransaction;
|
||||
this.lastTranTime = lastTranTime;
|
||||
this.value = value;
|
||||
this.latitude = latitude;
|
||||
this.longitude = longitude;
|
||||
}
|
||||
|
||||
public void setSerial(String serial) {
|
||||
@ -57,7 +80,7 @@ public class SiriusRequest {
|
||||
this.lastTransaction = lastTransaction;
|
||||
}
|
||||
|
||||
public void setLastTranTime(String lastTranTime) {
|
||||
public void setLastTranTime(Long lastTranTime) {
|
||||
this.lastTranTime = lastTranTime;
|
||||
}
|
||||
|
||||
@ -89,7 +112,31 @@ public class SiriusRequest {
|
||||
return lastTransaction;
|
||||
}
|
||||
|
||||
public String getLastTranTime() {
|
||||
public Long getLastTranTime() {
|
||||
return lastTranTime;
|
||||
}
|
||||
|
||||
public String getValue(){
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public void setValue(String value){
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public double getLatitude(){
|
||||
return this.latitude;
|
||||
}
|
||||
|
||||
public void setLatitude(double latitude){
|
||||
this.latitude = latitude;
|
||||
}
|
||||
|
||||
public double getLongitude(){
|
||||
return this.longitude;
|
||||
}
|
||||
|
||||
public void setLongitude(double longitude){
|
||||
this.longitude = longitude;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,6 @@
|
||||
package com.utsmyanmar.baselib.util;
|
||||
|
||||
import android.os.RemoteException;
|
||||
|
||||
import com.sunmi.pay.hardware.aidlv2.system.BasicOptV2;
|
||||
import com.utsmyanmar.baselib.BaseApplication;
|
||||
import com.utsmyanmar.paylibs.utils.core_utils.ByteUtil;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@ -12,53 +9,28 @@ import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Random;
|
||||
|
||||
public class TerminalUtilsImpl implements TerminalUtils{
|
||||
|
||||
long number = 2485718;
|
||||
|
||||
long sub = 1251151;
|
||||
|
||||
public static native String getHiddenFromNative();
|
||||
|
||||
public static native String getEncryptedFromNative();
|
||||
|
||||
|
||||
static {
|
||||
System.loadLibrary("native-lib");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateHashString(String random,BasicOptV2 basicOptV2) throws NoSuchAlgorithmException {
|
||||
String sn = getSerialNumber(basicOptV2);
|
||||
String snPN = BaseApplication.getInstance().getPackageName();
|
||||
String nonce = random;
|
||||
String text = sn + snPN + nonce;
|
||||
// LogUtil.d(TAG,"Plain Text: "+text);
|
||||
String sn = "P30224BSJ0276";
|
||||
String snPN = "com.mob.utsmyanmar";
|
||||
String text = sn + snPN + random;
|
||||
MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
||||
byte[] hash = digest.digest(text.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
|
||||
return ByteUtil.bytes2HexStr(hash);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateRandom() {
|
||||
Random rnd = new Random();
|
||||
StringBuilder sb = new StringBuilder((1000000 + rnd.nextInt(9000000)));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(1000000 + rnd.nextInt(9000000));
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSerialNumber(BasicOptV2 basicOptV2){
|
||||
String data = "";
|
||||
try {
|
||||
data = basicOptV2.getSysParam(getEncryptedFromNative());
|
||||
} catch (RemoteException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return data;
|
||||
|
||||
|
||||
return "abcd";
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -38,7 +38,7 @@ public class SystemParamsSettings implements Serializable {
|
||||
|
||||
private boolean checkExpSwitch = false;
|
||||
|
||||
private String tmsAddress = "https://tms.smile-mm.com";
|
||||
private String tmsAddress = "https://sirius-nest.utsmyanmar.com/api/v1";
|
||||
// private String tmsAddress = "http://128.199.170.203";
|
||||
|
||||
private String terminalCapability = "E0E8C8";
|
||||
|
||||
Loading…
Reference in New Issue
Block a user