From 6dc180e7913d7f7c2507c8720b8b6b8aebdf353d Mon Sep 17 00:00:00 2001 From: moon <56061215+MgKyawLay@users.noreply.github.com> Date: Tue, 9 Jun 2026 20:22:23 +0630 Subject: [PATCH] converted tms configs into kotlin --- .../utsmyanmar/model/sirius/TMSValidity.kt | 6 + .../utsmyanmar/model/sirius/ValidityStatus.kt | 6 + .../mob/utsmyanmar/utils/tms/Connectivity.kt | 89 ++++++++++ .../mob/utsmyanmar/utils/tms/TMSSetupsImpl.kt | 29 ++- .../com/mob/utsmyanmar/utils/tms/TMSUtil.kt | 165 ++++++++++++++++++ 5 files changed, 291 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/com/mob/utsmyanmar/model/sirius/TMSValidity.kt create mode 100644 app/src/main/java/com/mob/utsmyanmar/model/sirius/ValidityStatus.kt create mode 100644 app/src/main/java/com/mob/utsmyanmar/utils/tms/Connectivity.kt create mode 100644 app/src/main/java/com/mob/utsmyanmar/utils/tms/TMSUtil.kt diff --git a/app/src/main/java/com/mob/utsmyanmar/model/sirius/TMSValidity.kt b/app/src/main/java/com/mob/utsmyanmar/model/sirius/TMSValidity.kt new file mode 100644 index 0000000..408a17a --- /dev/null +++ b/app/src/main/java/com/mob/utsmyanmar/model/sirius/TMSValidity.kt @@ -0,0 +1,6 @@ +package com.mob.utsmyanmar.model.sirius + +data class TMSValidity( + var status: ValidityStatus? = null, + var message: String? = null +) \ No newline at end of file diff --git a/app/src/main/java/com/mob/utsmyanmar/model/sirius/ValidityStatus.kt b/app/src/main/java/com/mob/utsmyanmar/model/sirius/ValidityStatus.kt new file mode 100644 index 0000000..a4836d3 --- /dev/null +++ b/app/src/main/java/com/mob/utsmyanmar/model/sirius/ValidityStatus.kt @@ -0,0 +1,6 @@ +package com.mob.utsmyanmar.model.sirius + +enum class ValidityStatus { + SUCCESS, + FAILURE +} \ No newline at end of file diff --git a/app/src/main/java/com/mob/utsmyanmar/utils/tms/Connectivity.kt b/app/src/main/java/com/mob/utsmyanmar/utils/tms/Connectivity.kt new file mode 100644 index 0000000..d965834 --- /dev/null +++ b/app/src/main/java/com/mob/utsmyanmar/utils/tms/Connectivity.kt @@ -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" + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mob/utsmyanmar/utils/tms/TMSSetupsImpl.kt b/app/src/main/java/com/mob/utsmyanmar/utils/tms/TMSSetupsImpl.kt index 41cb43a..dd4b6b6 100644 --- a/app/src/main/java/com/mob/utsmyanmar/utils/tms/TMSSetupsImpl.kt +++ b/app/src/main/java/com/mob/utsmyanmar/utils/tms/TMSSetupsImpl.kt @@ -3,6 +3,7 @@ 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 @@ -236,19 +237,39 @@ class TMSSetupsImpl : TMSSetups { } override fun convertToArray(string: String): ArrayList { - TODO("Not yet implemented") + if (string.isEmpty()) return ArrayList() + return ArrayList(string.split(",").filter { it.isNotEmpty() }) } override fun getPayHardwareVersion(): String { - TODO("Not yet implemented") + return try { + BaseApplication.getInstance().applicationContext.packageManager + .getPackageInfo("com.sunmi.pay.hardware_v3", 0) + .versionName ?: "?" + } catch (e: Exception) { + "?" + } } override fun getRomVersion(): String { - TODO("Not yet implemented") + return try { + android.os.Build.VERSION.RELEASE + } catch (e: Exception) { + "UNKNOWN" + } } override fun generateFinalVersion(): String { - TODO("Not yet implemented") + 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(); diff --git a/app/src/main/java/com/mob/utsmyanmar/utils/tms/TMSUtil.kt b/app/src/main/java/com/mob/utsmyanmar/utils/tms/TMSUtil.kt new file mode 100644 index 0000000..f8d35aa --- /dev/null +++ b/app/src/main/java/com/mob/utsmyanmar/utils/tms/TMSUtil.kt @@ -0,0 +1,165 @@ +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.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.BuildConfig +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 = 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: String): SiriusRequest = + SiriusRequest().apply { + serial = getSerialNumber() + appPackage = BuildConfig.APPLICATION_ID + androidVersion = Build.VERSION.RELEASE + firmwareVersion = getSystemParams(AidlConstants.SysParam.FIRMWARE_VERSION) + currentNetwork = getNetworkType() + lastTransaction = lastTransName + lastTranTime = lastTransTime + } + + //---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" + } + } +} \ No newline at end of file